Skip to content

Commit 64a86e3

Browse files
committedJun 7, 2017
Add an explicit argument to set QgsGeometryValidator method
Previously this was always read from settings when using QgsGeometryValidator. It's now an explicit argument when constructing QgsGeometryValidator or calling the static validation methods, allowing choice of internal/GEOS validation methods. Helps remove more QgsSettings use from core.
1 parent 5f1a78d commit 64a86e3

File tree

9 files changed

+162
-122
lines changed

9 files changed

+162
-122
lines changed
 

‎python/core/geometry/qgsgeometry.sip

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,9 +1077,16 @@ Ring 0 is outer ring and can't be deleted.
10771077
%End
10781078
};
10791079

1080-
void validateGeometry( QList<QgsGeometry::Error> &errors /Out/ );
1080+
enum ValidationMethod
1081+
{
1082+
ValidatorQgisInternal,
1083+
ValidatorGeos,
1084+
};
1085+
1086+
void validateGeometry( QList<QgsGeometry::Error> &errors /Out/, ValidationMethod method = ValidatorQgisInternal );
10811087
%Docstring
1082-
Validate geometry and produce a list of geometry errors
1088+
Validate geometry and produce a list of geometry errors.
1089+
The ``method`` argument dictates which validator to utilize.
10831090
.. versionadded:: 1.5
10841091
.. note::
10851092

‎python/core/qgsgeometryvalidator.sip

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@ class QgsGeometryValidator : QThread
1515
#include "qgsgeometryvalidator.h"
1616
%End
1717
public:
18-
QgsGeometryValidator( const QgsGeometry *g, QList<QgsGeometry::Error> *errors = 0 );
18+
19+
QgsGeometryValidator( const QgsGeometry *g, QList<QgsGeometry::Error> *errors = 0, QgsGeometry::ValidationMethod method = QgsGeometry::ValidatorQgisInternal );
1920
%Docstring
20-
Constructor
21+
Constructor for QgsGeometryValidator.
2122
%End
2223
~QgsGeometryValidator();
2324

2425
virtual void run();
2526

2627
void stop();
2728

28-
static void validateGeometry( const QgsGeometry *g, QList<QgsGeometry::Error> &errors /Out/ );
29+
static void validateGeometry( const QgsGeometry *g, QList<QgsGeometry::Error> &errors /Out/, QgsGeometry::ValidationMethod method = QgsGeometry::ValidatorQgisInternal );
2930
%Docstring
3031
Validate geometry and produce a list of geometry errors
3132
%End
@@ -36,7 +37,7 @@ Validate geometry and produce a list of geometry errors
3637
public slots:
3738
void addError( const QgsGeometry::Error & );
3839

39-
}; // class QgsGeometryValidator
40+
};
4041

