43 changes: 42 additions & 1 deletion src/core/geometry/qgscurvev2.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,71 @@
class QgsLineStringV2;
class QPainterPath;

/**\ingroup core
* \class QgsCurveV2
* \brief Abstract base class for curved geometry type
* \note added in QGIS 2.10
*/
class CORE_EXPORT QgsCurveV2: public QgsAbstractGeometryV2
{
public:
QgsCurveV2();
virtual ~QgsCurveV2();

/** Returns the starting point of the curve.
* @see endPoint
*/
virtual QgsPointV2 startPoint() const = 0;

/** Returns the end point of the curve.
* @see startPoint
*/
virtual QgsPointV2 endPoint() const = 0;

/** Returns true if the curve is closed.
*/
virtual bool isClosed() const;

/** Returns true if the curve is a ring.
*/
virtual bool isRing() const;

/** Returns a new line string geometry corresponding to a segmentized approximation
* of the curve.
*/
virtual QgsLineStringV2* curveToLine() const = 0;

/** Adds a curve to a painter path.
*/
virtual void addToPainterPath( QPainterPath& path ) const = 0;

/** Draws the curve as a polygon on the specifed QPainter.
* @param p destination QPainter
*/
virtual void drawAsPolygon( QPainter& p ) const = 0;

/** Returns a list of points within the curve.
*/
virtual void points( QList<QgsPointV2>& pt ) const = 0;

/** Returns the number of points in the curve.
*/
virtual int numPoints() const = 0;

virtual double area() const override;

/** Calculates the area of the curve. Derived classes should override this
* to return the correct area of the curve.
*/
virtual void sumUpArea( double& sum ) const = 0;

virtual void coordinateSequence( QList< QList< QList< QgsPointV2 > > >& coord ) const override;
virtual bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const override;

/** Returns the point and vertex id of a point within the curve.
*/
virtual bool pointAt( int i, QgsPointV2& vertex, QgsVertexId::VertexType& type ) const = 0;

/**Returns a geometry without curves. Caller takes ownership*/
QgsAbstractGeometryV2* segmentize() const override;
};

Expand Down
32 changes: 29 additions & 3 deletions src/core/geometry/qgsgeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ bool QgsGeometry::moveVertex( double x, double y, int atVertex )
return false;
}

detach( true );

removeWkbGeos();
return d->geometry->moveVertex( id, QgsPointV2( x, y ) );
}
Expand All @@ -400,6 +402,8 @@ bool QgsGeometry::moveVertex( const QgsPointV2& p, int atVertex )
return false;
}

detach( true );

removeWkbGeos();
return d->geometry->moveVertex( id, p );
}
Expand All @@ -417,6 +421,8 @@ bool QgsGeometry::deleteVertex( int atVertex )
return false;
}

detach( true );

removeWkbGeos();
return d->geometry->deleteVertex( id );
}
Expand Down Expand Up @@ -507,6 +513,8 @@ double QgsGeometry::closestSegmentWithContext(

int QgsGeometry::addRing( const QList<QgsPoint>& ring )
{
detach( true );

removeWkbGeos();
QgsLineStringV2* ringLine = new QgsLineStringV2();
QList< QgsPointV2 > ringPoints;
Expand All @@ -522,6 +530,8 @@ int QgsGeometry::addRing( QgsCurveV2* ring )
return 1;
}

detach( true );

removeWkbGeos();
return QgsGeometryEditUtils::addRing( d->geometry, ring );
}
Expand All @@ -534,6 +544,8 @@ int QgsGeometry::addPart( const QList<QgsPoint> &points, QGis::GeometryType geom
return 2;
}

detach( true );

if ( !isMultipart() )
{
convertToMultiType();
Expand All @@ -558,6 +570,8 @@ int QgsGeometry::addPart( const QList<QgsPoint> &points, QGis::GeometryType geom

int QgsGeometry::addPart( QgsCurveV2* part )
{
detach( true );

removeWkbGeos();
return QgsGeometryEditUtils::addPart( d->geometry, part );
}
Expand All @@ -569,6 +583,8 @@ int QgsGeometry::addPart( const QgsGeometry *newPart )
return 1;
}

detach( true );

QgsAbstractGeometryV2* g = d->geometry->clone();
QgsCurveV2* curve = dynamic_cast<QgsCurveV2*>( g );
if ( !curve )
Expand All @@ -585,6 +601,8 @@ int QgsGeometry::addPart( GEOSGeometry *newPart )
return 1;
}

detach( true );

QgsAbstractGeometryV2* geom = QgsGeos::fromGeos( newPart );
removeWkbGeos();
return QgsGeometryEditUtils::addPart( d->geometry, geom );
Expand All @@ -597,6 +615,8 @@ int QgsGeometry::translate( double dx, double dy )
return 1;
}

detach( true );

d->geometry->transform( QTransform::fromTranslate( dx, dy ) );
removeWkbGeos();
return 0;
Expand All @@ -609,6 +629,8 @@ int QgsGeometry::rotate( double rotation, const QgsPoint& center )
return 1;
}

detach( true );

