34#include <QPainterPath> 
   36#include <nlohmann/json.hpp> 
   66  auto result = std::make_unique< QgsPolyhedralSurface >();
 
   68  return result.release();
 
 
   73  return QStringLiteral( 
"PolyhedralSurface" );
 
 
   90    mPatches.push_back( patch->clone() );
 
 
  108      mPatches.push_back( patch->clone() );
 
 
  146  std::unique_ptr< QgsPolygon > currentPatch;
 
  147  for ( 
int i = 0; i < nPatches; ++i )
 
  150    wkbPtr -= 1 + 
sizeof( int );
 
  160    currentPatch->fromWkb( wkbPtr );  
 
  161    mPatches.append( currentPatch.release() );
 
 
  178  QString secondWithoutParentheses = 
parts.second;
 
  179  secondWithoutParentheses = secondWithoutParentheses.remove( 
'(' ).remove( 
')' ).simplified().remove( 
' ' );
 
  180  if ( ( 
parts.second.compare( QLatin1String( 
"EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
 
  181       secondWithoutParentheses.isEmpty() )
 
  184  QString defaultChildWkbType = QStringLiteral( 
"Polygon%1%2" ).arg( 
is3D() ? QStringLiteral( 
"Z" ) : QString(), 
isMeasure() ? QStringLiteral( 
"M" ) : QString() );
 
  187  for ( 
const QString &childWkt : blocks )
 
  201    if ( !
mPatches.back()->fromWkt( childWkt ) )
 
 
  219  for ( 
int i = 1; i < 
mPatches.size(); ++i )
 
 
  229  int binarySize = 
sizeof( char ) + 
sizeof( quint32 ) + 
sizeof( quint32 );
 
  232    binarySize += patch->wkbSize( flags );
 
 
  243  wkb << static_cast<quint32>( 
wkbType() );
 
  244  wkb << static_cast<quint32>( 
mPatches.size() );
 
  247    wkb << patch->asWkb( flags );
 
 
  257    wkt += QLatin1String( 
" EMPTY" );
 
  260    wkt += QLatin1String( 
" (" );
 
  263      QString childWkt = patch->asWkt( 
precision );
 
  264      if ( qgsgeometry_cast<const QgsPolygon *>( patch ) )
 
  267        childWkt = childWkt.mid( childWkt.indexOf( 
'(' ) );
 
  269      wkt += childWkt + 
',';
 
  271    if ( wkt.endsWith( 
',' ) )
 
 
  282  QgsDebugError( QStringLiteral( 
"gml version 2 does not support PolyhedralSurface geometry" ) );
 
  283  return QDomElement();
 
 
  288  QDomElement elemPolyhedralSurface = doc.createElementNS( ns, QStringLiteral( 
"PolyhedralSurface" ) );
 
  291    return elemPolyhedralSurface;
 
  293  QDomElement elemPolygonPatches = doc.createElementNS( ns, QStringLiteral( 
"polygonPatches" ) );
 
  297    QDomElement elemPolygonPatch = patch->asGml3( doc, 
precision, ns, axisOrder );
 
  298    elemPolygonPatch.setTagName( 
"PolygonPatch" );
 
  300    elemPolygonPatches.appendChild( elemPolygonPatch );
 
  302  elemPolyhedralSurface.appendChild( elemPolygonPatches );
 
  304  return elemPolyhedralSurface;
 
 
  311  std::unique_ptr<QgsMultiPolygon> multiPolygon( 
toMultiPolygon() );
 
  312  return multiPolygon->asJsonObject( 
precision );
 
 
  317  QgsDebugError( QStringLiteral( 
"kml format does not support PolyhedralSurface geometry" ) );
 
  318  return QString( 
"" );
 
 
  325    QgsCurve *exteriorRing = patch->exteriorRing();
 
  331    if ( patch->numInteriorRings() > 0 )
 
  333      QVector<QgsCurve *> interiorRings;
 
  334      for ( 
int i = 0, n = patch->numInteriorRings(); i < n; ++i )
 
  336        interiorRings.push_back( patch->interiorRing( i )->clone() );
 
  340      std::sort( interiorRings.begin(), interiorRings.end(), []( 
const QgsCurve * a, 
const QgsCurve * b )
 
  342        return a->compareTo( b ) > 0;
 
  345      patch->removeInteriorRings();
 
  346      for ( 
QgsCurve *curve : interiorRings )
 
  347        patch->addInteriorRing( curve );
 
 
  358    area += patch->area();
 
 
  378  auto multiLine = std::make_unique<QgsMultiLineString>();
 
  379  multiLine->reserve( 
mPatches.size() );
 
  382    std::unique_ptr<QgsAbstractGeometry> polygonBoundary( polygon->boundary() );
 
  383    if ( 
QgsLineString *lineStringBoundary = qgsgeometry_cast< QgsLineString * >( polygonBoundary.get() ) )
 
  385      multiLine->addGeometry( lineStringBoundary->clone() );
 
  387    else if ( 
QgsMultiLineString *multiLineStringBoundary = qgsgeometry_cast< QgsMultiLineString * >( polygonBoundary.get() ) )
 
  389      for ( 
int j = 0; j < multiLineStringBoundary->numGeometries(); ++j )
 
  391        multiLine->addGeometry( multiLineStringBoundary->geometryN( j )->clone() );
 
  396  if ( multiLine->numGeometries() == 0 )
 
  400  return multiLine.release();
 
 
  410    std::unique_ptr<QgsCurve> exteriorRing( 
static_cast< QgsCurve *
>( patch->exteriorRing()->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, removeRedundantPoints ) ) );
 
  416    auto gridifiedPatch = std::make_unique<QgsPolygon>();
 
  417    gridifiedPatch->setExteriorRing( exteriorRing.release() );
 
  420    for ( 
int i = 0, n = patch->numInteriorRings(); i < n; ++i )
 
  422      QgsCurve *interiorRing = patch->interiorRing( i );
 
  426      std::unique_ptr<QgsCurve> gridifiedInterior( 
static_cast< QgsCurve * 
>( interiorRing->
snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, removeRedundantPoints ) ) );
 
  427      if ( gridifiedInterior )
 
  428        gridifiedPatch->addInteriorRing( gridifiedInterior.release() );
 
  431    surface->addPatch( gridifiedPatch.release() );
 
  434  return surface.release();
 
 
  442  auto simplifiedGeom = std::make_unique< QgsPolyhedralSurface >();
 
  445    std::unique_ptr<QgsCurvePolygon> polygonSimplified( polygon->simplifyByDistance( tolerance ) );
 
  446    simplifiedGeom->addPatch( polygonSimplified->surfaceToPolygon() );
 
  448  return simplifiedGeom.release();
 
 
  457    if ( patch->removeDuplicateNodes( epsilon, useZValues ) )
 
 
  480    if ( patch->boundingBoxIntersects( box3d ) )
 
 
  518  else if ( !patch->
is3D() )
 
 
  532  if ( patchIndex < 0 || patchIndex >= 
mPatches.size() )
 
  537  delete mPatches.takeAt( patchIndex );
 
 
  544  QPainterPath painterPath;
 
  547    QPainterPath patchPath = patch->asQPainterPath();
 
  548    patchPath.closeSubpath();
 
  549    painterPath.addPath( patchPath );
 
 
  570    patch->transform( ct, d, transformZ );
 
 
  579    patch->transform( t, zTranslate, zScale, mTranslate, mScale );
 
 
  590    QgsCoordinateSequence::const_iterator cIt = polyCoords.constBegin();
 
  591    for ( ; cIt != polyCoords.constEnd(); ++cIt )
 
  593      sequence.push_back( *cIt );
 
 
  605    count += patch->nCoordinates();
 
 
  612  if ( 
id.part < 0 || id.part >= 
partCount() )
 
  616  for ( 
int i = 0; i < 
mPatches.count(); ++i )
 
  620      int partNumber = 
mPatches.at( i )->vertexNumberFromVertexId( 
QgsVertexId( 0, 
id.ring, 
id.vertex ) );
 
  621      if ( partNumber == -1 )
 
  626      return number + partNumber;
 
  630      number += 
mPatches.at( i )->nCoordinates();
 
 
  644  QVector<QgsPolygon *> segmentList = 
mPatches;
 
 
  757  Q_UNUSED( tolerance )
 
  758  Q_UNUSED( toleranceType )
 
 
  805  if ( 
id.part < 0 || id.part >= 
partCount() )
 
  808  return mPatches[
id.part]->vertexAt( 
id );
 
 
  833    patch->addZValue( zValue );
 
 
  850    patch->addMValue( mValue );
 
 
  899  auto multiSurface = std::make_unique< QgsMultiSurface >();
 
  900  multiSurface->reserve( 
mPatches.size() );
 
  903    multiSurface->addGeometry( polygon->clone() );
 
  905  return multiSurface.release();
 
 
  917    res = patch->transform( transformer );
 
 
  931  auto multiPolygon = std::make_unique< QgsMultiPolygon >();
 
  932  multiPolygon->reserve( 
mPatches.size() );
 
  935    multiPolygon->addGeometry( polygon->clone() );
 
  937  return multiPolygon.release();
 
 
  944    patch->filterVertices( filter );
 
 
  972  const QgsPolyhedralSurface *otherPolySurface = qgsgeometry_cast<const QgsPolyhedralSurface *>( other );
 
  973  if ( !otherPolySurface )
 
  976  const int nPatches1 = 
mPatches.size();
 
  977  const int nPatches2 = otherPolySurface->
mPatches.size();
 
  978  if ( nPatches1 < nPatches2 )
 
  982  if ( nPatches1 > nPatches2 )
 
  987  for ( 
int i = 0; i < nPatches1; i++ )
 
  989    const int polygonComp = 
mPatches.at( i )->compareTo( otherPolySurface->
mPatches.at( i ) );
 
  990    if ( polygonComp != 0 )
 
 
 1005    return error.isEmpty();
 
 1014  for ( 
int i = 0; i < 
mPatches.size(); ++i )
 
 1020      error = QStringLiteral( 
"Polygon %1 is invalid: %2" ).arg( QString::number( i ), error );
 
 1029  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.
 
Abstract base class for all geometries.
 
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.
 
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.
 
bool intersects(const QgsBox3D &other) const
Returns true if box intersects with another box.
 
void combineWith(const QgsBox3D &box)
Expands the bbox so that it covers both the original rectangle and the given rectangle.
 
bool isNull() const
Test if the box is null (holding no spatial information).
 
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.
 
Polyhedral surface geometry type.
 
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.
 
QVector< QgsRingSequence > QgsCoordinateSequence
 
#define QgsDebugError(str)
 
Utility class for identifying a unique vertex within a geometry.