mirror of
https://github.com/qgis/QGIS.git
synced 2025-11-30 00:04:58 -05:00
Make asGridified and newSameType (helper function)
This commit is contained in:
parent
99b1c74c4e
commit
3f5b11bffe
@ -71,6 +71,16 @@ class QgsAbstractGeometry
|
|||||||
virtual ~QgsAbstractGeometry();
|
virtual ~QgsAbstractGeometry();
|
||||||
QgsAbstractGeometry( const QgsAbstractGeometry &geom );
|
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/;
|
virtual QgsAbstractGeometry *clone() const = 0 /Factory/;
|
||||||
%Docstring
|
%Docstring
|
||||||
Clones the geometry by performing a deep copy
|
Clones the geometry by performing a deep copy
|
||||||
@ -402,6 +412,32 @@ Returns the centroid of the geometry
|
|||||||
:rtype: QgsAbstractGeometry
|
:rtype: QgsAbstractGeometry
|
||||||
%End
|
%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/;
|
||||||
|
%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.
|
||||||
|
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);
|
||||||
|
\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.
|
||||||
|
\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
|
||||||
|
|
||||||
virtual double vertexAngle( QgsVertexId vertex ) const = 0;
|
virtual double vertexAngle( QgsVertexId vertex ) const = 0;
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns approximate angle at a vertex. This is usually the average angle between adjacent
|
Returns approximate angle at a vertex. This is usually the average angle between adjacent
|
||||||
|
|||||||
@ -29,6 +29,7 @@ class QgsCircularString: QgsCurve
|
|||||||
|
|
||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
virtual int dimension() const;
|
virtual int dimension() const;
|
||||||
|
virtual QgsCircularString *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsCircularString *clone() const /Factory/;
|
virtual QgsCircularString *clone() const /Factory/;
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,7 @@ class QgsCompoundCurve: QgsCurve
|
|||||||
|
|
||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
virtual int dimension() const;
|
virtual int dimension() const;
|
||||||
|
virtual QgsCompoundCurve *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsCompoundCurve *clone() const /Factory/;
|
virtual QgsCompoundCurve *clone() const /Factory/;
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
|
|||||||
@ -126,6 +126,8 @@ class QgsCurve: QgsAbstractGeometry
|
|||||||
|
|
||||||
virtual QgsAbstractGeometry *boundary() const /Factory/;
|
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/;
|
virtual QgsCurve *segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ class QgsCurvePolygon: QgsSurface
|
|||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
|
||||||
virtual int dimension() const;
|
virtual int dimension() const;
|
||||||
|
virtual QgsCurvePolygon *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsCurvePolygon *clone() const /Factory/;
|
virtual QgsCurvePolygon *clone() const /Factory/;
|
||||||
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
@ -64,7 +64,8 @@ class QgsCurvePolygon: QgsSurface
|
|||||||
virtual QgsPolygonV2 *surfaceToPolygon() const /Factory/;
|
virtual QgsPolygonV2 *surfaceToPolygon() const /Factory/;
|
||||||
|
|
||||||
virtual QgsAbstractGeometry *boundary() 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/;
|
||||||
|
|
||||||
int numInteriorRings() const;
|
int numInteriorRings() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
|
|||||||
@ -26,6 +26,7 @@ class QgsGeometryCollection: QgsAbstractGeometry
|
|||||||
QgsGeometryCollection( const QgsGeometryCollection &c );
|
QgsGeometryCollection( const QgsGeometryCollection &c );
|
||||||
virtual ~QgsGeometryCollection();
|
virtual ~QgsGeometryCollection();
|
||||||
|
|
||||||
|
virtual QgsGeometryCollection *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsGeometryCollection *clone() const /Factory/;
|
virtual QgsGeometryCollection *clone() const /Factory/;
|
||||||
|
|
||||||
|
|
||||||
@ -50,7 +51,8 @@ class QgsGeometryCollection: QgsAbstractGeometry
|
|||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
|
||||||
virtual void clear();
|
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 QgsAbstractGeometry *boundary() const /Factory/;
|
virtual QgsAbstractGeometry *boundary() const /Factory/;
|
||||||
|
|
||||||
virtual void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex /Out/, QgsVertexId &nextVertex /Out/ ) const;
|
virtual void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex /Out/, QgsVertexId &nextVertex /Out/ ) const;
|
||||||
|
|||||||
@ -170,13 +170,15 @@ Closes the line string by appending the first point to the end of the line, if i
|
|||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
|
||||||
virtual int dimension() const;
|
virtual int dimension() const;
|
||||||
|
virtual QgsLineString *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsLineString *clone() const /Factory/;
|
virtual QgsLineString *clone() const /Factory/;
|
||||||
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
virtual bool isEmpty() const;
|
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 bool fromWkb( QgsConstWkbPtr &wkb );
|
virtual bool fromWkb( QgsConstWkbPtr &wkb );
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ class QgsMultiCurve: QgsGeometryCollection
|
|||||||
public:
|
public:
|
||||||
QgsMultiCurve();
|
QgsMultiCurve();
|
||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
virtual QgsMultiCurve *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsMultiCurve *clone() const /Factory/;
|
virtual QgsMultiCurve *clone() const /Factory/;
|
||||||
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class QgsMultiLineString: QgsMultiCurve
|
|||||||
QgsMultiLineString();
|
QgsMultiLineString();
|
||||||
|
|
||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
virtual QgsMultiLineString *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsMultiLineString *clone() const /Factory/;
|
virtual QgsMultiLineString *clone() const /Factory/;
|
||||||
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class QgsMultiPointV2: QgsGeometryCollection
|
|||||||
QgsMultiPointV2();
|
QgsMultiPointV2();
|
||||||
|
|
||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
virtual QgsMultiPointV2 *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsMultiPointV2 *clone() const /Factory/;
|
virtual QgsMultiPointV2 *clone() const /Factory/;
|
||||||
|
|
||||||
virtual QgsMultiPointV2 *toCurveType() const /Factory/;
|
virtual QgsMultiPointV2 *toCurveType() const /Factory/;
|
||||||
|
|||||||
@ -21,7 +21,7 @@ class QgsMultiPolygonV2: QgsMultiSurface
|
|||||||
public:
|
public:
|
||||||
QgsMultiPolygonV2();
|
QgsMultiPolygonV2();
|
||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
virtual QgsMultiPolygonV2 *createEmptyWithSameType() const /Factory/;
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
virtual QgsMultiPolygonV2 *clone() const /Factory/;
|
virtual QgsMultiPolygonV2 *clone() const /Factory/;
|
||||||
|
|||||||
@ -21,9 +21,8 @@ class QgsMultiSurface: QgsGeometryCollection
|
|||||||
public:
|
public:
|
||||||
QgsMultiSurface();
|
QgsMultiSurface();
|
||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
virtual QgsMultiSurface *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsMultiSurface *clone() const /Factory/;
|
virtual QgsMultiSurface *clone() const /Factory/;
|
||||||
|
|
||||||
virtual QgsMultiSurface *toCurveType() const /Factory/;
|
virtual QgsMultiSurface *toCurveType() const /Factory/;
|
||||||
|
|||||||
@ -335,9 +335,10 @@ class QgsPoint: QgsAbstractGeometry
|
|||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
|
||||||
virtual int dimension() const;
|
virtual int dimension() const;
|
||||||
|
virtual QgsPoint *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsPoint *clone() const /Factory/;
|
virtual QgsPoint *clone() const /Factory/;
|
||||||
|
virtual QgsPoint *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
|
||||||
|
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
virtual bool fromWkb( QgsConstWkbPtr &wkb );
|
virtual bool fromWkb( QgsConstWkbPtr &wkb );
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class QgsPolygonV2: QgsCurvePolygon
|
|||||||
QgsPolygonV2();
|
QgsPolygonV2();
|
||||||
|
|
||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
virtual QgsPolygonV2 *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsPolygonV2 *clone() const /Factory/;
|
virtual QgsPolygonV2 *clone() const /Factory/;
|
||||||
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|||||||
@ -25,6 +25,9 @@ class QgsSurface: QgsAbstractGeometry
|
|||||||
:rtype: QgsPolygonV2
|
:rtype: QgsPolygonV2
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
virtual QgsSurface *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
|
||||||
|
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;
|
||||||
|
|
||||||
virtual QgsRectangle boundingBox() const;
|
virtual QgsRectangle boundingBox() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns the minimal bounding box for the geometry
|
Returns the minimal bounding box for the geometry
|
||||||
|
|||||||
@ -53,7 +53,7 @@ class QgsTriangle : QgsPolygonV2
|
|||||||
%End
|
%End
|
||||||
|
|
||||||
virtual QString geometryType() const;
|
virtual QString geometryType() const;
|
||||||
|
virtual QgsTriangle *createEmptyWithSameType() const /Factory/;
|
||||||
virtual QgsTriangle *clone() const /Factory/;
|
virtual QgsTriangle *clone() const /Factory/;
|
||||||
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|||||||
@ -467,6 +467,7 @@ SET(QGIS_CORE_SRCS
|
|||||||
geometry/qgsrectangle.cpp
|
geometry/qgsrectangle.cpp
|
||||||
geometry/qgsreferencedgeometry.cpp
|
geometry/qgsreferencedgeometry.cpp
|
||||||
geometry/qgsregularpolygon.cpp
|
geometry/qgsregularpolygon.cpp
|
||||||
|
geometry/qgssurface.cpp
|
||||||
geometry/qgstriangle.cpp
|
geometry/qgstriangle.cpp
|
||||||
geometry/qgswkbptr.cpp
|
geometry/qgswkbptr.cpp
|
||||||
geometry/qgswkbtypes.cpp
|
geometry/qgswkbtypes.cpp
|
||||||
|
|||||||
@ -110,6 +110,14 @@ class CORE_EXPORT QgsAbstractGeometry
|
|||||||
QgsAbstractGeometry( const QgsAbstractGeometry &geom );
|
QgsAbstractGeometry( const QgsAbstractGeometry &geom );
|
||||||
QgsAbstractGeometry &operator=( const QgsAbstractGeometry &geom );
|
QgsAbstractGeometry &operator=( const QgsAbstractGeometry &geom );
|
||||||
|
|
||||||
|
/** 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.
|
||||||
|
* \returns the new empty geometry. Callee takes ownership.
|
||||||
|
* \see clone
|
||||||
|
* \since 3.0
|
||||||
|
*/
|
||||||
|
virtual QgsAbstractGeometry *createEmptyWithSameType() const = 0 SIP_FACTORY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clones the geometry by performing a deep copy
|
* Clones the geometry by performing a deep copy
|
||||||
*/
|
*/
|
||||||
@ -411,6 +419,30 @@ class CORE_EXPORT QgsAbstractGeometry
|
|||||||
*/
|
*/
|
||||||
virtual QgsAbstractGeometry *toCurveType() const = 0 SIP_FACTORY;
|
virtual QgsAbstractGeometry *toCurveType() const = 0 SIP_FACTORY;
|
||||||
|
|
||||||
|
/** 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 nullptr.
|
||||||
|
* 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);
|
||||||
|
* \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.
|
||||||
|
* \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).
|
||||||
|
* \returns the segmentized geometry or nullptr if it wasn't possible to make. Caller takes ownership.
|
||||||
|
* \see segmentize
|
||||||
|
* \since 3.0
|
||||||
|
*/
|
||||||
|
virtual QgsAbstractGeometry *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0, double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const = 0 SIP_FACTORY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns approximate angle at a vertex. This is usually the average angle between adjacent
|
* Returns approximate angle at a vertex. This is usually the average angle between adjacent
|
||||||
* segments, and can be pictured as the orientation of a line following the curvature of the
|
* segments, and can be pictured as the orientation of a line following the curvature of the
|
||||||
|
|||||||
@ -66,6 +66,13 @@ bool QgsCircularString::operator!=( const QgsCurve &other ) const
|
|||||||
return !operator==( other );
|
return !operator==( other );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsCircularString *QgsCircularString::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsCircularString();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QString QgsCircularString::geometryType() const
|
QString QgsCircularString::geometryType() const
|
||||||
{
|
{
|
||||||
return QStringLiteral( "CircularString" );
|
return QStringLiteral( "CircularString" );
|
||||||
|
|||||||
@ -41,6 +41,7 @@ class CORE_EXPORT QgsCircularString: public QgsCurve
|
|||||||
|
|
||||||
virtual QString geometryType() const override;
|
virtual QString geometryType() const override;
|
||||||
virtual int dimension() const override;
|
virtual int dimension() const override;
|
||||||
|
virtual QgsCircularString *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
virtual QgsCircularString *clone() const override SIP_FACTORY;
|
virtual QgsCircularString *clone() const override SIP_FACTORY;
|
||||||
virtual void clear() override;
|
virtual void clear() override;
|
||||||
|
|
||||||
|
|||||||
@ -61,6 +61,13 @@ bool QgsCompoundCurve::operator!=( const QgsCurve &other ) const
|
|||||||
return !operator==( other );
|
return !operator==( other );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsCompoundCurve *QgsCompoundCurve::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsCompoundCurve();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QString QgsCompoundCurve::geometryType() const
|
QString QgsCompoundCurve::geometryType() const
|
||||||
{
|
{
|
||||||
return QStringLiteral( "CompoundCurve" );
|
return QStringLiteral( "CompoundCurve" );
|
||||||
|
|||||||
@ -41,6 +41,7 @@ class CORE_EXPORT QgsCompoundCurve: public QgsCurve
|
|||||||
|
|
||||||
virtual QString geometryType() const override;
|
virtual QString geometryType() const override;
|
||||||
virtual int dimension() const override;
|
virtual int dimension() const override;
|
||||||
|
virtual QgsCompoundCurve *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
virtual QgsCompoundCurve *clone() const override SIP_FACTORY;
|
virtual QgsCompoundCurve *clone() const override SIP_FACTORY;
|
||||||
virtual void clear() override;
|
virtual void clear() override;
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,8 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "qgscurve.h"
|
#include "qgscurve.h"
|
||||||
#include "qgslinestring.h"
|
#include "qgslinestring.h"
|
||||||
#include "qgspoint.h"
|
#include "qgspoint.h"
|
||||||
@ -129,6 +131,13 @@ QgsAbstractGeometry *QgsCurve::boundary() const
|
|||||||
return multiPoint;
|
return multiPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsCurve *QgsCurve::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing,
|
||||||
|
double tolerance, SegmentationToleranceType toleranceType ) const
|
||||||
|
{
|
||||||
|
std::unique_ptr<QgsLineString> line { curveToLine( tolerance, toleranceType ) };
|
||||||
|
return line->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing );
|
||||||
|
}
|
||||||
|
|
||||||
QgsCurve *QgsCurve::segmentize( double tolerance, SegmentationToleranceType toleranceType ) const
|
QgsCurve *QgsCurve::segmentize( double tolerance, SegmentationToleranceType toleranceType ) const
|
||||||
{
|
{
|
||||||
return curveToLine( tolerance, toleranceType );
|
return curveToLine( tolerance, toleranceType );
|
||||||
|
|||||||
@ -123,6 +123,9 @@ class CORE_EXPORT QgsCurve: public QgsAbstractGeometry
|
|||||||
|
|
||||||
QgsAbstractGeometry *boundary() const override SIP_FACTORY;
|
QgsAbstractGeometry *boundary() const override SIP_FACTORY;
|
||||||
|
|
||||||
|
virtual QgsCurve *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
|
||||||
|
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a geometry without curves. Caller takes ownership
|
* Returns a geometry without curves. Caller takes ownership
|
||||||
* \param tolerance segmentation tolerance
|
* \param tolerance segmentation tolerance
|
||||||
|
|||||||
@ -38,6 +38,13 @@ QgsCurvePolygon::~QgsCurvePolygon()
|
|||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsCurvePolygon *QgsCurvePolygon::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsCurvePolygon();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QString QgsCurvePolygon::geometryType() const
|
QString QgsCurvePolygon::geometryType() const
|
||||||
{
|
{
|
||||||
return QStringLiteral( "CurvePolygon" );
|
return QStringLiteral( "CurvePolygon" );
|
||||||
@ -495,6 +502,49 @@ QgsAbstractGeometry *QgsCurvePolygon::boundary() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsCurvePolygon *QgsCurvePolygon::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing,
|
||||||
|
double tolerance, SegmentationToleranceType toleranceType ) const
|
||||||
|
{
|
||||||
|
if ( !mExteriorRing )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
std::unique_ptr<QgsPolygonV2> polygon;
|
||||||
|
if ( QgsWkbTypes::flatType( mWkbType ) == QgsWkbTypes::Triangle || QgsWkbTypes::flatType( mWkbType ) == QgsWkbTypes::Polygon )
|
||||||
|
{
|
||||||
|
polygon = std::unique_ptr<QgsPolygonV2> { static_cast< QgsPolygonV2 const *>( this )->createEmptyWithSameType() };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
polygon = std::unique_ptr<QgsPolygonV2> { new QgsPolygonV2() };
|
||||||
|
polygon->mWkbType = QgsWkbTypes::zmType( QgsWkbTypes::Polygon, QgsWkbTypes::hasZ( mWkbType ), QgsWkbTypes::hasM( mWkbType ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// exterior ring
|
||||||
|
auto exterior = std::unique_ptr<QgsCurve> { mExteriorRing->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, tolerance, toleranceType ) };
|
||||||
|
|
||||||
|
if ( !exterior )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
polygon->mExteriorRing = exterior.release();
|
||||||
|
|
||||||
|
//interior rings
|
||||||
|
for ( auto interior : mInteriorRings )
|
||||||
|
{
|
||||||
|
if ( !interior )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QgsCurve *gridifiedInterior = interior->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, tolerance, toleranceType );
|
||||||
|
|
||||||
|
if ( !gridifiedInterior )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
polygon->mInteriorRings.append( gridifiedInterior );
|
||||||
|
}
|
||||||
|
|
||||||
|
return polygon.release();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QgsPolygonV2 *QgsCurvePolygon::toPolygon( double tolerance, SegmentationToleranceType toleranceType ) const
|
QgsPolygonV2 *QgsCurvePolygon::toPolygon( double tolerance, SegmentationToleranceType toleranceType ) const
|
||||||
{
|
{
|
||||||
std::unique_ptr< QgsPolygonV2 > poly( new QgsPolygonV2() );
|
std::unique_ptr< QgsPolygonV2 > poly( new QgsPolygonV2() );
|
||||||
|
|||||||
@ -45,6 +45,7 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
|
|||||||
|
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
int dimension() const override;
|
int dimension() const override;
|
||||||
|
virtual QgsCurvePolygon *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
QgsCurvePolygon *clone() const override SIP_FACTORY;
|
QgsCurvePolygon *clone() const override SIP_FACTORY;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
|
|
||||||
@ -62,6 +63,8 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
|
|||||||
double perimeter() const override;
|
double perimeter() const override;
|
||||||
QgsPolygonV2 *surfaceToPolygon() const override SIP_FACTORY;
|
QgsPolygonV2 *surfaceToPolygon() const override SIP_FACTORY;
|
||||||
QgsAbstractGeometry *boundary() const override SIP_FACTORY;
|
QgsAbstractGeometry *boundary() const override SIP_FACTORY;
|
||||||
|
virtual QgsCurvePolygon *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
|
||||||
|
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
|
||||||
|
|
||||||
//curve polygon interface
|
//curve polygon interface
|
||||||
int numInteriorRings() const;
|
int numInteriorRings() const;
|
||||||
|
|||||||
@ -26,6 +26,7 @@ email : marco.hugentobler at sourcepole dot com
|
|||||||
#include "qgspolygon.h"
|
#include "qgspolygon.h"
|
||||||
#include "qgsmultipolygon.h"
|
#include "qgsmultipolygon.h"
|
||||||
#include "qgswkbptr.h"
|
#include "qgswkbptr.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
QgsGeometryCollection::QgsGeometryCollection()
|
QgsGeometryCollection::QgsGeometryCollection()
|
||||||
{
|
{
|
||||||
@ -63,6 +64,13 @@ QgsGeometryCollection::~QgsGeometryCollection()
|
|||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsGeometryCollection *QgsGeometryCollection::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsGeometryCollection();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QgsGeometryCollection *QgsGeometryCollection::clone() const
|
QgsGeometryCollection *QgsGeometryCollection::clone() const
|
||||||
{
|
{
|
||||||
return new QgsGeometryCollection( *this );
|
return new QgsGeometryCollection( *this );
|
||||||
@ -75,6 +83,26 @@ void QgsGeometryCollection::clear()
|
|||||||
clearCache(); //set bounding box invalid
|
clearCache(); //set bounding box invalid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsGeometryCollection *QgsGeometryCollection::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing,
|
||||||
|
double tolerance, SegmentationToleranceType toleranceType ) const
|
||||||
|
{
|
||||||
|
std::unique_ptr<QgsGeometryCollection> result;
|
||||||
|
|
||||||
|
for ( auto geom : mGeometries )
|
||||||
|
{
|
||||||
|
std::unique_ptr<QgsAbstractGeometry> gridified { geom->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, tolerance, toleranceType ) };
|
||||||
|
if ( gridified )
|
||||||
|
{
|
||||||
|
if ( !result )
|
||||||
|
result = std::unique_ptr<QgsGeometryCollection> { createEmptyWithSameType() };
|
||||||
|
|
||||||
|
result->mGeometries.append( gridified.release() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.release();
|
||||||
|
}
|
||||||
|
|
||||||
QgsAbstractGeometry *QgsGeometryCollection::boundary() const
|
QgsAbstractGeometry *QgsGeometryCollection::boundary() const
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@ -39,6 +39,7 @@ class CORE_EXPORT QgsGeometryCollection: public QgsAbstractGeometry
|
|||||||
QgsGeometryCollection &operator=( const QgsGeometryCollection &c );
|
QgsGeometryCollection &operator=( const QgsGeometryCollection &c );
|
||||||
virtual ~QgsGeometryCollection();
|
virtual ~QgsGeometryCollection();
|
||||||
|
|
||||||
|
virtual QgsGeometryCollection *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
QgsGeometryCollection *clone() const override SIP_FACTORY;
|
QgsGeometryCollection *clone() const override SIP_FACTORY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,6 +65,8 @@ class CORE_EXPORT QgsGeometryCollection: public QgsAbstractGeometry
|
|||||||
int dimension() const override;
|
int dimension() const override;
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
|
virtual QgsGeometryCollection *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
|
||||||
|
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
|
||||||
QgsAbstractGeometry *boundary() const override SIP_FACTORY;
|
QgsAbstractGeometry *boundary() const override SIP_FACTORY;
|
||||||
void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const override;
|
void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const override;
|
||||||
int vertexNumberFromVertexId( QgsVertexId id ) const override;
|
int vertexNumberFromVertexId( QgsVertexId id ) const override;
|
||||||
|
|||||||
@ -23,6 +23,8 @@
|
|||||||
#include "qgsmaptopixel.h"
|
#include "qgsmaptopixel.h"
|
||||||
#include "qgswkbptr.h"
|
#include "qgswkbptr.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <memory>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <QDomDocument>
|
#include <QDomDocument>
|
||||||
@ -187,6 +189,84 @@ bool QgsLineString::isEmpty() const
|
|||||||
return mX.isEmpty();
|
return mX.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsLineString *QgsLineString::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing,
|
||||||
|
double /*tolerance*/, SegmentationToleranceType /*toleranceType*/ ) const
|
||||||
|
{
|
||||||
|
int length = numPoints();
|
||||||
|
|
||||||
|
if ( length <= 0 )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// prepare result
|
||||||
|
std::unique_ptr<QgsLineString> result { createEmptyWithSameType() };
|
||||||
|
|
||||||
|
|
||||||
|
// helper functions
|
||||||
|
auto roundVertex = [&]( QgsPoint & out, int i )
|
||||||
|
{
|
||||||
|
if ( hSpacing > 0 )
|
||||||
|
out.setX( std::round( mX.at( i ) / hSpacing ) * hSpacing );
|
||||||
|
|
||||||
|
if ( vSpacing > 0 )
|
||||||
|
out.setY( std::round( mY.at( i ) / vSpacing ) * vSpacing );
|
||||||
|
|
||||||
|
if ( dSpacing > 0 && QgsWkbTypes::hasZ( mWkbType ) )
|
||||||
|
out.setZ( std::round( mZ.at( i ) / dSpacing ) * dSpacing );
|
||||||
|
|
||||||
|
if ( mSpacing > 0 && QgsWkbTypes::hasM( mWkbType ) )
|
||||||
|
out.setM( std::round( mM.at( i ) / mSpacing ) * mSpacing );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
auto append = [this, &result]( QgsPoint const & point )
|
||||||
|
{
|
||||||
|
result->mX.append( point.x() );
|
||||||
|
|
||||||
|
result->mY.append( point.y() );
|
||||||
|
|
||||||
|
if ( QgsWkbTypes::hasZ( mWkbType ) )
|
||||||
|
result->mZ.append( point.z() );
|
||||||
|
|
||||||
|
if ( QgsWkbTypes::hasM( mWkbType ) )
|
||||||
|
result->mM.append( point.m() );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
auto isPointEqual = [&]( const QgsPoint & a, const QgsPoint & b )
|
||||||
|
{
|
||||||
|
return ( a.x() == b.x() )
|
||||||
|
&& ( a.y() == b.y() )
|
||||||
|
&& ( !QgsWkbTypes::hasZ( mWkbType ) || dSpacing <= 0 || a.z() == b.z() )
|
||||||
|
&& ( !QgsWkbTypes::hasM( mWkbType ) || mSpacing <= 0 || a.m() == b.m() );
|
||||||
|
};
|
||||||
|
|
||||||
|
// temporary values
|
||||||
|
QgsWkbTypes::Type pointType = QgsWkbTypes::zmType( QgsWkbTypes::Point, QgsWkbTypes::hasZ( mWkbType ), QgsWkbTypes::hasM( mWkbType ) );
|
||||||
|
QgsPoint last( pointType );
|
||||||
|
QgsPoint current( pointType );
|
||||||
|
|
||||||
|
// Actual code (what does all the work)
|
||||||
|
roundVertex( last, 0 );
|
||||||
|
append( last );
|
||||||
|
|
||||||
|
for ( int i = 1; i < length; ++i )
|
||||||
|
{
|
||||||
|
roundVertex( current, i );
|
||||||
|
if ( !isPointEqual( current, last ) )
|
||||||
|
{
|
||||||
|
append( current );
|
||||||
|
last = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's not closed, with 2 points you get a correct line
|
||||||
|
// if it is, you need at least 4 (3 + the vertex that closes)
|
||||||
|
if ( result->mX.length() < 2 || ( isClosed() && result->mX.length() < 4 ) )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return result.release();
|
||||||
|
}
|
||||||
|
|
||||||
bool QgsLineString::fromWkb( QgsConstWkbPtr &wkbPtr )
|
bool QgsLineString::fromWkb( QgsConstWkbPtr &wkbPtr )
|
||||||
{
|
{
|
||||||
if ( !wkbPtr )
|
if ( !wkbPtr )
|
||||||
@ -711,6 +791,13 @@ void QgsLineString::extend( double startDistance, double endDistance )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsLineString *QgsLineString::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsLineString();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QString QgsLineString::geometryType() const
|
QString QgsLineString::geometryType() const
|
||||||
{
|
{
|
||||||
return QStringLiteral( "LineString" );
|
return QStringLiteral( "LineString" );
|
||||||
|
|||||||
@ -176,9 +176,12 @@ class CORE_EXPORT QgsLineString: public QgsCurve
|
|||||||
|
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
int dimension() const override;
|
int dimension() const override;
|
||||||
|
virtual QgsLineString *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
QgsLineString *clone() const override SIP_FACTORY;
|
QgsLineString *clone() const override SIP_FACTORY;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
bool isEmpty() const override;
|
bool isEmpty() const override;
|
||||||
|
virtual QgsLineString *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
|
||||||
|
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
|
||||||
|
|
||||||
bool fromWkb( QgsConstWkbPtr &wkb ) override;
|
bool fromWkb( QgsConstWkbPtr &wkb ) override;
|
||||||
bool fromWkt( const QString &wkt ) override;
|
bool fromWkt( const QString &wkt ) override;
|
||||||
|
|||||||
@ -33,6 +33,13 @@ QString QgsMultiCurve::geometryType() const
|
|||||||
return QStringLiteral( "MultiCurve" );
|
return QStringLiteral( "MultiCurve" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsMultiCurve *QgsMultiCurve::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsMultiCurve();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QgsMultiCurve *QgsMultiCurve::clone() const
|
QgsMultiCurve *QgsMultiCurve::clone() const
|
||||||
{
|
{
|
||||||
return new QgsMultiCurve( *this );
|
return new QgsMultiCurve( *this );
|
||||||
|
|||||||
@ -31,6 +31,7 @@ class CORE_EXPORT QgsMultiCurve: public QgsGeometryCollection
|
|||||||
public:
|
public:
|
||||||
QgsMultiCurve();
|
QgsMultiCurve();
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
|
virtual QgsMultiCurve *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
QgsMultiCurve *clone() const override SIP_FACTORY;
|
QgsMultiCurve *clone() const override SIP_FACTORY;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
QgsMultiCurve *toCurveType() const override SIP_FACTORY;
|
QgsMultiCurve *toCurveType() const override SIP_FACTORY;
|
||||||
|
|||||||
@ -32,6 +32,13 @@ QString QgsMultiLineString::geometryType() const
|
|||||||
return QStringLiteral( "MultiLineString" );
|
return QStringLiteral( "MultiLineString" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsMultiLineString *QgsMultiLineString::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsMultiLineString();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QgsMultiLineString *QgsMultiLineString::clone() const
|
QgsMultiLineString *QgsMultiLineString::clone() const
|
||||||
{
|
{
|
||||||
return new QgsMultiLineString( *this );
|
return new QgsMultiLineString( *this );
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class CORE_EXPORT QgsMultiLineString: public QgsMultiCurve
|
|||||||
QgsMultiLineString();
|
QgsMultiLineString();
|
||||||
|
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
|
virtual QgsMultiLineString *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
QgsMultiLineString *clone() const override SIP_FACTORY;
|
QgsMultiLineString *clone() const override SIP_FACTORY;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
bool fromWkt( const QString &wkt ) override;
|
bool fromWkt( const QString &wkt ) override;
|
||||||
|
|||||||
@ -29,6 +29,13 @@ QString QgsMultiPointV2::geometryType() const
|
|||||||
return QStringLiteral( "MultiPoint" );
|
return QStringLiteral( "MultiPoint" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsMultiPointV2 *QgsMultiPointV2::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsMultiPointV2();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QgsMultiPointV2 *QgsMultiPointV2::clone() const
|
QgsMultiPointV2 *QgsMultiPointV2::clone() const
|
||||||
{
|
{
|
||||||
return new QgsMultiPointV2( *this );
|
return new QgsMultiPointV2( *this );
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class CORE_EXPORT QgsMultiPointV2: public QgsGeometryCollection
|
|||||||
QgsMultiPointV2();
|
QgsMultiPointV2();
|
||||||
|
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
|
virtual QgsMultiPointV2 *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
QgsMultiPointV2 *clone() const override SIP_FACTORY;
|
QgsMultiPointV2 *clone() const override SIP_FACTORY;
|
||||||
QgsMultiPointV2 *toCurveType() const override SIP_FACTORY;
|
QgsMultiPointV2 *toCurveType() const override SIP_FACTORY;
|
||||||
bool fromWkt( const QString &wkt ) override;
|
bool fromWkt( const QString &wkt ) override;
|
||||||
|
|||||||
@ -38,6 +38,13 @@ void QgsMultiPolygonV2::clear()
|
|||||||
mWkbType = QgsWkbTypes::MultiPolygon;
|
mWkbType = QgsWkbTypes::MultiPolygon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsMultiPolygonV2 *QgsMultiPolygonV2::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsMultiPolygonV2();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QgsMultiPolygonV2 *QgsMultiPolygonV2::clone() const
|
QgsMultiPolygonV2 *QgsMultiPolygonV2::clone() const
|
||||||
{
|
{
|
||||||
return new QgsMultiPolygonV2( *this );
|
return new QgsMultiPolygonV2( *this );
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class CORE_EXPORT QgsMultiPolygonV2: public QgsMultiSurface
|
|||||||
QgsMultiPolygonV2();
|
QgsMultiPolygonV2();
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
|
virtual QgsMultiPolygonV2 *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
QgsMultiPolygonV2 *clone() const override SIP_FACTORY;
|
QgsMultiPolygonV2 *clone() const override SIP_FACTORY;
|
||||||
bool fromWkt( const QString &wkt ) override;
|
bool fromWkt( const QString &wkt ) override;
|
||||||
QDomElement asGML2( QDomDocument &doc, int precision = 17, const QString &ns = "gml" ) const override;
|
QDomElement asGML2( QDomDocument &doc, int precision = 17, const QString &ns = "gml" ) const override;
|
||||||
|
|||||||
@ -39,6 +39,13 @@ void QgsMultiSurface::clear()
|
|||||||
mWkbType = QgsWkbTypes::MultiSurface;
|
mWkbType = QgsWkbTypes::MultiSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsMultiSurface *QgsMultiSurface::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsMultiSurface();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QgsMultiSurface *QgsMultiSurface::clone() const
|
QgsMultiSurface *QgsMultiSurface::clone() const
|
||||||
{
|
{
|
||||||
return new QgsMultiSurface( *this );
|
return new QgsMultiSurface( *this );
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class CORE_EXPORT QgsMultiSurface: public QgsGeometryCollection
|
|||||||
QgsMultiSurface();
|
QgsMultiSurface();
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
|
virtual QgsMultiSurface *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
QgsMultiSurface *clone() const override SIP_FACTORY;
|
QgsMultiSurface *clone() const override SIP_FACTORY;
|
||||||
QgsMultiSurface *toCurveType() const override SIP_FACTORY;
|
QgsMultiSurface *toCurveType() const override SIP_FACTORY;
|
||||||
bool fromWkt( const QString &wkt ) override;
|
bool fromWkt( const QString &wkt ) override;
|
||||||
|
|||||||
@ -22,6 +22,8 @@
|
|||||||
#include "qgsgeometryutils.h"
|
#include "qgsgeometryutils.h"
|
||||||
#include "qgsmaptopixel.h"
|
#include "qgsmaptopixel.h"
|
||||||
#include "qgswkbptr.h"
|
#include "qgswkbptr.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
@ -114,6 +116,28 @@ QgsPoint *QgsPoint::clone() const
|
|||||||
return new QgsPoint( *this );
|
return new QgsPoint( *this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsPoint *QgsPoint::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing,
|
||||||
|
double /*tolerance*/, SegmentationToleranceType /*toleranceType*/ ) const
|
||||||
|
{
|
||||||
|
// helper function
|
||||||
|
auto gridifyValue = []( double value, double spacing, bool extraCondition = true ) -> double
|
||||||
|
{
|
||||||
|
if ( spacing > 0 && extraCondition )
|
||||||
|
return std::round( value / spacing ) * spacing;
|
||||||
|
else
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the new values
|
||||||
|
auto x = gridifyValue( mX, hSpacing );
|
||||||
|
auto y = gridifyValue( mY, vSpacing );
|
||||||
|
auto z = gridifyValue( mZ, dSpacing, QgsWkbTypes::hasZ( mWkbType ) );
|
||||||
|
auto m = gridifyValue( mM, mSpacing, QgsWkbTypes::hasM( mWkbType ) );
|
||||||
|
|
||||||
|
// return the new object
|
||||||
|
return new QgsPoint( mWkbType, x, y, z, m );
|
||||||
|
}
|
||||||
|
|
||||||
bool QgsPoint::fromWkb( QgsConstWkbPtr &wkbPtr )
|
bool QgsPoint::fromWkb( QgsConstWkbPtr &wkbPtr )
|
||||||
{
|
{
|
||||||
QgsWkbTypes::Type type = wkbPtr.readHeader();
|
QgsWkbTypes::Type type = wkbPtr.readHeader();
|
||||||
@ -669,3 +693,9 @@ QgsPoint QgsPoint::childPoint( int index ) const
|
|||||||
Q_ASSERT( index == 0 );
|
Q_ASSERT( index == 0 );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsPoint *QgsPoint::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
double nan = std::numeric_limits<double>::quiet_NaN();
|
||||||
|
return new QgsPoint( nan, nan, nan, nan, mWkbType );
|
||||||
|
}
|
||||||
|
|||||||
@ -390,7 +390,10 @@ class CORE_EXPORT QgsPoint: public QgsAbstractGeometry
|
|||||||
QgsRectangle boundingBox() const override;
|
QgsRectangle boundingBox() const override;
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
int dimension() const override;
|
int dimension() const override;
|
||||||
|
virtual QgsPoint *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
QgsPoint *clone() const override SIP_FACTORY;
|
QgsPoint *clone() const override SIP_FACTORY;
|
||||||
|
virtual QgsPoint *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
|
||||||
|
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
bool fromWkb( QgsConstWkbPtr &wkb ) override;
|
bool fromWkb( QgsConstWkbPtr &wkb ) override;
|
||||||
bool fromWkt( const QString &wkt ) override;
|
bool fromWkt( const QString &wkt ) override;
|
||||||
|
|||||||
@ -32,6 +32,13 @@ QString QgsPolygonV2::geometryType() const
|
|||||||
return QStringLiteral( "Polygon" );
|
return QStringLiteral( "Polygon" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsPolygonV2 *QgsPolygonV2::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsPolygonV2();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QgsPolygonV2 *QgsPolygonV2::clone() const
|
QgsPolygonV2 *QgsPolygonV2::clone() const
|
||||||
{
|
{
|
||||||
return new QgsPolygonV2( *this );
|
return new QgsPolygonV2( *this );
|
||||||
|
|||||||
@ -35,6 +35,7 @@ class CORE_EXPORT QgsPolygonV2: public QgsCurvePolygon
|
|||||||
|
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
QgsPolygonV2 *clone() const override SIP_FACTORY;
|
QgsPolygonV2 *clone() const override SIP_FACTORY;
|
||||||
|
virtual QgsPolygonV2 *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
bool fromWkb( QgsConstWkbPtr &wkb ) override;
|
bool fromWkb( QgsConstWkbPtr &wkb ) override;
|
||||||
QByteArray asWkb() const override;
|
QByteArray asWkb() const override;
|
||||||
|
|||||||
32
src/core/geometry/qgssurface.cpp
Normal file
32
src/core/geometry/qgssurface.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgscurvepolygon.cpp
|
||||||
|
---------------------
|
||||||
|
begin : August 2017
|
||||||
|
copyright : (C) 2017 by Martí Angelats i Ribera
|
||||||
|
email : marti dot angelats at psig dot cat
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "qgssurface.h"
|
||||||
|
#include "qgspoint.h"
|
||||||
|
#include "qgspolygon.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
QgsSurface *QgsSurface::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing,
|
||||||
|
double /*tolerance*/, SegmentationToleranceType /*toleranceType*/ ) const
|
||||||
|
{
|
||||||
|
std::unique_ptr<QgsPolygonV2> polygon { surfaceToPolygon() };
|
||||||
|
if ( !polygon )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return polygon->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing );
|
||||||
|
}
|
||||||
@ -39,6 +39,9 @@ class CORE_EXPORT QgsSurface: public QgsAbstractGeometry
|
|||||||
*/
|
*/
|
||||||
virtual QgsPolygonV2 *surfaceToPolygon() const = 0 SIP_FACTORY;
|
virtual QgsPolygonV2 *surfaceToPolygon() const = 0 SIP_FACTORY;
|
||||||
|
|
||||||
|
virtual QgsSurface *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0,
|
||||||
|
double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the minimal bounding box for the geometry
|
* Returns the minimal bounding box for the geometry
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -89,6 +89,13 @@ QString QgsTriangle::geometryType() const
|
|||||||
return QStringLiteral( "Triangle" );
|
return QStringLiteral( "Triangle" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsTriangle *QgsTriangle::createEmptyWithSameType() const
|
||||||
|
{
|
||||||
|
auto result = new QgsTriangle();
|
||||||
|
result->mWkbType = mWkbType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void QgsTriangle::clear()
|
void QgsTriangle::clear()
|
||||||
{
|
{
|
||||||
QgsCurvePolygon::clear();
|
QgsCurvePolygon::clear();
|
||||||
|
|||||||
@ -64,6 +64,7 @@ class CORE_EXPORT QgsTriangle : public QgsPolygonV2
|
|||||||
|
|
||||||
QString geometryType() const override;
|
QString geometryType() const override;
|
||||||
QgsTriangle *clone() const override SIP_FACTORY;
|
QgsTriangle *clone() const override SIP_FACTORY;
|
||||||
|
virtual QgsTriangle *createEmptyWithSameType() const override SIP_FACTORY;
|
||||||
void clear() override;
|
void clear() override;
|
||||||
|
|
||||||
bool fromWkb( QgsConstWkbPtr &wkbPtr ) override;
|
bool fromWkb( QgsConstWkbPtr &wkbPtr ) override;
|
||||||
|
|||||||
@ -13,6 +13,9 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include "qgstest.h"
|
#include "qgstest.h"
|
||||||
|
#include <cmath>
|
||||||
|
#include <memory>
|
||||||
|
#include <limits>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@ -101,6 +104,8 @@ class TestQgsGeometry : public QObject
|
|||||||
void comparePolylines();
|
void comparePolylines();
|
||||||
void comparePolygons();
|
void comparePolygons();
|
||||||
|
|
||||||
|
void createEmptyWithSameType();
|
||||||
|
|
||||||
// MK, Disabled 14.11.2014
|
// MK, Disabled 14.11.2014
|
||||||
// Too unclear what exactly should be tested and which variations are allowed for the line
|
// Too unclear what exactly should be tested and which variations are allowed for the line
|
||||||
#if 0
|
#if 0
|
||||||
@ -138,6 +143,7 @@ class TestQgsGeometry : public QObject
|
|||||||
|
|
||||||
void minimalEnclosingCircle( );
|
void minimalEnclosingCircle( );
|
||||||
void splitGeometry();
|
void splitGeometry();
|
||||||
|
void snappedToGrid();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! A helper method to do a render check to see if the geometry op is as expected
|
//! A helper method to do a render check to see if the geometry op is as expected
|
||||||
@ -14749,6 +14755,66 @@ void TestQgsGeometry::comparePolygons()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function (in anonymous namespace to prevent possible link with the extirior)
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
inline void testCreateEmptyWithSameType( bool canBeEmpty = true )
|
||||||
|
{
|
||||||
|
std::unique_ptr<QgsAbstractGeometry> geom { new T() };
|
||||||
|
std::unique_ptr<QgsAbstractGeometry> created { geom->createEmptyWithSameType() };
|
||||||
|
if ( canBeEmpty )
|
||||||
|
{
|
||||||
|
QVERIFY( created->isEmpty() );
|
||||||
|
}
|
||||||
|
// Check that it is the correct type
|
||||||
|
QVERIFY( static_cast<T *>( created.get() ) != nullptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsGeometry::createEmptyWithSameType()
|
||||||
|
{
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsCircularString" );
|
||||||
|
testCreateEmptyWithSameType<QgsCircularString>();
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsCompoundCurve" );
|
||||||
|
testCreateEmptyWithSameType<QgsCompoundCurve>();
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsLineString" );
|
||||||
|
testCreateEmptyWithSameType<QgsLineString>();
|
||||||
|
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsGeometryCollection" );
|
||||||
|
testCreateEmptyWithSameType<QgsGeometryCollection>();
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsMultiCurve" );
|
||||||
|
testCreateEmptyWithSameType<QgsMultiCurve>();
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsMultiLineString" );
|
||||||
|
testCreateEmptyWithSameType<QgsMultiLineString>();
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsMultiPointV2" );
|
||||||
|
testCreateEmptyWithSameType<QgsMultiPointV2>();
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsMultiSurface" );
|
||||||
|
testCreateEmptyWithSameType<QgsMultiSurface>();
|
||||||
|
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsPoint" );
|
||||||
|
testCreateEmptyWithSameType<QgsPoint>( false );
|
||||||
|
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsCurvePolygon" );
|
||||||
|
testCreateEmptyWithSameType<QgsCurvePolygon>();
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsPolygonV2" );
|
||||||
|
testCreateEmptyWithSameType<QgsPolygonV2>();
|
||||||
|
|
||||||
|
qDebug( "createEmptyWithSameType(): QgsTriangle" );
|
||||||
|
testCreateEmptyWithSameType<QgsTriangle>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MK, Disabled 14.11.2014
|
// MK, Disabled 14.11.2014
|
||||||
// Too unclear what exactly should be tested and which variations are allowed for the line
|
// Too unclear what exactly should be tested and which variations are allowed for the line
|
||||||
@ -15595,6 +15661,95 @@ void TestQgsGeometry::splitGeometry()
|
|||||||
QVERIFY( newGeoms.isEmpty() );
|
QVERIFY( newGeoms.isEmpty() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestQgsGeometry::snappedToGrid()
|
||||||
|
{
|
||||||
|
qDebug( "SnappedToGrid" );
|
||||||
|
// points
|
||||||
|
{
|
||||||
|
qDebug( "\tPoints:" );
|
||||||
|
auto check = []( QgsPoint * _a, QgsPoint const & b )
|
||||||
|
{
|
||||||
|
std::unique_ptr<QgsPoint> a {_a};
|
||||||
|
// because it is to check after snapping, there shouldn't be small precision errors
|
||||||
|
|
||||||
|
qDebug( "\t\tGridified point: %f, %f, %f, %f", a->x(), a->y(), a->z(), a->m() );
|
||||||
|
qDebug( "\t\tExpected point: %f, %f, %f, %f", b.x(), b.y(), b.z(), b.m() );
|
||||||
|
if ( !std::isnan( b.x() ) )
|
||||||
|
QVERIFY( ( float )a->x() == ( float )b.x() );
|
||||||
|
|
||||||
|
if ( !std::isnan( b.y() ) )
|
||||||
|
QVERIFY( ( float )a->y() == ( float )b.y() );
|
||||||
|
|
||||||
|
if ( !std::isnan( b.z() ) )
|
||||||
|
QVERIFY( ( float )a->z() == ( float )b.z() );
|
||||||
|
|
||||||
|
if ( !std::isnan( b.m() ) )
|
||||||
|
QVERIFY( ( float )a->m() == ( float )b.m() );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
check( QgsPoint( 0, 0 ).snappedToGrid( 1, 1 ),
|
||||||
|
QgsPoint( 0, 0 ) );
|
||||||
|
|
||||||
|
check( QgsPoint( 1, 2.732 ).snappedToGrid( 1, 1 ),
|
||||||
|
QgsPoint( 1, 3 ) );
|
||||||
|
|
||||||
|
check( QgsPoint( 1.3, 6.4 ).snappedToGrid( 1, 1 ),
|
||||||
|
QgsPoint( 1, 6 ) );
|
||||||
|
|
||||||
|
check( QgsPoint( 1.3, 6.4 ).snappedToGrid( 1, 0 ),
|
||||||
|
QgsPoint( 1, 6.4 ) );
|
||||||
|
|
||||||
|
|
||||||
|
// multiple checks with the same point
|
||||||
|
auto p1 = QgsPoint( 1.38, 2.4432 );
|
||||||
|
|
||||||
|
check( p1.snappedToGrid( 1, 1 ),
|
||||||
|
QgsPoint( 1, 2 ) );
|
||||||
|
|
||||||
|
check( p1.snappedToGrid( 1, 0.1 ),
|
||||||
|
QgsPoint( 1, 2.4 ) );
|
||||||
|
|
||||||
|
check( p1.snappedToGrid( 1, 0.01 ),
|
||||||
|
QgsPoint( 1, 2.44 ) );
|
||||||
|
|
||||||
|
// Let's test more dimensions
|
||||||
|
auto p2 = QgsPoint( 4.2134212, 543.1231, 0.123, 12.944145 );
|
||||||
|
|
||||||
|
check( p2.snappedToGrid( 0, 0, 0, 0 ),
|
||||||
|
p2 );
|
||||||
|
|
||||||
|
check( p2.snappedToGrid( 0, 0, 1, 1 ),
|
||||||
|
QgsPoint( 4.2134212, 543.1231, 0, 13 ) );
|
||||||
|
|
||||||
|
check( p2.snappedToGrid( 1, 0.1, 0.01, 0.001 ),
|
||||||
|
QgsPoint( 4, 543.1, 0.12, 12.944 ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiPolygon (testing QgsCollection, QgsCurvePolygon and QgsLineString)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* List of tested edge cases:
|
||||||
|
*
|
||||||
|
* - QgsLineString becoming a point
|
||||||
|
* - QgsLineString losing enough points so it is no longer closed
|
||||||
|
* - QgsCurvePolygon losing its external ring
|
||||||
|
* - QgsCurvePolygon losing an internal ring
|
||||||
|
* - QgsCurvePolygon losing all internal rings
|
||||||
|
* - QgsCollection losing one of its members
|
||||||
|
* - QgsCollection losing all its members
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto in = QString( "MultiPolygon (((-1.2 -0.87, -0.943 0.8, 0.82 1.4, 1.2 0.9, 0.9 -0.6, -1.2 -0.87),(0.4 0, -0.4 0, 0 0.2, 0.4 0)),((2 0, 2.2 0.2, 2.2 -0.2)),((3 0, 4 0.2, 4 -0.2, 3 0)),((4 8, 3.6 4.1, 0.3 4.9, -0.2 7.8, 4 8),(6.7 7.3, 7 6.4, 5.6 5.9, 6.2 6.8, 6.7 7.3),(6 5.2, 4.9 5.3, 4.8 6.2, 6 5.2)))" );
|
||||||
|
auto out = QString( "MultiPolygon (((-1 -1, -1 1, 1 1, 1 -1, -1 -1)),((4 8, 4 4, 0 5, 0 8, 4 8),(7 7, 7 6, 6 6, 6 7, 7 7),(6 5, 5 5, 5 6, 6 5)))" );
|
||||||
|
|
||||||
|
auto inGeom = QgsGeometryFactory::geomFromWkt( in );
|
||||||
|
|
||||||
|
std::unique_ptr<QgsAbstractGeometry> snapped { inGeom->snappedToGrid( 1, 1 ) };
|
||||||
|
QCOMPARE( snapped->asWkt(), out );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QGSTEST_MAIN( TestQgsGeometry )
|
QGSTEST_MAIN( TestQgsGeometry )
|
||||||
#include "testqgsgeometry.moc"
|
#include "testqgsgeometry.moc"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user