29 #include <QJsonObject> 31 #include <QPainterPath> 33 #include <nlohmann/json.hpp> 47 auto result = qgis::make_unique< QgsCurvePolygon >();
49 return result.release();
54 return QStringLiteral(
"CurvePolygon" );
171 std::unique_ptr< QgsCurve > currentCurve;
172 for (
int i = 0; i < nRings; ++i )
175 wkbPtr -= 1 +
sizeof( int );
193 currentCurve->fromWkb( wkbPtr );
218 QString defaultChildWkbType = QStringLiteral(
"LineString%1%2" ).arg(
is3D() ? QStringLiteral(
"Z" ) : QString(),
isMeasure() ? QStringLiteral(
"M" ) : QString() );
221 for (
const QString &childWkt : blocks )
263 hasZ = hasZ || curve->is3D();
264 hasM = hasM || curve->isMeasure();
287 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
288 QVector<QByteArray> wkbForRings;
293 binarySize += wkb.length();
298 QByteArray wkb( curve->asWkb() );
299 binarySize += wkb.length();
304 wkbArray.resize( binarySize );
307 wkbPtr << static_cast<quint32>(
wkbType() );
308 wkbPtr << static_cast<quint32>( wkbForRings.count() );
309 for (
const QByteArray &wkb : qgis::as_const( wkbForRings ) )
318 QString wkt =
wktTypeStr() + QLatin1String(
" (" );
322 if ( qgsgeometry_cast<QgsLineString *>(
mExteriorRing.get() ) )
325 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
327 wkt += childWkt +
',';
331 QString childWkt = curve->asWkt( precision );
332 if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
335 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
337 wkt += childWkt +
',';
339 if ( wkt.endsWith(
',' ) )
350 QDomElement elemPolygon = doc.createElementNS( ns, QStringLiteral(
"Polygon" ) );
355 QDomElement elemOuterBoundaryIs = doc.createElementNS( ns, QStringLiteral(
"outerBoundaryIs" ) );
356 std::unique_ptr< QgsLineString > exteriorLineString(
exteriorRing()->curveToLine() );
357 QDomElement outerRing = exteriorLineString->asGml2( doc, precision, ns, axisOrder );
358 outerRing.toElement().setTagName( QStringLiteral(
"LinearRing" ) );
359 elemOuterBoundaryIs.appendChild( outerRing );
360 elemPolygon.appendChild( elemOuterBoundaryIs );
361 std::unique_ptr< QgsLineString > interiorLineString;
364 QDomElement elemInnerBoundaryIs = doc.createElementNS( ns, QStringLiteral(
"innerBoundaryIs" ) );
365 interiorLineString.reset(
interiorRing( i )->curveToLine() );
366 QDomElement innerRing = interiorLineString->asGml2( doc, precision, ns, axisOrder );
367 innerRing.toElement().setTagName( QStringLiteral(
"LinearRing" ) );
368 elemInnerBoundaryIs.appendChild( innerRing );
369 elemPolygon.appendChild( elemInnerBoundaryIs );
376 QDomElement elemCurvePolygon = doc.createElementNS( ns, QStringLiteral(
"Polygon" ) );
379 return elemCurvePolygon;
381 QDomElement elemExterior = doc.createElementNS( ns, QStringLiteral(
"exterior" ) );
383 if ( curveElem.tagName() == QLatin1String(
"LineString" ) )
385 curveElem.setTagName( QStringLiteral(
"LinearRing" ) );
387 elemExterior.appendChild( curveElem );
388 elemCurvePolygon.appendChild( elemExterior );
392 QDomElement elemInterior = doc.createElementNS( ns, QStringLiteral(
"interior" ) );
394 if ( innerRing.tagName() == QLatin1String(
"LineString" ) )
396 innerRing.setTagName( QStringLiteral(
"LinearRing" ) );
398 elemInterior.appendChild( innerRing );
399 elemCurvePolygon.appendChild( elemInterior );
401 return elemCurvePolygon;
406 json coordinates( json::array( ) );
409 std::unique_ptr< QgsLineString > exteriorLineString(
exteriorRing()->curveToLine() );
411 exteriorLineString->points( exteriorPts );
414 std::unique_ptr< QgsLineString > interiorLineString;
417 interiorLineString.reset(
interiorRing( i )->curveToLine() );
419 interiorLineString->points( interiorPts );
425 {
"type",
"Polygon" },
426 {
"coordinates", coordinates }
437 double totalArea = 0.0;
443 totalArea += std::fabs( area );
449 if ( ring->isRing() )
451 ring->sumUpArea( area );
452 totalArea -= std::fabs( area );
467 perimeter += ring->length();
474 std::unique_ptr< QgsPolygon > polygon(
new QgsPolygon() );
476 return polygon.release();
478 polygon->setExteriorRing(
exteriorRing()->curveToLine() );
479 QVector<QgsCurve *> interiors;
481 interiors.reserve( n );
482 for (
int i = 0; i < n; ++i )
486 polygon->setInteriorRings( interiors );
487 return polygon.release();
504 for (
int i = 0; i < nInteriorRings; ++i )
521 auto exterior = std::unique_ptr<QgsCurve> {
static_cast< QgsCurve *
>(
mExteriorRing->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) };
526 polygon->mExteriorRing = std::move( exterior );
534 QgsCurve *gridifiedInterior =
static_cast< QgsCurve *
>( interior->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) );
536 if ( !gridifiedInterior )
539 polygon->mInteriorRings.append( gridifiedInterior );
542 return polygon.release();
549 auto cleanRing = [epsilon, useZValues ](
QgsCurve * ring )->
bool 551 if ( ring->numPoints() <= 4 )
554 if ( ring->removeDuplicateNodes( epsilon, useZValues ) )
558 ring->pointAt( 0, startPoint, type );
572 result = result || cleanRing( ring );
579 std::unique_ptr< QgsPolygon > poly(
new QgsPolygon() );
582 return poly.release();
585 poly->setExteriorRing(
mExteriorRing->curveToLine( tolerance, toleranceType ) );
587 QVector<QgsCurve *> rings;
591 rings.push_back( ring->curveToLine( tolerance, toleranceType ) );
593 poly->setInteriorRings( rings );
594 return poly.release();
652 else if ( !ring->
is3D() )
677 for (
int ringIndex =
mInteriorRings.size() - 1; ringIndex >= 0; --ringIndex )
679 if ( minimumAllowedArea < 0 )
685 if ( area < minimumAllowedArea )
695 QVector<QgsCurve *> validRings;
699 if ( !curve->isRing() )
717 std::unique_ptr< QgsCurve > flipped(
mExteriorRing->reversed() );
721 QVector<QgsCurve *> validRings;
728 validRings << flipped;
755 ring->addToPainterPath( path );
770 curve->transform( ct, d, transformZ );
779 mExteriorRing->transform( t, zTranslate, zScale, mTranslate, mScale );
784 curve->transform( t, zTranslate, zScale, mTranslate, mScale );
803 ring->points( sequence.back().back() );
820 count += ring->nCoordinates();
831 if (
id.ring < 0 || id.ring >=
ringCount() )
846 if (
id.ring == i + 1 )
849 if ( partNumber == -1 )
851 return number + partNumber;
875 QVector<QgsCurve *> segmentList;
927 if ( vertex.
vertex == 0 && n < 3 )
931 else if ( vertex.
vertex == 0 )
939 if ( vertex.
vertex == n - 1 && n < 3 )
943 else if ( vertex.
vertex == n - 1 )
962 if ( vertex.
ring == 0 )
990 else if ( vId.
vertex == n )
1007 bool success = ring->
moveVertex( vId, newPos );
1013 else if ( vId.
vertex == n - 1 )
1032 if ( vId.
ring == 0 )
1056 else if ( vId.
vertex == n - 1 )
1072 if ( ring->hasCurvedSegments() )
1082 return toPolygon( tolerance, toleranceType );
1139 curve->addZValue( zValue );
1156 curve->addMValue( mValue );
1172 curve->dropZValue();
1188 curve->dropMValue();
1217 curve->filterVertices( filter );
bool isMeasure() const
Returns true if the geometry contains m values.
QByteArray asWkb() const override
Returns a WKB representation of the geometry.
virtual QgsCurve * reversed() const =0
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
virtual void setExteriorRing(QgsCurve *ring)
Sets the exterior ring of the polygon.
void ringAdjacentVertices(const QgsCurve *curve, QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex)
bool dropMValue() override
Drops any measure values which exist in the geometry.
void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
A rectangle specified with double values.
bool operator==(const QgsAbstractGeometry &other) const override
QgsCurvePolygon & operator=(const QgsCurvePolygon &p)
virtual bool deleteVertex(QgsVertexId position)=0
Deletes a vertex within the geometry.
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
QgsAbstractGeometry & operator=(const QgsAbstractGeometry &geom)
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
static QPair< QgsWkbTypes::Type, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
virtual bool insertVertex(QgsVertexId position, const QgsPoint &vertex)=0
Inserts a vertex into the geometry.
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
virtual void addInteriorRing(QgsCurve *ring)
Adds an interior ring to the geometry (takes ownership)
QVector< QgsRingSequence > QgsCoordinateSequence
void swapXy() override
Swaps the x and y coordinates from the geometry.
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
QgsCurvePolygon * toCurveType() const override
Returns the geometry converted to the more generic curve type.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
Curve polygon geometry type.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle...
void clear() override
Clears the geometry, ie reset it to a null geometry.
void forceRHR()
Forces the geometry to respect the Right-Hand-Rule, in which the area that is bounded by the polygon ...
static endian_t endian()
Returns whether this machine uses big or little endian.
double area() const override
Returns the area of the geometry.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
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 Type dropM(Type type)
Drops the m dimension (if present) for a WKB type and returns the new type.
QgsWkbTypes::Type mWkbType
bool removeInteriorRing(int ringIndex)
Removes an interior ring from the polygon.
QVector< QgsCurve * > mInteriorRings
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
void removeInvalidRings()
Removes any interior rings which are not valid from the polygon.
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
~QgsCurvePolygon() override
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
Type
The WKB type describes the number of dimensions a geometry has.
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...
int childCount() const override
Returns number of child geometries (for geometries with child geometries) or child points (for geomet...
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
virtual double segmentLength(QgsVertexId startVertex) const =0
Returns the length of the segment of the geometry which begins at startVertex.
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
Utility class for identifying a unique vertex within a geometry.
int ringCount(int part=0) const override
Returns the number of rings of which this geometry is built.
int dimension() const override
Returns the inherent dimension of the geometry.
QgsCurvePolygon * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership...
QgsRectangle calculateBoundingBox() const override
Default calculator for the minimal bounding box for the geometry.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
QString geometryType() const override
Returns a unique string representing the geometry type.
QgsCurvePolygon * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid...
QgsPoint vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
Multi curve geometry collection.
double perimeter() const override
Returns the perimeter of the geometry.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
Abstract base class for curved geometry type.
virtual QgsPolygon * toPolygon(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a new polygon geometry corresponding to a segmentized approximation of the curve...
QgsAbstractGeometry * childGeometry(int index) const override
Returns pointer to child geometry (for geometries with child geometries - i.e.
Abstract base class for all geometries.
QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
QgsPoint vertexAt(QgsVertexId id) const override
Returns the point corresponding to a specified vertex id.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Counter-clockwise orientation.
Point geometry type, with support for z-dimension and m-values.
AxisOrder
Axis order for GML generation.
bool operator!=(const QgsAbstractGeometry &other) const override
double vertexAngle(QgsVertexId vertex) const override
Returns approximate rotation angle for a vertex.
static json pointsToJson(const QgsPointSequence &points, int precision)
Returns coordinates as json object.
int partCount() const override
Returns count of parts contained in the geometry.
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
QVector< QgsPoint > QgsPointSequence
void adjacentVertices(QgsVertexId vertex, QgsVertexId &previousVertex, QgsVertexId &nextVertex) const override
Returns the vertices adjacent to a specified vertex within a geometry.
QVector< QgsPointSequence > QgsRingSequence
static Type dropZ(Type type)
Drops the z dimension (if present) for a WKB type and returns the new type.
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
virtual bool moveVertex(QgsVertexId position, const QgsPoint &newPos)=0
Moves a vertex within the geometry.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
Line string geometry type, with support for z-dimension and m-values.
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
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...
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
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.
QgsAbstractGeometry * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Compound curve geometry type.
Circular string geometry type.
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 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...
QgsCurvePolygon * clone() const override
Clones the geometry by performing a deep copy.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
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.
int vertexCount(int part=0, int ring=0) const override
Returns the number of vertices of which this geometry is built.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
void setInteriorRings(const QVector< QgsCurve *> &rings)
Sets all interior rings (takes ownership)
std::unique_ptr< QgsCurve > mExteriorRing
QgsPolygon * surfaceToPolygon() const override
Gets a polygon representation of this surface.
static Type flatType(Type type)
Returns the flat type for a WKB type.
QgsWkbTypes::Type readHeader() const
readHeader
void removeInteriorRings(double minimumAllowedArea=-1)
Removes the interior rings from the polygon.
bool isEmpty() const override
Returns true if the geometry is empty.
virtual int numPoints() const =0
Returns the number of points in the curve.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'. Negativ values mean left a...
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
static double closestSegmentFromComponents(T &container, ComponentType ctype, const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon)
virtual QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const =0
Returns a GML3 representation of the geometry.