QTransform t = QTransform::fromTranslate( center.x(), center.y() );
t.rotate( -rotation );
t.translate( -center.x(), -center.y() );
Expand Down Expand Up @@ -637,7 +659,6 @@ int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeome
if ( result == 0 )
{
detach( false );
delete d->geometry;
d->geometry = newGeoms.at( 0 );

newGeometries.clear();
Expand Down Expand Up @@ -875,6 +896,7 @@ bool QgsGeometry::convertToMultiType()
}

multiGeom->addGeometry( d->geometry );
detach( false );
d->geometry = multiGeom;
removeWkbGeos();
return true;
Expand Down Expand Up @@ -1254,7 +1276,7 @@ QgsGeometry* QgsGeometry::convexHull() const
return new QgsGeometry( cHull );
}

QgsGeometry* QgsGeometry::interpolate( double distance )
QgsGeometry* QgsGeometry::interpolate( double distance ) const
{
if ( !d || !d->geometry )
{
Expand Down Expand Up @@ -1400,6 +1422,8 @@ bool QgsGeometry::deleteRing( int ringNum, int partNum )
return false;
}

detach( true );

return QgsGeometryEditUtils::deleteRing( d->geometry, ringNum, partNum );
}

Expand All @@ -1410,6 +1434,8 @@ bool QgsGeometry::deletePart( int partNum )
return false;
}

detach( true );

return QgsGeometryEditUtils::deletePart( d->geometry, partNum );
}

