QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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"
19 #include "qgsmapclippingregion.h"
20 #include "qgslogger.h"
21 #include <algorithm>
22 
23 QList<QgsMapClippingRegion> QgsMapClippingUtils::collectClippingRegionsForLayer( const QgsRenderContext &context, const QgsMapLayer *layer )
24 {
25  QList< QgsMapClippingRegion > res;
26  const QList< QgsMapClippingRegion > regions = context.clippingRegions();
27  res.reserve( regions.size() );
28 
29  std::copy_if( regions.begin(), regions.end(), std::back_inserter( res ), [layer]( const QgsMapClippingRegion & region )
30  {
31  return region.appliesToLayer( layer );
32  } );
33 
34  return res;
35 }
36 
37 QgsGeometry QgsMapClippingUtils::calculateFeatureRequestGeometry( const QList< QgsMapClippingRegion > &regions, const QgsRenderContext &context, bool &shouldFilter )
38 {
39  QgsGeometry result;
40  bool first = true;
41  shouldFilter = false;
42  for ( const QgsMapClippingRegion &region : regions )
43  {
44  if ( region.geometry().type() != QgsWkbTypes::PolygonGeometry )
45  continue;
46 
47  shouldFilter = true;
48  if ( first )
49  {
50  result = region.geometry();
51  first = false;
52  }
53  else
54  {
55  result = result.intersection( region.geometry() );
56  }
57  }
58 
59  if ( !shouldFilter )
60  return QgsGeometry();
61 
62  // filter out polygon parts from result only
64 
65  // lastly transform back to layer CRS
66  try
67  {
69  }
70  catch ( QgsCsException & )
71  {
72  QgsDebugMsg( QStringLiteral( "Could not transform clipping region to layer CRS" ) );
73  shouldFilter = false;
74  return QgsGeometry();
75  }
76 
77  return result;
78 }
79 
80 QgsGeometry QgsMapClippingUtils::calculateFeatureIntersectionGeometry( const QList<QgsMapClippingRegion> &regions, const QgsRenderContext &context, bool &shouldClip )
81 {
82  QgsGeometry result;
83  bool first = true;
84  shouldClip = false;
85  for ( const QgsMapClippingRegion &region : regions )
86  {
87  if ( region.geometry().type() != QgsWkbTypes::PolygonGeometry )
88  continue;
89 
91  continue;
92 
93  shouldClip = true;
94  if ( first )
95  {
96  result = region.geometry();
97  first = false;
98  }
99  else
100  {
101  result = result.intersection( region.geometry() );
102  }
103  }
104 
105  if ( !shouldClip )
106  return QgsGeometry();
107 
108  // filter out polygon parts from result only
110 
111  // lastly transform back to layer CRS
112  try
113  {
115  }
116  catch ( QgsCsException & )
117  {
118  QgsDebugMsg( QStringLiteral( "Could not transform clipping region to layer CRS" ) );
119  shouldClip = false;
120  return QgsGeometry();
121  }
122 
123  return result;
124 }
125 
126 QPainterPath QgsMapClippingUtils::calculatePainterClipRegion( const QList<QgsMapClippingRegion> &regions, const QgsRenderContext &context, QgsMapLayerType layerType, bool &shouldClip )
127 {
128  QgsGeometry result;
129  bool first = true;
130  shouldClip = false;
131  for ( const QgsMapClippingRegion &region : regions )
132  {
133  if ( region.geometry().type() != QgsWkbTypes::PolygonGeometry )
134  continue;
135 
136  switch ( layerType )
137  {
140  continue;
141  break;
142 
144  // for now, we ignore the region's featureClip behavior when rendering vector tiles
145  // TODO: ideally we should apply this during rendering, just like we do for normal
146  // vector layers
147  break;
148 
153  // for these layer types, we ignore the region's featureClip behavior.
154  break;
155 
156  }
157 
158  shouldClip = true;
159  if ( first )
160  {
161  result = region.geometry();
162  first = false;
163  }
164  else
165  {
166  result = result.intersection( region.geometry() );
167  }
168  }
169 
170  if ( !shouldClip )
171  return QPainterPath();
172 
173  // transform to painter coordinates
174  result.mapToPixel( context.mapToPixel() );
175 
176  return result.constGet()->asQPainterPath();
177 }
178 
179 QgsGeometry QgsMapClippingUtils::calculateLabelIntersectionGeometry( const QList<QgsMapClippingRegion> &regions, const QgsRenderContext &context, bool &shouldClip )
180 {
181  QgsGeometry result;
182  bool first = true;
183  shouldClip = false;
184  for ( const QgsMapClippingRegion &region : regions )
185  {
186  if ( region.geometry().type() != QgsWkbTypes::PolygonGeometry )
187  continue;
188 
189  // for labeling, we clip using either painter clip regions or intersects type regions.
190  // unlike feature rendering, we clip features to painter clip regions for labeling, because
191  // we want the label to sit within the clip region if possible
192  if ( region.featureClip() != QgsMapClippingRegion::FeatureClippingType::ClipPainterOnly &&
194  continue;
195 
196  shouldClip = true;
197  if ( first )
198  {
199  result = region.geometry();
200  first = false;
201  }
202  else
203  {
204  result = result.intersection( region.geometry() );
205  }
206  }
207 
208  if ( !shouldClip )
209  return QgsGeometry();
210 
211  // filter out polygon parts from result only
213 
214  // lastly transform back to layer CRS
215  try
216  {
218  }
219  catch ( QgsCsException & )
220  {
221  QgsDebugMsg( QStringLiteral( "Could not transform clipping region to layer CRS" ) );
222  shouldClip = false;
223  return QgsGeometry();
224  }
225 
226  return result;
227 }
QgsMapClippingUtils::collectClippingRegionsForLayer
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.
Definition: qgsmapclippingutils.cpp:23
QgsGeometry::transform
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Definition: qgsgeometry.cpp:2813
QgsGeometry::convertGeometryCollectionToSubclass
bool convertGeometryCollectionToSubclass(QgsWkbTypes::GeometryType geomType)
Converts geometry collection to a the desired geometry type subclass (multi-point,...
Definition: qgsgeometry.cpp:1507
QgsRenderContext::mapToPixel
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
Definition: qgsrendercontext.h:325
QgsMapClippingRegion
A map clipping region (in map coordinates and CRS).
Definition: qgsmapclippingregion.h:32
QgsMapClippingUtils::calculateFeatureIntersectionGeometry
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...
Definition: qgsmapclippingutils.cpp:80
QgsMapLayerType::MeshLayer
@ MeshLayer
Added in 3.2.
QgsAbstractGeometry::asQPainterPath
virtual QPainterPath asQPainterPath() const =0
Returns the geometry represented as a QPainterPath.
QgsMapLayerType::VectorLayer
@ VectorLayer
QgsMapLayerType
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:68
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:58
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsCoordinateTransform::ReverseTransform
@ ReverseTransform
Transform from destination to source CRS.
Definition: qgscoordinatetransform.h:61
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:144
QgsGeometry::intersection
QgsGeometry intersection(const QgsGeometry &geometry) const
Returns a geometry representing the points shared by this geometry and other.
Definition: qgsgeometry.cpp:2380
QgsRenderContext::coordinateTransform
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Definition: qgsrendercontext.h:245
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
QgsMapClippingUtils::calculatePainterClipRegion
static QPainterPath calculatePainterClipRegion(const QList< QgsMapClippingRegion > &regions, const QgsRenderContext &context, QgsMapLayerType layerType, bool &shouldClip)
Returns a QPainterPath representing the intersection of clipping regions from context which should be...
Definition: qgsmapclippingutils.cpp:126
QgsMapClippingRegion::FeatureClippingType::ClipToIntersection
@ ClipToIntersection
Clip the geometry of these features to the region prior to rendering (i.e. feature boundaries will fo...
QgsMapLayerType::RasterLayer
@ RasterLayer
QgsMapClippingUtils::calculateLabelIntersectionGeometry
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...
Definition: qgsmapclippingutils.cpp:179
qgsrendercontext.h
QgsMapClippingUtils::calculateFeatureRequestGeometry
static QgsGeometry calculateFeatureRequestGeometry(const QList< QgsMapClippingRegion > &regions, const QgsRenderContext &context, bool &shouldFilter)
Returns the geometry representing the intersection of clipping regions from context.
Definition: qgsmapclippingutils.cpp:37
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:128
qgsgeometry.h
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsMapClippingRegion::FeatureClippingType::ClipPainterOnly
@ ClipPainterOnly
Applying clipping on the painter only (i.e. feature boundaries will be unchanged, but may be invisibl...
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsMapLayerType::VectorTileLayer
@ VectorTileLayer
Added in 3.14.
qgsmapclippingutils.h
QgsGeometry::mapToPixel
void mapToPixel(const QgsMapToPixel &mtp)
Transforms the geometry from map units to pixels in place.
Definition: qgsgeometry.cpp:2837
QgsRenderContext::clippingRegions
QList< QgsMapClippingRegion > clippingRegions() const
Returns the list of clipping regions to apply during the render.
Definition: qgsrendercontext.cpp:525
qgslogger.h
QgsMapLayerType::PluginLayer
@ PluginLayer
qgsmapclippingregion.h