Skip to content
Permalink
Browse files

Improvements to QgsAbstractGeometry::snappedToGrid

- Fix loss of coordinates when not rounding a particular dimension
- Don't segmentize curved geometries
- Add extra unit tests
- Make createEmptyWithSameType() protected and skip from Python bindings.
This method relies on low-level manipulation of the returned geometry
which we do not want to expose as public/fixed API
  • Loading branch information
nyalldawson committed Oct 27, 2017
1 parent 3f5b11b commit c67e39812de0290a94c45a7410ef12b89f002553
Showing with 470 additions and 301 deletions.
  1. +5 −18 python/core/geometry/qgsabstractgeometry.sip
  2. +25 −6 python/core/geometry/qgscircularstring.sip
  3. +28 −6 python/core/geometry/qgscompoundcurve.sip
  4. +1 −2 python/core/geometry/qgscurve.sip
  5. +8 −3 python/core/geometry/qgscurvepolygon.sip
  6. +6 −3 python/core/geometry/qgsgeometrycollection.sip
  7. +4 −3 python/core/geometry/qgslinestring.sip
  8. +6 −1 python/core/geometry/qgsmulticurve.sip
  9. +2 −1 python/core/geometry/qgsmultilinestring.sip
  10. +2 −1 python/core/geometry/qgsmultipoint.sip
  11. +2 −1 python/core/geometry/qgsmultipolygon.sip
  12. +6 −1 python/core/geometry/qgsmultisurface.sip
  13. +7 −3 python/core/geometry/qgspoint.sip
  14. +8 −1 python/core/geometry/qgspolygon.sip
  15. +0 −3 python/core/geometry/qgssurface.sip
  16. +6 −1 python/core/geometry/qgstriangle.sip
  17. +19 −17 src/core/geometry/qgsabstractgeometry.h
  18. +15 −2 src/core/geometry/qgscircularstring.cpp
  19. +25 −30 src/core/geometry/qgscircularstring.h
  20. +21 −2 src/core/geometry/qgscompoundcurve.cpp
  21. +27 −31 src/core/geometry/qgscompoundcurve.h
  22. +91 −7 src/core/geometry/qgscurve.cpp
  23. +11 −3 src/core/geometry/qgscurve.h
  24. +8 −17 src/core/geometry/qgscurvepolygon.cpp
  25. +4 −5 src/core/geometry/qgscurvepolygon.h
  26. +4 −5 src/core/geometry/qgsgeometrycollection.cpp
  27. +4 −5 src/core/geometry/qgsgeometrycollection.h
  28. +8 −73 src/core/geometry/qgslinestring.cpp
  29. +2 −4 src/core/geometry/qgslinestring.h
  30. +2 −2 src/core/geometry/qgsmulticurve.cpp
  31. +4 −1 src/core/geometry/qgsmulticurve.h
  32. +2 −2 src/core/geometry/qgsmultilinestring.cpp
  33. +1 −2 src/core/geometry/qgsmultilinestring.h
  34. +2 −2 src/core/geometry/qgsmultipoint.cpp
  35. +1 −2 src/core/geometry/qgsmultipoint.h
  36. +2 −2 src/core/geometry/qgsmultipolygon.cpp
  37. +1 −2 src/core/geometry/qgsmultipolygon.h
  38. +2 −2 src/core/geometry/qgsmultisurface.cpp
  39. +3 −1 src/core/geometry/qgsmultisurface.h
  40. +1 −2 src/core/geometry/qgspoint.cpp
  41. +4 −5 src/core/geometry/qgspoint.h
  42. +2 −2 src/core/geometry/qgspolygon.cpp
  43. +7 −1 src/core/geometry/qgspolygon.h
  44. +0 −10 src/core/geometry/qgssurface.cpp
  45. +0 −3 src/core/geometry/qgssurface.h
  46. +2 −2 src/core/geometry/qgstriangle.cpp
  47. +4 −1 src/core/geometry/qgstriangle.h
  48. +75 −2 tests/src/core/testqgsgeometry.cpp
@@ -71,16 +71,6 @@ class QgsAbstractGeometry
virtual ~QgsAbstractGeometry();
QgsAbstractGeometry( const QgsAbstractGeometry &geom );

virtual QgsAbstractGeometry *createEmptyWithSameType() const = 0 /Factory/;
%Docstring
Makes a new geometry with the same class and same WKB and transfers ownership.
To create it, the geometry is default constructedand then the WKB is changed.
:return: the new empty geometry. Callee takes ownership.
.. seealso:: clone
.. versionadded:: 3.0
:rtype: QgsAbstractGeometry
%End

virtual QgsAbstractGeometry *clone() const = 0 /Factory/;
%Docstring
Clones the geometry by performing a deep copy
@@ -412,14 +402,14 @@ Returns the centroid of the geometry
:rtype: QgsAbstractGeometry
%End

virtual QgsAbstractGeometry *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0, double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const = 0 /Factory/;
virtual QgsAbstractGeometry *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const = 0 /Factory/;
%Docstring
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
It transfers ownership to the callee.
If it couldn't make the gridified geometry it returns None.
Ownership is transferred to the caller.

