Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[pal] Catch GEOS exceptions
  • Loading branch information
nyalldawson committed Aug 14, 2015
1 parent 480a0f1 commit fec5d5e
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 157 deletions.
38 changes: 0 additions & 38 deletions src/core/geometry/qgsgeos.cpp
Expand Up @@ -36,44 +36,6 @@ email : marco.hugentobler at sourcepole dot com
return r; \
}

class GEOSException
{
public:
GEOSException( QString theMsg )
{
if ( theMsg == "Unknown exception thrown" && lastMsg.isNull() )
{
msg = theMsg;
}
else
{
msg = theMsg;
lastMsg = msg;
}
}

// copy constructor
GEOSException( const GEOSException &rhs )
{
*this = rhs;
}

~GEOSException()
{
if ( lastMsg == msg )
lastMsg = QString::null;
}

QString what()
{
return msg;
}

private:
QString msg;
static QString lastMsg;
};

QString GEOSException::lastMsg;

static void throwGEOSException( const char *fmt, ... )
Expand Down
42 changes: 42 additions & 0 deletions src/core/geometry/qgsgeos.h
Expand Up @@ -135,4 +135,46 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
static int geomDigits( const GEOSGeometry* geom );
};

/// @cond

class GEOSException
{
public:
GEOSException( QString theMsg )
{
if ( theMsg == "Unknown exception thrown" && lastMsg.isNull() )
{
msg = theMsg;
}
else
{
msg = theMsg;
lastMsg = msg;
}
}

// copy constructor
GEOSException( const GEOSException &rhs )
{
*this = rhs;
}

~GEOSException()
{
if ( lastMsg == msg )
lastMsg = QString::null;
}

QString what()
{
return msg;
}

private:
QString msg;
static QString lastMsg;
};

/// @endcond

#endif // QGSGEOS_H
85 changes: 59 additions & 26 deletions src/core/pal/feature.cpp
Expand Up @@ -43,6 +43,8 @@
#include "pointset.h"
#include "util.h"
#include "qgis.h"
#include "qgsgeos.h"
#include "qgsmessagelog.h"
#include <QLinkedList>
#include <cmath>
#include <cfloat>
Expand Down Expand Up @@ -1322,8 +1324,16 @@ namespace pal
if ( geomType == GEOS_LINESTRING )
{
double length;
if ( GEOSLength_r( ctxt, mGeos, &length ) != 1 )
return; // failed to calculate length
try
{
if ( GEOSLength_r( ctxt, mGeos, &length ) != 1 )
return; // failed to calculate length
}
catch ( GEOSException &e )
{
QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
return;
}
double bbox_length = qMax( bbx[2] - bbx[0], bby[2] - bby[0] );
if ( length >= bbox_length / 4 )
return; // the line is longer than quarter of height or width - don't penalize it
Expand All @@ -1333,8 +1343,16 @@ namespace pal
else if ( geomType == GEOS_POLYGON )
{
double area;
if ( GEOSArea_r( ctxt, mGeos, &area ) != 1 )
try
{
if ( GEOSArea_r( ctxt, mGeos, &area ) != 1 )
return;
}
catch ( GEOSException &e )
{
QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
return;
}
double bbox_area = ( bbx[2] - bbx[0] ) * ( bby[2] - bby[0] );
if ( area >= bbox_area / 16 )
return; // covers more than 1/16 of our view - don't penalize it
Expand All @@ -1358,7 +1376,15 @@ namespace pal
if ( !p2->mGeos )
p2->createGeosGeom();

return ( GEOSPreparedTouches_r( geosContext(), preparedGeom(), p2->mGeos ) == 1 );
try
{
return ( GEOSPreparedTouches_r( geosContext(), preparedGeom(), p2->mGeos ) == 1 );
}
catch ( GEOSException &e )
{
QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
return false;
}
}

bool FeaturePart::mergeWithFeaturePart( FeaturePart* other )
Expand All @@ -1369,31 +1395,38 @@ namespace pal
other->createGeosGeom();

GEOSContextHandle_t ctxt = geosContext();
GEOSGeometry* g1 = GEOSGeom_clone_r( ctxt, mGeos );
GEOSGeometry* g2 = GEOSGeom_clone_r( ctxt, other->mGeos );
GEOSGeometry* geoms[2] = { g1, g2 };
GEOSGeometry* g = GEOSGeom_createCollection_r( ctxt, GEOS_MULTILINESTRING, geoms, 2 );
GEOSGeometry* gTmp = GEOSLineMerge_r( ctxt, g );
GEOSGeom_destroy_r( ctxt, g );

if ( GEOSGeomTypeId_r( ctxt, gTmp ) != GEOS_LINESTRING )
try
{
// sometimes it's not possible to merge lines (e.g. they don't touch at endpoints)
GEOSGeom_destroy_r( ctxt, gTmp );
return false;
}

invalidateGeos();
GEOSGeometry* g1 = GEOSGeom_clone_r( ctxt, mGeos );
GEOSGeometry* g2 = GEOSGeom_clone_r( ctxt, other->mGeos );
GEOSGeometry* geoms[2] = { g1, g2 };
GEOSGeometry* g = GEOSGeom_createCollection_r( ctxt, GEOS_MULTILINESTRING, geoms, 2 );
GEOSGeometry* gTmp = GEOSLineMerge_r( ctxt, g );
GEOSGeom_destroy_r( ctxt, g );

if ( GEOSGeomTypeId_r( ctxt, gTmp ) != GEOS_LINESTRING )
{
// sometimes it's not possible to merge lines (e.g. they don't touch at endpoints)
GEOSGeom_destroy_r( ctxt, gTmp );
return false;
}
invalidateGeos();

// set up new geometry
mGeos = gTmp;
mOwnsGeom = true;
// set up new geometry
mGeos = gTmp;
mOwnsGeom = true;

deleteCoords();
qDeleteAll( mHoles );
mHoles.clear();
extractCoords( mGeos );
return true;
deleteCoords();
qDeleteAll( mHoles );
mHoles.clear();
extractCoords( mGeos );
return true;
}
catch ( GEOSException &e )
{
QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
return false;
}
}

} // end namespace pal
48 changes: 37 additions & 11 deletions src/core/pal/labelposition.cpp
Expand Up @@ -35,6 +35,8 @@
#include "feature.h"
#include "geomfunction.h"
#include "labelposition.h"
#include "qgsgeos.h"
#include "qgsmessagelog.h"
#include <iostream>
#include <fstream>
#include <cmath>
Expand Down Expand Up @@ -273,8 +275,16 @@ namespace pal
lp->createGeosGeom();

