Skip to content
Permalink
Browse files

Gracefully handle topology errors when tracing (fixes #14447)

(cherry picked from commit 11e7140)
  • Loading branch information
wonder-sk committed Apr 27, 2016
1 parent 8244947 commit 80102b1a388c7c52fc09293c130f8c158046d98a
Showing with 45 additions and 9 deletions.
  1. +5 −0 python/core/qgstracer.sip
  2. +27 −9 src/core/qgstracer.cpp
  3. +8 −0 src/core/qgstracer.h
  4. +5 −0 src/gui/qgsmapcanvastracer.cpp
@@ -49,6 +49,11 @@ class QgsTracer : QObject
//! Whether the internal data structures have been initialized
bool isInitialized() const;

//! Whether there was an error during graph creation due to noding exception,
//! indicating some input data topology problems
//! @note added in QGIS 2.14.2
bool hasTopologyProblem() const;

//! Possible errors that may happen when calling findShortestPath()
enum PathError
{
@@ -17,6 +17,7 @@

#include "qgsgeometry.h"
#include "qgsgeometryutils.h"
#include "qgsgeos.h"
#include "qgslogger.h"
#include "qgsvectorlayer.h"

@@ -439,6 +440,7 @@ QgsTracer::QgsTracer()
: mGraph( 0 )
, mReprojectionEnabled( false )
, mMaxFeatureCount( 0 )
, mHasTopologyProblem( false )
{
}

@@ -448,6 +450,8 @@ bool QgsTracer::initGraph()
if ( mGraph )
return true; // already initialized

mHasTopologyProblem = false;

QgsFeature f;
QgsMultiPolyline mpl;

@@ -499,23 +503,37 @@ bool QgsTracer::initGraph()

t2.start();

int timeNodingCall = 0;

#if 0
// without noding - if data are known to be noded beforehand
int timeNodingCall = 0;
#else
QgsGeometry* allGeom = QgsGeometry::fromMultiPolyline( mpl );

t2a.start();
GEOSGeometry* allNoded = GEOSNode_r( QgsGeometry::getGEOSHandler(), allGeom->asGeos() );
int timeNodingCall = t2a.elapsed();
try
{
t2a.start();
// GEOSNode_r may throw an exception
GEOSGeometry* allNoded = GEOSNode_r( QgsGeometry::getGEOSHandler(), allGeom->asGeos() );
timeNodingCall = t2a.elapsed();

QgsGeometry* noded = new QgsGeometry;
noded->fromGeos( allNoded );
delete allGeom;

QgsGeometry* noded = new QgsGeometry;
noded->fromGeos( allNoded );
delete allGeom;
mpl = noded->asMultiPolyline();

mpl = noded->asMultiPolyline();
delete noded;
}
catch ( GEOSException &e )
{
// no big deal... we will just not have nicely noded linework, potentially
// missing some intersections

delete noded;
mHasTopologyProblem = true;

QgsDebugMsg( "Tracer Noding Exception: " + e.what() );
}
#endif

int timeNoding = t2.elapsed();
@@ -76,6 +76,11 @@ class CORE_EXPORT QgsTracer : public QObject
//! Whether the internal data structures have been initialized
bool isInitialized() const { return mGraph != nullptr; }

//! Whether there was an error during graph creation due to noding exception,
//! indicating some input data topology problems
//! @note added in QGIS 2.14.2
bool hasTopologyProblem() const { return mHasTopologyProblem; }

//! Possible errors that may happen when calling findShortestPath()
enum PathError
{
@@ -127,6 +132,9 @@ class CORE_EXPORT QgsTracer : public QObject
//! Limit of how many features can be in the graph (0 means no limit).
//! This is to avoid possibly long graph preparation for complicated layers
int mMaxFeatureCount;
//! A flag indicating that there was an error during graph creation
//! due to noding exception, indicating some input data topology problems
bool mHasTopologyProblem;
};


@@ -65,6 +65,11 @@ void QgsMapCanvasTracer::reportError( QgsTracer::PathError err, bool addingVerte
break;
}

if ( message.isEmpty() && hasTopologyProblem() )
{
message = tr( "Tracing may not work correctly. Please check topology of the input layers." );
}

if ( message.isEmpty() )
return;

0 comments on commit 80102b1

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