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 if ( parts.second.compare( QLatin1String(
"EMPTY" ), Qt::CaseInsensitive ) == 0 )
221 QString defaultChildWkbType = QStringLiteral(
"LineString%1%2" ).arg(
is3D() ? QStringLiteral(
"Z" ) : QString(),
isMeasure() ? QStringLiteral(
"M" ) : QString() );
224 for (
const QString &childWkt : blocks )
266 hasZ = hasZ || curve->is3D();
267 hasM = hasM || curve->isMeasure();
290 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
291 QVector<QByteArray> wkbForRings;
296 binarySize += wkb.length();
301 QByteArray wkb( curve->asWkb() );
302 binarySize += wkb.length();
307 wkbArray.resize( binarySize );
310 wkbPtr << static_cast<quint32>(
wkbType() );
311 wkbPtr << static_cast<quint32>( wkbForRings.count() );
312 for (
const QByteArray &wkb : qgis::as_const( wkbForRings ) )
324 wkt += QStringLiteral(
" EMPTY" );
327 wkt += QLatin1String(
" (" );
331 if ( qgsgeometry_cast<QgsLineString *>(
mExteriorRing.get() ) )
334 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
336 wkt += childWkt +
',';
340 QString childWkt = curve->asWkt( precision );
341 if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
344 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
346 wkt += childWkt +
',';
348 if ( wkt.endsWith(
',' ) )
360 QDomElement elemPolygon = doc.createElementNS( ns, QStringLiteral(
"Polygon" ) );
365 QDomElement elemOuterBoundaryIs = doc.createElementNS( ns, QStringLiteral(
"outerBoundaryIs" ) );
366 std::unique_ptr< QgsLineString > exteriorLineString(
exteriorRing()->curveToLine() );
367 QDomElement outerRing = exteriorLineString->asGml2( doc, precision, ns, axisOrder );
368 outerRing.toElement().setTagName( QStringLiteral(
"LinearRing" ) );
369 elemOuterBoundaryIs.appendChild( outerRing );
370 elemPolygon.appendChild( elemOuterBoundaryIs );
371 std::unique_ptr< QgsLineString > interiorLineString;
374 QDomElement elemInnerBoundaryIs = doc.createElementNS( ns, QStringLiteral(
"innerBoundaryIs" ) );
375 interiorLineString.reset(
interiorRing( i )->curveToLine() );
376 QDomElement innerRing = interiorLineString->asGml2( doc, precision, ns, axisOrder );
377 innerRing.toElement().setTagName( QStringLiteral(
"LinearRing" ) );
378 elemInnerBoundaryIs.appendChild( innerRing );
379 elemPolygon.appendChild( elemInnerBoundaryIs );
386 QDomElement elemCurvePolygon = doc.createElementNS( ns, QStringLiteral(
"Polygon" ) );
389 return elemCurvePolygon;
391 QDomElement elemExterior = doc.createElementNS( ns, QStringLiteral(
"exterior" ) );
393 if ( curveElem.tagName() == QLatin1String(
"LineString" ) )
395 curveElem.setTagName( QStringLiteral(
"LinearRing" ) );
397 elemExterior.appendChild( curveElem );
398 elemCurvePolygon.appendChild( elemExterior );
402 QDomElement elemInterior = doc.createElementNS( ns, QStringLiteral(
"interior" ) );
404 if ( innerRing.tagName() == QLatin1String(
"LineString" ) )
406 innerRing.setTagName( QStringLiteral(
"LinearRing" ) );
408 elemInterior.appendChild( innerRing );
409 elemCurvePolygon.appendChild( elemInterior );
411 return elemCurvePolygon;
416 json coordinates( json::array( ) );
419 std::unique_ptr< QgsLineString > exteriorLineString(
exteriorRing()->curveToLine() );
421 exteriorLineString->points( exteriorPts );
424 std::unique_ptr< QgsLineString > interiorLineString;
427 interiorLineString.reset(
interiorRing( i )->curveToLine() );
429 interiorLineString->points( interiorPts );
435 {
"type",
"Polygon" },
436 {
"coordinates", coordinates }
447 double totalArea = 0.0;
453 totalArea += std::fabs( area );
459 if ( ring->isRing() )
461 ring->sumUpArea( area );
462 totalArea -= std::fabs( area );
477 perimeter += ring->length();
484 std::unique_ptr< QgsPolygon > polygon(
new QgsPolygon() );
486 return polygon.release();
488 polygon->setExteriorRing(
exteriorRing()->curveToLine() );
489 QVector<QgsCurve *> interiors;
491 interiors.reserve( n );
492 for (
int i = 0; i < n; ++i )
496 polygon->setInteriorRings( interiors );
497 return polygon.release();
513 multiCurve->
reserve( nInteriorRings + 1 );
515 for (
int i = 0; i < nInteriorRings; ++i )
532 auto exterior = std::unique_ptr<QgsCurve> {
static_cast< QgsCurve *
>(
mExteriorRing->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) };
537 polygon->mExteriorRing = std::move( exterior );
545 QgsCurve *gridifiedInterior =
static_cast< QgsCurve *
>( interior->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) );
547 if ( !gridifiedInterior )
550 polygon->mInteriorRings.append( gridifiedInterior );
553 return polygon.release();
560 auto cleanRing = [epsilon, useZValues ](
QgsCurve * ring )->
bool 562 if ( ring->numPoints() <= 4 )
565 if ( ring->removeDuplicateNodes( epsilon, useZValues ) )
569 ring->pointAt( 0, startPoint, type );
583 result = result || cleanRing( ring );
590 std::unique_ptr< QgsPolygon > poly(
new QgsPolygon() );
593 return poly.release();
596 poly->setExteriorRing(
mExteriorRing->curveToLine( tolerance, toleranceType ) );
598 QVector<QgsCurve *> rings;
602 rings.push_back( ring->curveToLine( tolerance, toleranceType ) );
604 poly->setInteriorRings( rings );
605 return poly.release();
663 else if ( !ring->
is3D() )
688 for (
int ringIndex =
mInteriorRings.size() - 1; ringIndex >= 0; --ringIndex )
690 if ( minimumAllowedArea < 0 )
696 if ( area < minimumAllowedArea )
706 QVector<QgsCurve *> validRings;
710 if ( !curve->isRing() )
728 std::unique_ptr< QgsCurve > flipped(
mExteriorRing->reversed() );
732 QVector<QgsCurve *> validRings;
739 validRings << flipped;
766 ring->addToPainterPath( path );
781 curve->transform( ct, d, transformZ );
790 mExteriorRing->transform( t, zTranslate, zScale, mTranslate, mScale );
795 curve->transform( t, zTranslate, zScale, mTranslate, mScale );
814 ring->points( sequence.back().back() );
831 count += ring->nCoordinates();
842 if (
id.ring < 0 || id.ring >=
ringCount() )
857 if (
id.ring == i + 1 )
860 if ( partNumber == -1 )
862 return number + partNumber;
886 QVector<QgsCurve *> segmentList;
938 if ( vertex.
vertex == 0 && n < 3 )
942 else if ( vertex.
vertex == 0 )
950 if ( vertex.
vertex == n - 1 && n < 3 )
954 else if ( vertex.
vertex == n - 1 )
973 if ( vertex.
ring == 0 )
1001 else if ( vId.
vertex == n )
1018 bool success = ring->
moveVertex( vId, newPos );
1024 else if ( vId.
vertex == n - 1 )
1043 if ( vId.
ring == 0 )
1067 else if ( vId.
vertex == n - 1 )
1083 if ( ring->hasCurvedSegments() )
1093 return toPolygon( tolerance, toleranceType );
1150 curve->addZValue( zValue );
1167 curve->addMValue( mValue );
1183 curve->dropZValue();
1199 curve->dropMValue();
1228 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 planar, 2-dimensional 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 planar, 2-dimensional 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
void reserve(int size)
Attempts to allocate memory for at least size geometries.
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.