QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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  , mOriginalMapExtent( rh.mOriginalMapExtent )
47  , mMapToPixel( rh.mMapToPixel )
48  , mRenderingStopped( rh.mRenderingStopped )
49  , mScaleFactor( rh.mScaleFactor )
50  , mRendererScale( rh.mRendererScale )
51  , mLabelingEngine( rh.mLabelingEngine )
52  , mSelectionColor( rh.mSelectionColor )
53  , mVectorSimplifyMethod( rh.mVectorSimplifyMethod )
54  , mExpressionContext( rh.mExpressionContext )
55  , mGeometry( rh.mGeometry )
56  , mFeatureFilterProvider( rh.mFeatureFilterProvider ? rh.mFeatureFilterProvider->clone() : nullptr )
57  , mSegmentationTolerance( rh.mSegmentationTolerance )
58  , mSegmentationToleranceType( rh.mSegmentationToleranceType )
59  , mTransformContext( rh.mTransformContext )
60  , mPathResolver( rh.mPathResolver )
61  , mTextRenderFormat( rh.mTextRenderFormat )
62 #ifdef QGISDEBUG
63  , mHasTransformContext( rh.mHasTransformContext )
64 #endif
65 {
66 }
67 
69 {
70  mFlags = rh.mFlags;
71  mPainter = rh.mPainter;
72  mCoordTransform = rh.mCoordTransform;
73  mExtent = rh.mExtent;
74  mOriginalMapExtent = rh.mOriginalMapExtent;
75  mMapToPixel = rh.mMapToPixel;
76  mRenderingStopped = rh.mRenderingStopped;
77  mScaleFactor = rh.mScaleFactor;
78  mRendererScale = rh.mRendererScale;
79  mLabelingEngine = rh.mLabelingEngine;
80  mSelectionColor = rh.mSelectionColor;
81  mVectorSimplifyMethod = rh.mVectorSimplifyMethod;
82  mExpressionContext = rh.mExpressionContext;
83  mGeometry = rh.mGeometry;
84  mFeatureFilterProvider.reset( rh.mFeatureFilterProvider ? rh.mFeatureFilterProvider->clone() : nullptr );
85  mSegmentationTolerance = rh.mSegmentationTolerance;
86  mSegmentationToleranceType = rh.mSegmentationToleranceType;
87  mDistanceArea = rh.mDistanceArea;
88  mTransformContext = rh.mTransformContext;
89  mPathResolver = rh.mPathResolver;
90  mTextRenderFormat = rh.mTextRenderFormat;
91 #ifdef QGISDEBUG
92  mHasTransformContext = rh.mHasTransformContext;
93 #endif
94 
95  return *this;
96 }
97 
99 {
100  QgsRenderContext context;
101  context.setPainter( painter );
102  if ( painter && painter->device() )
103  {
104  context.setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
105  }
106  else
107  {
108  context.setScaleFactor( 3.465 ); //assume 88 dpi as standard value
109  }
110  if ( painter && painter->renderHints() & QPainter::Antialiasing )
111  {
112  context.setFlag( QgsRenderContext::Antialiasing, true );
113  }
114  return context;
115 }
116 
118 {
119 #ifdef QGISDEBUG
120  if ( !mHasTransformContext )
121  QgsDebugMsgLevel( QStringLiteral( "No QgsCoordinateTransformContext context set for transform" ), 4 );
122 #endif
123  return mTransformContext;
124 }
125 
127 {
128  mTransformContext = context;
129 #ifdef QGISDEBUG
130  mHasTransformContext = true;
131 #endif
132 }
133 
134 void QgsRenderContext::setFlags( QgsRenderContext::Flags flags )
135 {
136  mFlags = flags;
137 }
138 
140 {
141  if ( on )
142  mFlags |= flag;
143  else
144  mFlags &= ~flag;
145 }
146 
147 QgsRenderContext::Flags QgsRenderContext::flags() const
148 {
149  return mFlags;
150 }
151 
153 {
154  return mFlags.testFlag( flag );
155 }
156 
158 {
159  QgsRenderContext ctx;
160  ctx.setMapToPixel( mapSettings.mapToPixel() );
161  ctx.setExtent( mapSettings.visibleExtent() );
162  ctx.setMapExtent( mapSettings.visibleExtent() );
168  ctx.setSelectionColor( mapSettings.selectionColor() );
175  ctx.setScaleFactor( mapSettings.outputDpi() / 25.4 ); // = pixels per mm
176  ctx.setRendererScale( mapSettings.scale() );
177  ctx.setExpressionContext( mapSettings.expressionContext() );
178  ctx.setSegmentationTolerance( mapSettings.segmentationTolerance() );
180  ctx.mDistanceArea.setSourceCrs( mapSettings.destinationCrs(), mapSettings.transformContext() );
181  ctx.mDistanceArea.setEllipsoid( mapSettings.ellipsoid() );
182  ctx.setTransformContext( mapSettings.transformContext() );
183  ctx.setPathResolver( mapSettings.pathResolver() );
184  ctx.setTextRenderFormat( mapSettings.textRenderFormat() );
185  //this flag is only for stopping during the current rendering progress,
186  //so must be false at every new render operation
187  ctx.setRenderingStopped( false );
188 
189  return ctx;
190 }
191 
193 {
194  return mFlags.testFlag( ForceVectorOutput );
195 }
196 
198 {
199  return mFlags.testFlag( UseAdvancedEffects );
200 }
201 
203 {
204  setFlag( UseAdvancedEffects, enabled );
205 }
206 
208 {
209  return mFlags.testFlag( DrawEditingInfo );
210 }
211 
213 {
214  return mFlags.testFlag( DrawSelection );
215 }
216 
218 {
219  mCoordTransform = t;
220 }
221 
223 {
224  setFlag( DrawEditingInfo, b );
225 }
226 
228 {
229  setFlag( ForceVectorOutput, force );
230 }
231 
233 {
234  setFlag( DrawSelection, showSelection );
235 }
236 
238 {
239  return mFlags.testFlag( UseRenderingOptimization );
240 }
241 
243 {
244  setFlag( UseRenderingOptimization, enabled );
245 }
246 
248 {
249  if ( ffp )
250  {
251  mFeatureFilterProvider.reset( ffp->clone() );
252  }
253  else
254  {
255  mFeatureFilterProvider.reset( nullptr );
256  }
257 }
258 
260 {
261  return mFeatureFilterProvider.get();
262 }
263 
265 {
266  double conversionFactor = 1.0;
267  switch ( unit )
268  {
270  conversionFactor = mScaleFactor;
271  break;
272 
274  conversionFactor = mScaleFactor / POINTS_TO_MM;
275  break;
276 
278  conversionFactor = mScaleFactor * INCH_TO_MM;
279  break;
280 
282  {
283  size = convertMetersToMapUnits( size );
285  // Fall through to RenderMapUnits with size in meters converted to size in MapUnits
287  }
289  {
290  double mup = scale.computeMapUnitsPerPixel( *this );
291  if ( mup > 0 )
292  {
293  conversionFactor = 1.0 / mup;
294  }
295  else
296  {
297  conversionFactor = 1.0;
298  }
299  break;
300  }
302  conversionFactor = 1.0;
303  break;
304 
307  //no sensible value
308  conversionFactor = 1.0;
309  break;
310  }
311 
312  double convertedSize = size * conversionFactor;
313 
314  if ( unit == QgsUnitTypes::RenderMapUnits )
315  {
316  //check max/min size
317  if ( scale.minSizeMMEnabled )
318  convertedSize = std::max( convertedSize, scale.minSizeMM * mScaleFactor );
319  if ( scale.maxSizeMMEnabled )
320  convertedSize = std::min( convertedSize, scale.maxSizeMM * mScaleFactor );
321  }
322 
323  return convertedSize;
324 }
325 
326 double QgsRenderContext::convertToMapUnits( double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale ) const
327 {
328  double mup = mMapToPixel.mapUnitsPerPixel();
329 
330  switch ( unit )
331  {
333  {
334  size = convertMetersToMapUnits( size );
335  // Fall through to RenderMapUnits with values of meters converted to MapUnits
337  }
339  {
340  // check scale
341  double minSizeMU = std::numeric_limits<double>::lowest();
342  if ( scale.minSizeMMEnabled )
343  {
344  minSizeMU = scale.minSizeMM * mScaleFactor * mup;
345  }
346  if ( !qgsDoubleNear( scale.minScale, 0.0 ) )
347  {
348  minSizeMU = std::max( minSizeMU, size * ( mRendererScale / scale.minScale ) );
349  }
350  size = std::max( size, minSizeMU );
351 
352  double maxSizeMU = std::numeric_limits<double>::max();
353  if ( scale.maxSizeMMEnabled )
354  {
355  maxSizeMU = scale.maxSizeMM * mScaleFactor * mup;
356  }
357  if ( !qgsDoubleNear( scale.maxScale, 0.0 ) )
358  {
359  maxSizeMU = std::min( maxSizeMU, size * ( mRendererScale / scale.maxScale ) );
360  }
361  size = std::min( size, maxSizeMU );
362 
363  return size;
364  }
366  {
367  return size * mScaleFactor * mup;
368  }
370  {
371  return size * mScaleFactor * mup / POINTS_TO_MM;
372  }
374  {
375  return size * mScaleFactor * mup * INCH_TO_MM;
376  }
378  {
379  return size * mup;
380  }
381 
384  //no sensible value
385  return 0.0;
386  }
387  return 0.0;
388 }
389 
390 double QgsRenderContext::convertFromMapUnits( double sizeInMapUnits, QgsUnitTypes::RenderUnit outputUnit ) const
391 {
392  double mup = mMapToPixel.mapUnitsPerPixel();
393 
394  switch ( outputUnit )
395  {
397  {
398  return sizeInMapUnits / convertMetersToMapUnits( 1.0 );
399  }
401  {
402  return sizeInMapUnits;
403  }
405  {
406  return sizeInMapUnits / ( mScaleFactor * mup );
407  }
409  {
410  return sizeInMapUnits / ( mScaleFactor * mup / POINTS_TO_MM );
411  }
413  {
414  return sizeInMapUnits / ( mScaleFactor * mup * INCH_TO_MM );
415  }
417  {
418  return sizeInMapUnits / mup;
419  }
420 
423  //no sensible value
424  return 0.0;
425  }
426  return 0.0;
427 }
428 
429 double QgsRenderContext::convertMetersToMapUnits( double meters ) const
430 {
431  switch ( mDistanceArea.sourceCrs().mapUnits() )
432  {
434  return meters;
436  {
437  QgsPointXY pointCenter = mExtent.center();
438  // The Extent is in the sourceCrs(), when different from destinationCrs()
439  // - the point must be transformed, since DistanceArea uses the destinationCrs()
440  // Note: the default QgsCoordinateTransform() : authid() will return an empty String
441  if ( !mCoordTransform.isShortCircuited() )
442  {
443  pointCenter = mCoordTransform.transform( pointCenter );
444  }
445  return mDistanceArea.measureLineProjected( pointCenter, meters );
446  }
455  return ( meters * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceMeters, mDistanceArea.sourceCrs().mapUnits() ) );
456  }
457  return meters;
458 }
459 
460 
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
Meters value as Map units.
Definition: qgsunittypes.h:119
Enable layer opacity and blending effects.
void setRenderingStopped(bool stopped)
Sets whether the rendering operation has been stopped and any ongoing rendering should be canceled im...
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.
double scale() const
Returns the calculated map scale.
void setFlags(QgsRenderContext::Flags flags)
Set combination of flags that will be used for rendering.
Use antialiasing while drawing.
void setCoordinateTransform(const QgsCoordinateTransform &t)
Sets the current coordinate transform for the context.
QColor selectionColor() const
Gets color that is used for drawing of selected vector features.
QgsPointXY transform(const QgsPointXY &point, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
A class to represent a 2D point.
Definition: qgspointxy.h:43
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:278
double computeMapUnitsPerPixel(const QgsRenderContext &c) const
Computes a map units per pixel scaling factor, respecting the minimum and maximum scales set for the ...
void setSimplifyHints(SimplifyHints simplifyHints)
Sets the simplification hints of the vector layer managed.
void setRendererScale(double scale)
Sets the renderer map scale.
double convertToMapUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
Whether to make extra effort to update map image with partially rendered layers (better for interacti...
void setPathResolver(const QgsPathResolver &resolver)
Sets the path resolver for conversion between relative and absolute paths during rendering operations...
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes takes output image size into accou...
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the context&#39;s coordinate transform context, which stores various information regarding which dat...
double convertFromMapUnits(double sizeInMapUnits, QgsUnitTypes::RenderUnit outputUnit) const
Converts a size from map units to the specified units.
bool showSelection() const
Returns true if vector selections should be shown in the rendered map.
const QgsMapToPixel & mapToPixel() const
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
Percentage of another measurement (e.g., canvas size, feature size)
Definition: qgsunittypes.h:115
Enable layer opacity and blending effects.
bool isShortCircuited() const
Returns true if the transform short circuits because the source and destination are equivalent...
void setTextRenderFormat(TextRenderFormat format)
Sets the text render format, which dictates how text is rendered (e.g.
Whether vector selections should be shown in the rendered map.
void setExtent(const QgsRectangle &extent)
When rendering a map layer, calling this method sets the "clipping" extent for the layer (in the laye...
double maxScale
The maximum scale, or 0.0 if unset.
void setMapExtent(const QgsRectangle &extent)
Sets the original extent of the map being rendered.
bool minSizeMMEnabled
Whether the minimum size in mm should be respected.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Vector graphics should not be cached and drawn as raster images.
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
The QgsMapSettings class contains configuration for rendering of the map.
bool useAdvancedEffects() const
Returns true if advanced effects such as blend modes such be used.
void setSelectionColor(const QColor &color)
Sets the color to use when rendering selected features.
No simplification can be applied.
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:646
QgsRenderContext & operator=(const QgsRenderContext &rh)
#define INCH_TO_MM
double segmentationTolerance() const
Gets the segmentation tolerance applied when rendering curved geometries.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
Whether vector selections should be shown in the rendered map.
QgsRenderContext::TextRenderFormat textRenderFormat() const
Returns the text render format, which dictates how text is rendered (e.g.
void setDrawEditingInformation(bool b)
Sets whether edit markers should be drawn during the render operation.
Enable anti-aliasing for map rendering.
points (e.g., for font sizes)
Definition: qgsunittypes.h:117
QgsPointXY center() const
Returns the center point of the rectangle.
Definition: qgsrectangle.h:229
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
bool forceVectorOutput() const
Returns TRUE if rendering operations should use vector operations instead of any faster raster shortc...
Draw bounds of symbols (for debugging/testing)
Degrees, for planar geographic CRS distance measurements.
Definition: qgsunittypes.h:61
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
double mapUnitsPerPixel() const
Returns current map units per pixel.
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...
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
Contains information about the context in which a coordinate transform is executed.
bool useRenderingOptimization() const
Returns true if the rendering optimization (geometry simplification) can be executed.
double convertMetersToMapUnits(double meters) const
Convert meter distances to active MapUnit values for QgsUnitTypes::RenderMetersInMapUnits.
Draw bounds of symbols (for debugging/testing)
Vector graphics should not be cached and drawn as raster images.
bool drawEditingInformation() const
Returns TRUE if edit markers should be drawn during the render operation.
Enable drawing of vertex markers for layers in editing mode.
QgsAbstractGeometry::SegmentationToleranceType segmentationToleranceType() const
Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation...
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
void setSegmentationTolerance(double tolerance)
Sets the segmentation tolerance applied when rendering curved geometries.
Draw map such that there are no problems between adjacent tiles.
Unknown distance unit.
Definition: qgsunittypes.h:64
const QgsPathResolver & pathResolver() const
Returns the path resolver for conversion between relative and absolute paths during rendering operati...
Render is a &#39;canvas preview&#39; render, and shortcuts should be taken to ensure fast rendering...
Render is a &#39;canvas preview&#39; render, and shortcuts should be taken to ensure fast rendering...
Contains information about the context of a rendering operation.
#define POINTS_TO_MM
QPainter * painter()
Returns the destination QPainter for the render operation.
double maxSizeMM
The maximum size in millimeters, or 0.0 if unset.
void setShowSelection(bool showSelection)
Sets whether vector selections should be shown in the rendered map.
QString ellipsoid() const
Returns ellipsoid&#39;s acronym.
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...
const QgsFeatureFilterProvider * featureFilterProvider() const
Gets the filter feature provider used for additional filtering of rendered features.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context&#39;s map to pixel transform, which transforms between map coordinates and device coordi...
Flags flags() const
Returns combination of flags used for rendering.
Class for doing transforms between two map coordinate systems.
void setUseRenderingOptimization(bool enabled)
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
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.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
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...
double outputDpi() const
Returns DPI used for conversion between real world units (e.g.
Terrestrial miles.
Definition: qgsunittypes.h:60
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.
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source spatial reference system.
QgsCoordinateTransformContext transformContext() const
Returns the context&#39;s coordinate transform context, which stores various information regarding which ...
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:110
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
const QgsExpressionContext & expressionContext() const
Gets the expression context.