1 /*************************************************************************** 2 qgscompoundcurve.h 3 --------------------- 4 begin : September 2014 5 copyright : (C) 2014 by Marco Hugentobler 6 email : marco at sourcepole dot ch 7 ***************************************************************************/ 8 9 /*************************************************************************** 10 * * 11 * This program is free software; you can redistribute it and/or modify * 12 * it under the terms of the GNU General Public License as published by * 13 * the Free Software Foundation; either version 2 of the License, or * 14 * (at your option) any later version. * 15 * * 16 ***************************************************************************/ 17 18 #ifndef QGSCOMPOUNDCURVE_H 19 #define QGSCOMPOUNDCURVE_H 20 21 #include "qgis_core.h" 22 #include "qgis_sip.h" 23 #include "qgscurve.h" 24 25 /** 26 * \ingroup core 27 * \class QgsCompoundCurve 28 * \brief Compound curve geometry type 29 * \since QGIS 2.10 30 */ 31 class CORE_EXPORT QgsCompoundCurve: public QgsCurve 32 { 33 public: 34 QgsCompoundCurve(); 35 QgsCompoundCurve( const QgsCompoundCurve &curve ); 36 QgsCompoundCurve &operator=( const QgsCompoundCurve &curve ); 37 ~QgsCompoundCurve() override; 38 39 bool equals( const QgsCurve &other ) const override; 40 41 QString geometryType() const override SIP_HOLDGIL; 42 int dimension() const override SIP_HOLDGIL; 43 QgsCompoundCurve *clone() const override SIP_FACTORY; 44 void clear() override; 45 46 bool fromWkb( QgsConstWkbPtr &wkb ) override; 47 bool fromWkt( const QString &wkt ) override; 48 49 int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override; 50 QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override; 51 QString asWkt( int precision = 17 ) const override; 52 QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override; 53 QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override; 54 json asJsonObject( int precision = 17 ) const override SIP_SKIP; 55 56 //curve interface 57 double length() const override SIP_HOLDGIL; 58 QgsPoint startPoint() const override SIP_HOLDGIL; 59 QgsPoint endPoint() const override SIP_HOLDGIL; 60 void points( QgsPointSequence &pts SIP_OUT ) const override; 61 int numPoints() const override SIP_HOLDGIL; 62 bool isEmpty() const override SIP_HOLDGIL; 63 bool isValid( QString &error SIP_OUT, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const override; 64 int indexOf( const QgsPoint &point ) const final; 65 66 /** 67 * Returns a new line string geometry corresponding to a segmentized approximation 68 * of the curve. 69 * \param tolerance segmentation tolerance 70 * \param toleranceType maximum segmentation angle or maximum difference between approximation and curve 71 */ 72 QgsLineString *curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY; 73 74 QgsCompoundCurve *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const override SIP_FACTORY; 75 bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override; 76 bool boundingBoxIntersects( const QgsRectangle &rectangle ) const override SIP_HOLDGIL; 77 const QgsAbstractGeometry *simplifiedTypeRef() const override SIP_HOLDGIL; 78 79 /** 80 * Returns the number of curves in the geometry. 81 */ nCurves()82 int nCurves() const SIP_HOLDGIL { return mCurves.size(); } 83 84 /** 85 * Returns the curve at the specified index. 86 */ 87 const QgsCurve *curveAt( int i ) const SIP_HOLDGIL; 88 89 /** 90 * Adds a curve to the geometry (takes ownership). 91 * 92 * Since QGIS 3.20, if \a extendPrevious is TRUE, then adding a LineString when the last existing curve 93 * in the compound curve is also a LineString will cause the existing linestring to be 94 * extended with the newly added LineString vertices instead of appending a whole new 95 * LineString curve to the compound curve. This can result in simplified compound curves with lesser number 96 * of component curves while still being topologically identical to the desired result. 97 */ 98 void addCurve( QgsCurve *c SIP_TRANSFER, bool extendPrevious = false ); 99 100 /** 101 * Removes a curve from the geometry. 102 * \param i index of curve to remove 103 */ 104 void removeCurve( int i ); 105 106 /** 107 * Adds a vertex to the end of the geometry. 108 */ 109 void addVertex( const QgsPoint &pt ); 110 111 /** 112 * Condenses the curves in this geometry by combining adjacent linestrings a to a single continuous linestring, 113 * and combining adjacent circularstrings to a single continuous circularstring. 114 * 115 * \since QGIS 3.20 116 */ 117 void condenseCurves(); 118 119 /** 120 * Converts the vertex at the given position from/to circular 121 * \returns FALSE if atVertex does not correspond to a valid vertex 122 * on this geometry (including if this geometry is a Point), 123 * or if the specified vertex can't be converted (e.g. start/end points). 124 * 125 * \since QGIS 3.20 126 */ 127 bool toggleCircularAtVertex( QgsVertexId position ); 128 129 void draw( QPainter &p ) const override; 130 void transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection d = Qgis::TransformDirection::Forward, bool transformZ = false ) override SIP_THROW( QgsCsException ); 131 void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override; 132 void addToPainterPath( QPainterPath &path ) const override; 133 void drawAsPolygon( QPainter &p ) const override; 134 bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override; 135 bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override; 136 bool deleteVertex( QgsVertexId position ) override; 137 double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT, QgsVertexId &vertexAfter SIP_OUT, int *leftOf SIP_OUT = nullptr, double epsilon = 4 * std::numeric_limits<double>::epsilon() ) const override; 138 bool pointAt( int node, QgsPoint &point, Qgis::VertexType &type ) const override; 139 void sumUpArea( double &sum SIP_OUT ) const override; 140 141 //! Appends first point if not already closed. 142 void close(); 143 144 bool hasCurvedSegments() const override; 145 double vertexAngle( QgsVertexId vertex ) const override; 146 double segmentLength( QgsVertexId startVertex ) const override; 147 QgsCompoundCurve *reversed() const override SIP_FACTORY; 148 QgsPoint *interpolatePoint( double distance ) const override SIP_FACTORY; 149 QgsCompoundCurve *curveSubstring( double startDistance, double endDistance ) const override SIP_FACTORY; 150 151 bool addZValue( double zValue = 0 ) override; 152 bool addMValue( double mValue = 0 ) override; 153 154 bool dropZValue() override; 155 bool dropMValue() override; 156 void swapXy() override; 157 158 double xAt( int index ) const override SIP_HOLDGIL; 159 double yAt( int index ) const override SIP_HOLDGIL; 160 161 bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) override; 162 void scroll( int firstVertexIndex ) final; 163 164 #ifndef SIP_RUN 165 void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override; 166 void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override; 167 std::tuple< std::unique_ptr< QgsCurve >, std::unique_ptr< QgsCurve > > splitCurveAtVertex( int index ) const final; 168 169 /** 170 * Cast the \a geom to a QgsCompoundCurve. 171 * Should be used by qgsgeometry_cast<QgsCompoundCurve *>( geometry ). 172 * 173 * \note Not available in Python. Objects will be automatically be converted to the appropriate target type. 174 * \since QGIS 3.0 175 */ cast(const QgsAbstractGeometry * geom)176 inline static const QgsCompoundCurve *cast( const QgsAbstractGeometry *geom ) 177 { 178 if ( geom && QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::CompoundCurve ) 179 return static_cast<const QgsCompoundCurve *>( geom ); 180 return nullptr; 181 } 182 #endif 183 184 QgsCompoundCurve *createEmptyWithSameType() const override SIP_FACTORY; 185 186 #ifdef SIP_RUN 187 SIP_PYOBJECT __repr__(); 188 % MethodCode 189 QString wkt = sipCpp->asWkt(); 190 if ( wkt.length() > 1000 ) 191 wkt = wkt.left( 1000 ) + QStringLiteral( "..." ); 192 QString str = QStringLiteral( "<QgsCompoundCurve: %1>" ).arg( wkt ); 193 sipRes = PyUnicode_FromString( str.toUtf8().constData() ); 194 % End 195 #endif 196 197 protected: 198 199 int compareToSameClass( const QgsAbstractGeometry *other ) const final; 200 QgsRectangle calculateBoundingBox() const override; 201 202 private: 203 QVector< QgsCurve * > mCurves; 204 205 /** 206 * Turns a vertex id for the compound curve into one or more ids for the subcurves 207 * \returns the index of the subcurve or -1 in case of error 208 */ 209 QVector< QPair<int, QgsVertexId> > curveVertexId( QgsVertexId id ) const; 210 211 }; 212 213 // clazy:excludeall=qstring-allocations 214 215 #endif // QGSCOMPOUNDCURVE_H 216