If the gridified geometry could not be calculated a None will be returned.
It may generate an invalid geometry (in some corner cases).
It can also be thought as rounding the edges and it may be useful for removing errors.
If the geometry is curved, it will be segmentized before gridifying it.
Example:
\code
geometry->snappedToGrid(1, 1);
@@ -430,10 +420,6 @@ Returns the centroid of the geometry
\param vSpacing Vertical spacing of the grid (y axis). 0 to disable.
\param dSpacing Depth spacing of the grid (z axis). 0 (default) to disable.
\param mSpacing Custom dimension spacing of the grid (m axis). 0 (default) to disable.
\param tolerance In case of segmentation, the tolerance to use (passed to segmentize as is).
\param toleranceType In case of segmentation, the toleranceType to use (passed to segmentize as is).
:return: the segmentized geometry or None if it wasn't possible to make. Caller takes ownership.
.. seealso:: segmentize
.. versionadded:: 3.0
:rtype: QgsAbstractGeometry
%End
@@ -528,6 +514,7 @@ Returns the centroid of the geometry

protected:


virtual bool hasChildGeometries() const;
%Docstring
Returns whether the geometry has any child geometries (false for point / curve, true otherwise)
@@ -25,17 +25,24 @@ class QgsCircularString: QgsCurve
QgsCircularString();

virtual bool operator==( const QgsCurve &other ) const;

virtual bool operator!=( const QgsCurve &other ) const;


virtual QString geometryType() const;

virtual int dimension() const;
virtual QgsCircularString *createEmptyWithSameType() const /Factory/;

virtual QgsCircularString *clone() const /Factory/;

virtual void clear();


virtual bool fromWkb( QgsConstWkbPtr &wkb );

virtual bool fromWkt( const QString &wkt );


virtual QByteArray asWkb() const;

virtual QString asWkt( int precision = 17 ) const;
@@ -67,10 +74,14 @@ class QgsCircularString: QgsCurve
%End

virtual double length() const;

virtual QgsPoint startPoint() const;

virtual QgsPoint endPoint() const;


virtual QgsLineString *curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;

%Docstring
Returns a new line string geometry corresponding to a segmentized approximation
of the curve.
@@ -82,6 +93,9 @@ class QgsCircularString: QgsCurve
:rtype: QgsLineString
%End

virtual QgsCircularString *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const /Factory/;


virtual void draw( QPainter &p ) const;

virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
@@ -90,17 +104,15 @@ class QgsCircularString: QgsCurve

virtual void addToPainterPath( QPainterPath &path ) const;


virtual void drawAsPolygon( QPainter &p ) const;


virtual bool insertVertex( QgsVertexId position, const QgsPoint &vertex );

virtual bool moveVertex( QgsVertexId position, const QgsPoint &newPos );

virtual bool deleteVertex( QgsVertexId position );

virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/,
QgsVertexId &vertexAfter /Out/,
bool *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;
virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, bool *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;

virtual bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const;

@@ -120,21 +132,28 @@ class QgsCircularString: QgsCurve

virtual QgsCircularString *reversed() const /Factory/;


virtual bool addZValue( double zValue = 0 );

virtual bool addMValue( double mValue = 0 );


virtual bool dropZValue();

virtual bool dropMValue();


virtual double xAt( int index ) const;

virtual double yAt( int index ) const;


protected:
virtual QgsCircularString *createEmptyWithSameType() const /Factory/;

virtual QgsRectangle calculateBoundingBox() const;


};


@@ -25,17 +25,24 @@ class QgsCompoundCurve: QgsCurve
~QgsCompoundCurve();

virtual bool operator==( const QgsCurve &other ) const;

virtual bool operator!=( const QgsCurve &other ) const;


virtual QString geometryType() const;

virtual int dimension() const;
virtual QgsCompoundCurve *createEmptyWithSameType() const /Factory/;

virtual QgsCompoundCurve *clone() const /Factory/;

virtual void clear();


virtual bool fromWkb( QgsConstWkbPtr &wkb );

virtual bool fromWkt( const QString &wkt );


virtual QByteArray asWkb() const;

virtual QString asWkt( int precision = 17 ) const;
@@ -48,14 +55,20 @@ class QgsCompoundCurve: QgsCurve


virtual double length() const;

virtual QgsPoint startPoint() const;

virtual QgsPoint endPoint() const;

virtual void points( QgsPointSequence &pts /Out/ ) const;

virtual int numPoints() const;

virtual bool isEmpty() const;


virtual QgsLineString *curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;

%Docstring
Returns a new line string geometry corresponding to a segmentized approximation
of the curve.
@@ -64,6 +77,9 @@ class QgsCompoundCurve: QgsCurve
:rtype: QgsLineString
%End

virtual QgsCompoundCurve *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const /Factory/;


int nCurves() const;
%Docstring
Returns the number of curves in the geometry.
@@ -102,18 +118,16 @@ class QgsCompoundCurve: QgsCurve

