Skip to content

Commit

Permalink
Make geometry import/export more robust in case of invalid geometries.
Browse files Browse the repository at this point in the history
…Fixes #12836
  • Loading branch information
mhugent committed Jun 4, 2015
1 parent f39fbf4 commit 08f2f41
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 13 deletions.
33 changes: 25 additions & 8 deletions src/core/geometry/qgsgeometrycollectionv2.cpp
Expand Up @@ -177,13 +177,24 @@ bool QgsGeometryCollectionV2::fromWkb( const unsigned char * wkb )
wkbPtr >> mWkbType;
int nGeometries = 0;
wkbPtr >> nGeometries;
mGeometries.resize( nGeometries );

QList<QgsAbstractGeometryV2*> geometryList;
for ( int i = 0; i < nGeometries; ++i )
{
QgsAbstractGeometryV2* geom = QgsGeometryImport::geomFromWkb( wkbPtr );
mGeometries[i] = geom;
wkbPtr += geom->wkbSize();
if ( geom )
{
geometryList.append( geom );
wkbPtr += geom->wkbSize();
}
}

mGeometries.resize( geometryList.size() );
for ( int i = 0; i < geometryList.size(); ++i )
{
mGeometries[i] = geometryList.at( i );
}

return true;
}

Expand All @@ -198,7 +209,10 @@ int QgsGeometryCollectionV2::wkbSize() const
int size = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
foreach ( const QgsAbstractGeometryV2 *geom, mGeometries )
{
size += geom->wkbSize();
if ( geom )
{
size += geom->wkbSize();
}
}
return size;
}
Expand All @@ -214,10 +228,13 @@ unsigned char* QgsGeometryCollectionV2::asWkb( int& binarySize ) const
foreach ( const QgsAbstractGeometryV2 *geom, mGeometries )
{
int geomWkbLen = 0;
unsigned char* geomWkb = geom->asWkb( geomWkbLen );
memcpy( wkb, geomWkb, geomWkbLen );
wkb += geomWkbLen;
delete[] geomWkb;
if ( geom )
{
unsigned char* geomWkb = geom->asWkb( geomWkbLen );
memcpy( wkb, geomWkb, geomWkbLen );
wkb += geomWkbLen;
delete[] geomWkb;
}
}
return geomPtr;
}
Expand Down
7 changes: 7 additions & 0 deletions src/core/geometry/qgsgeometryimport.cpp
Expand Up @@ -21,6 +21,7 @@
#include "qgscurvepolygonv2.h"
#include "qgspointv2.h"
#include "qgspolygonv2.h"
#include "qgscurvepolygonv2.h"
#include "qgslinestringv2.h"
#include "qgsmulticurvev2.h"
#include "qgsmultilinestringv2.h"
Expand Down Expand Up @@ -229,6 +230,12 @@ QgsAbstractGeometryV2* QgsGeometryImport::geomFromWkbType( QgsWKBTypes::Type t )
return new QgsMultiPolygonV2();
case QgsWKBTypes::MultiPoint:
return new QgsMultiPointV2();
case QgsWKBTypes::MultiCurve:
return new QgsMultiCurveV2();
case QgsWKBTypes::MultiSurface:
return new QgsMultiSurfaceV2();
case QgsWKBTypes::GeometryCollection:
return new QgsGeometryCollectionV2();
default:
return 0;
}
Expand Down
42 changes: 38 additions & 4 deletions src/core/geometry/qgsgeos.cpp
Expand Up @@ -1009,12 +1009,42 @@ GEOSGeometry* QgsGeos::asGeos( const QgsAbstractGeometryV2* geom )
{
return 0;
}
GEOSGeometry **geomarr = new GEOSGeometry*[ c->numGeometries()];
for ( int i = 0; i < c->numGeometries(); ++i )

try
{
geomarr[i] = asGeos( c->geometryN( i ) );

//GEOSGeometry **geomarr = new GEOSGeometry*[ c->numGeometries()];
QList< GEOSGeometry* > validGeoms;
GEOSGeometry* geosGeom = 0;
for ( int i = 0; i < c->numGeometries(); ++i )
{
geosGeom = asGeos( c->geometryN( i ) );
if ( geosGeom )
{
validGeoms.append( geosGeom );
}
}

if ( validGeoms.size() < 1 )
{
return 0;
}

GEOSGeometry **geomarr = new GEOSGeometry*[ validGeoms.size()];
for ( int i = 0; i < validGeoms.size(); ++i )
{
geomarr[i] = validGeoms.at( i );
}

return GEOSGeom_createCollection_r( geosinit.ctxt, geosType, geomarr, validGeoms.size() );
}

catch ( GEOSException &e )
{
Q_UNUSED( e );
//delete?
return 0;
}
return GEOSGeom_createCollection_r( geosinit.ctxt, geosType, geomarr, c->numGeometries() ); //todo: geos exceptions
}

return 0;
Expand Down Expand Up @@ -1415,6 +1445,10 @@ GEOSGeometry* QgsGeos::createGeosPolygon( const QgsAbstractGeometryV2* poly )
return 0;

const QgsCurveV2* exteriorRing = polygon->exteriorRing();
if ( !exteriorRing )
{
return 0;
}
GEOSGeometry* exteriorRingGeos = GEOSGeom_createLinearRing_r( geosinit.ctxt, createCoordinateSequence( exteriorRing ) );

int nHoles = polygon->numInteriorRings();
Expand Down
7 changes: 6 additions & 1 deletion src/core/geometry/qgspolygonv2.cpp
Expand Up @@ -48,7 +48,12 @@ bool QgsPolygonV2::fromWkb( const unsigned char* wkb )
{
QgsLineStringV2* line = new QgsLineStringV2();
line->fromWkbPoints( mWkbType, wkbPtr );
if ( i == 0 )
if ( !line->isRing() )
{
delete line; continue;
}

if ( !mExteriorRing )
{
mExteriorRing = line;
}
Expand Down

1 comment on commit 08f2f41

@nirvn
Copy link
Contributor

@nirvn nirvn commented on 08f2f41 Jun 5, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhugent happy to report that this has indeed fixed the issue I reported. Thanks :)

Please sign in to comment.