Skip to content

Commit

Permalink
Merge pull request #5475 from nyalldawson/snap_to_grid
Browse files Browse the repository at this point in the history
[FEATURE][processing] Native c++ snap to grid algorithm
  • Loading branch information
nyalldawson committed Oct 27, 2017
2 parents edecd49 + 4372ac2 commit 68179e2
Show file tree
Hide file tree
Showing 62 changed files with 1,040 additions and 320 deletions.
34 changes: 34 additions & 0 deletions python/core/geometry/qgsabstractgeometry.sip
Expand Up @@ -402,6 +402,28 @@ Returns the centroid of the geometry
:rtype: QgsAbstractGeometry
%End

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.
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.
Example:
\code
geometry->snappedToGrid(1, 1);
\endcode
In this case we use a 2D grid of 1x1 to gridify.
In this case, it can be thought like rounding the x and y of all the points/vertices to full units (remove all decimals).
\param hSpacing Horizontal spacing of the grid (x axis). 0 to disable.
\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.
.. versionadded:: 3.0
:rtype: QgsAbstractGeometry
%End

virtual double vertexAngle( QgsVertexId vertex ) const = 0;
%Docstring
Returns approximate angle at a vertex. This is usually the average angle between adjacent
Expand Down Expand Up @@ -492,6 +514,18 @@ Returns the centroid of the geometry

protected:

virtual QgsAbstractGeometry *createEmptyWithSameType() const = 0 /Factory/;
%Docstring
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
To create it, the geometry is default constructed and then the WKB is changed.
.. seealso:: clone()
.. versionadded:: 3.0
.. note::

Not available in Python bindings
:rtype: QgsAbstractGeometry
%End

virtual bool hasChildGeometries() const;
%Docstring
Returns whether the geometry has any child geometries (false for point / curve, true otherwise)
Expand Down
30 changes: 25 additions & 5 deletions python/core/geometry/qgscircularstring.sip
Expand Up @@ -25,16 +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 *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;
Expand Down Expand Up @@ -66,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.
Expand All @@ -81,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,
Expand All @@ -89,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;

Expand All @@ -119,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;


};


Expand Down
33 changes: 28 additions & 5 deletions python/core/geometry/qgscompoundcurve.sip
Expand Up @@ -25,16 +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 *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;
Expand All @@ -47,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.
Expand All @@ -63,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.
Expand Down Expand Up @@ -101,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;


Expand All @@ -135,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;
Expand All @@ -150,6 +170,9 @@ Appends first point if not already closed.

virtual QgsRectangle calculateBoundingBox() const;

virtual QgsCompoundCurve *createEmptyWithSameType() const /Factory/;


};


Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgscurve.sip
Expand Up @@ -184,6 +184,7 @@ class QgsCurve: QgsAbstractGeometry
virtual int childCount() const;
virtual QgsPoint childPoint( int index ) const;


};

/************************************************************************
Expand Down
6 changes: 6 additions & 0 deletions python/core/geometry/qgscurvepolygon.sip
Expand Up @@ -65,6 +65,8 @@ class QgsCurvePolygon: QgsSurface

virtual QgsAbstractGeometry *boundary() const /Factory/;

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


int numInteriorRings() const;
%Docstring
Expand Down Expand Up @@ -196,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:


Expand Down
15 changes: 15 additions & 0 deletions python/core/geometry/qgsgeometry.sip
Expand Up @@ -665,6 +665,21 @@ Returns true if WKB of the geometry is of WKBMulti* type
:rtype: QgsGeometry
%End

QgsGeometry snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const;
%Docstring
Returns a new geometry with all points or vertices snapped to the closest point of the grid.

If the gridified geometry could not be calculated (or was totally collapsed) an empty geometry will be returned.
Note that snapping to grid 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.
\param hSpacing Horizontal spacing of the grid (x axis). 0 to disable.
\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.
.. versionadded:: 3.0
:rtype: QgsGeometry
%End

bool intersects( const QgsRectangle &r ) const;
%Docstring
Tests for intersection with a rectangle (uses GEOS)
Expand Down
5 changes: 5 additions & 0 deletions python/core/geometry/qgsgeometrycollection.sip
Expand Up @@ -51,6 +51,7 @@ class QgsGeometryCollection: QgsAbstractGeometry

virtual void clear();

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;
Expand Down Expand Up @@ -173,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;
Expand Down
3 changes: 3 additions & 0 deletions python/core/geometry/qgslinestring.sip
Expand Up @@ -177,6 +177,8 @@ Closes the line string by appending the first point to the end of the line, if i

virtual bool isEmpty() const;

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


virtual bool fromWkb( QgsConstWkbPtr &wkb );

Expand Down Expand Up @@ -268,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;

Expand Down
5 changes: 5 additions & 0 deletions python/core/geometry/qgsmulticurve.sip
Expand Up @@ -52,6 +52,11 @@ class QgsMultiCurve: QgsGeometryCollection



protected:

virtual QgsMultiCurve *createEmptyWithSameType() const /Factory/;


};


Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgsmultilinestring.sip
Expand Up @@ -49,6 +49,7 @@ class QgsMultiLineString: QgsMultiCurve
%End

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

virtual bool wktOmitChildType() const;

Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgsmultipoint.sip
Expand Up @@ -50,6 +50,7 @@ class QgsMultiPointV2: QgsGeometryCollection


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

virtual bool wktOmitChildType() const;

Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgsmultipolygon.sip
Expand Up @@ -51,6 +51,7 @@ class QgsMultiPolygonV2: QgsMultiSurface


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

virtual bool wktOmitChildType() const;

Expand Down
4 changes: 4 additions & 0 deletions python/core/geometry/qgsmultisurface.sip
Expand Up @@ -44,6 +44,10 @@ class QgsMultiSurface: QgsGeometryCollection



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


};


Expand Down

0 comments on commit 68179e2

Please sign in to comment.