QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsticksscalebarrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsticksscalebarrenderer.cpp
3  ----------------------------
4  begin : June 2008
5  copyright : (C) 2008 by Marco Hugentobler
6  email : [email protected]
7  ***************************************************************************/
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
18 #include "qgsscalebarsettings.h"
19 #include "qgslayoututils.h"
20 #include "qgssymbol.h"
21 #include "qgstextrenderer.h"
22 #include <QPainter>
23 
25  : mTickPosition( position )
26 {
27 
28 }
29 
31 {
32  switch ( mTickPosition )
33  {
34  case TicksUp:
35  return QStringLiteral( "Line Ticks Up" );
36  case TicksDown:
37  return QStringLiteral( "Line Ticks Down" );
38  case TicksMiddle:
39  return QStringLiteral( "Line Ticks Middle" );
40  }
41  return QString(); // to make gcc happy
42 }
43 
45 {
46  switch ( mTickPosition )
47  {
48  case TicksUp:
49  return QObject::tr( "Line Ticks Up" );
50  case TicksDown:
51  return QObject::tr( "Line Ticks Down" );
52  case TicksMiddle:
53  return QObject::tr( "Line Ticks Middle" );
54  }
55  return QString(); // to make gcc happy
56 
57 }
58 
60 {
61  switch ( mTickPosition )
62  {
63  case TicksUp:
64  return 5;
65  case TicksDown:
66  return 4;
67  case TicksMiddle:
68  return 3;
69  }
70  return 6;
71 }
72 
73 QgsScaleBarRenderer::Flags QgsTicksScaleBarRenderer::flags() const
74 {
87 }
88 
90 {
91  return new QgsTicksScaleBarRenderer( * this );
92 }
93 
94 void QgsTicksScaleBarRenderer::draw( QgsRenderContext &context, const QgsScaleBarSettings &settings, const ScaleBarContext &scaleContext ) const
95 {
96  if ( !context.painter() )
97  return;
98 
99  QPainter *painter = context.painter();
100 
101  const double scaledLabelBarSpace = context.convertToPainterUnits( settings.labelBarSpace(), QgsUnitTypes::RenderMillimeters );
102  const double scaledBoxContentSpace = context.convertToPainterUnits( settings.boxContentSpace(), QgsUnitTypes::RenderMillimeters );
103  const QFontMetricsF fontMetrics = QgsTextRenderer::fontMetrics( context, settings.textFormat() );
104  const double barTopPosition = scaledBoxContentSpace + ( settings.labelVerticalPlacement() == QgsScaleBarSettings::LabelAboveSegment ? fontMetrics.ascent() + scaledLabelBarSpace : 0 );
105  const double scaledHeight = context.convertToPainterUnits( settings.height(), QgsUnitTypes::RenderMillimeters );
106  const double scaledSubdivisionsHeight = context.convertToPainterUnits( settings.subdivisionsHeight(), QgsUnitTypes::RenderMillimeters );
107  const double scaledMaxHeight = ( ( settings.numberOfSubdivisions() > 1 ) && ( scaledSubdivisionsHeight > scaledHeight ) ) ? scaledSubdivisionsHeight : scaledHeight;
108  const double middlePosition = barTopPosition + scaledMaxHeight / 2.0;
109  const double bottomPosition = barTopPosition + scaledMaxHeight;
110 
111  const double xOffset = firstLabelXOffset( settings, context, scaleContext );
112 
113  painter->save();
114  context.setPainterFlagsUsingContext( painter );
115 
116  std::unique_ptr< QgsLineSymbol > symbol( settings.lineSymbol()->clone() );
117  symbol->startRender( context );
118 
119  std::unique_ptr< QgsLineSymbol > divisionSymbol( settings.divisionLineSymbol()->clone() );
120  divisionSymbol->startRender( context );
121 
122  std::unique_ptr< QgsLineSymbol > subdivisionSymbol( settings.subdivisionLineSymbol()->clone() );
123  subdivisionSymbol->startRender( context );
124 
125  const QList<double> positions = segmentPositions( context, scaleContext, settings );
126 
127  // vertical positions
128  double verticalPos = 0.0;
129  QList<double> subTickPositionsY;
130  QList<double> tickPositionsY;
131  switch ( mTickPosition )
132  {
133  case TicksDown:
134  verticalPos = barTopPosition;
135  subTickPositionsY << verticalPos;
136  subTickPositionsY << verticalPos + scaledSubdivisionsHeight;
137  tickPositionsY << verticalPos;
138  tickPositionsY << verticalPos + scaledHeight;
139  break;
140  case TicksMiddle:
141  verticalPos = middlePosition;
142  subTickPositionsY << verticalPos + scaledSubdivisionsHeight / 2.0;
143  subTickPositionsY << verticalPos - scaledSubdivisionsHeight / 2.0;
144  tickPositionsY << verticalPos + scaledHeight / 2.0;
145  tickPositionsY << verticalPos - scaledHeight / 2.0;
146  break;
147  case TicksUp:
148  verticalPos = bottomPosition;
149  subTickPositionsY << verticalPos;
150  subTickPositionsY << verticalPos - scaledSubdivisionsHeight;
151  tickPositionsY << verticalPos;
152  tickPositionsY << verticalPos - scaledHeight;
153  break;
154  }
155 
156  int symbolLayerCount = symbol->symbolLayerCount();
157  symbolLayerCount = std::max( symbolLayerCount, divisionSymbol->symbolLayerCount() );
158  symbolLayerCount = std::max( symbolLayerCount, subdivisionSymbol->symbolLayerCount() );
159 
160  // we render the bar symbol-layer-by-symbol-layer, to avoid ugliness where the lines overlap in multi-layer symbols
161  for ( int layer = 0; layer < symbolLayerCount; ++ layer )
162  {
163  const bool drawDivisionsForThisSymbolLayer = layer < divisionSymbol->symbolLayerCount();
164  const bool drawSubdivisionsForThisSymbolLayer = layer < subdivisionSymbol->symbolLayerCount();
165  const bool drawLineForThisSymbolLayer = layer < symbol->symbolLayerCount();
166 
167  if ( drawDivisionsForThisSymbolLayer )
168  {
169  // first draw the vertical lines for segments
170  for ( int i = 0; i < positions.size(); ++i )
171  {
172  const double thisX = context.convertToPainterUnits( positions.at( i ), QgsUnitTypes::RenderMillimeters ) + xOffset;
173  divisionSymbol->renderPolyline( QPolygonF() << QPointF( thisX, tickPositionsY.at( 0 ) )
174  << QPointF( thisX, tickPositionsY.at( 1 ) ), nullptr, context, layer );
175  }
176  }
177 
178  // draw the vertical lines for right subdivisions
179  if ( drawSubdivisionsForThisSymbolLayer )
180  {
181  for ( int i = settings.numberOfSegmentsLeft(); i < positions.size(); ++i )
182  {
183  for ( int j = 1; j < settings.numberOfSubdivisions(); ++j )
184  {
185  const double thisSubX = context.convertToPainterUnits( positions.at( i ) + j * scaleContext.segmentWidth / settings.numberOfSubdivisions(), QgsUnitTypes::RenderMillimeters ) + xOffset;
186  subdivisionSymbol->renderPolyline( QPolygonF() << QPointF( thisSubX, subTickPositionsY.at( 0 ) )
187  << QPointF( thisSubX, subTickPositionsY.at( 1 ) ), nullptr, context, layer );
188  }
189  }
190  }
191 
192  //draw last tick and horizontal line
193  if ( !positions.isEmpty() )
194  {
195  double lastTickPositionX = context.convertToPainterUnits( positions.at( positions.size() - 1 ) + scaleContext.segmentWidth, QgsUnitTypes::RenderMillimeters ) + xOffset;
196 
197  //last vertical line
198  if ( drawDivisionsForThisSymbolLayer )
199  {
200  divisionSymbol->renderPolyline( QPolygonF() << QPointF( lastTickPositionX, tickPositionsY.at( 0 ) )
201  << QPointF( lastTickPositionX, tickPositionsY.at( 1 ) ),
202  nullptr, context, layer );
203  }
204 
205  //horizontal line
206  if ( drawLineForThisSymbolLayer )
207  {
208  symbol->renderPolyline( QPolygonF() << QPointF( xOffset + context.convertToPainterUnits( positions.at( 0 ), QgsUnitTypes::RenderMillimeters ), verticalPos )
209  << QPointF( lastTickPositionX, verticalPos ), nullptr, context, layer );
210  }
211  }
212  }
213 
214  symbol->stopRender( context );
215  divisionSymbol->stopRender( context );
216  subdivisionSymbol->stopRender( context );
217 
218  painter->restore();
219 
220  //draw labels using the default method
221  drawDefaultLabels( context, settings, scaleContext );
222 }
223 
224 
QgsScaleBarSettings::height
double height() const
Returns the scalebar height (in millimeters).
Definition: qgsscalebarsettings.h:550
QgsTicksScaleBarRenderer::TicksUp
@ TicksUp
Render ticks above line.
Definition: qgsticksscalebarrenderer.h:36
QgsScaleBarSettings::lineSymbol
QgsLineSymbol * lineSymbol() const
Returns the line symbol used to render the scalebar (only used for some scalebar types).
Definition: qgsscalebarsettings.cpp:191
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:318
QgsRenderContext::setPainterFlagsUsingContext
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
Definition: qgsrendercontext.cpp:143
QgsScaleBarRenderer::ScaleBarContext
Contains parameters regarding scalebar calculations.
Definition: qgsscalebarrenderer.h:71
QgsScaleBarRenderer::Flag::FlagUsesUnitLabel
@ FlagUsesUnitLabel
Renderer uses the QgsScaleBarSettings::unitLabel() setting.
qgstextrenderer.h
QgsTicksScaleBarRenderer::flags
Flags flags() const override
Returns the scalebar rendering flags, which dictates the renderer's behavior.
Definition: qgsticksscalebarrenderer.cpp:73
QgsTicksScaleBarRenderer::clone
QgsTicksScaleBarRenderer * clone() const override
Returns a clone of the renderer.
Definition: qgsticksscalebarrenderer.cpp:89
QgsLineSymbol::clone
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:2193
QgsTextRenderer::fontMetrics
static QFontMetricsF fontMetrics(QgsRenderContext &context, const QgsTextFormat &format, double scaleFactor=1.0)
Returns the font metrics for the given text format, when rendered in the specified render context.
Definition: qgstextrenderer.cpp:261
QgsTicksScaleBarRenderer::QgsTicksScaleBarRenderer
QgsTicksScaleBarRenderer(TickPosition position=TicksMiddle)
Constructor for QgsTicksScaleBarRenderer.
Definition: qgsticksscalebarrenderer.cpp:24
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:58
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:168
QgsTicksScaleBarRenderer::TicksMiddle
@ TicksMiddle
Render ticks crossing line.
Definition: qgsticksscalebarrenderer.h:38
QgsScaleBarRenderer::Flag::FlagUsesLabelHorizontalPlacement
@ FlagUsesLabelHorizontalPlacement
Renderer uses the QgsScaleBarSettings::labelHorizontalPlacement() setting.
QgsTicksScaleBarRenderer::TicksDown
@ TicksDown
Render ticks below line.
Definition: qgsticksscalebarrenderer.h:37
qgsscalebarsettings.h
qgslayoututils.h
QgsScaleBarSettings::subdivisionsHeight
double subdivisionsHeight() const
Returns the scalebar subdivisions height (in millimeters) for segments included in the right part of ...
Definition: qgsscalebarsettings.h:150
QgsScaleBarSettings::labelBarSpace
double labelBarSpace() const
Returns the spacing (in millimeters) between labels and the scalebar.
Definition: qgsscalebarsettings.h:562
QgsTicksScaleBarRenderer::visibleName
QString visibleName() const override
Returns the user friendly, translated name for the renderer.
Definition: qgsticksscalebarrenderer.cpp:44
QgsScaleBarRenderer::Flag::FlagUsesLabelVerticalPlacement
@ FlagUsesLabelVerticalPlacement
Renderer uses the QgsScaleBarSettings::labelVerticalPlacement() setting.
QgsScaleBarSettings::boxContentSpace
double boxContentSpace() const
Returns the spacing (margin) between the scalebar box and content in millimeters.
Definition: qgsscalebarsettings.h:602
QgsScaleBarSettings::labelVerticalPlacement
LabelVerticalPlacement labelVerticalPlacement() const
Returns the vertical placement of text labels.
Definition: qgsscalebarsettings.h:575
QgsScaleBarSettings::textFormat
QgsTextFormat & textFormat()
Returns the text format used for drawing text in the scalebar.
Definition: qgsscalebarsettings.h:268
QgsScaleBarRenderer::Flag::FlagUsesLineSymbol
@ FlagUsesLineSymbol
Renderer utilizes the scalebar line symbol (see QgsScaleBarSettings::lineSymbol() )
QgsScaleBarSettings
The QgsScaleBarSettings class stores the appearance and layout settings for scalebar drawing with Qgs...
Definition: qgsscalebarsettings.h:41
QgsScaleBarRenderer::Flag::FlagRespectsMapUnitsPerScaleBarUnit
@ FlagRespectsMapUnitsPerScaleBarUnit
Renderer respects the QgsScaleBarSettings::mapUnitsPerScaleBarUnit() setting.
QgsScaleBarSettings::numberOfSegmentsLeft
int numberOfSegmentsLeft() const
Returns the number of segments included in the left part of the scalebar.
Definition: qgsscalebarsettings.h:114
QgsScaleBarRenderer::firstLabelXOffset
Q_DECL_DEPRECATED double firstLabelXOffset(const QgsScaleBarSettings &settings) const
Returns the x-offset (in millimeters) used for the first label in the scalebar.
Definition: qgsscalebarrenderer.cpp:318
QgsTicksScaleBarRenderer::TickPosition
TickPosition
Tick positions.
Definition: qgsticksscalebarrenderer.h:35
QgsScaleBarRenderer::ScaleBarContext::segmentWidth
double segmentWidth
The width, in millimeters, of each individual segment drawn.
Definition: qgsscalebarrenderer.h:77
QgsScaleBarSettings::LabelAboveSegment
@ LabelAboveSegment
Labels are drawn above the scalebar.
Definition: qgsscalebarsettings.h:68
QgsScaleBarRenderer::drawDefaultLabels
void drawDefaultLabels(QgsRenderContext &context, const QgsScaleBarSettings &settings, const QgsScaleBarRenderer::ScaleBarContext &scaleContext) const
Draws default scalebar labels using the specified settings and scaleContext to a destination render c...
Definition: qgsscalebarrenderer.cpp:28
QgsScaleBarRenderer::Flag::FlagUsesSubdivisions
@ FlagUsesSubdivisions
Renderer uses the scalebar subdivisions (see QgsScaleBarSettings::numberOfSubdivisions() )
qgsticksscalebarrenderer.h
QgsScaleBarSettings::divisionLineSymbol
QgsLineSymbol * divisionLineSymbol() const
Returns the line symbol used to render the scalebar divisions (only used for some scalebar types).
Definition: qgsscalebarsettings.cpp:201
QgsScaleBarRenderer::Flag::FlagRespectsUnits
@ FlagRespectsUnits
Renderer respects the QgsScaleBarSettings::units() setting.
QgsScaleBarSettings::subdivisionLineSymbol
QgsLineSymbol * subdivisionLineSymbol() const
Returns the line symbol used to render the scalebar subdivisions (only used for some scalebar types).
Definition: qgsscalebarsettings.cpp:211
QgsScaleBarSettings::numberOfSubdivisions
int numberOfSubdivisions() const
Returns the number of subdivisions for segments included in the right part of the scalebar (only used...
Definition: qgsscalebarsettings.h:132
QgsScaleBarRenderer::Flag::FlagUsesSubdivisionsHeight
@ FlagUsesSubdivisionsHeight
Renderer uses the scalebar subdivisions height (see QgsScaleBarSettings::subdivisionsHeight() )
QgsTicksScaleBarRenderer
A scale bar that draws segments using short ticks.
Definition: qgsticksscalebarrenderer.h:30
QgsScaleBarRenderer::Flag::FlagUsesLabelBarSpace
@ FlagUsesLabelBarSpace
Renderer uses the QgsScaleBarSettings::labelBarSpace() setting.
QgsScaleBarRenderer::Flag::FlagUsesSegments
@ FlagUsesSegments
Renderer uses the scalebar segments.
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:179
QgsScaleBarRenderer::Flag::FlagUsesDivisionSymbol
@ FlagUsesDivisionSymbol
Renderer utilizes the scalebar division symbol (see QgsScaleBarSettings::divisionLineSymbol() )
QgsScaleBarRenderer::Flag::FlagUsesSubdivisionSymbol
@ FlagUsesSubdivisionSymbol
Renderer utilizes the scalebar subdivision symbol (see QgsScaleBarSettings::subdivisionLineSymbol() )
qgssymbol.h
QgsTicksScaleBarRenderer::draw
void draw(QgsRenderContext &context, const QgsScaleBarSettings &settings, const QgsScaleBarRenderer::ScaleBarContext &scaleContext) const override
Draws the scalebar using the specified settings and scaleContext to a destination render context.
Definition: qgsticksscalebarrenderer.cpp:94
QgsTicksScaleBarRenderer::id
QString id() const override
Returns the unique ID for this renderer.
Definition: qgsticksscalebarrenderer.cpp:30
QgsTicksScaleBarRenderer::sortKey
int sortKey() const override
Returns a sorting key value, where renderers with a lower sort key will be shown earlier in lists.
Definition: qgsticksscalebarrenderer.cpp:59
QgsScaleBarRenderer::segmentPositions
Q_DECL_DEPRECATED QList< double > segmentPositions(const QgsScaleBarRenderer::ScaleBarContext &scaleContext, const QgsScaleBarSettings &settings) const
Returns a list of positions for each segment within the scalebar.
Definition: qgsscalebarrenderer.cpp:348