4142
/************************************************************************
4243
* This file has been generated automatically from *

‎src/app/nodetool/qgsnodetool.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1814,7 +1814,12 @@ void QgsNodeTool::GeometryValidation::start( QgsGeometry &geom, QgsNodeTool *t,
18141814
{
18151815
tool = t;
18161816
layer = l;
1817-
validator = new QgsGeometryValidator( &geom );
1817+
QgsGeometry::ValidationMethod method = QgsGeometry::ValidatorQgisInternal;
1818+
QgsSettings settings;
1819+
if ( settings.value( QStringLiteral( "qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 )
1820+
method = QgsGeometry::ValidatorGeos;
1821+
1822+
validator = new QgsGeometryValidator( &geom, nullptr, method );
18181823
connect( validator, &QgsGeometryValidator::errorFound, tool, &QgsNodeTool::validationErrorFound );
18191824
connect( validator, &QThread::finished, tool, &QgsNodeTool::validationFinished );
18201825
validator->start();

‎src/app/nodetool/qgsselectedfeature.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,10 @@ void QgsSelectedFeature::validateGeometry( QgsGeometry *g )
185185
delete vm;
186186
}
187187

188-
mValidator = new QgsGeometryValidator( g );
188+
QgsGeometry::ValidationMethod method = QgsGeometry::ValidatorQgisInternal;
189+
if ( settings.value( QStringLiteral( "qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 )
190+
method = QgsGeometry::ValidatorGeos;
191+
mValidator = new QgsGeometryValidator( g, nullptr, method );
189192
connect( mValidator, &QgsGeometryValidator::errorFound, this, &QgsSelectedFeature::addError );
190193
connect( mValidator, &QThread::finished, this, &QgsSelectedFeature::validationFinished );
191194
mValidator->start();

‎src/core/geometry/qgsgeometry.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,9 +1964,9 @@ QgsGeometry QgsGeometry::makeValid()
19641964
}
19651965

19661966

1967-
void QgsGeometry::validateGeometry( QList<QgsGeometry::Error> &errors )
1967+
void QgsGeometry::validateGeometry( QList<QgsGeometry::Error> &errors, ValidationMethod method )
19681968
{
1969-
QgsGeometryValidator::validateGeometry( this, errors );
1969+
QgsGeometryValidator::validateGeometry( this, errors, method );
19701970
}
19711971

19721972
bool QgsGeometry::isGeosValid() const

‎src/core/geometry/qgsgeometry.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -946,11 +946,22 @@ class CORE_EXPORT QgsGeometry
946946
bool hasWhere() { return hasLocation; }
947947
};
948948

949-
/** Validate geometry and produce a list of geometry errors
949+
/**
950+
* Available methods for validating geometries.
951+
* \since QGIS 3.0
952+
*/
953+
enum ValidationMethod
954+
{
955+
ValidatorQgisInternal, //!< Use internal QgsGeometryValidator method
956+
ValidatorGeos, //!< Use GEOS validation methods
957+
};
958+
959+
/** Validate geometry and produce a list of geometry errors.
960+
* The \a method argument dictates which validator to utilize.
950961
* \since QGIS 1.5
951962
* \note Available in Python bindings since QGIS 1.6
952963
**/
953-
void validateGeometry( QList<QgsGeometry::Error> &errors SIP_OUT );
964+
void validateGeometry( QList<QgsGeometry::Error> &errors SIP_OUT, ValidationMethod method = ValidatorQgisInternal );
954965

