QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsmapclippingutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmapclippingutils.cpp
3 --------------------------------------
4 Date : June 2020
5 Copyright : (C) 2020 by Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsmapclippingutils.h"
17#include "qgsgeometry.h"
18#include "qgsrendercontext.h"
20#include "qgslogger.h"
21#include <algorithm>
22#include <QPointer>
23
24QList<QgsMapClippingRegion> QgsMapClippingUtils::collectClippingRegionsForLayer( const QgsRenderContext &context, const QgsMapLayer *layer )
25{
26 QList< QgsMapClippingRegion > res;
27 const QList< QgsMapClippingRegion > regions = context.clippingRegions();
28 res.reserve( regions.size() );
29
30 std::copy_if( regions.begin(), regions.end(), std::back_inserter( res ), [layer]( const QgsMapClippingRegion & region )
31 {
32 return region.appliesToLayer( layer );
33 } );
34
35 return res;
36}
37
38QgsGeometry QgsMapClippingUtils::calculateFeatureRequestGeometry( const QList< QgsMapClippingRegion > &regions, const QgsRenderContext &context, bool &shouldFilter )
39{
40 QgsGeometry result;
41 bool first = true;
42 shouldFilter = false;
43 for ( const QgsMapClippingRegion &region : regions )
44 {
45 if ( region.geometry().type() != Qgis::GeometryType::Polygon )
46 continue;
47
48 shouldFilter = true;
49 if ( first )
50 {
51 result = region.geometry();
52 first = false;
53 }
54 else
55 {
56 result = result.intersection( region.geometry() );
57 }
58 }
59
60 if ( !shouldFilter )
61 return QgsGeometry();
62
63 // filter out polygon parts from result only
65
66 // lastly transform back to layer CRS
67 try
68 {
70 }
71 catch ( QgsCsException & )
72 {
73 QgsDebugError( QStringLiteral( "Could not transform clipping region to layer CRS" ) );
74 shouldFilter = false;
75 return QgsGeometry();
76 }
77
78 return result;
79}
80
81QgsGeometry QgsMapClippingUtils::calculateFeatureIntersectionGeometry( const QList<QgsMapClippingRegion> &regions, const QgsRenderContext &context, bool &shouldClip )
82{
83 QgsGeometry result;
84 bool first = true;
85 shouldClip = false;
86 for ( const QgsMapClippingRegion &region : regions )
87 {
88 if ( region.geometry().type() != Qgis::GeometryType::Polygon )
89 continue;
90
92 continue;
93
94 shouldClip = true;
95 if ( first )
96 {
97 result = region.geometry();
98 first = false;
99 }
100 else
101 {
102 result = result.intersection( region.geometry() );
103 }
104 }
105
106 if ( !shouldClip )
107 return QgsGeometry();
108
109 // filter out polygon parts from result only
111
112 // lastly transform back to layer CRS
113 try
114 {
116 }
117 catch ( QgsCsException & )
118 {
119 QgsDebugError( QStringLiteral( "Could not transform clipping region to layer CRS" ) );
120 shouldClip = false;
121 return QgsGeometry();
122 }
123
124 return result;
125}
126
127QPainterPath QgsMapClippingUtils::calculatePainterClipRegion( const QList<QgsMapClippingRegion> &regions, const QgsRenderContext &context, Qgis::LayerType layerType, bool &shouldClip )
128{
129 QgsGeometry result;
130 bool first = true;
131 shouldClip = false;
132 for ( const QgsMapClippingRegion &region : regions )
133 {
134 if ( region.geometry().type() != Qgis::GeometryType::Polygon )
135 continue;
136
137 switch ( layerType )
138 {
141 continue;
142 break;
143
145 // for now, we ignore the region's featureClip behavior when rendering vector tiles
146 // TODO: ideally we should apply this during rendering, just like we do for normal
147 // vector layers
148 break;
149
157 // for these layer types, we ignore the region's featureClip behavior.
158 break;
159
160 }
161
162 shouldClip = true;
163 if ( first )
164 {
165 result = region.geometry();
166 first = false;
167 }
168 else
169 {
170 result = result.intersection( region.geometry() );
171 }
172 }
173
174 if ( !shouldClip )
175 return QPainterPath();
176
177 // transform to painter coordinates
178 result.mapToPixel( context.mapToPixel() );
179
180 return result.constGet()->asQPainterPath();
181}
182
183QgsGeometry QgsMapClippingUtils::calculateLabelIntersectionGeometry( const QList<QgsMapClippingRegion> &regions, const QgsRenderContext &context, bool &shouldClip )
184{
185 QgsGeometry result;
186 bool first = true;
187 shouldClip = false;
188 for ( const QgsMapClippingRegion &region : regions )
189 {
190 if ( region.geometry().type() != Qgis::GeometryType::Polygon )
191 continue;
192
193 // for labeling, we clip using either painter clip regions or intersects type regions.
194 // unlike feature rendering, we clip features to painter clip regions for labeling, because
195 // we want the label to sit within the clip region if possible
198 continue;
199
200 shouldClip = true;
201 if ( first )
202 {
203 result = region.geometry();
204 first = false;
205 }
206 else
207 {
208 result = result.intersection( region.geometry() );
209 }
210 }
211
212 if ( !shouldClip )
213 return QgsGeometry();
214
215 // filter out polygon parts from result only
217
218 // lastly transform back to layer CRS
219 try
220 {
222 }
223 catch ( QgsCsException & )
224 {
225 QgsDebugError( QStringLiteral( "Could not transform clipping region to layer CRS" ) );
226 shouldClip = false;
227 return QgsGeometry();
228 }
229
230 return result;
231}
@ Polygon
Polygons.
LayerType
Types of layers that can be added to a map.
Definition: qgis.h:114
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ Vector
Vector layer.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ Raster
Raster layer.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
@ Reverse
Reverse/inverse transform (from destination to source)
virtual QPainterPath asQPainterPath() const =0
Returns the geometry represented as a QPainterPath.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:67
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:162
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
void mapToPixel(const QgsMapToPixel &mtp)
Transforms the geometry from map units to pixels in place.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters &parameters=QgsGeometryParameters()) const
Returns a geometry representing the points shared by this geometry and other.
bool convertGeometryCollectionToSubclass(Qgis::GeometryType geomType)
Converts geometry collection to a the desired geometry type subclass (multi-point,...
A map clipping region (in map coordinates and CRS).
@ ClipPainterOnly
Applying clipping on the painter only (i.e. feature boundaries will be unchanged, but may be invisibl...
@ ClipToIntersection
Clip the geometry of these features to the region prior to rendering (i.e. feature boundaries will fo...
static QPainterPath calculatePainterClipRegion(const QList< QgsMapClippingRegion > &regions, const QgsRenderContext &context, Qgis::LayerType layerType, bool &shouldClip)
Returns a QPainterPath representing the intersection of clipping regions from context which should be...
static QList< QgsMapClippingRegion > collectClippingRegionsForLayer(const QgsRenderContext &context, const QgsMapLayer *layer)
Collects the list of map clipping regions from a context which apply to a map layer.
static QgsGeometry calculateLabelIntersectionGeometry(const QList< QgsMapClippingRegion > &regions, const QgsRenderContext &context, bool &shouldClip)
Returns the geometry representing the intersection of clipping regions from context which should be u...
static QgsGeometry calculateFeatureIntersectionGeometry(const QList< QgsMapClippingRegion > &regions, const QgsRenderContext &context, bool &shouldClip)
Returns the geometry representing the intersection of clipping regions from context which should be u...
static QgsGeometry calculateFeatureRequestGeometry(const QList< QgsMapClippingRegion > &regions, const QgsRenderContext &context, bool &shouldFilter)
Returns the geometry representing the intersection of clipping regions from context.
Base class for all map layer types.
Definition: qgsmaplayer.h:75
Contains information about the context of a rendering operation.
QList< QgsMapClippingRegion > clippingRegions() const
Returns the list of clipping regions to apply during the render.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
#define QgsDebugError(str)
Definition: qgslogger.h:38