21#include <nlohmann/json.hpp>
38#include <QPainterPath>
68 auto result = std::make_unique< QgsPolyhedralSurface >();
70 return result.release();
75 return QStringLiteral(
"PolyhedralSurface" );
92 mPatches.push_back( patch->clone() );
148 std::unique_ptr< QgsPolygon > currentPatch;
149 for (
int i = 0; i < nPatches; ++i )
152 wkbPtr -= 1 +
sizeof( int );
156 currentPatch = std::make_unique<QgsPolygon>( );
162 currentPatch->fromWkb( wkbPtr );
163 mPatches.append( currentPatch.release() );
180 QString secondWithoutParentheses =
parts.second;
181 secondWithoutParentheses = secondWithoutParentheses.remove(
'(' ).remove(
')' ).simplified().remove(
' ' );
182 if ( (
parts.second.compare( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
183 secondWithoutParentheses.isEmpty() )
186 QString defaultChildWkbType = QStringLiteral(
"Polygon%1%2" ).arg(
is3D() ? QStringLiteral(
"Z" ) : QString(),
isMeasure() ? QStringLiteral(
"M" ) : QString() );
189 for (
const QString &childWkt : blocks )
203 if ( !
mPatches.back()->fromWkt( childWkt ) )
221 for (
int i = 1; i <
mPatches.size(); ++i )
231 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
234 binarySize += patch->wkbSize( flags );
245 wkb << static_cast<quint32>(
wkbType() );
246 wkb << static_cast<quint32>(
mPatches.size() );
249 wkb << patch->asWkb( flags );
259 wkt += QLatin1String(
" EMPTY" );
262 wkt += QLatin1String(
" (" );
265 QString childWkt = patch->asWkt( precision );
269 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
271 wkt += childWkt +
',';
273 if ( wkt.endsWith(
',' ) )
284 QgsDebugError( QStringLiteral(
"gml version 2 does not support PolyhedralSurface geometry" ) );
285 return QDomElement();
290 QDomElement elemPolyhedralSurface = doc.createElementNS( ns, QStringLiteral(
"PolyhedralSurface" ) );
293 return elemPolyhedralSurface;
295 QDomElement elemPolygonPatches = doc.createElementNS( ns, QStringLiteral(
"polygonPatches" ) );
299 QDomElement elemPolygonPatch = patch->asGml3( doc, precision, ns, axisOrder );
300 elemPolygonPatch.setTagName(
"PolygonPatch" );
302 elemPolygonPatches.appendChild( elemPolygonPatch );
304 elemPolyhedralSurface.appendChild( elemPolygonPatches );
306 return elemPolyhedralSurface;
313 std::unique_ptr<QgsMultiPolygon> multiPolygon(
toMultiPolygon() );
314 return multiPolygon->asJsonObject( precision );
319 QgsDebugError( QStringLiteral(
"kml format does not support PolyhedralSurface geometry" ) );
320 return QString(
"" );
327 QgsCurve *exteriorRing = patch->exteriorRing();
333 if ( patch->numInteriorRings() > 0 )
335 QVector<QgsCurve *> interiorRings;
336 for (
int i = 0, n = patch->numInteriorRings(); i < n; ++i )
338 interiorRings.push_back( patch->interiorRing( i )->clone() );
342 std::sort( interiorRings.begin(), interiorRings.end(), [](
const QgsCurve * a,
const QgsCurve * b )
344 return a->compareTo( b ) > 0;
347 patch->removeInteriorRings();
348 for (
QgsCurve *curve : interiorRings )
349 patch->addInteriorRing( curve );
360 area += patch->area();
380 auto multiLine = std::make_unique<QgsMultiLineString>();
381 multiLine->reserve(
mPatches.size() );
384 std::unique_ptr<QgsAbstractGeometry> polygonBoundary( polygon->boundary() );
387 multiLine->addGeometry( lineStringBoundary->clone() );
391 for (
int j = 0; j < multiLineStringBoundary->numGeometries(); ++j )
393 multiLine->addGeometry( multiLineStringBoundary->geometryN( j )->clone() );
398 if ( multiLine->numGeometries() == 0 )
402 return multiLine.release();
412 std::unique_ptr<QgsCurve> exteriorRing(
static_cast< QgsCurve *
>( patch->exteriorRing()->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, removeRedundantPoints ) ) );
418 auto gridifiedPatch = std::make_unique<QgsPolygon>();
419 gridifiedPatch->setExteriorRing( exteriorRing.release() );
422 for (
int i = 0, n = patch->numInteriorRings(); i < n; ++i )
424 QgsCurve *interiorRing = patch->interiorRing( i );
428 std::unique_ptr<QgsCurve> gridifiedInterior(
static_cast< QgsCurve *
>( interiorRing->
snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, removeRedundantPoints ) ) );
429 if ( gridifiedInterior )
430 gridifiedPatch->addInteriorRing( gridifiedInterior.release() );
433 surface->addPatch( gridifiedPatch.release() );
436 return surface.release();
444 auto simplifiedGeom = std::make_unique< QgsPolyhedralSurface >();
447 std::unique_ptr<QgsCurvePolygon> polygonSimplified( polygon->simplifyByDistance( tolerance ) );
448 simplifiedGeom->addPatch( polygonSimplified->surfaceToPolygon() );
450 return simplifiedGeom.release();
459 if ( patch->removeDuplicateNodes( epsilon, useZValues ) )
482 if ( patch->boundingBoxIntersects( box3d ) )
520 else if ( !patch->
is3D() )
534 if ( patchIndex < 0 || patchIndex >=
mPatches.size() )
539 delete mPatches.takeAt( patchIndex );
546 QPainterPath painterPath;
549 QPainterPath patchPath = patch->asQPainterPath();
550 patchPath.closeSubpath();
551 painterPath.addPath( patchPath );
572 patch->transform( ct, d, transformZ );
581 patch->transform( t, zTranslate, zScale, mTranslate, mScale );
592 QgsCoordinateSequence::const_iterator cIt = polyCoords.constBegin();
593 for ( ; cIt != polyCoords.constEnd(); ++cIt )
595 sequence.push_back( *cIt );
607 count += patch->nCoordinates();
614 if (
id.part < 0 || id.part >=
partCount() )
618 for (
int i = 0; i <
mPatches.count(); ++i )
622 int partNumber =
mPatches.at( i )->vertexNumberFromVertexId(
QgsVertexId( 0,
id.ring,
id.vertex ) );
623 if ( partNumber == -1 )
628 return number + partNumber;
632 number +=
mPatches.at( i )->nCoordinates();
646 QVector<QgsPolygon *> segmentList =
mPatches;
759 Q_UNUSED( tolerance )
760 Q_UNUSED( toleranceType )
807 if (
id.part < 0 || id.part >=
partCount() )
810 return mPatches[
id.part]->vertexAt(
id );
835 patch->addZValue( zValue );
852 patch->addMValue( mValue );
901 auto multiSurface = std::make_unique< QgsMultiSurface >();
902 multiSurface->reserve(
mPatches.size() );
905 multiSurface->addGeometry( polygon->clone() );
907 return multiSurface.release();
919 res = patch->transform( transformer );
933 auto multiPolygon = std::make_unique< QgsMultiPolygon >();
934 multiPolygon->reserve(
mPatches.size() );
937 multiPolygon->addGeometry( polygon->clone() );
939 return multiPolygon.release();
946 patch->filterVertices( filter );
975 if ( !otherPolySurface )
978 const int nPatches1 =
mPatches.size();
979 const int nPatches2 = otherPolySurface->
mPatches.size();
980 if ( nPatches1 < nPatches2 )
984 if ( nPatches1 > nPatches2 )
989 for (
int i = 0; i < nPatches1; i++ )
991 const int polygonComp =
mPatches.at( i )->compareTo( otherPolySurface->
mPatches.at( i ) );
992 if ( polygonComp != 0 )
1007 return error.isEmpty();
1016 for (
int i = 0; i <
mPatches.size(); ++i )
1022 error = QStringLiteral(
"Polygon %1 is invalid: %2" ).arg( QString::number( i ), error );
1031 const bool valid = error.isEmpty();
@ AllowSelfTouchingHoles
Indicates that self-touching holes are permitted. OGC validity states that self-touching holes are NO...
QFlags< GeometryValidityFlag > GeometryValidityFlags
Geometry validity flags.
QFlags< GeosCreationFlag > GeosCreationFlags
Geos geometry creation behavior flags.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ PolyhedralSurface
PolyhedralSurface.
TransformDirection
Indicates the direction (forward or inverse) of a transform.
virtual QgsAbstractGeometry * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0, bool removeRedundantPoints=false) const =0
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
bool isMeasure() const
Returns true if the geometry contains m values.
QFlags< WkbFlag > WkbFlags
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
AxisOrder
Axis order for GML generation.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
QgsAbstractGeometry & operator=(const QgsAbstractGeometry &geom)
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, Qgis::WkbType baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
virtual bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
QgsAbstractGeometry()=default
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
static endian_t endian()
Returns whether this machine uses big or little endian.
A 3-dimensional box composed of x, y, z coordinates.
void combineWith(const QgsBox3D &box)
Expands the bbox so that it covers both the original rectangle and the given rectangle.
Qgis::WkbType readHeader() const
readHeader
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate rotation angle for a vertex.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
void adjacentVertices(QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex) const override
Returns the vertices adjacent to a specified vertex within a geometry.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
bool dropMValue() override
Drops any measure values which exist in the geometry.
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
Abstract base class for curved geometry type.
void normalize() final
Reorganizes the geometry into a normalized form (or "canonical" form).
int vertexCount(int part=0, int ring=0) const override
Returns the number of vertices of which this geometry is built.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
bool isEmpty() const override
Returns true if the geometry is empty.
int numGeometries() const
Returns the number of geometries within the collection.
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType=QString())
Parses a WKT string and returns of list of blocks contained in the WKT.
static QPair< Qgis::WkbType, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
static double closestSegmentFromComponents(T &container, ComponentType ctype, const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon)
Does vector analysis using the GEOS library and handles import, export, and exception handling.
Line string geometry type, with support for z-dimension and m-values.
Multi line string geometry collection.
Multi polygon geometry collection.
QgsPolygon * polygonN(int index)
Returns the polygon with the specified index.
Multi surface geometry collection.
Point geometry type, with support for z-dimension and m-values.
QgsPolygon * clone() const override
Clones the geometry by performing a deep copy.
QgsPolyhedralSurface * clone() const override
Clones the geometry by performing a deep copy.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
QVector< QgsPolygon * > mPatches
double area() const override
Returns the planar, 2-dimensional area of the geometry.
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns a WKB representation of the geometry.
~QgsPolyhedralSurface() override
QgsAbstractGeometry * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
QString geometryType() const override
Returns a unique string representing the geometry type.
int wkbSize(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const override
Returns the length of the QByteArray returned by asWkb().
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
QgsAbstractGeometry * childGeometry(int index) const override
Returns pointer to child geometry (for geometries with child geometries - i.e.
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
int dimension() const final
Returns the inherent dimension of the geometry.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
void normalize() override
Reorganizes the geometry into a normalized form (or "canonical" form).
bool removePatch(int patchIndex)
Removes a patch from the polyhedral surface.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
bool dropMValue() override
Drops any measure values which exist in the geometry.
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
int compareToSameClass(const QgsAbstractGeometry *other) const override
Compares to an other geometry of the same class, and returns a integer for sorting of the two geometr...
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
QgsPolyhedralSurface * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
void adjacentVertices(QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex) const override
Returns the vertices adjacent to a specified vertex within a geometry.
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
QgsPolyhedralSurface * simplifyByDistance(double tolerance) const override
Simplifies the geometry by applying the Douglas Peucker simplification by distance algorithm.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
QPainterPath asQPainterPath() const override
Returns the geometry represented as a QPainterPath.
virtual void addPatch(QgsPolygon *patch)
Adds a patch to the geometry, transferring ownership to the polyhedral surface.
QgsBox3D calculateBoundingBox3D() const override
Calculates the minimal 3D bounding box for the geometry.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
void filterVertices(const std::function< bool(const QgsPoint &) > &filter) override
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
bool hasCurvedSegments() const final
Returns true if the geometry contains curved segments.
QgsPoint vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate rotation angle for a vertex.
virtual void setPatches(const QVector< QgsPolygon * > &patches)
Sets all patches, transferring ownership to the polyhedral surface.
void clear() override
Clears the geometry, ie reset it to a null geometry.
bool isEmpty() const override
Returns true if the geometry is empty.
void transformVertices(const std::function< QgsPoint(const QgsPoint &) > &transform) override
Transforms the vertices from the geometry in place, applying the transform function to every vertex.
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
QgsPolyhedralSurface * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0, bool removeRedundantPoints=false) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
int vertexCount(int part=0, int ring=0) const override
Returns the number of vertices of which this geometry is built.
double perimeter() const override
Returns the planar, 2-dimensional perimeter of the geometry.
QgsMultiSurface * toCurveType() const override
Returns the geometry converted to the more generic curve type.
QString asKml(int precision=17) const override
Returns a KML representation of the geometry.
int childCount() const override
Returns number of child geometries (for geometries with child geometries) or child points (for geomet...
int partCount() const override
Returns count of parts contained in the geometry.
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
void swapXy() override
Swaps the x and y coordinates from the geometry.
QgsPolyhedralSurface & operator=(const QgsPolyhedralSurface &p)
double closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *std::numeric_limits< double >::epsilon()) const override
Searches for the closest segment of the geometry to a given point.
int ringCount(int part=0) const override
Returns the number of rings of which this geometry is built.
bool boundingBoxIntersects(const QgsBox3D &box3d) const override
Returns true if the bounding box of this geometry intersects with a box3d.
QgsMultiPolygon * toMultiPolygon() const
Converts a polyhedral surface to a multipolygon.
QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
QString mValidityFailureReason
static Qgis::WkbType dropM(Qgis::WkbType type)
Drops the m dimension (if present) for a WKB type and returns the new type.
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...
static Qgis::WkbType dropZ(Qgis::WkbType type)
Drops the z dimension (if present) for a WKB type and returns the new type.
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
Contains geos related utilities and functions.
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QVector< QgsRingSequence > QgsCoordinateSequence
#define QgsDebugError(str)
Utility class for identifying a unique vertex within a geometry.