QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsalgorithmtessellate.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmtessellate.cpp
3 ---------------------
4 begin : November 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
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
19#include "qgstessellator.h"
20#include "qgsmultipolygon.h"
21#include "qgspolygon.h"
22#include <geos_c.h>
23
25
26QString QgsTessellateAlgorithm::name() const
27{
28 return QStringLiteral( "tessellate" );
29}
30
31QString QgsTessellateAlgorithm::displayName() const
32{
33 return QObject::tr( "Tessellate" );
34}
35
36QStringList QgsTessellateAlgorithm::tags() const
37{
38 return QObject::tr( "3d,triangle" ).split( ',' );
39}
40
41QString QgsTessellateAlgorithm::group() const
42{
43 return QObject::tr( "Vector geometry" );
44}
45
46QString QgsTessellateAlgorithm::groupId() const
47{
48 return QStringLiteral( "vectorgeometry" );
49}
50
51QString QgsTessellateAlgorithm::outputName() const
52{
53 return QObject::tr( "Tessellated" );
54}
55
56Qgis::ProcessingSourceType QgsTessellateAlgorithm::outputLayerType() const
57{
59}
60
61Qgis::WkbType QgsTessellateAlgorithm::outputWkbType( Qgis::WkbType inputWkbType ) const
62{
64}
65
66QString QgsTessellateAlgorithm::shortHelpString() const
67{
68 return QObject::tr( "This algorithm tessellates a polygon geometry layer, dividing the geometries into triangular components." )
69 + QStringLiteral( "\n\n" )
70 + QObject::tr( "The output layer consists of multipolygon geometries for each input feature, with each multipolygon consisting of multiple triangle component polygons." );
71}
72
73QList<int> QgsTessellateAlgorithm::inputLayerTypes() const
74{
75 return QList<int>() << static_cast< int >( Qgis::ProcessingSourceType::VectorPolygon );
76}
77
78QgsTessellateAlgorithm *QgsTessellateAlgorithm::createInstance() const
79{
80 return new QgsTessellateAlgorithm();
81}
82
83QgsFeatureList QgsTessellateAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback )
84{
85 QgsFeature f = feature;
86 if ( f.hasGeometry() )
87 {
89 f.clearGeometry();
90 else
91 {
92 const QgsGeometry inputGeometry = f.geometry();
93 bool tessellationComplete = false;
94#if (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=11) || GEOS_VERSION_MAJOR>3
95 if ( !inputGeometry.constGet()->is3D() )
96 {
97 // on supported GEOS versions we prefer to use GEOS GEOSConstrainedDelaunayTriangulation
98 // for 2D triangulation, as it's more stable and tolerant to situations like polygon
99 // holes touching an exterior ring vs the poly2tri based tessellation
100 const QgsGeometry triangulation = inputGeometry.constrainedDelaunayTriangulation();
101 if ( triangulation.isEmpty() && !inputGeometry.isEmpty() )
102 {
103 if ( !triangulation.lastError().isEmpty() )
104 {
105 feedback->reportError( QObject::tr( "Feature ID %1 could not be tessellated: %2" ).arg( f.id() ).arg( triangulation.lastError() ) );
106 }
107 else
108 {
109 feedback->reportError( QObject::tr( "Feature ID %1 could not be tessellated" ).arg( f.id() ) );
110 }
111 }
112 else
113 {
114 f.setGeometry( triangulation );
115 }
116 tessellationComplete = true;
117 }
118#endif
119
120 if ( !tessellationComplete )
121 {
122 // 3D case, or 2D case with unsupported GEOS version -- use less stable poly2tri backend
123 const QgsRectangle bounds = f.geometry().boundingBox();
124 QgsTessellator t( bounds, false );
125
126 if ( f.geometry().isMultipart() )
127 {
128 const QgsMultiSurface *ms = qgsgeometry_cast< const QgsMultiSurface * >( f.geometry().constGet() );
129 for ( int i = 0; i < ms->numGeometries(); ++i )
130 {
131 const std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( ms->geometryN( i )->segmentize() ) );
132 t.addPolygon( *p, 0 );
133 }
134 }
135 else
136 {
137 const std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( f.geometry().constGet()->segmentize() ) );
138 t.addPolygon( *p, 0 );
139 }
140 QgsGeometry g( t.asMultiPolygon() );
141 if ( !g.isEmpty() )
142 {
143 if ( !t.error().isEmpty() )
144 {
145 feedback->reportError( QObject::tr( "Feature ID %1 was only partially tessellated: %2" ).arg( f.id() ).arg( t.error() ) );
146 }
147
148 g.translate( bounds.xMinimum(), bounds.yMinimum() );
149 }
150 else
151 {
152 if ( !t.error().isEmpty() )
153 feedback->reportError( QObject::tr( "Feature ID %1 could not be tessellated: %2" ).arg( f.id() ).arg( t.error() ) );
154 else
155 feedback->reportError( QObject::tr( "Feature ID %1 could not be divided into triangular components." ).arg( f.id() ) );
156 }
157 if ( !inputGeometry.constGet()->is3D() )
158 g.get()->dropZValue();
159
160 f.setGeometry( g );
161 }
162 }
163 }
164 return QgsFeatureList() << f;
165}
166
168
169
ProcessingSourceType
Processing data source types.
Definition: qgis.h:2858
@ VectorPolygon
Vector polygon layers.
@ Polygon
Polygons.
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:182
@ MultiPolygon
MultiPolygon.
@ MultiPolygonZ
MultiPolygonZ.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:181
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:230
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:167
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:162
QString lastError() const
Returns an error string referring to the last error encountered either when this geometry was created...
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsGeometry constrainedDelaunayTriangulation() const
Returns a constrained Delaunay triangulation for the vertices of the geometry.
Multi surface geometry collection.
Contains information about the context in which a processing algorithm is executed.
Base class for providing feedback from a processing algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:201
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:211
Class that takes care of tessellation of polygons into triangles.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:862
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:973
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:917