955966
/** Compute the unary union on a list of \a geometries. May be faster than an iterative union on a set of geometries.
956967
* The returned geometry will be fully noded, i.e. a node will be created at every common intersection of the

‎src/core/qgsgeometryvalidator.cpp

Lines changed: 111 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ email : jef at norbit dot de
1717
#include "qgsgeometryvalidator.h"
1818
#include "qgsgeometry.h"
1919
#include "qgslogger.h"
20-
#include "qgssettings.h"
2120

22-
QgsGeometryValidator::QgsGeometryValidator( const QgsGeometry *g, QList<QgsGeometry::Error> *errors )
21+
QgsGeometryValidator::QgsGeometryValidator( const QgsGeometry *g, QList<QgsGeometry::Error> *errors, QgsGeometry::ValidationMethod method )
2322
: QThread()
2423
, mErrors( errors )
2524
, mStop( false )
2625
, mErrorCount( 0 )
26+
, mMethod( method )
2727
{
2828
Q_ASSERT( g );
2929
if ( g )
@@ -215,134 +215,140 @@ void QgsGeometryValidator::validatePolygon( int idx, const QgsPolygon &polygon )
215215
void QgsGeometryValidator::run()
216216
{
217217
mErrorCount = 0;
218-
QgsSettings settings;
219-
if ( settings.value( QStringLiteral( "qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 )
218+
switch ( mMethod )
220219
{
221-
char *r = nullptr;
222-
GEOSGeometry *g0 = mG.exportToGeos();
223-
GEOSContextHandle_t handle = QgsGeometry::getGEOSHandler();
224-
if ( !g0 )
220+
case QgsGeometry::ValidatorGeos:
225221
{
226-
emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:could not produce geometry for GEOS (check log window)" ) ) );
227-
}
228-
else
229-
{
230-
GEOSGeometry *g1 = nullptr;
231-
char res = GEOSisValidDetail_r( handle, g0, GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 );
232-
GEOSGeom_destroy_r( handle, g0 );
233-
if ( res != 1 )
222+
char *r = nullptr;
223+
GEOSGeometry *g0 = mG.exportToGeos();
224+
GEOSContextHandle_t handle = QgsGeometry::getGEOSHandler();
225+
if ( !g0 )
226+
{
227+
emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:could not produce geometry for GEOS (check log window)" ) ) );
228+
}
229+
else
234230
{
235-
if ( g1 )
231+
GEOSGeometry *g1 = nullptr;
232+
char res = GEOSisValidDetail_r( handle, g0, GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 );
233+
GEOSGeom_destroy_r( handle, g0 );
234+
if ( res != 1 )
236235
{
237-
const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( handle, g1 );
238-
239-
unsigned int n;
240-
if ( GEOSCoordSeq_getSize_r( handle, cs, &n ) && n == 1 )
236+
if ( g1 )
237+
{
238+
const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( handle, g1 );
239+
240+
unsigned int n;
241+
if ( GEOSCoordSeq_getSize_r( handle, cs, &n ) && n == 1 )
242+
{
243+
double x, y;
244+
GEOSCoordSeq_getX_r( handle, cs, 0, &x );
245+
GEOSCoordSeq_getY_r( handle, cs, 0, &y );
246+
emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:%1" ).arg( r ), QgsPointXY( x, y ) ) );
247+
mErrorCount++;
248+
}
249+
250+
GEOSGeom_destroy_r( handle, g1 );
251+
}
252+
else
241253
{
242-
double x, y;
243-
GEOSCoordSeq_getX_r( handle, cs, 0, &x );
244-
GEOSCoordSeq_getY_r( handle, cs, 0, &y );
245-
emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:%1" ).arg( r ), QgsPointXY( x, y ) ) );
254+
emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:%1" ).arg( r ) ) );
246255
mErrorCount++;
247256
}
248257

249-
GEOSGeom_destroy_r( handle, g1 );
250-
}
251-
else
252-
{
253-
emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:%1" ).arg( r ) ) );
254-
mErrorCount++;
258+
GEOSFree_r( handle, r );
255259
}
256-
257-
GEOSFree_r( handle, r );
258260
}
259-
}
260-
261-
return;
262-
}
263261

264-
QgsDebugMsg( "validation thread started." );
265-
266-
QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( mG.wkbType() );
267-
//if ( flatType == QgsWkbTypes::Point || flatType == QgsWkbTypes::MultiPoint )
268-
// break;
269-
if ( flatType == QgsWkbTypes::LineString )
270-
{
271-
validatePolyline( 0, mG.asPolyline() );
272-
}
273-
else if ( flatType == QgsWkbTypes::MultiLineString )
274-
{
275-
QgsMultiPolyline mp = mG.asMultiPolyline();
276-
for ( int i = 0; !mStop && i < mp.size(); i++ )
277-
validatePolyline( i, mp[i] );
278-
}
279-
else if ( flatType == QgsWkbTypes::Polygon )
280-
{
281-
validatePolygon( 0, mG.asPolygon() );
282-
}
283-
else if ( flatType == QgsWkbTypes::MultiPolygon )
284-
{
285-
QgsMultiPolygon mp = mG.asMultiPolygon();
286-
for ( int i = 0; !mStop && i < mp.size(); i++ )
287-
{
288-
validatePolygon( i, mp[i] );
262+
break;
289263
}
290264

291-
for ( int i = 0; !mStop && i < mp.size(); i++ )
265+
case QgsGeometry::ValidatorQgisInternal:
292266
{
293-
if ( mp[i].isEmpty() )
267+
QgsDebugMsg( "validation thread started." );
268+
269+
QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( mG.wkbType() );
270+
//if ( flatType == QgsWkbTypes::Point || flatType == QgsWkbTypes::MultiPoint )
271+
// break;
272+
if ( flatType == QgsWkbTypes::LineString )
294273
{
295-
emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 has no rings" ).arg( i ) ) );
296-
mErrorCount++;
297-
continue;
274+
validatePolyline( 0, mG.asPolyline() );
298275
}
299-
300-
for ( int j = i + 1; !mStop && j < mp.size(); j++ )
276+
else if ( flatType == QgsWkbTypes::MultiLineString )
301277
{
302-
if ( mp[j].isEmpty() )
303-
continue;
304-
305-
if ( ringInRing( mp[i][0], mp[j][0] ) )
306-
{
307-
emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) ) );
308-
mErrorCount++;
309-
}
310-
else if ( ringInRing( mp[j][0], mp[i][0] ) )
278+
QgsMultiPolyline mp = mG.asMultiPolyline();
279+
for ( int i = 0; !mStop && i < mp.size(); i++ )
280+
validatePolyline( i, mp[i] );
281+
}
282+
else if ( flatType == QgsWkbTypes::Polygon )
283+
{
284+
validatePolygon( 0, mG.asPolygon() );
285+
}
286+
else if ( flatType == QgsWkbTypes::MultiPolygon )
287+
{
288+
QgsMultiPolygon mp = mG.asMultiPolygon();
289+
for ( int i = 0; !mStop && i < mp.size(); i++ )
311290
{
312-
emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) ) );
313-
mErrorCount++;
291+
validatePolygon( i, mp[i] );
314292
}
315-
else
293+
294+
for ( int i = 0; !mStop && i < mp.size(); i++ )
316295
{
317-
checkRingIntersections( i, 0, mp[i][0], j, 0, mp[j][0] );
296+
if ( mp[i].isEmpty() )
297+
{
298+
emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 has no rings" ).arg( i ) ) );
299+
mErrorCount++;
300+
continue;
301+
}
302+
303+
for ( int j = i + 1; !mStop && j < mp.size(); j++ )
304+
{
305+
if ( mp[j].isEmpty() )
306+
continue;
307+
308+
if ( ringInRing( mp[i][0], mp[j][0] ) )
309+
{
310+
emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) ) );
311+
mErrorCount++;
312+
}
313+
else if ( ringInRing( mp[j][0], mp[i][0] ) )
314+
{
315+
emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) ) );
316+
mErrorCount++;
317+
}
318+
else
319+
{
320+
checkRingIntersections( i, 0, mp[i][0], j, 0, mp[j][0] );
321+
}
322+
}
318323
}
319324
}
320-
}
321-
}
322325

323-
else if ( flatType == QgsWkbTypes::Unknown )
324-
{
325-
QgsDebugMsg( QObject::tr( "Unknown geometry type" ) );
326-
emit errorFound( QgsGeometry::Error( QObject::tr( "Unknown geometry type %1" ).arg( mG.wkbType() ) ) );
327-
mErrorCount++;
328-
}
326+
else if ( flatType == QgsWkbTypes::Unknown )
327+
{
328+
QgsDebugMsg( QObject::tr( "Unknown geometry type" ) );
329+
emit errorFound( QgsGeometry::Error( QObject::tr( "Unknown geometry type %1" ).arg( mG.wkbType() ) ) );
330+
mErrorCount++;
331+
}
329332

330-
QgsDebugMsg( "validation finished." );
333+
QgsDebugMsg( "validation finished." );
331334

332-
if ( mStop )
333-
{
334-
emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry validation was aborted." ) ) );
335-
}
336-
else if ( mErrorCount > 0 )
337-
{
338-
emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry has %1 errors." ).arg( mErrorCount ) ) );
339-
}
335+
if ( mStop )
336+
{
337+
emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry validation was aborted." ) ) );
338+
}
339+
else if ( mErrorCount > 0 )
340+
{
341+
emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry has %1 errors." ).arg( mErrorCount ) ) );
342+
}
340343
#if 0
341-
else
342-
{
343-
emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry is valid." ) ) );
344-
}
344+
else
345+
{
346+
emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry is valid." ) ) );
347+
}
345348
#endif
349+
break;
350+
}
351+
}
346352
}
347353

348354
void QgsGeometryValidator::addError( const QgsGeometry::Error &e )
@@ -351,9 +357,9 @@ void QgsGeometryValidator::addError( const QgsGeometry::Error &e )
351357
*mErrors << e;
352358
}
353359

354-
void QgsGeometryValidator::validateGeometry( const QgsGeometry *g, QList<QgsGeometry::Error> &errors )
360+
void QgsGeometryValidator::validateGeometry( const QgsGeometry *g, QList<QgsGeometry::Error> &errors, QgsGeometry::ValidationMethod method )
355361
{
356-
QgsGeometryValidator *gv = new QgsGeometryValidator( g, &errors );
362+
QgsGeometryValidator *gv = new QgsGeometryValidator( g, &errors, method );
357363
connect( gv, &QgsGeometryValidator::errorFound, gv, &QgsGeometryValidator::addError );
358364
gv->run();
359365
gv->wait();

‎src/core/qgsgeometryvalidator.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,18 @@ class CORE_EXPORT QgsGeometryValidator : public QThread
2929
Q_OBJECT
3030

3131
public:
32-
//! Constructor
33-
QgsGeometryValidator( const QgsGeometry *g, QList<QgsGeometry::Error> *errors = nullptr );
32+
33+
/**
34+
* Constructor for QgsGeometryValidator.
35+
*/
36+
QgsGeometryValidator( const QgsGeometry *g, QList<QgsGeometry::Error> *errors = nullptr, QgsGeometry::ValidationMethod method = QgsGeometry::ValidatorQgisInternal );
3437
~QgsGeometryValidator();
3538