Expand All @@ -1423,7 +1449,7 @@ int QgsGeometry::avoidIntersections( QMap<QgsVectorLayer*, QSet< QgsFeatureId >
QgsAbstractGeometryV2* diffGeom = QgsGeometryEditUtils::avoidIntersections( *( d->geometry ), ignoreFeatures );
if ( diffGeom )
{
delete d->geometry;
detach( false );
d->geometry = diffGeom;
removeWkbGeos();
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/geometry/qgsgeometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ class CORE_EXPORT QgsGeometry
/* Return interpolated point on line at distance
* @note added in 1.9
*/
QgsGeometry* interpolate( double distance );
QgsGeometry* interpolate( double distance ) const;

/** Returns a geometry representing the points shared by this geometry and other. */
QgsGeometry* intersection( const QgsGeometry* geometry ) const;
Expand Down
25 changes: 23 additions & 2 deletions src/core/geometry/qgsgeometrycollectionv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ email : marco.hugentobler at sourcepole dot com
#include "qgsabstractgeometryv2.h"
#include <QVector>

/**\ingroup core
* \class QgsGeometryCollectionV2
* \brief Geometry collection
* \note added in QGIS 2.10
*/
class CORE_EXPORT QgsGeometryCollectionV2: public QgsAbstractGeometryV2
{
public:
Expand All @@ -29,17 +34,32 @@ class CORE_EXPORT QgsGeometryCollectionV2: public QgsAbstractGeometryV2

virtual QgsAbstractGeometryV2* clone() const override;

/** Returns the number of geometries within the collection.
*/
int numGeometries() const;

/** Returns a const reference to a geometry from within the collection.
* @param n index of geometry to return
*/
const QgsAbstractGeometryV2* geometryN( int n ) const;

/** Returns a geometry from within the collection.
* @param n index of geometry to return
*/
QgsAbstractGeometryV2* geometryN( int n );

//methods inherited from QgsAbstractGeometry
virtual int dimension() const override;
virtual QString geometryType() const override { return "GeometryCollection"; }
virtual void clear() override;

/**Adds a geometry and takes ownership. Returns true in case of success*/
/**Adds a geometry and takes ownership. Returns true in case of success.*/
virtual bool addGeometry( QgsAbstractGeometryV2* g );

/** Removes a geometry from the collection.
* @param nr index of geometry to remove
* @returns true if removal was successful.
*/
virtual bool removeGeometry( int nr );

virtual void transform( const QgsCoordinateTransform& ct ) override;
Expand Down Expand Up @@ -74,8 +94,9 @@ class CORE_EXPORT QgsGeometryCollectionV2: public QgsAbstractGeometryV2

protected:
QVector< QgsAbstractGeometryV2* > mGeometries;
void removeGeometries();

/** Reads a collection from a WKT string.
*/
bool fromCollectionWkt( const QString &wkt, const QList<QgsAbstractGeometryV2*>& subtypes, const QString& defaultChildWkbType = QString() );

};
Expand Down
18 changes: 17 additions & 1 deletion src/core/geometry/qgsgeometryeditutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ class QgsVectorLayer;
#include "qgsfeature.h"
#include <QMap>

/**Convenience functions for geometry editing*/
/**\ingroup core
* \class QgsGeometryEditUtils
* \brief Convenience functions for geometry editing
* \note added in QGIS 2.10
*/
class QgsGeometryEditUtils
{
public:
Expand All @@ -38,12 +42,24 @@ class QgsGeometryEditUtils
not disjoint with existing polygons of the feature*/
static int addPart( QgsAbstractGeometryV2* geom, QgsAbstractGeometryV2* part );

/** Deletes a ring from a geometry.
* @returns true if delete was successful
*/
static bool deleteRing( QgsAbstractGeometryV2* geom, int ringNum, int partNum = 0 );

/** Deletes a part from a geometry.
* @returns true if delete was successful
*/
static bool deletePart( QgsAbstractGeometryV2* geom, int partNum );

/** Alters a geometry so that it avoids intersections with features from all open vector layers.
* @param geom geometry to alter
* @param ignoreFeatures map of layer to feature id of features to ignore
*/
static QgsAbstractGeometryV2* avoidIntersections( const QgsAbstractGeometryV2& geom, QMap<QgsVectorLayer*, QSet<QgsFeatureId> > ignoreFeatures = ( QMap<QgsVectorLayer*, QSet<QgsFeatureId> >() ) );

/** Creates and returns a new geometry engine
*/
static QgsGeometryEngine* createGeometryEngine( const QgsAbstractGeometryV2* geometry );
};

Expand Down
11 changes: 11 additions & 0 deletions src/core/geometry/qgsgeometryimport.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,22 @@ typedef QVector<QgsPoint> QgsMultiPoint;
typedef QVector<QgsPolyline> QgsMultiPolyline;
typedef QVector<QgsPolygon> QgsMultiPolygon;

/**\ingroup core
* \class QgsGeometryImport
* \brief Contains geometry importing routines.
* \note added in QGIS 2.10
*/
class CORE_EXPORT QgsGeometryImport
{
public:
/** Construct geometry from a WKB string.
*/
static QgsAbstractGeometryV2* geomFromWkb( const unsigned char* wkb );

/** Construct geometry from a WKT string.
*/
static QgsAbstractGeometryV2* geomFromWkt( const QString& text );

/** construct geometry from a point */
static QgsAbstractGeometryV2* fromPoint( const QgsPoint& point );
/** construct geometry from a multipoint */
Expand Down
27 changes: 22 additions & 5 deletions src/core/geometry/qgsgeometryutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,36 @@ email : marco.hugentobler at sourcepole dot com
#include "qgspointv2.h"
#include <limits>

/**\ingroup core
* \class QgsGeometryUtils
* \brief Contains various geometry utility functions.
* \note added in QGIS 2.10
*/
class CORE_EXPORT QgsGeometryUtils
{
public:

/** Returns the closest vertex to a geometry for a specified point
*/
static QgsPointV2 closestVertex( const QgsAbstractGeometryV2& geom, const QgsPointV2& pt, QgsVertexId& id );

/** Returns vertices adjacent to a specified vertex within a geometry.
*/
static void adjacentVertices( const QgsAbstractGeometryV2& geom, const QgsVertexId& atVertex, QgsVertexId& beforeVertex, QgsVertexId& afterVertex );

/** Returns the squared 2D distance between two points.
*/
static double sqrDistance2D( const QgsPointV2& pt1, const QgsPointV2& pt2 );

/** Returns the squared distance between a point and a line.
*/
static double sqrDistToLine( double ptX, double ptY, double x1, double y1, double x2, double y2, double& minDistX, double& minDistY, double epsilon );

/**Returns < 0 if point(x/y) is left of the line x1,y1 -> x2,y2*/
static double leftOfLine( double x, double y, double x1, double y1, double x2, double y2 );

/** Returns a point a specified distance toward a second point.
*/
static QgsPointV2 pointOnLineWithDistance( const QgsPointV2& startPoint, const QgsPointV2& directionPoint, double distance );

/**Returns the counter clockwise angle between a line with components dx, dy and the line with dx > 0 and dy = 0*/
Expand Down Expand Up @@ -59,15 +76,15 @@ class CORE_EXPORT QgsGeometryUtils
static bool segmentMidPoint( const QgsPointV2& p1, const QgsPointV2& p2, QgsPointV2& result, double radius, const QgsPointV2& mousePos );

static QList<QgsPointV2> pointsFromWKT( const QString& wktCoordinateList, bool is3D, bool isMeasure );
// Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }
/** Returns a LinearRing { uint32 numPoints; Point points[numPoints]; } */
static void pointsToWKB( QgsWkbPtr &wkb, const QList<QgsPointV2>& points, bool is3D, bool isMeasure );
// Returns a WKT coordinate list
/** Returns a WKT coordinate list */
static QString pointsToWKT( const QList<QgsPointV2>& points, int precision, bool is3D, bool isMeasure );
// Returns a gml::coordinates DOM element
/** Returns a gml::coordinates DOM element */
static QDomElement pointsToGML2( const QList<QgsPointV2>& points, QDomDocument &doc, int precision, const QString& ns );
// Returns a gml::posList DOM element
/** Returns a gml::posList DOM element */
static QDomElement pointsToGML3( const QList<QgsPointV2>& points, QDomDocument &doc, int precision, const QString& ns, bool is3D );
// Returns a geoJSON coordinates string
/** Returns a geoJSON coordinates string */
static QString pointsToJSON( const QList<QgsPointV2>& points, int precision );

// "TYPE (contents)" -> Pair(wkbType, "contents")
Expand Down