virtual void drawAsPolygon( QPainter &p ) const;


virtual bool insertVertex( QgsVertexId position, const QgsPoint &vertex );

virtual bool moveVertex( QgsVertexId position, const QgsPoint &newPos );

virtual bool deleteVertex( QgsVertexId position );

virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/,
QgsVertexId &vertexAfter /Out/, bool *leftOf /Out/ = 0,
double epsilon = 4 * DBL_EPSILON ) const;
virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, bool *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;

virtual bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const;


virtual void sumUpArea( double &sum /Out/ ) const;


@@ -136,12 +150,17 @@ Appends first point if not already closed.

virtual QgsCompoundCurve *reversed() const /Factory/;


virtual bool addZValue( double zValue = 0 );

virtual bool addMValue( double mValue = 0 );


virtual bool dropZValue();

virtual bool dropMValue();


virtual double xAt( int index ) const;

virtual double yAt( int index ) const;
@@ -151,6 +170,9 @@ Appends first point if not already closed.

virtual QgsRectangle calculateBoundingBox() const;

virtual QgsCompoundCurve *createEmptyWithSameType() const /Factory/;


};


@@ -126,8 +126,6 @@ class QgsCurve: QgsAbstractGeometry

virtual QgsAbstractGeometry *boundary() const /Factory/;

virtual QgsCurve *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;

virtual QgsCurve *segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;

@@ -186,6 +184,7 @@ class QgsCurve: QgsAbstractGeometry
virtual int childCount() const;
virtual QgsPoint childPoint( int index ) const;


};

/************************************************************************
@@ -35,7 +35,7 @@ class QgsCurvePolygon: QgsSurface
virtual QString geometryType() const;

virtual int dimension() const;
virtual QgsCurvePolygon *createEmptyWithSameType() const /Factory/;

virtual QgsCurvePolygon *clone() const /Factory/;

virtual void clear();
@@ -64,8 +64,9 @@ class QgsCurvePolygon: QgsSurface
virtual QgsPolygonV2 *surfaceToPolygon() const /Factory/;

virtual QgsAbstractGeometry *boundary() const /Factory/;
virtual QgsCurvePolygon *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;

virtual QgsCurvePolygon *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const /Factory/;


int numInteriorRings() const;
%Docstring
@@ -197,9 +198,13 @@ Adds an interior ring to the geometry (takes ownership)
virtual QgsCurvePolygon *toCurveType() const /Factory/;

protected:
virtual QgsCurvePolygon *createEmptyWithSameType() const /Factory/;

virtual int childCount() const;

virtual QgsAbstractGeometry *childGeometry( int index ) const;


protected:


@@ -26,7 +26,6 @@ class QgsGeometryCollection: QgsAbstractGeometry
QgsGeometryCollection( const QgsGeometryCollection &c );
virtual ~QgsGeometryCollection();

virtual QgsGeometryCollection *createEmptyWithSameType() const /Factory/;
virtual QgsGeometryCollection *clone() const /Factory/;


@@ -51,8 +50,8 @@ class QgsGeometryCollection: QgsAbstractGeometry
virtual QString geometryType() const;

virtual void clear();
virtual QgsGeometryCollection *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;

virtual QgsGeometryCollection *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const /Factory/;
virtual QgsAbstractGeometry *boundary() const /Factory/;

virtual void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex /Out/, QgsVertexId &nextVertex /Out/ ) const;
@@ -175,9 +174,13 @@ Adds a geometry and takes ownership. Returns true in case of success.


protected:
virtual QgsGeometryCollection *createEmptyWithSameType() const /Factory/;

virtual int childCount() const;

virtual QgsAbstractGeometry *childGeometry( int index ) const;


protected:

virtual bool wktOmitChildType() const;
@@ -170,15 +170,15 @@ Closes the line string by appending the first point to the end of the line, if i
virtual QString geometryType() const;

virtual int dimension() const;
virtual QgsLineString *createEmptyWithSameType() const /Factory/;

virtual QgsLineString *clone() const /Factory/;

virtual void clear();

virtual bool isEmpty() const;

virtual QgsLineString *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;
virtual QgsLineString *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const /Factory/;


virtual bool fromWkb( QgsConstWkbPtr &wkb );

@@ -270,6 +270,7 @@ Closes the line string by appending the first point to the end of the line, if i


protected:
virtual QgsLineString *createEmptyWithSameType() const /Factory/;

virtual QgsRectangle calculateBoundingBox() const;

@@ -21,7 +21,7 @@ class QgsMultiCurve: QgsGeometryCollection
public:
QgsMultiCurve();
virtual QString geometryType() const;
virtual QgsMultiCurve *createEmptyWithSameType() const /Factory/;

virtual QgsMultiCurve *clone() const /Factory/;

virtual void clear();
@@ -52,6 +52,11 @@ class QgsMultiCurve: QgsGeometryCollection



protected:

virtual QgsMultiCurve *createEmptyWithSameType() const /Factory/;


};


0 comments on commit c67e398

Please sign in to comment.
You can’t perform that action at this time.