QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
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
18#include <algorithm>
19
20#include "qgsgeometry.h"
21#include "qgslogger.h"
23#include "qgsrendercontext.h"
24
25#include <QPointer>
26
27QList<QgsMapClippingRegion> QgsMapClippingUtils::collectClippingRegionsForLayer( const QgsRenderContext &context, const QgsMapLayer *layer )
28{
29 QList< QgsMapClippingRegion > res;
30 const QList< QgsMapClippingRegion > regions = context.clippingRegions();
31 res.reserve( regions.size() );
32
33 std::copy_if( regions.begin(), regions.end(), std::back_inserter( res ), [layer]( const QgsMapClippingRegion & region )
34 {
35 return region.appliesToLayer( layer );
36 } );
37
38 return res;
39}
40
41QgsGeometry QgsMapClippingUtils::calculateFeatureRequestGeometry( const QList< QgsMapClippingRegion > &regions, const QgsRenderContext &context, bool &shouldFilter )
42{
43 QgsGeometry result;
44 bool first = true;
45 shouldFilter = false;
46 for ( const QgsMapClippingRegion &region : regions )
47 {
48 if ( region.geometry().type() != Qgis::GeometryType::Polygon )
49 continue;
50
51 shouldFilter = true;
52 if ( first )
53 {
54 result = region.geometry();
55 first = false;
56 }
57 else
58 {
59 result = result.intersection( region.geometry() );
60 }
61 }
62
63 if ( !shouldFilter )
64 return QgsGeometry();
65
66 // filter out polygon parts from result only
68
69 // lastly transform back to layer CRS
70 try
71 {
73 }
74 catch ( QgsCsException & )
75 {
76 QgsDebugError( QStringLiteral( "Could not transform clipping region to layer CRS" ) );
77 shouldFilter = false;
78 return QgsGeometry();
79 }
80
81 return result;
82}
83
84QgsGeometry QgsMapClippingUtils::calculateFeatureIntersectionGeometry( const QList<QgsMapClippingRegion> &regions, const QgsRenderContext &context, bool &shouldClip )
85{
86 QgsGeometry result;
87 bool first = true;
88 shouldClip = false;
89 for ( const QgsMapClippingRegion &region : regions )
90 {
91 if ( region.geometry().type() != Qgis::GeometryType::Polygon )
92 continue;
93
95 continue;
96
97 shouldClip = true;
98 if ( first )
99 {
100 result = region.geometry();
101 first = false;
102 }
103 else
104 {
105 result = result.intersection( region.geometry() );
106 }
107 }
108
109 if ( !shouldClip )
110 return QgsGeometry();
111
112 // filter out polygon parts from result only
114
115 // lastly transform back to layer CRS
116 try
117 {
119 }
120 catch ( QgsCsException & )
121 {
122 QgsDebugError( QStringLiteral( "Could not transform clipping region to layer CRS" ) );
123 shouldClip = false;
124 return QgsGeometry();
125 }
126
127 return result;
128}
129
130QPainterPath QgsMapClippingUtils::calculatePainterClipRegion( const QList<QgsMapClippingRegion> &regions, const QgsRenderContext &context, Qgis::LayerType layerType, bool &shouldClip )
131{
132 QgsGeometry result;
133 bool first = true;
134 shouldClip = false;
135 for ( const QgsMapClippingRegion &region : regions )
136 {
137 if ( region.geometry().type() != Qgis::GeometryType::Polygon )
138 continue;
139
140 switch ( layerType )
141 {
144 continue;
145 break;
146
148 // for now, we ignore the region's featureClip behavior when rendering vector tiles
149 // TODO: ideally we should apply this during rendering, just like we do for normal
150 // vector layers
151 break;
152
160 // for these layer types, we ignore the region's featureClip behavior.
161 break;
162
163 }
164
165 shouldClip = true;
166 if ( first )
167 {
168 result = region.geometry();
169 first = false;
170 }
171 else
172 {
173 result = result.intersection( region.geometry() );
174 }
175 }
176
177 if ( !shouldClip )
178 return QPainterPath();
179
180 // transform to painter coordinates
181 result.mapToPixel( context.mapToPixel() );
182
183 return result.constGet()->asQPainterPath();
184}
185
186QgsGeometry QgsMapClippingUtils::calculateLabelIntersectionGeometry( const QList<QgsMapClippingRegion> &regions, const QgsRenderContext &context, bool &shouldClip )
187{
188 QgsGeometry result;
189 bool first = true;
190 shouldClip = false;
191 for ( const QgsMapClippingRegion &region : regions )
192 {
193 if ( region.geometry().type() != Qgis::GeometryType::Polygon )
194 continue;
195
196 // for labeling, we clip using either painter clip regions or intersects type regions.
197 // unlike feature rendering, we clip features to painter clip regions for labeling, because
198 // we want the label to sit within the clip region if possible
201 continue;
202
203 shouldClip = true;
204 if ( first )
205 {
206 result = region.geometry();
207 first = false;
208 }
209 else
210 {
211 result = result.intersection( region.geometry() );
212 }
213 }
214
215 if ( !shouldClip )
216 return QgsGeometry();
217
218 // filter out polygon parts from result only
220
221 // lastly transform back to layer CRS
222 try
223 {
225 }
226 catch ( QgsCsException & )
227 {
228 QgsDebugError( QStringLiteral( "Could not transform clipping region to layer CRS" ) );
229 shouldClip = false;
230 return QgsGeometry();
231 }
232
233 return result;
234}
@ Polygon
Polygons.
Definition qgis.h:361
LayerType
Types of layers that can be added to a map.
Definition qgis.h:190
@ Group
Composite group layer. Added in QGIS 3.24.
Definition qgis.h:198
@ Plugin
Plugin based layer.
Definition qgis.h:193
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
Definition qgis.h:199
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Definition qgis.h:196
@ Vector
Vector layer.
Definition qgis.h:191
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:195
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:194
@ Raster
Raster layer.
Definition qgis.h:192
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:197
@ Reverse
Reverse/inverse transform (from destination to source).
Definition qgis.h:2673
virtual QPainterPath asQPainterPath() const =0
Returns the geometry represented as a QPainterPath.
Custom exception class for Coordinate Reference System related exceptions.
A geometry is the spatial representation of a feature.
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:80
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:57