GEOSContextHandle_t geosctxt = geosContext();
bool result = ( GEOSPreparedIntersects_r( geosctxt, preparedGeom(), lp->mGeos ) == 1 );
return result;
try
{
bool result = ( GEOSPreparedIntersects_r( geosctxt, preparedGeom(), lp->mGeos ) == 1 );
return result;
}
catch ( GEOSException &e )
{
QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
return false;
}
}

bool LabelPosition::isInConflictMultiPart( LabelPosition* lp )
Expand Down Expand Up @@ -516,13 +526,21 @@ namespace pal
line->createGeosGeom();

GEOSContextHandle_t geosctxt = geosContext();
if ( GEOSPreparedIntersects_r( geosctxt, line->preparedGeom(), mGeos ) == 1 )
try
{
return true;
if ( GEOSPreparedIntersects_r( geosctxt, line->preparedGeom(), mGeos ) == 1 )
{
return true;
}
else if ( nextPart )
{
return nextPart->crossesLine( line );
}
}
else if ( nextPart )
catch ( GEOSException &e )
{
return nextPart->crossesLine( line );
QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
return false;
}

return false;
Expand All @@ -537,14 +555,22 @@ namespace pal
polygon->createGeosGeom();

GEOSContextHandle_t geosctxt = geosContext();
if ( GEOSPreparedOverlaps_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1
|| GEOSPreparedTouches_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1 )
try
{
return true;
if ( GEOSPreparedOverlaps_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1
|| GEOSPreparedTouches_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1 )
{
return true;
}
else if ( nextPart )
{
return nextPart->crossesBoundary( polygon );
}
}
else if ( nextPart )
catch ( GEOSException &e )
{
return nextPart->crossesBoundary( polygon );
QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
return false;
}

return false;
Expand Down
17 changes: 0 additions & 17 deletions src/core/pal/pal.cpp
Expand Up @@ -53,23 +53,6 @@

namespace pal
{

void geosError( const char *fmt, ... )
{
va_list list;
va_start( list, fmt );
vfprintf( stderr, fmt, list );
va_end( list );
}

void geosNotice( const char *fmt, ... )
{
va_list list;
va_start( list, fmt );
vfprintf( stdout, fmt, list );
va_end( list );
}

GEOSContextHandle_t geosContext()
{
return QgsGeometry::getGEOSHandler();
Expand Down

0 comments on commit fec5d5e

Please sign in to comment.