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;
288 binarySize += wkb.length();
293 QByteArray wkb( curve->asWkb() );
294 binarySize += wkb.length();
299 wkbArray.resize( binarySize );
302 wkbPtr << static_cast<quint32>(
wkbType() );
303 wkbPtr << static_cast<quint32>( wkbForRings.count() );
304 for (
const QByteArray &wkb : qgis::as_const( wkbForRings ) )
317 if ( qgsgeometry_cast<QgsLineString *>(
mExteriorRing.get() ) )
320 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
322 wkt += childWkt +
',';
326 QString childWkt = curve->asWkt( precision );
327 if ( qgsgeometry_cast<const QgsLineString *>( curve ) )
330 childWkt = childWkt.mid( childWkt.indexOf(
'(' ) );
332 wkt += childWkt +
',';
334 if ( wkt.endsWith(
',' ) )
345 QDomElement elemPolygon = doc.createElementNS( ns, QStringLiteral(
"Polygon" ) );
350 QDomElement elemOuterBoundaryIs = doc.createElementNS( ns, QStringLiteral(
"outerBoundaryIs" ) );
351 std::unique_ptr< QgsLineString > exteriorLineString(
exteriorRing()->curveToLine() );
352 QDomElement outerRing = exteriorLineString->asGml2( doc, precision, ns );
353 outerRing.toElement().setTagName( QStringLiteral(
"LinearRing" ) );
354 elemOuterBoundaryIs.appendChild( outerRing );
355 elemPolygon.appendChild( elemOuterBoundaryIs );
356 std::unique_ptr< QgsLineString > interiorLineString;
359 QDomElement elemInnerBoundaryIs = doc.createElementNS( ns, QStringLiteral(
"innerBoundaryIs" ) );
360 interiorLineString.reset(
interiorRing( i )->curveToLine() );
361 QDomElement innerRing = interiorLineString->asGml2( doc, precision, ns );
362 innerRing.toElement().setTagName( QStringLiteral(
"LinearRing" ) );
363 elemInnerBoundaryIs.appendChild( innerRing );
364 elemPolygon.appendChild( elemInnerBoundaryIs );
371 QDomElement elemCurvePolygon = doc.createElementNS( ns, QStringLiteral(
"Polygon" ) );
374 return elemCurvePolygon;
376 QDomElement elemExterior = doc.createElementNS( ns, QStringLiteral(
"exterior" ) );
378 if ( curveElem.tagName() == QLatin1String(
"LineString" ) )
380 curveElem.setTagName( QStringLiteral(
"LinearRing" ) );
382 elemExterior.appendChild( curveElem );
383 elemCurvePolygon.appendChild( elemExterior );
387 QDomElement elemInterior = doc.createElementNS( ns, QStringLiteral(
"interior" ) );
389 if ( innerRing.tagName() == QLatin1String(
"LineString" ) )
391 innerRing.setTagName( QStringLiteral(
"LinearRing" ) );
393 elemInterior.appendChild( innerRing );
394 elemCurvePolygon.appendChild( elemInterior );
396 return elemCurvePolygon;
402 QString json = QStringLiteral(
"{\"type\": \"Polygon\", \"coordinates\": [" );
404 std::unique_ptr< QgsLineString > exteriorLineString(
exteriorRing()->curveToLine() );
406 exteriorLineString->points( exteriorPts );
409 std::unique_ptr< QgsLineString > interiorLineString;
412 interiorLineString.reset(
interiorRing( i )->curveToLine() );
414 interiorLineString->points( interiorPts );
417 if ( json.endsWith( QLatin1String(
", " ) ) )
421 json += QLatin1String(
"] }" );
432 double totalArea = 0.0;
438 totalArea += std::fabs( area );
444 if ( ring->isRing() )
446 ring->sumUpArea( area );
447 totalArea -= std::fabs( area );
462 perimeter += ring->length();
469 std::unique_ptr< QgsPolygon > polygon(
new QgsPolygon() );
471 return polygon.release();
473 polygon->setExteriorRing(
exteriorRing()->curveToLine() );
474 QVector<QgsCurve *> interiors;
476 interiors.reserve( n );
477 for (
int i = 0; i < n; ++i )
481 polygon->setInteriorRings( interiors );
482 return polygon.release();
499 for (
int i = 0; i < nInteriorRings; ++i )
516 auto exterior = std::unique_ptr<QgsCurve> {
static_cast< QgsCurve *
>(
mExteriorRing->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) ) };
521 polygon->mExteriorRing = std::move( exterior );
529 QgsCurve *gridifiedInterior =
static_cast< QgsCurve *
>( interior->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing ) );
531 if ( !gridifiedInterior )
534 polygon->mInteriorRings.append( gridifiedInterior );
537 return polygon.release();
544 auto cleanRing = [epsilon, useZValues ](
QgsCurve * ring )->
bool 546 if ( ring->numPoints() <= 4 )
549 if ( ring->removeDuplicateNodes( epsilon, useZValues ) )
553 ring->pointAt( 0, startPoint, type );
567 result = result || cleanRing( ring );
574 std::unique_ptr< QgsPolygon > poly(
new QgsPolygon() );
577 return poly.release();
580 poly->setExteriorRing(
mExteriorRing->curveToLine( tolerance, toleranceType ) );
582 QVector<QgsCurve *> rings;
585 rings.push_back( ring->curveToLine( tolerance, toleranceType ) );
587 poly->setInteriorRings( rings );
588 return poly.release();
665 else if ( !ring->
is3D() )
690 for (
int ringIndex =
mInteriorRings.size() - 1; ringIndex >= 0; --ringIndex )
692 if ( minimumAllowedArea < 0 )
698 if ( area < minimumAllowedArea )
722 ring->addToPainterPath( path );
737 curve->transform( ct, d, transformZ );
746 mExteriorRing->transform( t, zTranslate, zScale, mTranslate, mScale );
751 curve->transform( t, zTranslate, zScale, mTranslate, mScale );
770 ring->points( sequence.back().back() );
787 count += ring->nCoordinates();
798 if (
id.ring < 0 || id.ring >=
ringCount() )
813 if (
id.ring == i + 1 )
816 if ( partNumber == -1 )
818 return number + partNumber;
842 QVector<QgsCurve *> segmentList;
894 if ( vertex.
vertex == 0 && n < 3 )
898 else if ( vertex.
vertex == 0 )
906 if ( vertex.
vertex == n - 1 && n < 3 )
910 else if ( vertex.
vertex == n - 1 )
929 if ( vertex.
ring == 0 )
957 else if ( vId.
vertex == n )
974 bool success = ring->
moveVertex( vId, newPos );
980 else if ( vId.
vertex == n - 1 )
1023 else if ( vId.
vertex == n - 1 )
1039 if ( ring->hasCurvedSegments() )
1049 return toPolygon( tolerance, toleranceType );
1106 curve->addZValue( zValue );
1123 curve->addMValue( mValue );
1139 curve->dropZValue();
1155 curve->dropMValue();
bool isMeasure() const
Returns true if the geometry contains m values.
const QgsCurve * interiorRing(int i) const
QByteArray asWkb() const override
Returns a WKB representation of the geometry.
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 closestSegment(const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf=nullptr, double epsilon=4 *DBL_EPSILON) const override
Searches for the closest segment of the geometry to a given point.
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
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.
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.
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.
bool moveVertex(QgsVertexId position, const QgsPoint &newPos) override
Moves a vertex within the geometry.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
int numInteriorRings() const
~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.
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.
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.
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML3 representation of the geometry.
QgsCoordinateSequence coordinateSequence() const override
Retrieves the sequence of geometries, rings and nodes.
const QgsCurve * exteriorRing() const
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.
Point geometry type, with support for z-dimension and m-values.
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.
bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const override
Returns next vertex id and coordinates.
QgsAbstractGeometry * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml") const =0
Returns a GML3 representation of the geometry.
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Compound curve geometry type.
Circular string geometry type.
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.
int vertexCount(int part=0, int ring=0) const override
Returns the number of vertices of which this geometry is built.
void setInteriorRings(const QVector< QgsCurve *> &rings)
Sets all interior rings (takes ownership)
std::unique_ptr< QgsCurve > mExteriorRing
QgsPolygon * surfaceToPolygon() const override
Get a polygon representation of this surface.
static Type flatType(Type type)
Returns the flat type for a WKB type.
bool removeDuplicateNodes(double epsilon=4 *DBL_EPSILON, bool useZValues=false) override
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
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...
void transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
static double closestSegmentFromComponents(T &container, ComponentType ctype, const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon)