QGIS API Documentation  2.99.0-Master (f867b65)
qgsrendercontext.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrendercontext.cpp
3  --------------------
4  begin : March 16, 2008
5  copyright : (C) 2008 by Marco Hugentobler
6  email : marco dot hugentobler at karto dot baug dot ethz dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 
19 #include "qgsrendercontext.h"
20 
21 #include "qgsmapsettings.h"
22 #include "qgsexpression.h"
23 #include "qgsvectorlayer.h"
25 #include "qgslogger.h"
26 #include "qgspoint.h"
27 
28 #define POINTS_TO_MM 2.83464567
29 #define INCH_TO_MM 25.4
30 
32  : mFlags( DrawEditingInfo | UseAdvancedEffects | DrawSelection | UseRenderingOptimization )
33 {
35  // For RenderMetersInMapUnits support, when rendering in Degrees, the Ellipsoid must be set
36  // - for Previews/Icons the default Extent can be used
37  mDistanceArea.setEllipsoid( mDistanceArea.sourceCrs().ellipsoidAcronym() );
38 }
39 
41  : mFlags( rh.mFlags )
42  , mPainter( rh.mPainter )
43  , mCoordTransform( rh.mCoordTransform )
44  , mDistanceArea( rh.mDistanceArea )
45  , mExtent( rh.mExtent )
46  , mMapToPixel( rh.mMapToPixel )
47  , mRenderingStopped( rh.mRenderingStopped )
48  , mScaleFactor( rh.mScaleFactor )
49  , mRendererScale( rh.mRendererScale )
50  , mLabelingEngine( rh.mLabelingEngine )
51  , mSelectionColor( rh.mSelectionColor )
52  , mVectorSimplifyMethod( rh.mVectorSimplifyMethod )
53  , mExpressionContext( rh.mExpressionContext )
54  , mGeometry( rh.mGeometry )
55  , mFeatureFilterProvider( rh.mFeatureFilterProvider ? rh.mFeatureFilterProvider->clone() : nullptr )
56  , mSegmentationTolerance( rh.mSegmentationTolerance )
57  , mSegmentationToleranceType( rh.mSegmentationToleranceType )
58 {
59 }
60 
62 {
63  mFlags = rh.mFlags;
64  mPainter = rh.mPainter;
65  mCoordTransform = rh.mCoordTransform;
66  mExtent = rh.mExtent;
67  mMapToPixel = rh.mMapToPixel;
68  mRenderingStopped = rh.mRenderingStopped;
69  mScaleFactor = rh.mScaleFactor;
70  mRendererScale = rh.mRendererScale;
71  mLabelingEngine = rh.mLabelingEngine;
72  mSelectionColor = rh.mSelectionColor;
73  mVectorSimplifyMethod = rh.mVectorSimplifyMethod;
74  mExpressionContext = rh.mExpressionContext;
75  mGeometry = rh.mGeometry;
76  mFeatureFilterProvider.reset( rh.mFeatureFilterProvider ? rh.mFeatureFilterProvider->clone() : nullptr );
77  mSegmentationTolerance = rh.mSegmentationTolerance;
78  mSegmentationToleranceType = rh.mSegmentationToleranceType;
79  mDistanceArea = rh.mDistanceArea;
80  return *this;
81 }
82 
84 {
85  QgsRenderContext context;
86  context.setPainter( painter );
87  if ( painter && painter->device() )
88  {
89  context.setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
90  }
91  else
92  {
93  context.setScaleFactor( 3.465 ); //assume 88 dpi as standard value
94  }
95  return context;
96 }
97 
98 void QgsRenderContext::setFlags( QgsRenderContext::Flags flags )
99 {
100  mFlags = flags;
101 }
102 
104 {
105  if ( on )
106  mFlags |= flag;
107  else
108  mFlags &= ~flag;
109 }
110 
111 QgsRenderContext::Flags QgsRenderContext::flags() const
112 {
113  return mFlags;
114 }
115 
117 {
118  return mFlags.testFlag( flag );
119 }
120 
122 {
123  QgsRenderContext ctx;
124  ctx.setMapToPixel( mapSettings.mapToPixel() );
125  ctx.setExtent( mapSettings.visibleExtent() );
131  ctx.setSelectionColor( mapSettings.selectionColor() );
137  ctx.setScaleFactor( mapSettings.outputDpi() / 25.4 ); // = pixels per mm
138  ctx.setRendererScale( mapSettings.scale() );
139  ctx.setExpressionContext( mapSettings.expressionContext() );
140  ctx.setSegmentationTolerance( mapSettings.segmentationTolerance() );
142  ctx.mDistanceArea.setSourceCrs( mapSettings.destinationCrs() );
143  ctx.mDistanceArea.setEllipsoid( mapSettings.ellipsoid() );
144  //this flag is only for stopping during the current rendering progress,
145  //so must be false at every new render operation
146  ctx.setRenderingStopped( false );
147 
148  return ctx;
149 }
150 
152 {
153  return mFlags.testFlag( ForceVectorOutput );
154 }
155 
157 {
158  return mFlags.testFlag( UseAdvancedEffects );
159 }
160 
162 {
163  setFlag( UseAdvancedEffects, enabled );
164 }
165 
167 {
168  return mFlags.testFlag( DrawEditingInfo );
169 }
170 
172 {
173  return mFlags.testFlag( DrawSelection );
174 }
175 
177 {
178  mCoordTransform = t;
179 }
180 
182 {
183  setFlag( DrawEditingInfo, b );
184 }
185 
187 {
188  setFlag( ForceVectorOutput, force );
189 }
190 
192 {
193  setFlag( DrawSelection, showSelection );
194 }
195 
197 {
198  return mFlags.testFlag( UseRenderingOptimization );
199 }
200 
202 {
203  setFlag( UseRenderingOptimization, enabled );
204 }
205 
207 {
208  if ( ffp )
209  {
210  mFeatureFilterProvider.reset( ffp->clone() );
211  }
212  else
213  {
214  mFeatureFilterProvider.reset( nullptr );
215  }
216 }
217 
219 {
220  return mFeatureFilterProvider.get();
221 }
222 
224 {
225  double conversionFactor = 1.0;
226  switch ( unit )
227  {
229  conversionFactor = mScaleFactor;
230  break;
231 
233  conversionFactor = mScaleFactor / POINTS_TO_MM;
234  break;
235 
237  conversionFactor = mScaleFactor * INCH_TO_MM;
238  break;
239 
241  {
242  size = convertMetersToMapUnits( size );
244  // Fall through to RenderMapUnits with size in meters converted to size in MapUnits
245  FALLTHROUGH;
246  }
248  {
249  double mup = scale.computeMapUnitsPerPixel( *this );
250  if ( mup > 0 )
251  {
252  conversionFactor = 1.0 / mup;
253  }
254  else
255  {
256  conversionFactor = 1.0;
257  }
258  break;
259  }
261  conversionFactor = 1.0;
262  break;
263 
266  //no sensible value
267  conversionFactor = 1.0;
268  break;
269  }
270 
271  double convertedSize = size * conversionFactor;
272 
273  if ( unit == QgsUnitTypes::RenderMapUnits )
274  {
275  //check max/min size
276  if ( scale.minSizeMMEnabled )
277  convertedSize = qMax( convertedSize, scale.minSizeMM * mScaleFactor );
278  if ( scale.maxSizeMMEnabled )
279  convertedSize = qMin( convertedSize, scale.maxSizeMM * mScaleFactor );
280  }
281 
282  return convertedSize;
283 }
284 
285 double QgsRenderContext::convertToMapUnits( double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale ) const
286 {
287  double mup = mMapToPixel.mapUnitsPerPixel();
288 
289  switch ( unit )
290  {
292  {
293  size = convertMetersToMapUnits( size );
294  // Fall through to RenderMapUnits with values of meters converted to MapUnits
295  FALLTHROUGH;
296  }
298  {
299  // check scale
300  double minSizeMU = -DBL_MAX;
301  if ( scale.minSizeMMEnabled )
302  {
303  minSizeMU = scale.minSizeMM * mScaleFactor * mup;
304  }
305  if ( !qgsDoubleNear( scale.minScale, 0.0 ) )
306  {
307  minSizeMU = qMax( minSizeMU, size * ( mRendererScale / scale.minScale ) );
308  }
309  size = qMax( size, minSizeMU );
310 
311  double maxSizeMU = DBL_MAX;
312  if ( scale.maxSizeMMEnabled )
313  {
314  maxSizeMU = scale.maxSizeMM * mScaleFactor * mup;
315  }
316  if ( !qgsDoubleNear( scale.maxScale, 0.0 ) )
317  {
318  maxSizeMU = qMin( maxSizeMU, size * ( mRendererScale / scale.maxScale ) );
319  }
320  size = qMin( size, maxSizeMU );
321 
322  return size;
323  }
325  {
326  return size * mScaleFactor * mup;
327  }
329  {
330  return size * mScaleFactor * mup / POINTS_TO_MM;
331  }
333  {
334  return size * mScaleFactor * mup * INCH_TO_MM;
335  }
337  {
338  return size * mup;
339  }
340 
343  //no sensible value
344  return 0.0;
345  }
346  return 0.0;
347 }
348 
349 double QgsRenderContext::convertFromMapUnits( double sizeInMapUnits, QgsUnitTypes::RenderUnit outputUnit ) const
350 {
351  double mup = mMapToPixel.mapUnitsPerPixel();
352 
353  switch ( outputUnit )
354  {
356  {
357  return sizeInMapUnits / convertMetersToMapUnits( 1.0 );
358  }
360  {
361  return sizeInMapUnits;
362  }
364  {
365  return sizeInMapUnits / ( mScaleFactor * mup );
366  }
368  {
369  return sizeInMapUnits / ( mScaleFactor * mup / POINTS_TO_MM );
370  }
372  {
373  return sizeInMapUnits / ( mScaleFactor * mup * INCH_TO_MM );
374  }
376  {
377  return sizeInMapUnits / mup;
378  }
379 
382  //no sensible value
383  return 0.0;
384  }
385  return 0.0;
386 }
387 
388 double QgsRenderContext::convertMetersToMapUnits( double meters ) const
389 {
390  switch ( mDistanceArea.sourceCrs().mapUnits() )
391  {
393  return meters;
395  {
396  QgsPointXY pointCenter = mExtent.center();
397  // The Extent is in the sourceCrs(), when different from destinationCrs()
398  // - the point must be transformed, since DistanceArea uses the destinationCrs()
399  // Note: the default QgsCoordinateTransform() : authid() will return an empty String
400  if ( !mCoordTransform.isShortCircuited() )
401  {
402  pointCenter = mCoordTransform.transform( pointCenter );
403  }
404  return mDistanceArea.measureLineProjected( pointCenter, meters );
405  }
414  return ( meters * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceMeters, mDistanceArea.sourceCrs().mapUnits() ) );
415  }
416  return meters;
417 }
void setForceVectorOutput(bool force)
Meters value as Map units.
Definition: qgsunittypes.h:104
double convertToMapUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
Enable layer opacity and blending effects.
void setRenderingStopped(bool stopped)
double minSizeMM
The minimum size in millimeters, or 0.0 if unset.
Enable vector simplification and other rendering optimizations.
virtual QgsFeatureFilterProvider * clone() const =0
Create a clone of the feature filter provider.
const QgsExpressionContext & expressionContext() const
Gets the expression context.
void setFlags(QgsRenderContext::Flags flags)
Set combination of flags that will be used for rendering.
Use antialiasing while drawing.
double convertFromMapUnits(double sizeInMapUnits, QgsUnitTypes::RenderUnit outputUnit) const
Converts a size from map units to the specified units.
void setCoordinateTransform(const QgsCoordinateTransform &t)
Sets coordinate transformation.
A class to represent a 2D point.
Definition: qgspointxy.h:42
void setSimplifyHints(SimplifyHints simplifyHints)
Sets the simplification hints of the vector layer managed.
void setRendererScale(double scale)
Sets the renderer map scale.
Whether to make extra effort to update map image with partially rendered layers (better for interacti...
double computeMapUnitsPerPixel(const QgsRenderContext &c) const
Computes a map units per pixel scaling factor, respecting the minimum and maximum scales set for the ...
Flags flags() const
Return combination of flags used for rendering.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
Percentage of another measurement (e.g., canvas size, feature size)
Definition: qgsunittypes.h:100
Enable layer opacity and blending effects.
Whether vector selections should be shown in the rendered map.
void setExtent(const QgsRectangle &extent)
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:210
double maxScale
The maximum scale, or 0.0 if unset.
const QgsFeatureFilterProvider * featureFilterProvider() const
Get the filter feature provider used for additional filtering of rendered features.
bool minSizeMMEnabled
Whether the minimum size in mm should be respected.
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
Vector graphics should not be cached and drawn as raster images.
The QgsMapSettings class contains configuration for rendering of the map.
double convertMetersToMapUnits(double meters) const
Convert meter distances to active MapUnit values for QgsUnitTypes::RenderMetersInMapUnits.
void setSelectionColor(const QColor &color)
No simplification can be applied.
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
void setUseAdvancedEffects(bool enabled)
Used to enable or disable advanced effects such as blend modes.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
#define FALLTHROUGH
Definition: qgis.h:415
QgsRenderContext & operator=(const QgsRenderContext &rh)
#define INCH_TO_MM
bool isShortCircuited() const
Returns true if the transform short circuits because the source and destination are equivalent...
Whether vector selections should be shown in the rendered map.
double scale() const
Returns the calculated map scale.
void setDrawEditingInformation(bool b)
Enable anti-aliasing for map rendering.
points (e.g., for font sizes)
Definition: qgsunittypes.h:102
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
bool drawEditingInformation() const
Draw bounds of symbols (for debugging/testing)
Degrees, for planar geographic CRS distance measurements.
Definition: qgsunittypes.h:50
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
Abstract interface for use by classes that filter the features of a layer.
void setSegmentationToleranceType(QgsAbstractGeometry::SegmentationToleranceType type)
Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation...
double mapUnitsPerPixel() const
Return current map units per pixel.
const QgsMapToPixel & mapToPixel() const
Draw bounds of symbols (for debugging/testing)
Vector graphics should not be cached and drawn as raster images.
Enable drawing of vertex markers for layers in editing mode.
double measureLineProjected(const QgsPointXY &p1, double distance=1, double azimuth=M_PI/2, QgsPointXY *projectedPoint=nullptr) const
Calculates the distance from one point with distance in meters and azimuth (direction) When the sourc...
QgsAbstractGeometry::SegmentationToleranceType segmentationToleranceType() const
Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation...
bool forceVectorOutput() const
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source spatial reference system.
void setSegmentationTolerance(double tolerance)
Sets the segmentation tolerance applied when rendering curved geometries.
bool useRenderingOptimization() const
Returns true if the rendering optimization (geometry simplification) can be executed.
Draw map such that there are no problems between adjacent tiles.
Unknown distance unit.
Definition: qgsunittypes.h:53
double outputDpi() const
Return DPI used for conversion between real world units (e.g.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
#define POINTS_TO_MM
QString ellipsoid() const
Returns ellipsoid's acronym.
double segmentationTolerance() const
Gets the segmentation tolerance applied when rendering curved geometries.
QPainter * painter()
Returns the destination QPainter for the render operation.
double maxSizeMM
The maximum size in millimeters, or 0.0 if unset.
Struct for storing maximum and minimum scales for measurements in map units.
Whether to make extra effort to update map image with partially rendered layers (better for interacti...
QgsPointXY transform(const QgsPointXY &point, TransformDirection direction=ForwardTransform) const
Transform the point from the source CRS to the destination CRS.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
bool useAdvancedEffects() const
Returns true if advanced effects such as blend modes such be used.
void setMapToPixel(const QgsMapToPixel &mtp)
Class for doing transforms between two map coordinate systems.
void setUseRenderingOptimization(bool enabled)
bool showSelection() const
Returns true if vector selections should be shown in the rendered map.
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void setFeatureFilterProvider(const QgsFeatureFilterProvider *ffp)
Set a filter feature provider used for additional filtering of rendered features. ...
Enable vector simplification and other rendering optimizations.
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
void setSourceCrs(const QgsCoordinateReferenceSystem &srcCRS)
Sets source spatial reference system.
QColor selectionColor() const
Get color that is used for drawing of selected vector features.
QgsPointXY center() const
Returns the center point of the rectangle.
Definition: qgsrectangle.h:146
void setShowSelection(const bool showSelection)
Sets whether vector selections should be shown in the rendered map.
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
Terrestrial miles.
Definition: qgsunittypes.h:49
Draw map such that there are no problems between adjacent tiles.
Flag
Enumeration of flags that affect rendering operations.
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
Enable drawing of vertex markers for layers in editing mode.
double minScale
The minimum scale, or 0.0 if unset.
bool maxSizeMMEnabled
Whether the maximum size in mm should be respected.
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:95
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.