diff --git a/python/core/geometry/qgscircularstringv2.sip b/python/core/geometry/qgscircularstringv2.sip index 0bb0353980b..3003c5d9b03 100644 --- a/python/core/geometry/qgscircularstringv2.sip +++ b/python/core/geometry/qgscircularstringv2.sip @@ -60,6 +60,8 @@ class QgsCircularStringV2: public QgsCurveV2 @return rotation in radians, clockwise from north*/ double vertexAngle( const QgsVertexId& vertex ) const; + virtual QgsCircularStringV2* reversed() const /Factory/; + virtual bool addZValue( double zValue = 0 ); virtual bool addMValue( double mValue = 0 ); diff --git a/python/core/geometry/qgscompoundcurvev2.sip b/python/core/geometry/qgscompoundcurvev2.sip index a58d8fa3656..0bc62c01147 100644 --- a/python/core/geometry/qgscompoundcurvev2.sip +++ b/python/core/geometry/qgscompoundcurvev2.sip @@ -66,6 +66,8 @@ class QgsCompoundCurveV2: public QgsCurveV2 @return rotation in radians, clockwise from north*/ double vertexAngle( const QgsVertexId& vertex ) const; + virtual QgsCompoundCurveV2* reversed() const /Factory/; + virtual bool addZValue( double zValue = 0 ); virtual bool addMValue( double mValue = 0 ); }; diff --git a/python/core/geometry/qgscurvev2.sip b/python/core/geometry/qgscurvev2.sip index 7de886d780f..3227eb8381b 100644 --- a/python/core/geometry/qgscurvev2.sip +++ b/python/core/geometry/qgscurvev2.sip @@ -23,6 +23,11 @@ class QgsCurveV2: public QgsAbstractGeometryV2 virtual bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const; virtual bool pointAt( int i, QgsPointV2& vertex, QgsVertexId::VertexType& type ) const = 0; + /** Returns a reversed copy of the curve, where the direction of the curve has been flipped. + * @note added in QGIS 2.14 + */ + virtual QgsCurveV2* reversed() const = 0 /Factory/; + /** Returns a geometry without curves. Caller takes ownership*/ QgsAbstractGeometryV2* segmentize() const /Factory/; diff --git a/python/core/geometry/qgslinestringv2.sip b/python/core/geometry/qgslinestringv2.sip index aba911e5716..77cc3668908 100644 --- a/python/core/geometry/qgslinestringv2.sip +++ b/python/core/geometry/qgslinestringv2.sip @@ -1,3 +1,9 @@ +/** \ingroup core + * \class QgsLineStringV2 + * \brief Line string geometry type, with support for z-dimension and m-values. + * \note added in QGIS 2.10 + */ + class QgsLineStringV2: public QgsCurveV2 { %TypeHeaderCode @@ -8,13 +14,49 @@ class QgsLineStringV2: public QgsCurveV2 QgsLineStringV2(); ~QgsLineStringV2(); + /** Resets the line string to match the line string in a WKB geometry. + * @param type WKB type + * @param wkb WKB representation of line geometry + * @note not available in Python bindings + */ + //void fromWkbPoints( QgsWKBTypes::Type type, const QgsConstWkbPtr& wkb ); + + /** Returns the specified point from inside the line string. + * @param i index of point, starting at 0 for the first point + */ + QgsPointV2 pointN( int i ) const; + + /** Resets the line string to match the specified list of points. + * @param points new points for line string. If empty, line string will be cleared. + */ + void setPoints( const QList& points ); + + /** Appends the contents of another line string to the end of this line string. + * @param line line to append. Ownership is not transferred. + */ + void append( const QgsLineStringV2* line ); + + /** Adds a new vertex to the end of the line string. + * @param pt vertex to add + */ + void addVertex( const QgsPointV2& pt ); + + /** Closes the line string by appending the first point to the end of the line, if it is not already closed.*/ + void close(); + + virtual QgsLineStringV2* reversed() const /Factory/; + + /** Returns a QPolygonF representing the line string. + */ + QPolygonF asQPolygonF() const; + + //reimplemented methods + virtual QString geometryType() const; virtual int dimension() const; - virtual QgsLineStringV2* clone() const; - virtual void clear(); + virtual QgsLineStringV2* clone() const /Factory/; virtual bool fromWkb( const unsigned char* wkb ); - //void fromWkbPoints( QgsWKBTypes::Type type, const QgsConstWkbPtr& wkb ); virtual bool fromWkt( const QString& wkt ); int wkbSize() const; @@ -28,39 +70,30 @@ class QgsLineStringV2: public QgsCurveV2 virtual double length() const; virtual QgsPointV2 startPoint() const; virtual QgsPointV2 endPoint() const; - virtual QgsLineStringV2* curveToLine() const; + virtual QgsLineStringV2* curveToLine() const /Factory/; int numPoints() const; - QgsPointV2 pointN( int i ) const; void points( QList& pt ) const; - void setPoints( const QList& points ); - void append( const QgsLineStringV2* line ); - void draw( QPainter& p ) const; + void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ); void transform( const QTransform& t ); void addToPainterPath( QPainterPath& path ) const; void drawAsPolygon( QPainter& p ) const; - const QPolygonF& qPolygonF() const; - virtual bool insertVertex( const QgsVertexId& position, const QgsPointV2& vertex ); virtual bool moveVertex( const QgsVertexId& position, const QgsPointV2& newPos ); virtual bool deleteVertex( const QgsVertexId& position ); - void addVertex( const QgsPointV2& pt ); double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const; bool pointAt( int i, QgsPointV2& vertex, QgsVertexId::VertexType& type ) const; void sumUpArea( double& sum ) const; - - /** Returns approximate rotation angle for a vertex. Usually average angle between adjacent segments. - @param vertex the vertex id - @return rotation in radians, clockwise from north*/ double vertexAngle( const QgsVertexId& vertex ) const; virtual bool addZValue( double zValue = 0 ); virtual bool addMValue( double mValue = 0 ); + }; diff --git a/python/core/geometry/qgsmulticurvev2.sip b/python/core/geometry/qgsmulticurvev2.sip index 51defa1d991..59a78c6ebf6 100644 --- a/python/core/geometry/qgsmulticurvev2.sip +++ b/python/core/geometry/qgsmulticurvev2.sip @@ -22,4 +22,9 @@ class QgsMultiCurveV2: public QgsGeometryCollectionV2 virtual bool addGeometry( QgsAbstractGeometryV2* g ); /** Returns a geometry without curves. Caller takes ownership*/ QgsAbstractGeometryV2* segmentize() const /Factory/; + + /** Returns a copy of the multi curve, where each component curve has had its line direction reversed. + * @note added in QGIS 2.14 + */ + QgsMultiCurveV2* reversed() const /Factory/; }; diff --git a/python/core/geometry/qgspointv2.sip b/python/core/geometry/qgspointv2.sip index ec43799d64f..93182a92aab 100644 --- a/python/core/geometry/qgspointv2.sip +++ b/python/core/geometry/qgspointv2.sip @@ -117,7 +117,7 @@ class QgsPointV2: public QgsAbstractGeometryV2 //implementation of inherited methods virtual QString geometryType() const; virtual int dimension() const; - virtual QgsPointV2* clone() const; + virtual QgsPointV2* clone() const /Factory/; void clear(); virtual bool fromWkb( const unsigned char* wkb ); virtual bool fromWkt( const QString& wkt ); diff --git a/src/core/geometry/qgscircularstringv2.cpp b/src/core/geometry/qgscircularstringv2.cpp index 81ed491cdb3..ce2a5de3645 100644 --- a/src/core/geometry/qgscircularstringv2.cpp +++ b/src/core/geometry/qgscircularstringv2.cpp @@ -1009,6 +1009,22 @@ double QgsCircularStringV2::vertexAngle( const QgsVertexId& vId ) const return 0.0; } +QgsCircularStringV2* QgsCircularStringV2::reversed() const +{ + QgsCircularStringV2* copy = clone(); + std::reverse( copy->mX.begin(), copy->mX.end() ); + std::reverse( copy->mY.begin(), copy->mY.end() ); + if ( is3D() ) + { + std::reverse( copy->mZ.begin(), copy->mZ.end() ); + } + if ( isMeasure() ) + { + std::reverse( copy->mM.begin(), copy->mM.end() ); + } + return copy; +} + bool QgsCircularStringV2::addZValue( double zValue ) { if ( QgsWKBTypes::hasZ( mWkbType ) ) diff --git a/src/core/geometry/qgscircularstringv2.h b/src/core/geometry/qgscircularstringv2.h index 99de2a4d203..fe09f885b8e 100644 --- a/src/core/geometry/qgscircularstringv2.h +++ b/src/core/geometry/qgscircularstringv2.h @@ -125,6 +125,8 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2 @return rotation in radians, clockwise from north*/ double vertexAngle( const QgsVertexId& vertex ) const override; + virtual QgsCircularStringV2* reversed() const override; + virtual bool addZValue( double zValue = 0 ) override; virtual bool addMValue( double mValue = 0 ) override; diff --git a/src/core/geometry/qgscompoundcurvev2.cpp b/src/core/geometry/qgscompoundcurvev2.cpp index 056a05d9932..fb6b428b0d3 100644 --- a/src/core/geometry/qgscompoundcurvev2.cpp +++ b/src/core/geometry/qgscompoundcurvev2.cpp @@ -625,6 +625,17 @@ double QgsCompoundCurveV2::vertexAngle( const QgsVertexId& vertex ) const } } +QgsCompoundCurveV2* QgsCompoundCurveV2::reversed() const +{ + QgsCompoundCurveV2* clone = new QgsCompoundCurveV2(); + Q_FOREACH ( QgsCurveV2* curve, mCurves ) + { + QgsCurveV2* reversedCurve = curve->reversed(); + clone->addCurve( reversedCurve ); + } + return clone; +} + bool QgsCompoundCurveV2::addZValue( double zValue ) { if ( QgsWKBTypes::hasZ( mWkbType ) ) diff --git a/src/core/geometry/qgscompoundcurvev2.h b/src/core/geometry/qgscompoundcurvev2.h index e215608a935..81cb86b3530 100644 --- a/src/core/geometry/qgscompoundcurvev2.h +++ b/src/core/geometry/qgscompoundcurvev2.h @@ -109,6 +109,8 @@ class CORE_EXPORT QgsCompoundCurveV2: public QgsCurveV2 @return rotation in radians, clockwise from north*/ double vertexAngle( const QgsVertexId& vertex ) const override; + virtual QgsCompoundCurveV2* reversed() const override; + virtual bool addZValue( double zValue = 0 ) override; virtual bool addMValue( double mValue = 0 ) override; diff --git a/src/core/geometry/qgscurvev2.h b/src/core/geometry/qgscurvev2.h index 4639a5b81c4..63bec257ba7 100644 --- a/src/core/geometry/qgscurvev2.h +++ b/src/core/geometry/qgscurvev2.h @@ -87,6 +87,11 @@ class CORE_EXPORT QgsCurveV2: public QgsAbstractGeometryV2 */ virtual bool pointAt( int i, QgsPointV2& vertex, QgsVertexId::VertexType& type ) const = 0; + /** Returns a reversed copy of the curve, where the direction of the curve has been flipped. + * @note added in QGIS 2.14 + */ + virtual QgsCurveV2* reversed() const = 0; + QgsAbstractGeometryV2* segmentize() const override; virtual int vertexCount( int /*part*/ = 0, int /*ring*/ = 0 ) const override { return numPoints(); } diff --git a/src/core/geometry/qgslinestringv2.cpp b/src/core/geometry/qgslinestringv2.cpp index c9e673216d2..b7f3831ffd9 100644 --- a/src/core/geometry/qgslinestringv2.cpp +++ b/src/core/geometry/qgslinestringv2.cpp @@ -191,7 +191,7 @@ int QgsLineStringV2::numPoints() const QgsPointV2 QgsLineStringV2::pointN( int i ) const { - if ( mX.size() <= i ) + if ( i < 0 || i >= mX.size() ) { return QgsPointV2(); } @@ -240,7 +240,9 @@ void QgsLineStringV2::points( QList& pts ) const void QgsLineStringV2::setPoints( const QList& points ) { - if ( points.size() < 1 ) + mBoundingBox = QgsRectangle(); //set bounding box invalid + + if ( points.isEmpty() ) { mWkbType = QgsWKBTypes::Unknown; mX.clear(); @@ -307,11 +309,29 @@ void QgsLineStringV2::append( const QgsLineStringV2* line ) mY += line->mY; mZ += line->mZ; mM += line->mM; + + mBoundingBox = QgsRectangle(); //set bounding box invalid +} + +QgsLineStringV2* QgsLineStringV2::reversed() const +{ + QgsLineStringV2* copy = clone(); + std::reverse( copy->mX.begin(), copy->mX.end() ); + std::reverse( copy->mY.begin(), copy->mY.end() ); + if ( copy->is3D() ) + { + std::reverse( copy->mZ.begin(), copy->mZ.end() ); + } + if ( copy->isMeasure() ) + { + std::reverse( copy->mM.begin(), copy->mM.end() ); + } + return copy; } void QgsLineStringV2::draw( QPainter& p ) const { - p.drawPolyline( qPolygonF() ); + p.drawPolyline( asQPolygonF() ); } void QgsLineStringV2::addToPainterPath( QPainterPath& path ) const @@ -335,10 +355,10 @@ void QgsLineStringV2::addToPainterPath( QPainterPath& path ) const void QgsLineStringV2::drawAsPolygon( QPainter& p ) const { - p.drawPolygon( qPolygonF() ); + p.drawPolygon( asQPolygonF() ); } -QPolygonF QgsLineStringV2::qPolygonF() const +QPolygonF QgsLineStringV2::asQPolygonF() const { QPolygonF points; for ( int i = 0; i < mX.count(); ++i ) @@ -534,6 +554,7 @@ void QgsLineStringV2::importVerticesFromWkb( const QgsConstWkbPtr& wkb ) wkb >> mM[i]; } } + mBoundingBox = QgsRectangle(); //set bounding box invalid } void QgsLineStringV2::close() diff --git a/src/core/geometry/qgslinestringv2.h b/src/core/geometry/qgslinestringv2.h index c77d4d76884..8c98fcc5ce3 100644 --- a/src/core/geometry/qgslinestringv2.h +++ b/src/core/geometry/qgslinestringv2.h @@ -24,9 +24,8 @@ /** \ingroup core * \class QgsLineStringV2 - * \brief Line string geometry type. + * \brief Line string geometry type, with support for z-dimension and m-values. * \note added in QGIS 2.10 - * \note this API is not considered stable and may change for 2.12 */ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2 { @@ -34,13 +33,48 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2 QgsLineStringV2(); ~QgsLineStringV2(); + /** Resets the line string to match the line string in a WKB geometry. + * @param type WKB type + * @param wkb WKB representation of line geometry + * @note not available in Python bindings + */ + void fromWkbPoints( QgsWKBTypes::Type type, const QgsConstWkbPtr& wkb ); + + /** Returns the specified point from inside the line string. + * @param i index of point, starting at 0 for the first point + */ + QgsPointV2 pointN( int i ) const; + + /** Resets the line string to match the specified list of points. + * @param points new points for line string. If empty, line string will be cleared. + */ + void setPoints( const QList& points ); + + /** Appends the contents of another line string to the end of this line string. + * @param line line to append. Ownership is not transferred. + */ + void append( const QgsLineStringV2* line ); + + /** Adds a new vertex to the end of the line string. + * @param pt vertex to add + */ + void addVertex( const QgsPointV2& pt ); + + /** Closes the line string by appending the first point to the end of the line, if it is not already closed.*/ + void close(); + + /** Returns a QPolygonF representing the line string. + */ + QPolygonF asQPolygonF() const; + + //reimplemented methods + virtual QString geometryType() const override { return "LineString"; } virtual int dimension() const override { return 1; } virtual QgsLineStringV2* clone() const override; virtual void clear() override; virtual bool fromWkb( const unsigned char* wkb ) override; - void fromWkbPoints( QgsWKBTypes::Type type, const QgsConstWkbPtr& wkb ); virtual bool fromWkt( const QString& wkt ) override; int wkbSize() const override; @@ -57,42 +91,26 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2 virtual QgsLineStringV2* curveToLine() const override; int numPoints() const override; - QgsPointV2 pointN( int i ) const; void points( QList& pt ) const override; - void setPoints( const QList& points ); - void append( const QgsLineStringV2* line ); - void draw( QPainter& p ) const override; - /** Transforms the geometry using a coordinate transform - * @param ct coordinate transform - @param d transformation direction - */ void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) override; void transform( const QTransform& t ) override; void addToPainterPath( QPainterPath& path ) const override; void drawAsPolygon( QPainter& p ) const override; - QPolygonF qPolygonF() const; - virtual bool insertVertex( const QgsVertexId& position, const QgsPointV2& vertex ) override; virtual bool moveVertex( const QgsVertexId& position, const QgsPointV2& newPos ) override; virtual bool deleteVertex( const QgsVertexId& position ) override; - void addVertex( const QgsPointV2& pt ); + + virtual QgsLineStringV2* reversed() const override; double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const override; bool pointAt( int i, QgsPointV2& vertex, QgsVertexId::VertexType& type ) const override; void sumUpArea( double& sum ) const override; - - /** Appends first point if not already closed*/ - void close(); - - /** Returns approximate rotation angle for a vertex. Usually average angle between adjacent segments. - @param vertex the vertex id - @return rotation in radians, clockwise from north*/ double vertexAngle( const QgsVertexId& vertex ) const override; virtual bool addZValue( double zValue = 0 ) override; diff --git a/src/core/geometry/qgsmulticurvev2.cpp b/src/core/geometry/qgsmulticurvev2.cpp index 9c024c75623..3670612d13e 100644 --- a/src/core/geometry/qgsmulticurvev2.cpp +++ b/src/core/geometry/qgsmulticurvev2.cpp @@ -106,3 +106,16 @@ bool QgsMultiCurveV2::addGeometry( QgsAbstractGeometryV2* g ) setZMTypeFromSubGeometry( g, QgsWKBTypes::MultiCurve ); return QgsGeometryCollectionV2::addGeometry( g ); } + +QgsMultiCurveV2* QgsMultiCurveV2::reversed() const +{ + QgsMultiCurveV2* reversedMultiCurve = new QgsMultiCurveV2(); + Q_FOREACH ( const QgsAbstractGeometryV2 *geom, mGeometries ) + { + if ( dynamic_cast( geom ) ) + { + reversedMultiCurve->addGeometry( static_cast( geom )->reversed() ); + } + } + return reversedMultiCurve; +} diff --git a/src/core/geometry/qgsmulticurvev2.h b/src/core/geometry/qgsmulticurvev2.h index 56e3cc66c50..a668ce8304f 100644 --- a/src/core/geometry/qgsmulticurvev2.h +++ b/src/core/geometry/qgsmulticurvev2.h @@ -39,9 +39,13 @@ class CORE_EXPORT QgsMultiCurveV2: public QgsGeometryCollectionV2 QDomElement asGML3( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const override; QString asJSON( int precision = 17 ) const override; - /** Adds a geometry and takes ownership. Returns true in case of success*/ virtual bool addGeometry( QgsAbstractGeometryV2* g ) override; + + /** Returns a copy of the multi curve, where each component curve has had its line direction reversed. + * @note added in QGIS 2.14 + */ + QgsMultiCurveV2* reversed() const; }; #endif // QGSMULTICURVEV2_H diff --git a/src/core/geometry/qgsmultilinestringv2.h b/src/core/geometry/qgsmultilinestringv2.h index 803c11482f4..f3de42044a8 100644 --- a/src/core/geometry/qgsmultilinestringv2.h +++ b/src/core/geometry/qgsmultilinestringv2.h @@ -39,7 +39,6 @@ class CORE_EXPORT QgsMultiLineStringV2: public QgsMultiCurveV2 QDomElement asGML3( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const override; QString asJSON( int precision = 17 ) const override; - /** Adds a geometry and takes ownership. Returns true in case of success*/ virtual bool addGeometry( QgsAbstractGeometryV2* g ) override;