QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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  if ( context.flags() & QgsRenderContext::Antialiasing )
115  painter->setRenderHint( QPainter::Antialiasing, true );
116 
117  std::unique_ptr< QgsLineSymbol > symbol( settings.lineSymbol()->clone() );
118  symbol->startRender( context );
119 
120  std::unique_ptr< QgsLineSymbol > divisionSymbol( settings.divisionLineSymbol()->clone() );
121  divisionSymbol->startRender( context );
122 
123  std::unique_ptr< QgsLineSymbol > subdivisionSymbol( settings.subdivisionLineSymbol()->clone() );
124  subdivisionSymbol->startRender( context );
125 
126  const QList<double> positions = segmentPositions( context, scaleContext, settings );
127 
128  // vertical positions
129  double verticalPos = 0.0;
130  QList<double> subTickPositionsY;
131  QList<double> tickPositionsY;
132  switch ( mTickPosition )
133  {
134  case TicksDown:
135  verticalPos = barTopPosition;
136  subTickPositionsY << verticalPos;
137  subTickPositionsY << verticalPos + scaledSubdivisionsHeight;
138  tickPositionsY << verticalPos;
139  tickPositionsY << verticalPos + scaledHeight;
140  break;
141  case TicksMiddle:
142  verticalPos = middlePosition;
143  subTickPositionsY << verticalPos + scaledSubdivisionsHeight / 2.0;
144  subTickPositionsY << verticalPos - scaledSubdivisionsHeight / 2.0;
145  tickPositionsY << verticalPos + scaledHeight / 2.0;
146  tickPositionsY << verticalPos - scaledHeight / 2.0;
147  break;
148  case TicksUp:
149  verticalPos = bottomPosition;
150  subTickPositionsY << verticalPos;
151  subTickPositionsY << verticalPos - scaledSubdivisionsHeight;
152  tickPositionsY << verticalPos;
153  tickPositionsY << verticalPos - scaledHeight;
154  break;
155  }
156 
157  int symbolLayerCount = symbol->symbolLayerCount();
158  symbolLayerCount = std::max( symbolLayerCount, divisionSymbol->symbolLayerCount() );
159  symbolLayerCount = std::max( symbolLayerCount, subdivisionSymbol->symbolLayerCount() );
160 
161  // we render the bar symbol-layer-by-symbol-layer, to avoid ugliness where the lines overlap in multi-layer symbols
162  for ( int layer = 0; layer < symbolLayerCount; ++ layer )
163  {
164  const bool drawDivisionsForThisSymbolLayer = layer < divisionSymbol->symbolLayerCount();
165  const bool drawSubdivisionsForThisSymbolLayer = layer < subdivisionSymbol->symbolLayerCount();
166  const bool drawLineForThisSymbolLayer = layer < symbol->symbolLayerCount();
167 
168  if ( drawDivisionsForThisSymbolLayer )
169  {
170  // first draw the vertical lines for segments
171  for ( int i = 0; i < positions.size(); ++i )
172  {
173  const double thisX = context.convertToPainterUnits( positions.at( i ), QgsUnitTypes::RenderMillimeters ) + xOffset;
174  divisionSymbol->renderPolyline( QPolygonF() << QPointF( thisX, tickPositionsY.at( 0 ) )
175  << QPointF( thisX, tickPositionsY.at( 1 ) ), nullptr, context, layer );
176  }
177  }
178 
179  // draw the vertical lines for right subdivisions
180  if ( drawSubdivisionsForThisSymbolLayer )
181  {
182  for ( int i = settings.numberOfSegmentsLeft(); i < positions.size(); ++i )
183  {
184  for ( int j = 1; j < settings.numberOfSubdivisions(); ++j )
185  {
186  const double thisSubX = context.convertToPainterUnits( positions.at( i ) + j * scaleContext.segmentWidth / settings.numberOfSubdivisions(), QgsUnitTypes::RenderMillimeters ) + xOffset;
187  subdivisionSymbol->renderPolyline( QPolygonF() << QPointF( thisSubX, subTickPositionsY.at( 0 ) )
188  << QPointF( thisSubX, subTickPositionsY.at( 1 ) ), nullptr, context, layer );
189  }
190  }
191  }
192 
193  //draw last tick and horizontal line
194  if ( !positions.isEmpty() )
195  {
196  double lastTickPositionX = context.convertToPainterUnits( positions.at( positions.size() - 1 ) + scaleContext.segmentWidth, QgsUnitTypes::RenderMillimeters ) + xOffset;
197 
198  //last vertical line
199  if ( drawDivisionsForThisSymbolLayer )
200  {
201  divisionSymbol->renderPolyline( QPolygonF() << QPointF( lastTickPositionX, tickPositionsY.at( 0 ) )
202  << QPointF( lastTickPositionX, tickPositionsY.at( 1 ) ),
203  nullptr, context, layer );
204  }
205 
206  //horizontal line
207  if ( drawLineForThisSymbolLayer )
208  {
209  symbol->renderPolyline( QPolygonF() << QPointF( xOffset + context.convertToPainterUnits( positions.at( 0 ), QgsUnitTypes::RenderMillimeters ), verticalPos )
210  << QPointF( lastTickPositionX, verticalPos ), nullptr, context, layer );
211  }
212  }
213  }
214 
215  symbol->stopRender( context );
216  divisionSymbol->stopRender( context );
217  subdivisionSymbol->stopRender( context );
218 
219  painter->restore();
220 
221  //draw labels using the default method
222  drawDefaultLabels( context, settings, scaleContext );
223 }
224 
225 
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:287
QgsScaleBarRenderer::ScaleBarContext
Contains parameters regarding scalebar calculations.
Definition: qgsscalebarrenderer.h:70
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:2139
QgsTicksScaleBarRenderer::QgsTicksScaleBarRenderer
QgsTicksScaleBarRenderer(TickPosition position=TicksMiddle)
Constructor for QgsTicksScaleBarRenderer.
Definition: qgsticksscalebarrenderer.cpp:24
QgsRenderContext
Definition: qgsrendercontext.h:57
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.
QgsTextRenderer::fontMetrics
static QFontMetricsF fontMetrics(QgsRenderContext &context, const QgsTextFormat &format)
Returns the font metrics for the given text format, when rendered in the specified render context.
Definition: qgstextrenderer.cpp:231
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
Definition: qgsscalebarsettings.h:40
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:309
QgsTicksScaleBarRenderer::TickPosition
TickPosition
Tick positions.
Definition: qgsticksscalebarrenderer.h:34
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() )
QgsRenderContext::Antialiasing
@ Antialiasing
Use antialiasing while drawing.
Definition: qgsrendercontext.h:78
QgsTicksScaleBarRenderer
Definition: qgsticksscalebarrenderer.h:29
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:174
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
QgsRenderContext::flags
Flags flags() const
Returns combination of flags used for rendering.
Definition: qgsrendercontext.cpp:160
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:339