28 #include <QPainterPath> 43 auto result = qgis::make_unique< QgsCurvePolygon >();
45 return result.release();
50 return QStringLiteral(
"CurvePolygon" );
167 std::unique_ptr< QgsCurve > currentCurve;
168 for (
int i = 0; i < nRings; ++i )
171 wkbPtr -= 1 +
sizeof( int );
189 currentCurve->fromWkb( wkbPtr );
214 QString defaultChildWkbType = QStringLiteral(
"LineString%1%2" ).arg(
is3D() ? QStringLiteral(
"Z" ) : QString(),
isMeasure() ? QStringLiteral(
"M" ) : QString() );
217 for (
const QString &childWkt : blocks )
259 hasZ = hasZ || curve->is3D();
260 hasM = hasM || curve->isMeasure();
283 int binarySize =
sizeof( char ) +
sizeof( quint32 ) +
sizeof( quint32 );
284 QVector<QByteArray> wkbForRings;
289 binarySize += wkb.length();
294 QByteArray wkb( curve->asWkb() );
295 binarySize += wkb.length();
300 wkbArray.resize( binarySize );
303 wkbPtr << static_cast<quint32>(
wkbType() );
304 wkbPtr << static_cast<quint32>( wkbForRings.count() );
305 for (
const QByteArray &wkb : qgis::as_const( wkbForRings ) )
318 if ( qgsgeometry_cast<QgsLineString *>(
mExteriorRing.get() ) )
321 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
323 wkt += childWkt +
',';
327 QString childWkt = curve->asWkt( precision );
328 if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
331 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
333 wkt += childWkt +
',';
335 if ( wkt.endsWith(
',' ) )
346 QDomElement elemPolygon = doc.createElementNS( ns, QStringLiteral(
"Polygon" ) );
351 QDomElement elemOuterBoundaryIs = doc.createElementNS( ns, QStringLiteral(
"outerBoundaryIs" ) );
352 std::unique_ptr< QgsLineString > exteriorLineString(
exteriorRing()->curveToLine() );
353 QDomElement outerRing = exteriorLineString->asGml2( doc, precision, ns, axisOrder );
354 outerRing.toElement().setTagName( QStringLiteral(
"LinearRing" ) );
355 elemOuterBoundaryIs.appendChild( outerRing );
356 elemPolygon.appendChild( elemOuterBoundaryIs );
357 std::unique_ptr< QgsLineString > interiorLineString;
360 QDomElement elemInnerBoundaryIs = doc.createElementNS( ns, QStringLiteral(
"innerBoundaryIs" ) );
361 interiorLineString.reset(
interiorRing( i )->curveToLine() );
362 QDomElement innerRing = interiorLineString->asGml2( doc, precision, ns, axisOrder );
363 innerRing.toElement().setTagName( QStringLiteral(
"LinearRing" ) );
364 elemInnerBoundaryIs.appendChild( innerRing );
365 elemPolygon.appendChild( elemInnerBoundaryIs );
372 QDomElement elemCurvePolygon = doc.createElementNS( ns, QStringLiteral(
"Polygon" ) );
375 return elemCurvePolygon;
377 QDomElement elemExterior = doc.createElementNS( ns, QStringLiteral(
"exterior" ) );
379 if ( curveElem.tagName() == QLatin1String(
"LineString" ) )
381 curveElem.setTagName( QStringLiteral(
"LinearRing" ) );
383 elemExterior.appendChild( curveElem );
384 elemCurvePolygon.appendChild( elemExterior );
388 QDomElement elemInterior = doc.createElementNS( ns, QStringLiteral(
"interior" ) );
390 if ( innerRing.tagName() == QLatin1String(
"LineString" ) )
392 innerRing.setTagName( QStringLiteral(
"LinearRing" ) );
394 elemInterior.appendChild( innerRing );
395 elemCurvePolygon.appendChild( elemInterior );
397 return elemCurvePolygon;
403 QString json = QStringLiteral(
"{\"type\": \"Polygon\", \"coordinates\": [" );
405 std::unique_ptr< QgsLineString > exteriorLineString(
exteriorRing()->curveToLine() );
407 exteriorLineString->points( exteriorPts );
410 std::unique_ptr< QgsLineString > interiorLineString;
413 interiorLineString.reset(
interiorRing( i )->curveToLine() );
415 interiorLineString->points( interiorPts );
418 if ( json.endsWith( QLatin1String(
", " ) ) )
422 json += QLatin1String(
"] }" );
433 double totalArea = 0.0;
439 totalArea += std::fabs( area );
445 if ( ring->isRing() )
447 ring->sumUpArea( area );
448 totalArea -= std::fabs( area );
463 perimeter += ring->length();
470 std::unique_ptr< QgsPolygon > polygon(
new QgsPolygon() );
472 return polygon.release();
474 polygon->setExteriorRing(
exteriorRing()->curveToLine() );
475 QVector<QgsCurve *> interiors;
477 interiors.reserve( n );
478 for (
int i = 0; i < n; ++i )
482 polygon->setInteriorRings( interiors );
483 return polygon.release();
500 for (
int i = 0; i < nInteriorRings; ++i )
517 auto exterior = std::unique_ptr<QgsCurve> {
static_cast< QgsCurve *
>(
mExteriorRing->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) };
522 polygon->mExteriorRing = std::move( exterior );
530 QgsCurve *gridifiedInterior =
static_cast< QgsCurve *
>( interior->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) );
532 if ( !gridifiedInterior )
535 polygon->mInteriorRings.append( gridifiedInterior );
538 return polygon.release();
545 auto cleanRing = [epsilon, useZValues ](
QgsCurve * ring )->
bool 547 if ( ring->numPoints() <= 4 )
550 if ( ring->removeDuplicateNodes( epsilon, useZValues ) )
554 ring->pointAt( 0, startPoint, type );
568 result = result || cleanRing( ring );
575 std::unique_ptr< QgsPolygon > poly(
new QgsPolygon() );
578 return poly.release();
581 poly->setExteriorRing(
mExteriorRing->curveToLine( tolerance, toleranceType ) );
583 QVector<QgsCurve *> rings;
587 rings.push_back( ring->curveToLine( tolerance, toleranceType ) );
589 poly->setInteriorRings( rings );
590 return poly.release();
648 else if ( !ring->
is3D() )
673 for (
int ringIndex =
mInteriorRings.size() - 1; ringIndex >= 0; --ringIndex )
675 if ( minimumAllowedArea < 0 )
681 if ( area < minimumAllowedArea )
691 QVector<QgsCurve *> validRings;
695 if ( !curve->isRing() )
713 std::unique_ptr< QgsCurve > flipped(
mExteriorRing->reversed() );
717 QVector<QgsCurve *> validRings;
724 validRings << flipped;
751 ring->addToPainterPath( path );
766 curve->transform( ct, d, transformZ );
775 mExteriorRing->transform( t, zTranslate, zScale, mTranslate, mScale );
780 curve->transform( t, zTranslate, zScale, mTranslate, mScale );
799 ring->points( sequence.back().back() );
816 count += ring->nCoordinates();
827 if (
id.ring < 0 || id.ring >=
ringCount() )
842 if (
id.ring == i + 1 )
845 if ( partNumber == -1 )
847 return number + partNumber;
871 QVector<QgsCurve *> segmentList;
923 if ( vertex.
vertex == 0 && n < 3 )
927 else if ( vertex.
vertex == 0 )
935 if ( vertex.
vertex == n - 1 && n < 3 )
939 else if ( vertex.
vertex == n - 1 )
958 if ( vertex.
ring == 0 )
986 else if ( vId.
vertex == n )
1003 bool success = ring->
moveVertex( vId, newPos );
1009 else if ( vId.
vertex == n - 1 )
1028 if ( vId.
ring == 0 )
1052 else if ( vId.
vertex == n - 1 )
1068 if ( ring->hasCurvedSegments() )
1078 return toPolygon( tolerance, toleranceType );
1135 curve->addZValue( zValue );
1152 curve->addMValue( mValue );
1168 curve->dropZValue();
1184 curve->dropMValue();
1213 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.
static QString pointsToJSON(const QgsPointSequence &points, int precision)
Returns a geoJSON coordinates string.
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.
QString asJson(int precision=17) const override
Returns a GeoJSON representation 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.
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.
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.