3639
void run() override;
3740
void stop();
3841

3942
//! Validate geometry and produce a list of geometry errors
40-
static void validateGeometry( const QgsGeometry *g, QList<QgsGeometry::Error> &errors SIP_OUT );
43+
static void validateGeometry( const QgsGeometry *g, QList<QgsGeometry::Error> &errors SIP_OUT, QgsGeometry::ValidationMethod method = QgsGeometry::ValidatorQgisInternal );
4144

4245
signals:
4346
void errorFound( const QgsGeometry::Error & );
@@ -58,6 +61,7 @@ class CORE_EXPORT QgsGeometryValidator : public QThread
5861
QList<QgsGeometry::Error> *mErrors;
5962
bool mStop;
6063
int mErrorCount;
61-
}; // class QgsGeometryValidator
64+
QgsGeometry::ValidationMethod mMethod = QgsGeometry::ValidatorQgisInternal;
65+
};
6266

6367
#endif

‎src/gui/qgsmaptoolcapture.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,10 @@ void QgsMapToolCapture::validateGeometry()
663663
if ( !g )
664664
return;
665665

666-
mValidator = new QgsGeometryValidator( g.get() );
666+
QgsGeometry::ValidationMethod method = QgsGeometry::ValidatorQgisInternal;
667+
if ( settings.value( QStringLiteral( "qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 )
668+
method = QgsGeometry::ValidatorGeos;
669+
mValidator = new QgsGeometryValidator( g.get(), nullptr, method );
667670
connect( mValidator, &QgsGeometryValidator::errorFound, this, &QgsMapToolCapture::addError );
668671
connect( mValidator, &QThread::finished, this, &QgsMapToolCapture::validationFinished );
669672
mValidator->start();

0 commit comments

Comments
 (0)
Please sign in to comment.