30 #define DEFAULT_QUADRANT_SEGMENTS 8
32 #define CATCH_GEOS(r) \
33 catch (GEOSException &e) \
35 QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr("GEOS") ); \
44 if ( theMsg ==
"Unknown exception thrown" && lastMsg.
isNull() )
64 lastMsg = QString::null;
85 vsnprintf( buffer,
sizeof buffer, fmt, ap );
95 #if defined(QGISDEBUG)
100 vsnprintf( buffer,
sizeof buffer, fmt, ap );
121 finishGEOS_r(
ctxt );
134 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
135 GEOSPreparedGeom_destroy_r( geosinit.
ctxt, mGeosPrepared );
140 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
142 GEOSPreparedGeom_destroy_r( geosinit.
ctxt, mGeosPrepared );
149 GEOSPreparedGeom_destroy_r( geosinit.
ctxt, mGeosPrepared );
153 mGeosPrepared = GEOSPrepare_r( geosinit.
ctxt, mGeos );
157 void QgsGeos::cacheGeos()
const
169 return overlay( geom, INTERSECTION );
174 return overlay( geom, DIFFERENCE );
179 return overlay( geom, UNION );
187 for (
int i = 0; i < geomList.
size(); ++i )
189 geosGeometries[i] =
asGeos( geomList.
at( i ) );
192 GEOSGeometry* geomUnion = 0;
195 GEOSGeometry* geomCollection = createGeosCollection( GEOS_GEOMETRYCOLLECTION, geosGeometries );
196 geomUnion = GEOSUnaryUnion_r( geosinit.
ctxt, geomCollection );
197 GEOSGeom_destroy_r( geosinit.
ctxt, geomCollection );
202 GEOSGeom_destroy_r( geosinit.
ctxt, geomUnion );
208 return overlay( geom, SYMDIFFERENCE );
219 GEOSGeometry* otherGeosGeom =
asGeos( &geom );
220 if ( !otherGeosGeom )
227 GEOSDistance_r( geosinit.
ctxt, mGeos, otherGeosGeom, &distance );
236 return relation( geom, INTERSECTS );
241 return relation( geom, TOUCHES );
246 return relation( geom, CROSSES );
251 return relation( geom, WITHIN );
256 return relation( geom, OVERLAPS );
261 return relation( geom, CONTAINS );
266 return relation( geom, DISJOINT );
279 if ( GEOSArea_r( geosinit.
ctxt, mGeos, &area ) != 1 )
295 if ( GEOSLength_r( geosinit.
ctxt, mGeos, &length ) != 1 )
320 if ( !GEOSisValid_r( geosinit.
ctxt, mGeos ) )
328 newGeometries.
clear();
329 GEOSGeometry* splitLineGeos = 0;
335 splitLineGeos = createGeosLinestring( &splitLine );
340 splitLineGeos = createGeosPoint( &pt, 2 );
347 if ( !GEOSisValid_r( geosinit.
ctxt, splitLineGeos ) || !GEOSisSimple_r( geosinit.
ctxt, splitLineGeos ) )
349 GEOSGeom_destroy_r( geosinit.
ctxt, splitLineGeos );
356 if ( topologicalTestPointsSplit( splitLineGeos, topologyTestPoints ) != 0 )
363 returnCode = splitLinearGeometry( splitLineGeos, newGeometries );
364 GEOSGeom_destroy_r( geosinit.
ctxt, splitLineGeos );
368 returnCode = splitPolygonGeometry( splitLineGeos, newGeometries );
369 GEOSGeom_destroy_r( geosinit.
ctxt, splitLineGeos );
383 int QgsGeos::topologicalTestPointsSplit(
const GEOSGeometry* splitLine,
QList<QgsPointV2>& testPoints )
const
397 GEOSGeometry* intersectionGeom = GEOSIntersection_r( geosinit.
ctxt, mGeos, splitLine );
398 if ( !intersectionGeom )
402 int nIntersectGeoms = 1;
403 if ( GEOSGeomTypeId_r( geosinit.
ctxt, intersectionGeom ) == GEOS_LINESTRING
404 || GEOSGeomTypeId_r( geosinit.
ctxt, intersectionGeom ) == GEOS_POINT )
408 nIntersectGeoms = GEOSGetNumGeometries_r( geosinit.
ctxt, intersectionGeom );
410 for (
int i = 0; i < nIntersectGeoms; ++i )
412 const GEOSGeometry* currentIntersectGeom;
414 currentIntersectGeom = intersectionGeom;
416 currentIntersectGeom = GEOSGetGeometryN_r( geosinit.
ctxt, intersectionGeom, i );
418 const GEOSCoordSequence* lineSequence = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, currentIntersectGeom );
419 unsigned int sequenceSize = 0;
421 if ( GEOSCoordSeq_getSize_r( geosinit.
ctxt, lineSequence, &sequenceSize ) != 0 )
423 for (
unsigned int i = 0; i < sequenceSize; ++i )
425 if ( GEOSCoordSeq_getX_r( geosinit.
ctxt, lineSequence, i, &x ) != 0 )
427 if ( GEOSCoordSeq_getY_r( geosinit.
ctxt, lineSequence, i, &y ) != 0 )
435 GEOSGeom_destroy_r( geosinit.
ctxt, intersectionGeom );
442 GEOSGeometry*
QgsGeos::linePointDifference( GEOSGeometry* GEOSsplitPoint )
const
444 int type = GEOSGeomTypeId_r( geosinit.
ctxt, mGeos );
447 if ( type == GEOS_MULTILINESTRING )
451 else if ( type == GEOS_LINESTRING )
471 delete splitGeom;
return 0;
486 for (
int j = 1; j < ( nVertices - 1 ); ++j )
490 if ( currentPoint == *splitPoint )
516 if ( !GEOSIntersects_r( geosinit.
ctxt, splitLine, mGeos ) )
520 int linearIntersect = GEOSRelatePattern_r( geosinit.
ctxt, mGeos, splitLine,
"1********" );
521 if ( linearIntersect > 0 )
524 int splitGeomType = GEOSGeomTypeId_r( geosinit.
ctxt, splitLine );
526 GEOSGeometry* splitGeom;
527 if ( splitGeomType == GEOS_POINT )
529 splitGeom = linePointDifference( splitLine );
533 splitGeom = GEOSDifference_r( geosinit.
ctxt, mGeos, splitLine );
537 int splitType = GEOSGeomTypeId_r( geosinit.
ctxt, splitGeom );
538 if ( splitType == GEOS_MULTILINESTRING )
540 int nGeoms = GEOSGetNumGeometries_r( geosinit.
ctxt, splitGeom );
541 for (
int i = 0; i < nGeoms; ++i )
542 lineGeoms << GEOSGeom_clone_r( geosinit.
ctxt, GEOSGetGeometryN_r( geosinit.
ctxt, splitGeom, i ) );
547 lineGeoms << GEOSGeom_clone_r( geosinit.
ctxt, splitGeom );
550 mergeGeometriesMultiTypeSplit( lineGeoms );
552 for (
int i = 0; i < lineGeoms.
size(); ++i )
554 newGeometries <<
fromGeos( lineGeoms[i] );
557 GEOSGeom_destroy_r( geosinit.
ctxt, splitGeom );
570 if ( !GEOSIntersects_r( geosinit.
ctxt, splitLine, mGeos ) )
574 GEOSGeometry *nodedGeometry = nodeGeometries( splitLine, mGeos );
575 if ( !nodedGeometry )
578 GEOSGeometry *polygons = GEOSPolygonize_r( geosinit.
ctxt, &nodedGeometry, 1 );
579 if ( !polygons || numberOfGeometries( polygons ) == 0 )
582 GEOSGeom_destroy_r( geosinit.
ctxt, polygons );
584 GEOSGeom_destroy_r( geosinit.
ctxt, nodedGeometry );
589 GEOSGeom_destroy_r( geosinit.
ctxt, nodedGeometry );
594 GEOSGeometry *intersectGeometry = 0;
599 for (
int i = 0; i < numberOfGeometries( polygons ); i++ )
601 const GEOSGeometry *polygon = GEOSGetGeometryN_r( geosinit.
ctxt, polygons, i );
602 intersectGeometry = GEOSIntersection_r( geosinit.
ctxt, mGeos, polygon );
603 if ( !intersectGeometry )
609 double intersectionArea;
610 GEOSArea_r( geosinit.
ctxt, intersectGeometry, &intersectionArea );
613 GEOSArea_r( geosinit.
ctxt, polygon, &polygonArea );
615 const double areaRatio = intersectionArea / polygonArea;
616 if ( areaRatio > 0.99 && areaRatio < 1.01 )
617 testedGeometries << GEOSGeom_clone_r( geosinit.
ctxt, polygon );
619 GEOSGeom_destroy_r( geosinit.
ctxt, intersectGeometry );
622 bool splitDone =
true;
623 int nGeometriesThis = numberOfGeometries( mGeos );
624 if ( testedGeometries.
size() == nGeometriesThis )
629 mergeGeometriesMultiTypeSplit( testedGeometries );
634 for (
int i = 0; i < testedGeometries.
size(); ++i )
636 GEOSGeom_destroy_r( geosinit.
ctxt, testedGeometries[i] );
642 for ( i = 0; i < testedGeometries.
size() && GEOSisValid_r( geosinit.
ctxt, testedGeometries[i] ); ++i )
645 if ( i < testedGeometries.
size() )
647 for ( i = 0; i < testedGeometries.
size(); ++i )
648 GEOSGeom_destroy_r( geosinit.
ctxt, testedGeometries[i] );
653 for ( i = 0; i < testedGeometries.
size(); ++i )
654 newGeometries <<
fromGeos( testedGeometries[i] );
656 GEOSGeom_destroy_r( geosinit.
ctxt, polygons );
660 GEOSGeometry* QgsGeos::nodeGeometries(
const GEOSGeometry *splitLine,
const GEOSGeometry *geom )
662 if ( !splitLine || !geom )
665 GEOSGeometry *geometryBoundary = 0;
666 if ( GEOSGeomTypeId_r( geosinit.
ctxt, geom ) == GEOS_POLYGON || GEOSGeomTypeId_r( geosinit.
ctxt, geom ) == GEOS_MULTIPOLYGON )
667 geometryBoundary = GEOSBoundary_r( geosinit.
ctxt, geom );
669 geometryBoundary = GEOSGeom_clone_r( geosinit.
ctxt, geom );
671 GEOSGeometry *splitLineClone = GEOSGeom_clone_r( geosinit.
ctxt, splitLine );
672 GEOSGeometry *unionGeometry = GEOSUnion_r( geosinit.
ctxt, splitLineClone, geometryBoundary );
673 GEOSGeom_destroy_r( geosinit.
ctxt, splitLineClone );
675 GEOSGeom_destroy_r( geosinit.
ctxt, geometryBoundary );
676 return unionGeometry;
685 int type = GEOSGeomTypeId_r( geosinit.
ctxt, mGeos );
686 if ( type != GEOS_GEOMETRYCOLLECTION &&
687 type != GEOS_MULTILINESTRING &&
688 type != GEOS_MULTIPOLYGON &&
689 type != GEOS_MULTIPOINT )
698 for (
int i = 0; i < copyList.
size(); ++i )
702 for (
int j = 0; j < GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos ); j++ )
704 if ( GEOSEquals_r( geosinit.
ctxt, copyList[i], GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, j ) ) )
713 unionGeom << copyList[i];
718 geomVector << copyList[i];
720 if ( type == GEOS_MULTILINESTRING )
721 splitResult << createGeosCollection( GEOS_MULTILINESTRING, geomVector );
722 else if ( type == GEOS_MULTIPOLYGON )
723 splitResult << createGeosCollection( GEOS_MULTIPOLYGON, geomVector );
725 GEOSGeom_destroy_r( geosinit.
ctxt, copyList[i] );
730 if ( unionGeom.
size() > 0 )
732 if ( type == GEOS_MULTILINESTRING )
733 splitResult << createGeosCollection( GEOS_MULTILINESTRING, unionGeom );
734 else if ( type == GEOS_MULTIPOLYGON )
735 splitResult << createGeosCollection( GEOS_MULTIPOLYGON, unionGeom );
747 int nNullGeoms = geoms.
count( 0 );
748 int nNotNullGeoms = geoms.
size() - nNullGeoms;
750 GEOSGeometry **geomarr =
new GEOSGeometry*[ nNotNullGeoms ];
758 for ( ; geomIt != geoms.
constEnd(); ++geomIt )
762 geomarr[i] = *geomIt;
766 GEOSGeometry *geom = 0;
770 geom = GEOSGeom_createCollection_r( geosinit.
ctxt, typeId, geomarr, nNotNullGeoms );
789 int nCoordDims = GEOSGeom_getCoordinateDimension_r( geosinit.
ctxt, geos );
790 int nDims = GEOSGeom_getDimensions_r( geosinit.
ctxt, geos );
791 bool hasZ = ( nCoordDims == 3 );
792 bool hasM = (( nDims - nCoordDims ) == 1 );
794 switch ( GEOSGeomTypeId_r( geosinit.
ctxt, geos ) )
798 const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, geos );
801 case GEOS_LINESTRING:
803 return sequenceToLinestring( geos, hasZ, hasM );
809 case GEOS_MULTIPOINT:
812 int nParts = GEOSGetNumGeometries_r( geosinit.
ctxt, geos );
813 for (
int i = 0; i < nParts; ++i )
815 const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, GEOSGetGeometryN_r( geosinit.
ctxt, geos, i ) );
823 case GEOS_MULTILINESTRING:
826 int nParts = GEOSGetNumGeometries_r( geosinit.
ctxt, geos );
827 for (
int i = 0; i < nParts; ++i )
829 QgsLineStringV2* line = sequenceToLinestring( GEOSGetGeometryN_r( geosinit.
ctxt, geos, i ), hasZ, hasM );
835 return multiLineString;
837 case GEOS_MULTIPOLYGON:
841 int nParts = GEOSGetNumGeometries_r( geosinit.
ctxt, geos );
842 for (
int i = 0; i < nParts; ++i )
852 case GEOS_GEOMETRYCOLLECTION:
855 int nParts = GEOSGetNumGeometries_r( geosinit.
ctxt, geos );
856 for (
int i = 0; i < nParts; ++i )
864 return geomCollection;
872 if ( GEOSGeomTypeId_r( geosinit.
ctxt, geos ) != GEOS_POLYGON )
877 int nCoordDims = GEOSGeom_getCoordinateDimension_r( geosinit.
ctxt, geos );
878 int nDims = GEOSGeom_getDimensions_r( geosinit.
ctxt, geos );
879 bool hasZ = ( nCoordDims == 3 );
880 bool hasM = (( nDims - nCoordDims ) == 1 );
884 const GEOSGeometry* ring = GEOSGetExteriorRing_r( geosinit.
ctxt, geos );
891 for (
int i = 0; i < GEOSGetNumInteriorRings_r( geosinit.
ctxt, geos ); ++i )
893 ring = GEOSGetInteriorRingN_r( geosinit.
ctxt, geos, i );
896 interiorRings.
push_back( sequenceToLinestring( ring, hasZ, hasM ) );
904 QgsLineStringV2* QgsGeos::sequenceToLinestring(
const GEOSGeometry* geos,
bool hasZ,
bool hasM )
907 const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, geos );
908 unsigned int nPoints;
909 GEOSCoordSeq_getSize_r( geosinit.
ctxt, cs, &nPoints );
910 for (
unsigned int i = 0; i < nPoints; ++i )
919 int QgsGeos::numberOfGeometries( GEOSGeometry* g )
924 int geometryType = GEOSGeomTypeId_r( geosinit.
ctxt, g );
925 if ( geometryType == GEOS_POINT || geometryType == GEOS_LINESTRING || geometryType == GEOS_LINEARRING
926 || geometryType == GEOS_POLYGON )
930 return GEOSGetNumGeometries_r( geosinit.
ctxt, g );
943 GEOSCoordSeq_getX_r( geosinit.
ctxt, cs, i, &x );
944 GEOSCoordSeq_getY_r( geosinit.
ctxt, cs, i, &y );
947 GEOSCoordSeq_getZ_r( geosinit.
ctxt, cs, i, &z );
951 GEOSCoordSeq_getOrdinate_r( geosinit.
ctxt, cs, i, 3, &m );
988 return createGeosLinestring( lineString.data() );
990 else if ( curvePolygon )
993 return createGeosPolygon( polygon.data() );
997 return createGeosPoint( geom, coordDims );
1001 int geosType = GEOS_MULTIPOINT;
1004 geosType = GEOS_MULTIPOINT;
1008 geosType = GEOS_MULTILINESTRING;
1012 geosType = GEOS_MULTIPOLYGON;
1014 else if ( geom->
geometryType() ==
"GeometryCollection" )
1016 geosType = GEOS_GEOMETRYCOLLECTION;
1030 return createGeosCollection( geosType, geomVector );
1043 GEOSGeometry* geosGeom =
asGeos( &geom );
1051 GEOSGeometry* opGeom = 0;
1055 opGeom = GEOSIntersection_r( geosinit.
ctxt, mGeos, geosGeom );
1058 opGeom = GEOSDifference_r( geosinit.
ctxt, mGeos, geosGeom );
1061 opGeom = GEOSUnion_r( geosinit.
ctxt, mGeos, geosGeom );
1064 opGeom = GEOSSymDifference_r( geosinit.
ctxt, mGeos, geosGeom );
1067 GEOSGeom_destroy_r( geosinit.
ctxt, geosGeom );
1071 GEOSGeom_destroy_r( geosinit.
ctxt, opGeom );
1072 GEOSGeom_destroy_r( geosinit.
ctxt, geosGeom );
1078 GEOSGeom_destroy_r( geosinit.
ctxt, geosGeom );
1090 GEOSGeometry* geosGeom =
asGeos( &geom );
1096 bool result =
false;
1100 if ( mGeosPrepared )
1105 result = ( GEOSPreparedIntersects_r( geosinit.
ctxt, mGeosPrepared, geosGeom ) == 1 );
1108 result = ( GEOSPreparedTouches_r( geosinit.
ctxt, mGeosPrepared, geosGeom ) == 1 );
1111 result = ( GEOSPreparedCrosses_r( geosinit.
ctxt, mGeosPrepared, geosGeom ) == 1 );
1114 result = ( GEOSPreparedWithin_r( geosinit.
ctxt, mGeosPrepared, geosGeom ) == 1 );
1117 result = ( GEOSPreparedContains_r( geosinit.
ctxt, mGeosPrepared, geosGeom ) == 1 );
1120 result = ( GEOSPreparedDisjoint_r( geosinit.
ctxt, mGeosPrepared, geosGeom ) == 1 );
1123 result = ( GEOSPreparedOverlaps_r( geosinit.
ctxt, mGeosPrepared, geosGeom ) == 1 );
1126 GEOSGeom_destroy_r( geosinit.
ctxt, geosGeom );
1129 GEOSGeom_destroy_r( geosinit.
ctxt, geosGeom );
1136 result = ( GEOSIntersects_r( geosinit.
ctxt, mGeos, geosGeom ) == 1 );
1139 result = ( GEOSTouches_r( geosinit.
ctxt, mGeos, geosGeom ) == 1 );
1142 result = ( GEOSCrosses_r( geosinit.
ctxt, mGeos, geosGeom ) == 1 );
1145 result = ( GEOSWithin_r( geosinit.
ctxt, mGeos, geosGeom ) == 1 );
1148 result = ( GEOSContains_r( geosinit.
ctxt, mGeos, geosGeom ) == 1 );
1151 result = ( GEOSDisjoint_r( geosinit.
ctxt, mGeos, geosGeom ) == 1 );
1154 result = ( GEOSOverlaps_r( geosinit.
ctxt, mGeos, geosGeom ) == 1 );
1157 GEOSGeom_destroy_r( geosinit.
ctxt, geosGeom );
1164 GEOSGeom_destroy_r( geosinit.
ctxt, geosGeom );
1168 GEOSGeom_destroy_r( geosinit.
ctxt, geosGeom );
1179 GEOSGeometry* geos = 0;
1182 geos = GEOSBuffer_r( geosinit.
ctxt, mGeos, distance, segments );
1195 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
1196 ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
1198 GEOSGeometry* geos = 0;
1201 geos = GEOSBufferWithStyle_r( geosinit.
ctxt, mGeos, distance, segments, endCapStyle, joinStyle, mitreLimit );
1216 GEOSGeometry* geos = 0;
1219 geos = GEOSTopologyPreserveSimplify_r( geosinit.
ctxt, mGeos, tolerance );
1231 GEOSGeometry* geos = 0;
1234 geos = GEOSInterpolate_r( geosinit.
ctxt, mGeos, distance );
1247 GEOSGeometry* geos = 0;
1250 geos = GEOSGetCentroid_r( geosinit.
ctxt, mGeos );
1260 GEOSGeomGetX_r( geosinit.
ctxt, geos, &x );
1261 GEOSGeomGetY_r( geosinit.
ctxt, geos, &y );
1273 GEOSGeometry* geos = 0;
1276 geos = GEOSPointOnSurface_r( geosinit.
ctxt, mGeos );
1286 GEOSGeomGetX_r( geosinit.
ctxt, geos, &x );
1287 GEOSGeomGetY_r( geosinit.
ctxt, geos, &y );
1304 GEOSGeometry* cHull = GEOSConvexHull_r( geosinit.
ctxt, mGeos );
1306 GEOSGeom_destroy_r( geosinit.
ctxt, cHull );
1321 return GEOSisValid_r( geosinit.
ctxt, mGeos );
1335 GEOSGeometry* geosGeom =
asGeos( &geom );
1340 bool equal = GEOSEquals_r( geosinit.
ctxt, mGeos, geosGeom );
1341 GEOSGeom_destroy_r( geosinit.
ctxt, geosGeom );
1356 return GEOSisEmpty_r( geosinit.
ctxt, mGeos );
1361 GEOSCoordSequence* QgsGeos::createCoordinateSequence(
const QgsCurveV2* curve )
1363 bool segmentize =
false;
1377 bool hasZ = line->
is3D();
1390 GEOSCoordSequence* coordSeq = 0;
1393 coordSeq = GEOSCoordSeq_create_r( geosinit.
ctxt, numPoints, coordDims );
1394 for (
int i = 0; i < numPoints; ++i )
1397 GEOSCoordSeq_setX_r( geosinit.
ctxt, coordSeq, i, pt.
x() );
1398 GEOSCoordSeq_setY_r( geosinit.
ctxt, coordSeq, i, pt.
y() );
1401 GEOSCoordSeq_setOrdinate_r( geosinit.
ctxt, coordSeq, i, 2, pt.
z() );
1405 GEOSCoordSeq_setOrdinate_r( geosinit.
ctxt, coordSeq, i, 3, pt.
m() );
1424 GEOSGeometry* geosPoint = 0;
1428 GEOSCoordSequence* coordSeq = GEOSCoordSeq_create_r( geosinit.
ctxt, 1, coordDims );
1429 GEOSCoordSeq_setX_r( geosinit.
ctxt, coordSeq, 0, pt->
x() );
1430 GEOSCoordSeq_setY_r( geosinit.
ctxt, coordSeq, 0, pt->
y() );
1433 GEOSCoordSeq_setOrdinate_r( geosinit.
ctxt, coordSeq, 0, 2, pt->
z() );
1437 GEOSCoordSeq_setOrdinate_r( geosinit.
ctxt, coordSeq, 0, 3, pt->
m() );
1439 geosPoint = GEOSGeom_createPoint_r( geosinit.
ctxt, coordSeq );
1451 GEOSCoordSequence* coordSeq = createCoordinateSequence( c );
1455 GEOSGeometry* geosGeom = 0;
1458 geosGeom = GEOSGeom_createLineString_r( geosinit.
ctxt, coordSeq );
1471 if ( !exteriorRing )
1476 GEOSGeometry* geosPolygon = 0;
1479 GEOSGeometry* exteriorRingGeos = GEOSGeom_createLinearRing_r( geosinit.
ctxt, createCoordinateSequence( exteriorRing ) );
1483 GEOSGeometry** holes = 0;
1486 holes =
new GEOSGeometry*[ nHoles ];
1489 for (
int i = 0; i < nHoles; ++i )
1492 holes[i] = GEOSGeom_createLinearRing_r( geosinit.
ctxt, createCoordinateSequence( interiorRing ) );
1494 geosPolygon = GEOSGeom_createPolygon_r( geosinit.
ctxt, exteriorRingGeos, holes, nHoles );
1507 GEOSGeometry* offset = 0;
1510 offset = GEOSOffsetCurve_r( geosinit.
ctxt, mGeos, distance, segments, joinStyle, mitreLimit );
1514 GEOSGeom_destroy_r( geosinit.
ctxt, offset );
1522 if ( errorCode ) { *errorCode = 1; }
1526 GEOSGeometry* reshapeLineGeos = createGeosLinestring( &reshapeWithLine );
1529 int numGeoms = GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos );
1530 if ( numGeoms == -1 )
1532 if ( errorCode ) { *errorCode = 1; }
1536 bool isMultiGeom =
false;
1537 int geosTypeId = GEOSGeomTypeId_r( geosinit.
ctxt, mGeos );
1538 if ( geosTypeId == GEOS_MULTILINESTRING || geosTypeId == GEOS_MULTIPOLYGON )
1545 GEOSGeometry* reshapedGeometry;
1548 reshapedGeometry = reshapeLine( mGeos, reshapeLineGeos );
1552 reshapedGeometry = reshapePolygon( mGeos, reshapeLineGeos );
1555 if ( errorCode ) { *errorCode = 0; }
1557 GEOSGeom_destroy_r( geosinit.
ctxt, reshapedGeometry );
1558 return reshapeResult;
1565 bool reshapeTookPlace =
false;
1567 GEOSGeometry* currentReshapeGeometry = 0;
1568 GEOSGeometry** newGeoms =
new GEOSGeometry*[numGeoms];
1570 for (
int i = 0; i < numGeoms; ++i )
1573 currentReshapeGeometry = reshapeLine( GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i ), reshapeLineGeos );
1575 currentReshapeGeometry = reshapePolygon( GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i ), reshapeLineGeos );
1577 if ( currentReshapeGeometry )
1579 newGeoms[i] = currentReshapeGeometry;
1580 reshapeTookPlace =
true;
1584 newGeoms[i] = GEOSGeom_clone_r( geosinit.
ctxt, GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i ) );
1587 GEOSGeom_destroy_r( geosinit.
ctxt, reshapeLineGeos );
1589 GEOSGeometry* newMultiGeom = 0;
1592 newMultiGeom = GEOSGeom_createCollection_r( geosinit.
ctxt, GEOS_MULTILINESTRING, newGeoms, numGeoms );
1596 newMultiGeom = GEOSGeom_createCollection_r( geosinit.
ctxt, GEOS_MULTIPOLYGON, newGeoms, numGeoms );
1600 if ( !newMultiGeom )
1602 if ( errorCode ) { *errorCode = 3; }
1606 if ( reshapeTookPlace )
1608 if ( errorCode ) { *errorCode = 0; }
1610 GEOSGeom_destroy_r( geosinit.
ctxt, newMultiGeom );
1611 return reshapedMultiGeom;
1615 GEOSGeom_destroy_r( geosinit.
ctxt, newMultiGeom );
1616 if ( errorCode ) { *errorCode = 1; }
1625 GEOSGeometry* QgsGeos::reshapeLine(
const GEOSGeometry* line,
const GEOSGeometry* reshapeLineGeos )
1627 if ( !line || !reshapeLineGeos )
1630 bool atLeastTwoIntersections =
false;
1635 GEOSGeometry* intersectGeom = GEOSIntersection_r( geosinit.
ctxt, line, reshapeLineGeos );
1636 if ( intersectGeom )
1638 atLeastTwoIntersections = ( GEOSGeomTypeId_r( geosinit.
ctxt, intersectGeom ) == GEOS_MULTIPOINT
1639 && GEOSGetNumGeometries_r( geosinit.
ctxt, intersectGeom ) > 1 );
1640 GEOSGeom_destroy_r( geosinit.
ctxt, intersectGeom );
1646 atLeastTwoIntersections =
false;
1649 if ( !atLeastTwoIntersections )
1653 const GEOSCoordSequence* lineCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, line );
1654 if ( !lineCoordSeq )
1657 unsigned int lineCoordSeqSize;
1658 if ( GEOSCoordSeq_getSize_r( geosinit.
ctxt, lineCoordSeq, &lineCoordSeqSize ) == 0 )
1661 if ( lineCoordSeqSize < 2 )
1665 double x1, y1, x2, y2;
1666 GEOSCoordSeq_getX_r( geosinit.
ctxt, lineCoordSeq, 0, &x1 );
1667 GEOSCoordSeq_getY_r( geosinit.
ctxt, lineCoordSeq, 0, &y1 );
1668 GEOSCoordSeq_getX_r( geosinit.
ctxt, lineCoordSeq, lineCoordSeqSize - 1, &x2 );
1669 GEOSCoordSeq_getY_r( geosinit.
ctxt, lineCoordSeq, lineCoordSeqSize - 1, &y2 );
1671 GEOSGeometry* beginLineVertex = createGeosPoint( &beginPoint, 2 );
1673 GEOSGeometry* endLineVertex = createGeosPoint( &endPoint, 2 );
1675 bool isRing =
false;
1676 if ( GEOSGeomTypeId_r( geosinit.
ctxt, line ) == GEOS_LINEARRING
1677 || GEOSEquals_r( geosinit.
ctxt, beginLineVertex, endLineVertex ) == 1 )
1681 GEOSGeometry* nodedGeometry = nodeGeometries( reshapeLineGeos, line );
1682 if ( !nodedGeometry )
1684 GEOSGeom_destroy_r( geosinit.
ctxt, beginLineVertex );
1685 GEOSGeom_destroy_r( geosinit.
ctxt, endLineVertex );
1690 GEOSGeometry *mergedLines = GEOSLineMerge_r( geosinit.
ctxt, nodedGeometry );
1691 GEOSGeom_destroy_r( geosinit.
ctxt, nodedGeometry );
1694 GEOSGeom_destroy_r( geosinit.
ctxt, beginLineVertex );
1695 GEOSGeom_destroy_r( geosinit.
ctxt, endLineVertex );
1699 int numMergedLines = GEOSGetNumGeometries_r( geosinit.
ctxt, mergedLines );
1700 if ( numMergedLines < 2 )
1702 GEOSGeom_destroy_r( geosinit.
ctxt, beginLineVertex );
1703 GEOSGeom_destroy_r( geosinit.
ctxt, endLineVertex );
1704 if ( numMergedLines == 1 )
1705 return GEOSGeom_clone_r( geosinit.
ctxt, reshapeLineGeos );
1713 for (
int i = 0; i < numMergedLines; ++i )
1715 const GEOSGeometry* currentGeom;
1717 currentGeom = GEOSGetGeometryN_r( geosinit.
ctxt, mergedLines, i );
1718 const GEOSCoordSequence* currentCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, currentGeom );
1719 unsigned int currentCoordSeqSize;
1720 GEOSCoordSeq_getSize_r( geosinit.
ctxt, currentCoordSeq, ¤tCoordSeqSize );
1721 if ( currentCoordSeqSize < 2 )
1725 double xBegin, xEnd, yBegin, yEnd;
1726 GEOSCoordSeq_getX_r( geosinit.
ctxt, currentCoordSeq, 0, &xBegin );
1727 GEOSCoordSeq_getY_r( geosinit.
ctxt, currentCoordSeq, 0, &yBegin );
1728 GEOSCoordSeq_getX_r( geosinit.
ctxt, currentCoordSeq, currentCoordSeqSize - 1, &xEnd );
1729 GEOSCoordSeq_getY_r( geosinit.
ctxt, currentCoordSeq, currentCoordSeqSize - 1, &yEnd );
1731 GEOSGeometry* beginCurrentGeomVertex = createGeosPoint( &beginPoint, 2 );
1733 GEOSGeometry* endCurrentGeomVertex = createGeosPoint( &endPoint, 2 );
1736 int nEndpointsOnOriginalLine = 0;
1737 if ( pointContainedInLine( beginCurrentGeomVertex, line ) == 1 )
1738 nEndpointsOnOriginalLine += 1;
1740 if ( pointContainedInLine( endCurrentGeomVertex, line ) == 1 )
1741 nEndpointsOnOriginalLine += 1;
1744 int nEndpointsSameAsOriginalLine = 0;
1745 if ( GEOSEquals_r( geosinit.
ctxt, beginCurrentGeomVertex, beginLineVertex ) == 1
1746 || GEOSEquals_r( geosinit.
ctxt, beginCurrentGeomVertex, endLineVertex ) == 1 )
1747 nEndpointsSameAsOriginalLine += 1;
1749 if ( GEOSEquals_r( geosinit.
ctxt, endCurrentGeomVertex, beginLineVertex ) == 1
1750 || GEOSEquals_r( geosinit.
ctxt, endCurrentGeomVertex, endLineVertex ) == 1 )
1751 nEndpointsSameAsOriginalLine += 1;
1754 bool currentGeomOverlapsOriginalGeom =
false;
1755 bool currentGeomOverlapsReshapeLine =
false;
1756 if ( lineContainedInLine( currentGeom, line ) == 1 )
1757 currentGeomOverlapsOriginalGeom =
true;
1759 if ( lineContainedInLine( currentGeom, reshapeLineGeos ) == 1 )
1760 currentGeomOverlapsReshapeLine =
true;
1763 if ( nEndpointsSameAsOriginalLine == 1 && nEndpointsOnOriginalLine == 2 && currentGeomOverlapsOriginalGeom )
1765 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.
ctxt, currentGeom ) );
1768 else if ( isRing && nEndpointsOnOriginalLine == 2 && currentGeomOverlapsOriginalGeom )
1770 probableParts.
push_back( GEOSGeom_clone_r( geosinit.
ctxt, currentGeom ) );
1772 else if ( nEndpointsOnOriginalLine == 2 && !currentGeomOverlapsOriginalGeom )
1774 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.
ctxt, currentGeom ) );
1776 else if ( nEndpointsSameAsOriginalLine == 2 && !currentGeomOverlapsOriginalGeom )
1778 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.
ctxt, currentGeom ) );
1780 else if ( currentGeomOverlapsOriginalGeom && currentGeomOverlapsReshapeLine )
1782 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.
ctxt, currentGeom ) );
1785 GEOSGeom_destroy_r( geosinit.
ctxt, beginCurrentGeomVertex );
1786 GEOSGeom_destroy_r( geosinit.
ctxt, endCurrentGeomVertex );
1790 if ( isRing && probableParts.
size() > 0 )
1792 GEOSGeometry* maxGeom = 0;
1793 GEOSGeometry* currentGeom = 0;
1794 double maxLength = -DBL_MAX;
1795 double currentLength = 0;
1796 for (
int i = 0; i < probableParts.
size(); ++i )
1798 currentGeom = probableParts.
at( i );
1799 GEOSLength_r( geosinit.
ctxt, currentGeom, ¤tLength );
1800 if ( currentLength > maxLength )
1802 maxLength = currentLength;
1803 GEOSGeom_destroy_r( geosinit.
ctxt, maxGeom );
1804 maxGeom = currentGeom;
1808 GEOSGeom_destroy_r( geosinit.
ctxt, currentGeom );
1814 GEOSGeom_destroy_r( geosinit.
ctxt, beginLineVertex );
1815 GEOSGeom_destroy_r( geosinit.
ctxt, endLineVertex );
1816 GEOSGeom_destroy_r( geosinit.
ctxt, mergedLines );
1818 GEOSGeometry* result = 0;
1819 if ( resultLineParts.
size() < 1 )
1822 if ( resultLineParts.
size() == 1 )
1824 result = resultLineParts[0];
1828 GEOSGeometry **lineArray =
new GEOSGeometry*[resultLineParts.
size()];
1829 for (
int i = 0; i < resultLineParts.
size(); ++i )
1831 lineArray[i] = resultLineParts[i];
1835 GEOSGeometry* multiLineGeom = GEOSGeom_createCollection_r( geosinit.
ctxt, GEOS_MULTILINESTRING, lineArray, resultLineParts.
size() );
1836 delete [] lineArray;
1839 result = GEOSLineMerge_r( geosinit.
ctxt, multiLineGeom );
1840 GEOSGeom_destroy_r( geosinit.
ctxt, multiLineGeom );
1844 if ( GEOSGeomTypeId_r( geosinit.
ctxt, result ) != GEOS_LINESTRING )
1846 GEOSGeom_destroy_r( geosinit.
ctxt, result );
1853 GEOSGeometry* QgsGeos::reshapePolygon(
const GEOSGeometry* polygon,
const GEOSGeometry* reshapeLineGeos )
1856 int nIntersections = 0;
1857 int lastIntersectingRing = -2;
1858 const GEOSGeometry* lastIntersectingGeom = 0;
1860 int nRings = GEOSGetNumInteriorRings_r( geosinit.
ctxt, polygon );
1865 const GEOSGeometry* outerRing = GEOSGetExteriorRing_r( geosinit.
ctxt, polygon );
1866 if ( GEOSIntersects_r( geosinit.
ctxt, outerRing, reshapeLineGeos ) == 1 )
1869 lastIntersectingRing = -1;
1870 lastIntersectingGeom = outerRing;
1874 const GEOSGeometry **innerRings =
new const GEOSGeometry*[nRings];
1878 for (
int i = 0; i < nRings; ++i )
1880 innerRings[i] = GEOSGetInteriorRingN_r( geosinit.
ctxt, polygon, i );
1881 if ( GEOSIntersects_r( geosinit.
ctxt, innerRings[i], reshapeLineGeos ) == 1 )
1884 lastIntersectingRing = i;
1885 lastIntersectingGeom = innerRings[i];
1895 if ( nIntersections != 1 )
1897 delete [] innerRings;
1902 GEOSGeometry* reshapeResult = reshapeLine( lastIntersectingGeom, reshapeLineGeos );
1903 if ( !reshapeResult )
1905 delete [] innerRings;
1910 GEOSGeometry* newRing = 0;
1911 const GEOSCoordSequence* reshapeSequence = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, reshapeResult );
1912 GEOSCoordSequence* newCoordSequence = GEOSCoordSeq_clone_r( geosinit.
ctxt, reshapeSequence );
1914 GEOSGeom_destroy_r( geosinit.
ctxt, reshapeResult );
1916 newRing = GEOSGeom_createLinearRing_r( geosinit.
ctxt, newCoordSequence );
1919 delete [] innerRings;
1923 GEOSGeometry* newOuterRing = 0;
1924 if ( lastIntersectingRing == -1 )
1925 newOuterRing = newRing;
1927 newOuterRing = GEOSGeom_clone_r( geosinit.
ctxt, outerRing );
1933 GEOSGeometry* outerRingPoly = GEOSGeom_createPolygon_r( geosinit.
ctxt, GEOSGeom_clone_r( geosinit.
ctxt, newOuterRing ), 0, 0 );
1934 if ( outerRingPoly )
1936 GEOSGeometry* currentRing = 0;
1937 for (
int i = 0; i < nRings; ++i )
1939 if ( lastIntersectingRing == i )
1940 currentRing = newRing;
1942 currentRing = GEOSGeom_clone_r( geosinit.
ctxt, innerRings[i] );
1945 if ( GEOSContains_r( geosinit.
ctxt, outerRingPoly, currentRing ) == 1 )
1948 GEOSGeom_destroy_r( geosinit.
ctxt, currentRing );
1951 GEOSGeom_destroy_r( geosinit.
ctxt, outerRingPoly );
1954 GEOSGeometry** newInnerRings =
new GEOSGeometry*[ringList.
size()];
1955 for (
int i = 0; i < ringList.
size(); ++i )
1956 newInnerRings[i] = ringList.
at( i );
1958 delete [] innerRings;
1960 GEOSGeometry* reshapedPolygon = GEOSGeom_createPolygon_r( geosinit.
ctxt, newOuterRing, newInnerRings, ringList.
size() );
1961 delete[] newInnerRings;
1963 return reshapedPolygon;
1966 int QgsGeos::lineContainedInLine(
const GEOSGeometry* line1,
const GEOSGeometry* line2 )
1968 if ( !line1 || !line2 )
1973 double bufferDistance = pow( 10.0L, geomDigits( line2 ) - 11 );
1979 GEOSGeometry* intersectionGeom = GEOSIntersection_r( geosinit.
ctxt, bufferGeom, line1 );
1982 double intersectGeomLength;
1985 GEOSLength_r( geosinit.
ctxt, intersectionGeom, &intersectGeomLength );
1986 GEOSLength_r( geosinit.
ctxt, line1, &line1Length );
1988 GEOSGeom_destroy_r( geosinit.
ctxt, bufferGeom );
1989 GEOSGeom_destroy_r( geosinit.
ctxt, intersectionGeom );
1991 double intersectRatio = line1Length / intersectGeomLength;
1992 if ( intersectRatio > 0.9 && intersectRatio < 1.1 )
1998 int QgsGeos::pointContainedInLine(
const GEOSGeometry* point,
const GEOSGeometry* line )
2000 if ( !point || !line )
2003 double bufferDistance = pow( 10.0L, geomDigits( line ) - 11 );
2005 GEOSGeometry* lineBuffer = GEOSBuffer_r( geosinit.
ctxt, line, bufferDistance, 8 );
2009 bool contained =
false;
2010 if ( GEOSContains_r( geosinit.
ctxt, lineBuffer, point ) == 1 )
2013 GEOSGeom_destroy_r( geosinit.
ctxt, lineBuffer );
2017 int QgsGeos::geomDigits(
const GEOSGeometry* geom )
2019 GEOSGeometry* bbox = GEOSEnvelope_r( geosinit.
ctxt, geom );
2023 const GEOSGeometry* bBoxRing = GEOSGetExteriorRing_r( geosinit.
ctxt, bbox );
2027 const GEOSCoordSequence* bBoxCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, bBoxRing );
2029 if ( !bBoxCoordSeq )
2032 unsigned int nCoords = 0;
2033 if ( !GEOSCoordSeq_getSize_r( geosinit.
ctxt, bBoxCoordSeq, &nCoords ) )
2037 for (
unsigned int i = 0; i < nCoords - 1; ++i )
2040 GEOSCoordSeq_getX_r( geosinit.
ctxt, bBoxCoordSeq, i, &t );
2043 digits = ceil( log10( fabs( t ) ) );
2044 if ( digits > maxDigits )
2047 GEOSCoordSeq_getY_r( geosinit.
ctxt, bBoxCoordSeq, i, &t );
2048 digits = ceil( log10( fabs( t ) ) );
2049 if ( digits > maxDigits )
2058 return geosinit.
ctxt;
QgsAbstractGeometryV2 * reshapeGeometry(const QgsLineStringV2 &reshapeWithLine, int *errorCode) const
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
const QgsCurveV2 * exteriorRing() const
QgsAbstractGeometryV2 * difference(const QgsAbstractGeometryV2 &geom) const override
GEOSException(QString theMsg)
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
bool isEqual(const QgsAbstractGeometryV2 &geom) const override
bool isValid() const override
static bool isMultiType(Type type)
QgsPointV2 pointN(int i) const
QgsAbstractGeometryV2 * interpolate(double distance) const override
static QgsPointV2 coordSeqPoint(const GEOSCoordSequence *cs, int i, bool hasZ, bool hasM)
void push_back(const T &value)
QgsAbstractGeometryV2 * convexHull() const override
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
Multi curve geometry collection.
const_iterator constEnd() const
const T & at(int i) const
QgsAbstractGeometryV2 * simplify(double tolerance) const override
virtual QgsAbstractGeometryV2 * clone() const override
Clones the geometry by performing a deep copy.
Abstract base class for all geometries.
double length() const override
static QgsAbstractGeometryV2 * fromGeos(const GEOSGeometry *geos)
double distance(const QgsAbstractGeometryV2 &geom) const override
Multi point geometry collection.
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
bool pointOnSurface(QgsPointV2 &pt) const override
bool within(const QgsAbstractGeometryV2 &geom) const override
GEOSException(const GEOSException &rhs)
Multi line string geometry collection.
QString tr(const char *sourceText, const char *disambiguation, int n)
bool contains(const QgsAbstractGeometryV2 &geom) const override
static GEOSContextHandle_t getGEOSHandler()
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
bool crosses(const QgsAbstractGeometryV2 &geom) const override
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
QString fromUtf8(const char *str, int size)
static QgsPolygonV2 * fromGeosPolygon(const GEOSGeometry *geos)
int splitGeometry(const QgsLineStringV2 &splitLine, QList< QgsAbstractGeometryV2 * > &newGeometries, bool topological, QList< QgsPointV2 > &topologyTestPoints) const override
Splits this geometry according to a given line.
bool isMeasure() const
Returns true if the geometry contains m values.
Line string geometry type.
void prepareGeometry() override
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
virtual QgsPolygonV2 * toPolygon() const
QgsAbstractGeometryV2 * intersection(const QgsAbstractGeometryV2 &geom) const override
const QgsAbstractGeometryV2 * mGeometry
QgsGeos(const QgsAbstractGeometryV2 *geometry)
Does vector analysis using the geos library and handles import, export, exception handling*...
virtual QString geometryType() const =0
Returns a unique string representing the geometry type.
QgsAbstractGeometryV2 * symDifference(const QgsAbstractGeometryV2 &geom) const override
const QgsCurveV2 * interiorRing(int i) const
void geometryChanged() override
Removes caches.
static void printGEOSNotice(const char *fmt,...)
int numGeometries() const
Returns the number of geometries within the collection.
void addVertex(const QgsPointV2 &pt)
virtual QgsLineStringV2 * curveToLine() const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
const_iterator constBegin() const
QgsAbstractGeometryV2 * offsetCurve(double distance, int segments, int joinStyle, double mitreLimit) const override
bool intersects(const QgsAbstractGeometryV2 &geom) const override
static GEOSGeometry * asGeos(const QgsAbstractGeometryV2 *geom)
void setPoints(const QList< QgsPointV2 > &points)
void setExteriorRing(QgsCurveV2 *ring)
Sets exterior ring (takes ownership)
bool centroid(QgsPointV2 &pt) const override
QgsAbstractGeometryV2 * combine(const QgsAbstractGeometryV2 &geom) const override
bool overlaps(const QgsAbstractGeometryV2 &geom) const override
virtual bool addGeometry(QgsAbstractGeometryV2 *g)
Adds a geometry and takes ownership.
virtual int dimension() const =0
Returns the inherent dimension of the geometry.
static void throwGEOSException(const char *fmt,...)
int count(const T &value) const
const QgsAbstractGeometryV2 * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
Multi polygon geometry collection.
Contains geometry relation and modification algorithms.
QgsAbstractGeometryV2 * buffer(double distance, int segments) const override
Curve polygon geometry type.
int numInteriorRings() const
virtual QgsAbstractGeometryV2 * clone() const =0
Clones the geometry by performing a deep copy.
Abstract base class for curved geometry type.
bool touches(const QgsAbstractGeometryV2 &geom) const override
#define DEFAULT_QUADRANT_SEGMENTS
bool isEmpty() const override
void setInteriorRings(QList< QgsCurveV2 * > rings)
Sets all interior rings (takes ownership)
bool disjoint(const QgsAbstractGeometryV2 &geom) const override
int numPoints() const override
Returns the number of points in the curve.
double area() const override