mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Add QgsGeometry::isSimple() - useful for self-intersection checks
This commit is contained in:
parent
09975cec07
commit
e001d5c70a
@ -188,6 +188,19 @@ Returns true if WKB of the geometry is of WKBMulti* type
|
|||||||
:rtype: bool
|
:rtype: bool
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
bool isSimple() const;
|
||||||
|
%Docstring
|
||||||
|
Determines whether the geometry is simple (according to OGC definition),
|
||||||
|
i.e. it has no anomalous geometric points, such as self-intersection or self-tangency.
|
||||||
|
Uses GEOS library for the test.
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This is useful mainly for linestrings and linear rings. Polygons are simple by definition,
|
||||||
|
for checking anomalies in polygon geometries one can use isGeosValid().
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
:rtype: bool
|
||||||
|
%End
|
||||||
|
|
||||||
double area() const;
|
double area() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns the area of the geometry using GEOS
|
Returns the area of the geometry using GEOS
|
||||||
|
@ -155,6 +155,13 @@ class QgsGeometryEngine
|
|||||||
:rtype: bool
|
:rtype: bool
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
virtual bool isSimple( QString *errorMsg = 0 ) const = 0;
|
||||||
|
%Docstring
|
||||||
|
Determines whether the geometry is simple (according to OGC definition).
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
:rtype: bool
|
||||||
|
%End
|
||||||
|
|
||||||
virtual int splitGeometry( const QgsLineString &splitLine,
|
virtual int splitGeometry( const QgsLineString &splitLine,
|
||||||
QList<QgsAbstractGeometry *> &newGeometries,
|
QList<QgsAbstractGeometry *> &newGeometries,
|
||||||
bool topological,
|
bool topological,
|
||||||
|
@ -1980,6 +1980,15 @@ bool QgsGeometry::isGeosValid() const
|
|||||||
return geos.isValid();
|
return geos.isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QgsGeometry::isSimple() const
|
||||||
|
{
|
||||||
|
if ( !d->geometry )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QgsGeos geos( d->geometry );
|
||||||
|
return geos.isSimple();
|
||||||
|
}
|
||||||
|
|
||||||
bool QgsGeometry::isGeosEqual( const QgsGeometry &g ) const
|
bool QgsGeometry::isGeosEqual( const QgsGeometry &g ) const
|
||||||
{
|
{
|
||||||
if ( !d->geometry || !g.d->geometry )
|
if ( !d->geometry || !g.d->geometry )
|
||||||
|
@ -213,6 +213,15 @@ class CORE_EXPORT QgsGeometry
|
|||||||
*/
|
*/
|
||||||
bool isGeosValid() const;
|
bool isGeosValid() const;
|
||||||
|
|
||||||
|
/** Determines whether the geometry is simple (according to OGC definition),
|
||||||
|
* i.e. it has no anomalous geometric points, such as self-intersection or self-tangency.
|
||||||
|
* Uses GEOS library for the test.
|
||||||
|
* \note This is useful mainly for linestrings and linear rings. Polygons are simple by definition,
|
||||||
|
* for checking anomalies in polygon geometries one can use isGeosValid().
|
||||||
|
* \since QGIS 3.0
|
||||||
|
*/
|
||||||
|
bool isSimple() const;
|
||||||
|
|
||||||
/** Returns the area of the geometry using GEOS
|
/** Returns the area of the geometry using GEOS
|
||||||
\since QGIS 1.5
|
\since QGIS 1.5
|
||||||
*/
|
*/
|
||||||
|
@ -83,6 +83,11 @@ class CORE_EXPORT QgsGeometryEngine
|
|||||||
virtual bool isEqual( const QgsAbstractGeometry &geom, QString *errorMsg = nullptr ) const = 0;
|
virtual bool isEqual( const QgsAbstractGeometry &geom, QString *errorMsg = nullptr ) const = 0;
|
||||||
virtual bool isEmpty( QString *errorMsg ) const = 0;
|
virtual bool isEmpty( QString *errorMsg ) const = 0;
|
||||||
|
|
||||||
|
/** Determines whether the geometry is simple (according to OGC definition).
|
||||||
|
* \since QGIS 3.0
|
||||||
|
*/
|
||||||
|
virtual bool isSimple( QString *errorMsg = nullptr ) const = 0;
|
||||||
|
|
||||||
virtual int splitGeometry( const QgsLineString &splitLine,
|
virtual int splitGeometry( const QgsLineString &splitLine,
|
||||||
QList<QgsAbstractGeometry *> &newGeometries,
|
QList<QgsAbstractGeometry *> &newGeometries,
|
||||||
bool topological,
|
bool topological,
|
||||||
|
@ -1494,6 +1494,20 @@ bool QgsGeos::isEmpty( QString *errorMsg ) const
|
|||||||
CATCH_GEOS_WITH_ERRMSG( false );
|
CATCH_GEOS_WITH_ERRMSG( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QgsGeos::isSimple( QString *errorMsg ) const
|
||||||
|
{
|
||||||
|
if ( !mGeos )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return GEOSisSimple_r( geosinit.ctxt, mGeos );
|
||||||
|
}
|
||||||
|
CATCH_GEOS_WITH_ERRMSG( false );
|
||||||
|
}
|
||||||
|
|
||||||
GEOSCoordSequence *QgsGeos::createCoordinateSequence( const QgsCurve *curve, double precision, bool forceClose )
|
GEOSCoordSequence *QgsGeos::createCoordinateSequence( const QgsCurve *curve, double precision, bool forceClose )
|
||||||
{
|
{
|
||||||
bool segmentize = false;
|
bool segmentize = false;
|
||||||
|
@ -71,6 +71,7 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
|
|||||||
bool isValid( QString *errorMsg = nullptr ) const override;
|
bool isValid( QString *errorMsg = nullptr ) const override;
|
||||||
bool isEqual( const QgsAbstractGeometry &geom, QString *errorMsg = nullptr ) const override;
|
bool isEqual( const QgsAbstractGeometry &geom, QString *errorMsg = nullptr ) const override;
|
||||||
bool isEmpty( QString *errorMsg = nullptr ) const override;
|
bool isEmpty( QString *errorMsg = nullptr ) const override;
|
||||||
|
bool isSimple( QString *errorMsg = nullptr ) const override;
|
||||||
|
|
||||||
/** Splits this geometry according to a given line.
|
/** Splits this geometry according to a given line.
|
||||||
\param splitLine the line that splits the geometry
|
\param splitLine the line that splits the geometry
|
||||||
|
@ -124,6 +124,8 @@ class TestQgsGeometry : public QObject
|
|||||||
|
|
||||||
void makeValid();
|
void makeValid();
|
||||||
|
|
||||||
|
void isSimple();
|
||||||
|
|
||||||
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
|
||||||
bool renderCheck( const QString &testName, const QString &comment = QLatin1String( QLatin1String( "" ) ), int mismatchCount = 0 );
|
bool renderCheck( const QString &testName, const QString &comment = QLatin1String( QLatin1String( "" ) ), int mismatchCount = 0 );
|
||||||
@ -5423,5 +5425,32 @@ void TestQgsGeometry::makeValid()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestQgsGeometry::isSimple()
|
||||||
|
{
|
||||||
|
typedef QPair<QString, bool> InputWktAndExpectedResult;
|
||||||
|
QList<InputWktAndExpectedResult> geoms;
|
||||||
|
geoms << qMakePair( QString( "LINESTRING(0 0, 1 0, 1 1)" ), true );
|
||||||
|
geoms << qMakePair( QString( "LINESTRING(0 0, 1 0, 1 1, 0 0)" ), true ); // may be closed (linear ring)
|
||||||
|
geoms << qMakePair( QString( "LINESTRING(0 0, 1 0, 1 1, 0 -1)" ), false ); // self-intersection
|
||||||
|
geoms << qMakePair( QString( "LINESTRING(0 0, 1 0, 1 1, 0.5 0, 0 1)" ), false ); // self-tangency
|
||||||
|
geoms << qMakePair( QString( "POINT(1 1)" ), true ); // points are simple
|
||||||
|
geoms << qMakePair( QString( "POLYGON((0 0, 1 1, 1 1, 0 0))" ), true ); // polygons are always simple, even if they are invalid
|
||||||
|
geoms << qMakePair( QString( "MULTIPOINT((1 1), (2 2))" ), true );
|
||||||
|
geoms << qMakePair( QString( "MULTIPOINT((1 1), (1 1))" ), false ); // must not contain the same point twice
|
||||||
|
geoms << qMakePair( QString( "MULTILINESTRING((0 0, 1 0), (0 1, 1 1))" ), true );
|
||||||
|
geoms << qMakePair( QString( "MULTILINESTRING((0 0, 1 0), (0 0, 1 0))" ), true ); // may be touching at endpoints
|
||||||
|
geoms << qMakePair( QString( "MULTILINESTRING((0 0, 1 1), (0 1, 1 0))" ), false ); // must not intersect each other
|
||||||
|
geoms << qMakePair( QString( "MULTIPOLYGON(((0 0, 1 1, 1 1, 0 0)),((0 0, 1 1, 1 1, 0 0)))" ), true ); // multi-polygons are always simple
|
||||||
|
|
||||||
|
Q_FOREACH ( const InputWktAndExpectedResult &pair, geoms )
|
||||||
|
{
|
||||||
|
QgsGeometry gInput = QgsGeometry::fromWkt( pair.first );
|
||||||
|
QVERIFY( !gInput.isNull() );
|
||||||
|
|
||||||
|
bool res = gInput.isSimple();
|
||||||
|
QCOMPARE( res, pair.second );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QGSTEST_MAIN( TestQgsGeometry )
|
QGSTEST_MAIN( TestQgsGeometry )
|
||||||
#include "testqgsgeometry.moc"
|
#include "testqgsgeometry.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user