30 #include <QtCore/qmath.h> 32 #define DEFAULT_QUADRANT_SEGMENTS 8 34 #define CATCH_GEOS(r) \ 35 catch (GEOSException &e) \ 37 QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr("GEOS") ); \ 41 #define CATCH_GEOS_WITH_ERRMSG(r) \ 42 catch (GEOSException &e) \ 44 QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr("GEOS") ); \ 47 *errorMsg = e.what(); \ 54 static void throwGEOSException(
const char *fmt, ... )
60 vsnprintf( buffer,
sizeof buffer, fmt, ap );
68 static void printGEOSNotice(
const char *fmt, ... )
70 #if defined(QGISDEBUG) 75 vsnprintf( buffer,
sizeof buffer, fmt, ap );
87 GEOSContextHandle_t ctxt;
91 ctxt = initGEOS_r( printGEOSNotice, throwGEOSException );
101 GEOSInit(
const GEOSInit& rh );
102 GEOSInit& operator=(
const GEOSInit& rh );
105 static GEOSInit geosinit;
119 GEOSGeometry*
get()
const {
return mGeom; }
120 operator bool()
const {
return nullptr != mGeom; }
123 GEOSGeom_destroy_r( geosinit.ctxt, mGeom );
136 :
QgsGeometryEngine( geometry ), mGeos( nullptr ), mGeosPrepared( nullptr ), mPrecision( precision )
143 GEOSGeom_destroy_r( geosinit.ctxt, mGeos );
145 GEOSPreparedGeom_destroy_r( geosinit.ctxt, mGeosPrepared );
146 mGeosPrepared =
nullptr;
151 GEOSGeom_destroy_r( geosinit.ctxt, mGeos );
153 GEOSPreparedGeom_destroy_r( geosinit.ctxt, mGeosPrepared );
154 mGeosPrepared =
nullptr;
160 GEOSPreparedGeom_destroy_r( geosinit.ctxt, mGeosPrepared );
161 mGeosPrepared =
nullptr;
164 mGeosPrepared = GEOSPrepare_r( geosinit.ctxt, mGeos );
168 void QgsGeos::cacheGeos()
const 180 return overlay( geom, INTERSECTION, errorMsg );
185 return overlay( geom, DIFFERENCE, errorMsg );
190 return overlay( geom, UNION, errorMsg );
198 for (
int i = 0; i < geomList.
size(); ++i )
200 geosGeometries[i] =
asGeos( geomList.
at( i ), mPrecision );
203 GEOSGeometry* geomUnion =
nullptr;
206 GEOSGeometry* geomCollection = createGeosCollection( GEOS_GEOMETRYCOLLECTION, geosGeometries );
207 geomUnion = GEOSUnaryUnion_r( geosinit.ctxt, geomCollection );
208 GEOSGeom_destroy_r( geosinit.ctxt, geomCollection );
213 GEOSGeom_destroy_r( geosinit.ctxt, geomUnion );
219 return overlay( geom, SYMDIFFERENCE, errorMsg );
230 GEOSGeometry* otherGeosGeom =
asGeos( &geom, mPrecision );
231 if ( !otherGeosGeom )
238 GEOSDistance_r( geosinit.ctxt, mGeos, otherGeosGeom, &distance );
242 GEOSGeom_destroy_r( geosinit.ctxt, otherGeosGeom );
249 return relation( geom, INTERSECTS, errorMsg );
254 return relation( geom, TOUCHES, errorMsg );
259 return relation( geom, CROSSES, errorMsg );
264 return relation( geom, WITHIN, errorMsg );
269 return relation( geom, OVERLAPS, errorMsg );
274 return relation( geom, CONTAINS, errorMsg );
279 return relation( geom, DISJOINT, errorMsg );
298 char* r = GEOSRelate_r( geosinit.ctxt, mGeos, geosGeom.
get() );
302 GEOSFree_r( geosinit.ctxt, r );
305 catch ( GEOSException &e )
309 *errorMsg = e.what();
332 result = ( GEOSRelatePattern_r( geosinit.ctxt, mGeos, geosGeom.
get(), pattern.
toLocal8Bit().
constData() ) == 1 );
334 catch ( GEOSException &e )
338 *errorMsg = e.what();
355 if ( GEOSArea_r( geosinit.ctxt, mGeos, &area ) != 1 )
371 if ( GEOSLength_r( geosinit.ctxt, mGeos, &length ) != 1 )
397 if ( !GEOSisValid_r( geosinit.ctxt, mGeos ) )
405 newGeometries.
clear();
406 GEOSGeometry* splitLineGeos =
nullptr;
412 splitLineGeos = createGeosLinestring( &splitLine, mPrecision );
417 splitLineGeos = createGeosPoint( &pt, 2, mPrecision );
424 if ( !GEOSisValid_r( geosinit.ctxt, splitLineGeos ) || !GEOSisSimple_r( geosinit.ctxt, splitLineGeos ) )
426 GEOSGeom_destroy_r( geosinit.ctxt, splitLineGeos );
433 if ( topologicalTestPointsSplit( splitLineGeos, topologyTestPoints ) != 0 )
440 returnCode = splitLinearGeometry( splitLineGeos, newGeometries );
441 GEOSGeom_destroy_r( geosinit.ctxt, splitLineGeos );
445 returnCode = splitPolygonGeometry( splitLineGeos, newGeometries );
446 GEOSGeom_destroy_r( geosinit.ctxt, splitLineGeos );
460 int QgsGeos::topologicalTestPointsSplit(
const GEOSGeometry* splitLine,
QgsPointSequenceV2 &testPoints,
QString* errorMsg )
const 474 GEOSGeometry* intersectionGeom = GEOSIntersection_r( geosinit.ctxt, mGeos, splitLine );
475 if ( !intersectionGeom )
479 int nIntersectGeoms = 1;
480 if ( GEOSGeomTypeId_r( geosinit.ctxt, intersectionGeom ) == GEOS_LINESTRING
481 || GEOSGeomTypeId_r( geosinit.ctxt, intersectionGeom ) == GEOS_POINT )
485 nIntersectGeoms = GEOSGetNumGeometries_r( geosinit.ctxt, intersectionGeom );
487 for (
int i = 0; i < nIntersectGeoms; ++i )
489 const GEOSGeometry* currentIntersectGeom;
491 currentIntersectGeom = intersectionGeom;
493 currentIntersectGeom = GEOSGetGeometryN_r( geosinit.ctxt, intersectionGeom, i );
495 const GEOSCoordSequence* lineSequence = GEOSGeom_getCoordSeq_r( geosinit.ctxt, currentIntersectGeom );
496 unsigned int sequenceSize = 0;
498 if ( GEOSCoordSeq_getSize_r( geosinit.ctxt, lineSequence, &sequenceSize ) != 0 )
500 for (
unsigned int i = 0; i < sequenceSize; ++i )
502 if ( GEOSCoordSeq_getX_r( geosinit.ctxt, lineSequence, i, &x ) != 0 )
504 if ( GEOSCoordSeq_getY_r( geosinit.ctxt, lineSequence, i, &y ) != 0 )
512 GEOSGeom_destroy_r( geosinit.ctxt, intersectionGeom );
519 GEOSGeometry* QgsGeos::linePointDifference( GEOSGeometry* GEOSsplitPoint )
const 521 int type = GEOSGeomTypeId_r( geosinit.ctxt, mGeos );
524 if ( type == GEOS_MULTILINESTRING )
528 else if ( type == GEOS_LINESTRING )
564 for (
int j = 1; j < ( nVertices - 1 ); ++j )
568 if ( currentPoint == *splitPoint )
582 return asGeos( &lines, mPrecision );
594 if ( !GEOSIntersects_r( geosinit.ctxt, splitLine, mGeos ) )
598 int linearIntersect = GEOSRelatePattern_r( geosinit.ctxt, mGeos, splitLine,
"1********" );
599 if ( linearIntersect > 0 )
602 int splitGeomType = GEOSGeomTypeId_r( geosinit.ctxt, splitLine );
604 GEOSGeometry* splitGeom;
605 if ( splitGeomType == GEOS_POINT )
607 splitGeom = linePointDifference( splitLine );
611 splitGeom = GEOSDifference_r( geosinit.ctxt, mGeos, splitLine );
615 int splitType = GEOSGeomTypeId_r( geosinit.ctxt, splitGeom );
616 if ( splitType == GEOS_MULTILINESTRING )
618 int nGeoms = GEOSGetNumGeometries_r( geosinit.ctxt, splitGeom );
620 for (
int i = 0; i < nGeoms; ++i )
621 lineGeoms << GEOSGeom_clone_r( geosinit.ctxt, GEOSGetGeometryN_r( geosinit.ctxt, splitGeom, i ) );
626 lineGeoms << GEOSGeom_clone_r( geosinit.ctxt, splitGeom );
629 mergeGeometriesMultiTypeSplit( lineGeoms );
631 for (
int i = 0; i < lineGeoms.
size(); ++i )
633 newGeometries <<
fromGeos( lineGeoms[i] );
634 GEOSGeom_destroy_r( geosinit.ctxt, lineGeoms[i] );
637 GEOSGeom_destroy_r( geosinit.ctxt, splitGeom );
650 if ( !GEOSIntersects_r( geosinit.ctxt, splitLine, mGeos ) )
654 GEOSGeometry *nodedGeometry = nodeGeometries( splitLine, mGeos );
655 if ( !nodedGeometry )
658 GEOSGeometry *polygons = GEOSPolygonize_r( geosinit.ctxt, &nodedGeometry, 1 );
659 if ( !polygons || numberOfGeometries( polygons ) == 0 )
662 GEOSGeom_destroy_r( geosinit.ctxt, polygons );
664 GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
669 GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
674 GEOSGeometry *intersectGeometry =
nullptr;
679 for (
int i = 0; i < numberOfGeometries( polygons ); i++ )
681 const GEOSGeometry *polygon = GEOSGetGeometryN_r( geosinit.ctxt, polygons, i );
682 intersectGeometry = GEOSIntersection_r( geosinit.ctxt, mGeos, polygon );
683 if ( !intersectGeometry )
689 double intersectionArea;
690 GEOSArea_r( geosinit.ctxt, intersectGeometry, &intersectionArea );
693 GEOSArea_r( geosinit.ctxt, polygon, &polygonArea );
695 const double areaRatio = intersectionArea / polygonArea;
696 if ( areaRatio > 0.99 && areaRatio < 1.01 )
697 testedGeometries << GEOSGeom_clone_r( geosinit.ctxt, polygon );
699 GEOSGeom_destroy_r( geosinit.ctxt, intersectGeometry );
701 GEOSGeom_destroy_r( geosinit.ctxt, polygons );
703 bool splitDone =
true;
704 int nGeometriesThis = numberOfGeometries( mGeos );
705 if ( testedGeometries.
size() == nGeometriesThis )
710 mergeGeometriesMultiTypeSplit( testedGeometries );
715 for (
int i = 0; i < testedGeometries.
size(); ++i )
717 GEOSGeom_destroy_r( geosinit.ctxt, testedGeometries[i] );
723 for ( i = 0; i < testedGeometries.
size() && GEOSisValid_r( geosinit.ctxt, testedGeometries[i] ); ++i )
726 if ( i < testedGeometries.
size() )
728 for ( i = 0; i < testedGeometries.
size(); ++i )
729 GEOSGeom_destroy_r( geosinit.ctxt, testedGeometries[i] );
734 for ( i = 0; i < testedGeometries.
size(); ++i )
735 newGeometries <<
fromGeos( testedGeometries[i] );
740 GEOSGeometry* QgsGeos::nodeGeometries(
const GEOSGeometry *splitLine,
const GEOSGeometry *geom )
742 if ( !splitLine || !geom )
745 GEOSGeometry *geometryBoundary =
nullptr;
746 if ( GEOSGeomTypeId_r( geosinit.ctxt, geom ) == GEOS_POLYGON || GEOSGeomTypeId_r( geosinit.ctxt, geom ) == GEOS_MULTIPOLYGON )
747 geometryBoundary = GEOSBoundary_r( geosinit.ctxt, geom );
749 geometryBoundary = GEOSGeom_clone_r( geosinit.ctxt, geom );
751 GEOSGeometry *splitLineClone = GEOSGeom_clone_r( geosinit.ctxt, splitLine );
752 GEOSGeometry *unionGeometry = GEOSUnion_r( geosinit.ctxt, splitLineClone, geometryBoundary );
753 GEOSGeom_destroy_r( geosinit.ctxt, splitLineClone );
755 GEOSGeom_destroy_r( geosinit.ctxt, geometryBoundary );
756 return unionGeometry;
765 int type = GEOSGeomTypeId_r( geosinit.ctxt, mGeos );
766 if ( type != GEOS_GEOMETRYCOLLECTION &&
767 type != GEOS_MULTILINESTRING &&
768 type != GEOS_MULTIPOLYGON &&
769 type != GEOS_MULTIPOINT )
778 for (
int i = 0; i < copyList.
size(); ++i )
782 for (
int j = 0; j < GEOSGetNumGeometries_r( geosinit.ctxt, mGeos ); j++ )
784 if ( GEOSEquals_r( geosinit.ctxt, copyList[i], GEOSGetGeometryN_r( geosinit.ctxt, mGeos, j ) ) )
793 unionGeom << copyList[i];
798 geomVector << copyList[i];
800 if ( type == GEOS_MULTILINESTRING )
801 splitResult << createGeosCollection( GEOS_MULTILINESTRING, geomVector );
802 else if ( type == GEOS_MULTIPOLYGON )
803 splitResult << createGeosCollection( GEOS_MULTIPOLYGON, geomVector );
805 GEOSGeom_destroy_r( geosinit.ctxt, copyList[i] );
812 if ( type == GEOS_MULTILINESTRING )
813 splitResult << createGeosCollection( GEOS_MULTILINESTRING, unionGeom );
814 else if ( type == GEOS_MULTIPOLYGON )
815 splitResult << createGeosCollection( GEOS_MULTIPOLYGON, unionGeom );
827 int nNullGeoms = geoms.
count(
nullptr );
828 int nNotNullGeoms = geoms.
size() - nNullGeoms;
830 GEOSGeometry **geomarr =
new GEOSGeometry*[ nNotNullGeoms ];
838 for ( ; geomIt != geoms.
constEnd(); ++geomIt )
842 geomarr[i] = *geomIt;
846 GEOSGeometry *geom =
nullptr;
850 geom = GEOSGeom_createCollection_r( geosinit.ctxt, typeId, geomarr, nNotNullGeoms );
852 catch ( GEOSException &e )
869 int nCoordDims = GEOSGeom_getCoordinateDimension_r( geosinit.ctxt, geos );
870 int nDims = GEOSGeom_getDimensions_r( geosinit.ctxt, geos );
871 bool hasZ = ( nCoordDims == 3 );
872 bool hasM = (( nDims - nCoordDims ) == 1 );
874 switch ( GEOSGeomTypeId_r( geosinit.ctxt, geos ) )
878 const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r( geosinit.ctxt, geos );
881 case GEOS_LINESTRING:
883 return sequenceToLinestring( geos, hasZ, hasM );
889 case GEOS_MULTIPOINT:
892 int nParts = GEOSGetNumGeometries_r( geosinit.ctxt, geos );
893 for (
int i = 0; i < nParts; ++i )
895 const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r( geosinit.ctxt, GEOSGetGeometryN_r( geosinit.ctxt, geos, i ) );
903 case GEOS_MULTILINESTRING:
906 int nParts = GEOSGetNumGeometries_r( geosinit.ctxt, geos );
907 for (
int i = 0; i < nParts; ++i )
909 QgsLineStringV2* line = sequenceToLinestring( GEOSGetGeometryN_r( geosinit.ctxt, geos, i ), hasZ, hasM );
915 return multiLineString;
917 case GEOS_MULTIPOLYGON:
921 int nParts = GEOSGetNumGeometries_r( geosinit.ctxt, geos );
922 for (
int i = 0; i < nParts; ++i )
932 case GEOS_GEOMETRYCOLLECTION:
935 int nParts = GEOSGetNumGeometries_r( geosinit.ctxt, geos );
936 for (
int i = 0; i < nParts; ++i )
944 return geomCollection;
952 if ( GEOSGeomTypeId_r( geosinit.ctxt, geos ) != GEOS_POLYGON )
957 int nCoordDims = GEOSGeom_getCoordinateDimension_r( geosinit.ctxt, geos );
958 int nDims = GEOSGeom_getDimensions_r( geosinit.ctxt, geos );
959 bool hasZ = ( nCoordDims == 3 );
960 bool hasM = (( nDims - nCoordDims ) == 1 );
964 const GEOSGeometry* ring = GEOSGetExteriorRing_r( geosinit.ctxt, geos );
971 for (
int i = 0; i < GEOSGetNumInteriorRings_r( geosinit.ctxt, geos ); ++i )
973 ring = GEOSGetInteriorRingN_r( geosinit.ctxt, geos, i );
976 interiorRings.
push_back( sequenceToLinestring( ring, hasZ, hasM ) );
984 QgsLineStringV2* QgsGeos::sequenceToLinestring(
const GEOSGeometry* geos,
bool hasZ,
bool hasM )
987 const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r( geosinit.ctxt, geos );
988 unsigned int nPoints;
989 GEOSCoordSeq_getSize_r( geosinit.ctxt, cs, &nPoints );
991 for (
unsigned int i = 0; i < nPoints; ++i )
1000 int QgsGeos::numberOfGeometries( GEOSGeometry* g )
1005 int geometryType = GEOSGeomTypeId_r( geosinit.ctxt, g );
1006 if ( geometryType == GEOS_POINT || geometryType == GEOS_LINESTRING || geometryType == GEOS_LINEARRING
1007 || geometryType == GEOS_POLYGON )
1011 return GEOSGetNumGeometries_r( geosinit.ctxt, g );
1024 GEOSCoordSeq_getX_r( geosinit.ctxt, cs, i, &x );
1025 GEOSCoordSeq_getY_r( geosinit.ctxt, cs, i, &y );
1028 GEOSCoordSeq_getZ_r( geosinit.ctxt, cs, i, &z );
1032 GEOSCoordSeq_getOrdinate_r( geosinit.ctxt, cs, i, 3, &m );
1069 return createGeosLinestring( lineString.data(), precision );
1071 else if ( curvePolygon )
1074 return createGeosPolygon( polygon.data(), precision );
1078 return createGeosPoint( geom, coordDims, precision );
1082 int geosType = GEOS_MULTIPOINT;
1085 geosType = GEOS_MULTIPOINT;
1089 geosType = GEOS_MULTILINESTRING;
1093 geosType = GEOS_MULTIPOLYGON;
1095 else if ( geom->
geometryType() ==
"GeometryCollection" )
1097 geosType = GEOS_GEOMETRYCOLLECTION;
1111 return createGeosCollection( geosType, geomVector );
1136 opGeom.
reset( GEOSIntersection_r( geosinit.ctxt, mGeos, geosGeom.
get() ) );
1139 opGeom.
reset( GEOSDifference_r( geosinit.ctxt, mGeos, geosGeom.
get() ) );
1143 GEOSGeometry *unionGeometry = GEOSUnion_r( geosinit.ctxt, mGeos, geosGeom.
get() );
1145 if ( unionGeometry && GEOSGeomTypeId_r( geosinit.ctxt, unionGeometry ) == GEOS_MULTILINESTRING )
1147 GEOSGeometry *mergedLines = GEOSLineMerge_r( geosinit.ctxt, unionGeometry );
1150 GEOSGeom_destroy_r( geosinit.ctxt, unionGeometry );
1151 unionGeometry = mergedLines;
1155 opGeom.
reset( unionGeometry );
1159 opGeom.
reset( GEOSSymDifference_r( geosinit.ctxt, mGeos, geosGeom.
get() ) );
1167 catch ( GEOSException &e )
1171 *errorMsg = e.what();
1190 bool result =
false;
1193 if ( mGeosPrepared )
1198 result = ( GEOSPreparedIntersects_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1201 result = ( GEOSPreparedTouches_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1204 result = ( GEOSPreparedCrosses_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1207 result = ( GEOSPreparedWithin_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1210 result = ( GEOSPreparedContains_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1213 result = ( GEOSPreparedDisjoint_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1216 result = ( GEOSPreparedOverlaps_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1227 result = ( GEOSIntersects_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1230 result = ( GEOSTouches_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1233 result = ( GEOSCrosses_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1236 result = ( GEOSWithin_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1239 result = ( GEOSContains_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1242 result = ( GEOSDisjoint_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1245 result = ( GEOSOverlaps_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1251 catch ( GEOSException &e )
1255 *errorMsg = e.what();
1273 geos.
reset( GEOSBuffer_r( geosinit.ctxt, mGeos, distance, segments ) );
1286 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ 1287 ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3))) 1292 geos.
reset( GEOSBufferWithStyle_r( geosinit.ctxt, mGeos, distance, segments, endCapStyle, joinStyle, mitreLimit ) );
1310 geos.
reset( GEOSTopologyPreserveSimplify_r( geosinit.ctxt, mGeos, tolerance ) );
1325 geos.
reset( GEOSInterpolate_r( geosinit.ctxt, mGeos, distance ) );
1341 geos.
reset( GEOSGetCentroid_r( geosinit.ctxt, mGeos ) );
1351 GEOSGeomGetX_r( geosinit.ctxt, geos.
get(), &x );
1352 GEOSGeomGetY_r( geosinit.ctxt, geos.
get(), &y );
1367 geos.
reset( GEOSEnvelope_r( geosinit.ctxt, mGeos ) );
1383 geos.
reset( GEOSPointOnSurface_r( geosinit.ctxt, mGeos ) );
1385 if ( !geos || GEOSisEmpty_r( geosinit.ctxt, geos.
get() ) != 0 )
1391 GEOSGeomGetX_r( geosinit.ctxt, geos.
get(), &x );
1392 GEOSGeomGetY_r( geosinit.ctxt, geos.
get(), &y );
1411 GEOSGeometry* cHull = GEOSConvexHull_r( geosinit.ctxt, mGeos );
1413 GEOSGeom_destroy_r( geosinit.ctxt, cHull );
1428 return GEOSisValid_r( geosinit.ctxt, mGeos );
1447 bool equal = GEOSEquals_r( geosinit.ctxt, mGeos, geosGeom.
get() );
1462 return GEOSisEmpty_r( geosinit.ctxt, mGeos );
1467 GEOSCoordSequence* QgsGeos::createCoordinateSequence(
const QgsCurveV2* curve,
double precision )
1469 bool segmentize =
false;
1483 bool hasZ = line->
is3D();
1496 GEOSCoordSequence* coordSeq =
nullptr;
1499 coordSeq = GEOSCoordSeq_create_r( geosinit.ctxt, numPoints, coordDims );
1505 if ( precision > 0. )
1507 for (
int i = 0; i < numPoints; ++i )
1510 GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, i,
qgsRound( pt.
x() / precision ) * precision );
1511 GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, i,
qgsRound( pt.
y() / precision ) * precision );
1514 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 2,
qgsRound( pt.
z() / precision ) * precision );
1518 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 3, pt.
m() );
1524 for (
int i = 0; i < numPoints; ++i )
1527 GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, i, pt.
x() );
1528 GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, i, pt.
y() );
1531 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 2, pt.
z() );
1535 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 3, pt.
m() );
1549 GEOSGeometry* QgsGeos::createGeosPoint(
const QgsAbstractGeometryV2* point,
int coordDims,
double precision )
1555 GEOSGeometry* geosPoint =
nullptr;
1559 GEOSCoordSequence* coordSeq = GEOSCoordSeq_create_r( geosinit.ctxt, 1, coordDims );
1565 if ( precision > 0. )
1567 GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, 0,
qgsRound( pt->
x() / precision ) * precision );
1568 GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, 0,
qgsRound( pt->
y() / precision ) * precision );
1571 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, 0, 2,
qgsRound( pt->
z() / precision ) * precision );
1576 GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, 0, pt->
x() );
1577 GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, 0, pt->
y() );
1580 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, 0, 2, pt->
z() );
1583 #if 0 //disabled until geos supports m-coordinates 1586 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, 0, 3, pt->
m() );
1589 geosPoint = GEOSGeom_createPoint_r( geosinit.ctxt, coordSeq );
1595 GEOSGeometry* QgsGeos::createGeosLinestring(
const QgsAbstractGeometryV2* curve ,
double precision )
1601 GEOSCoordSequence* coordSeq = createCoordinateSequence( c, precision );
1605 GEOSGeometry* geosGeom =
nullptr;
1608 geosGeom = GEOSGeom_createLineString_r( geosinit.ctxt, coordSeq );
1621 if ( !exteriorRing )
1626 GEOSGeometry* geosPolygon =
nullptr;
1629 GEOSGeometry* exteriorRingGeos = GEOSGeom_createLinearRing_r( geosinit.ctxt, createCoordinateSequence( exteriorRing, precision ) );
1633 GEOSGeometry** holes =
nullptr;
1636 holes =
new GEOSGeometry*[ nHoles ];
1639 for (
int i = 0; i < nHoles; ++i )
1642 holes[i] = GEOSGeom_createLinearRing_r( geosinit.ctxt, createCoordinateSequence( interiorRing, precision ) );
1644 geosPolygon = GEOSGeom_createPolygon_r( geosinit.ctxt, exteriorRingGeos, holes, nHoles );
1657 GEOSGeometry* offset =
nullptr;
1660 offset = GEOSOffsetCurve_r( geosinit.ctxt, mGeos, distance, segments, joinStyle, mitreLimit );
1664 GEOSGeom_destroy_r( geosinit.ctxt, offset );
1672 if ( errorCode ) { *errorCode = 1; }
1676 GEOSGeometry* reshapeLineGeos = createGeosLinestring( &reshapeWithLine, mPrecision );
1679 int numGeoms = GEOSGetNumGeometries_r( geosinit.ctxt, mGeos );
1680 if ( numGeoms == -1 )
1682 if ( errorCode ) { *errorCode = 1; }
1683 GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
1687 bool isMultiGeom =
false;
1688 int geosTypeId = GEOSGeomTypeId_r( geosinit.ctxt, mGeos );
1689 if ( geosTypeId == GEOS_MULTILINESTRING || geosTypeId == GEOS_MULTIPOLYGON )
1696 GEOSGeometry* reshapedGeometry;
1699 reshapedGeometry = reshapeLine( mGeos, reshapeLineGeos, mPrecision );
1703 reshapedGeometry = reshapePolygon( mGeos, reshapeLineGeos, mPrecision );
1706 if ( errorCode ) { *errorCode = 0; }
1708 GEOSGeom_destroy_r( geosinit.ctxt, reshapedGeometry );
1709 GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
1710 return reshapeResult;
1717 bool reshapeTookPlace =
false;
1719 GEOSGeometry* currentReshapeGeometry =
nullptr;
1720 GEOSGeometry** newGeoms =
new GEOSGeometry*[numGeoms];
1722 for (
int i = 0; i < numGeoms; ++i )
1725 currentReshapeGeometry = reshapeLine( GEOSGetGeometryN_r( geosinit.ctxt, mGeos, i ), reshapeLineGeos, mPrecision );
1727 currentReshapeGeometry = reshapePolygon( GEOSGetGeometryN_r( geosinit.ctxt, mGeos, i ), reshapeLineGeos, mPrecision );
1729 if ( currentReshapeGeometry )
1731 newGeoms[i] = currentReshapeGeometry;
1732 reshapeTookPlace =
true;
1736 newGeoms[i] = GEOSGeom_clone_r( geosinit.ctxt, GEOSGetGeometryN_r( geosinit.ctxt, mGeos, i ) );
1739 GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
1741 GEOSGeometry* newMultiGeom =
nullptr;
1744 newMultiGeom = GEOSGeom_createCollection_r( geosinit.ctxt, GEOS_MULTILINESTRING, newGeoms, numGeoms );
1748 newMultiGeom = GEOSGeom_createCollection_r( geosinit.ctxt, GEOS_MULTIPOLYGON, newGeoms, numGeoms );
1752 if ( !newMultiGeom )
1754 if ( errorCode ) { *errorCode = 3; }
1758 if ( reshapeTookPlace )
1760 if ( errorCode ) { *errorCode = 0; }
1762 GEOSGeom_destroy_r( geosinit.ctxt, newMultiGeom );
1763 return reshapedMultiGeom;
1767 GEOSGeom_destroy_r( geosinit.ctxt, newMultiGeom );
1768 if ( errorCode ) { *errorCode = 1; }
1778 if ( !mGeos || other.
isEmpty() )
1793 GEOSCoordSequence* nearestCoord = GEOSNearestPoints_r( geosinit.ctxt, mGeos, otherGeom.
get() );
1795 ( void )GEOSCoordSeq_getX_r( geosinit.ctxt, nearestCoord, 0, &nx );
1796 ( void )GEOSCoordSeq_getY_r( geosinit.ctxt, nearestCoord, 0, &ny );
1797 GEOSCoordSeq_destroy_r( geosinit.ctxt, nearestCoord );
1799 catch ( GEOSException &e )
1803 *errorMsg = e.what();
1813 if ( !mGeos || other.
isEmpty() )
1830 GEOSCoordSequence* nearestCoord = GEOSNearestPoints_r( geosinit.ctxt, mGeos, otherGeom.
get() );
1832 ( void )GEOSCoordSeq_getX_r( geosinit.ctxt, nearestCoord, 0, &nx1 );
1833 ( void )GEOSCoordSeq_getY_r( geosinit.ctxt, nearestCoord, 0, &ny1 );
1834 ( void )GEOSCoordSeq_getX_r( geosinit.ctxt, nearestCoord, 1, &nx2 );
1835 ( void )GEOSCoordSeq_getY_r( geosinit.ctxt, nearestCoord, 1, &ny2 );
1837 GEOSCoordSeq_destroy_r( geosinit.ctxt, nearestCoord );
1839 catch ( GEOSException &e )
1843 *errorMsg = e.what();
1854 GEOSGeometry* QgsGeos::reshapeLine(
const GEOSGeometry* line,
const GEOSGeometry* reshapeLineGeos ,
double precision )
1856 if ( !line || !reshapeLineGeos )
1859 bool atLeastTwoIntersections =
false;
1864 GEOSGeometry* intersectGeom = GEOSIntersection_r( geosinit.ctxt, line, reshapeLineGeos );
1865 if ( intersectGeom )
1867 atLeastTwoIntersections = ( GEOSGeomTypeId_r( geosinit.ctxt, intersectGeom ) == GEOS_MULTIPOINT
1868 && GEOSGetNumGeometries_r( geosinit.ctxt, intersectGeom ) > 1 );
1869 GEOSGeom_destroy_r( geosinit.ctxt, intersectGeom );
1872 catch ( GEOSException &e )
1875 atLeastTwoIntersections =
false;
1878 if ( !atLeastTwoIntersections )
1882 const GEOSCoordSequence* lineCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.ctxt, line );
1883 if ( !lineCoordSeq )
1886 unsigned int lineCoordSeqSize;
1887 if ( GEOSCoordSeq_getSize_r( geosinit.ctxt, lineCoordSeq, &lineCoordSeqSize ) == 0 )
1890 if ( lineCoordSeqSize < 2 )
1894 double x1, y1, x2, y2;
1895 GEOSCoordSeq_getX_r( geosinit.ctxt, lineCoordSeq, 0, &x1 );
1896 GEOSCoordSeq_getY_r( geosinit.ctxt, lineCoordSeq, 0, &y1 );
1897 GEOSCoordSeq_getX_r( geosinit.ctxt, lineCoordSeq, lineCoordSeqSize - 1, &x2 );
1898 GEOSCoordSeq_getY_r( geosinit.ctxt, lineCoordSeq, lineCoordSeqSize - 1, &y2 );
1900 GEOSGeometry* beginLineVertex = createGeosPoint( &beginPoint, 2, precision );
1902 GEOSGeometry* endLineVertex = createGeosPoint( &endPoint, 2, precision );
1904 bool isRing =
false;
1905 if ( GEOSGeomTypeId_r( geosinit.ctxt, line ) == GEOS_LINEARRING
1906 || GEOSEquals_r( geosinit.ctxt, beginLineVertex, endLineVertex ) == 1 )
1910 GEOSGeometry* nodedGeometry = nodeGeometries( reshapeLineGeos, line );
1911 if ( !nodedGeometry )
1913 GEOSGeom_destroy_r( geosinit.ctxt, beginLineVertex );
1914 GEOSGeom_destroy_r( geosinit.ctxt, endLineVertex );
1919 GEOSGeometry *mergedLines = GEOSLineMerge_r( geosinit.ctxt, nodedGeometry );
1920 GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
1923 GEOSGeom_destroy_r( geosinit.ctxt, beginLineVertex );
1924 GEOSGeom_destroy_r( geosinit.ctxt, endLineVertex );
1928 int numMergedLines = GEOSGetNumGeometries_r( geosinit.ctxt, mergedLines );
1929 if ( numMergedLines < 2 )
1931 GEOSGeom_destroy_r( geosinit.ctxt, beginLineVertex );
1932 GEOSGeom_destroy_r( geosinit.ctxt, endLineVertex );
1933 if ( numMergedLines == 1 )
1934 return GEOSGeom_clone_r( geosinit.ctxt, reshapeLineGeos );
1942 for (
int i = 0; i < numMergedLines; ++i )
1944 const GEOSGeometry* currentGeom;
1946 currentGeom = GEOSGetGeometryN_r( geosinit.ctxt, mergedLines, i );
1947 const GEOSCoordSequence* currentCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.ctxt, currentGeom );
1948 unsigned int currentCoordSeqSize;
1949 GEOSCoordSeq_getSize_r( geosinit.ctxt, currentCoordSeq, ¤tCoordSeqSize );
1950 if ( currentCoordSeqSize < 2 )
1954 double xBegin, xEnd, yBegin, yEnd;
1955 GEOSCoordSeq_getX_r( geosinit.ctxt, currentCoordSeq, 0, &xBegin );
1956 GEOSCoordSeq_getY_r( geosinit.ctxt, currentCoordSeq, 0, &yBegin );
1957 GEOSCoordSeq_getX_r( geosinit.ctxt, currentCoordSeq, currentCoordSeqSize - 1, &xEnd );
1958 GEOSCoordSeq_getY_r( geosinit.ctxt, currentCoordSeq, currentCoordSeqSize - 1, &yEnd );
1960 GEOSGeometry* beginCurrentGeomVertex = createGeosPoint( &beginPoint, 2, precision );
1962 GEOSGeometry* endCurrentGeomVertex = createGeosPoint( &endPoint, 2, precision );
1965 int nEndpointsOnOriginalLine = 0;
1966 if ( pointContainedInLine( beginCurrentGeomVertex, line ) == 1 )
1967 nEndpointsOnOriginalLine += 1;
1969 if ( pointContainedInLine( endCurrentGeomVertex, line ) == 1 )
1970 nEndpointsOnOriginalLine += 1;
1973 int nEndpointsSameAsOriginalLine = 0;
1974 if ( GEOSEquals_r( geosinit.ctxt, beginCurrentGeomVertex, beginLineVertex ) == 1
1975 || GEOSEquals_r( geosinit.ctxt, beginCurrentGeomVertex, endLineVertex ) == 1 )
1976 nEndpointsSameAsOriginalLine += 1;
1978 if ( GEOSEquals_r( geosinit.ctxt, endCurrentGeomVertex, beginLineVertex ) == 1
1979 || GEOSEquals_r( geosinit.ctxt, endCurrentGeomVertex, endLineVertex ) == 1 )
1980 nEndpointsSameAsOriginalLine += 1;
1983 bool currentGeomOverlapsOriginalGeom =
false;
1984 bool currentGeomOverlapsReshapeLine =
false;
1985 if ( lineContainedInLine( currentGeom, line ) == 1 )
1986 currentGeomOverlapsOriginalGeom =
true;
1988 if ( lineContainedInLine( currentGeom, reshapeLineGeos ) == 1 )
1989 currentGeomOverlapsReshapeLine =
true;
1992 if ( !isRing && nEndpointsSameAsOriginalLine == 1 && nEndpointsOnOriginalLine == 2 && currentGeomOverlapsOriginalGeom )
1994 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.ctxt, currentGeom ) );
1997 else if ( isRing && nEndpointsOnOriginalLine == 2 && currentGeomOverlapsOriginalGeom )
1999 probableParts.
push_back( GEOSGeom_clone_r( geosinit.ctxt, currentGeom ) );
2001 else if ( nEndpointsOnOriginalLine == 2 && !currentGeomOverlapsOriginalGeom )
2003 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.ctxt, currentGeom ) );
2005 else if ( nEndpointsSameAsOriginalLine == 2 && !currentGeomOverlapsOriginalGeom )
2007 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.ctxt, currentGeom ) );
2009 else if ( currentGeomOverlapsOriginalGeom && currentGeomOverlapsReshapeLine )
2011 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.ctxt, currentGeom ) );
2014 GEOSGeom_destroy_r( geosinit.ctxt, beginCurrentGeomVertex );
2015 GEOSGeom_destroy_r( geosinit.ctxt, endCurrentGeomVertex );
2019 if ( isRing && !probableParts.
isEmpty() )
2021 GEOSGeometry* maxGeom =
nullptr;
2022 GEOSGeometry* currentGeom =
nullptr;
2024 double currentLength = 0;
2025 for (
int i = 0; i < probableParts.
size(); ++i )
2027 currentGeom = probableParts.
at( i );
2028 GEOSLength_r( geosinit.ctxt, currentGeom, ¤tLength );
2029 if ( currentLength > maxLength )
2031 maxLength = currentLength;
2032 GEOSGeom_destroy_r( geosinit.ctxt, maxGeom );
2033 maxGeom = currentGeom;
2037 GEOSGeom_destroy_r( geosinit.ctxt, currentGeom );
2043 GEOSGeom_destroy_r( geosinit.ctxt, beginLineVertex );
2044 GEOSGeom_destroy_r( geosinit.ctxt, endLineVertex );
2045 GEOSGeom_destroy_r( geosinit.ctxt, mergedLines );
2047 GEOSGeometry* result =
nullptr;
2048 if ( resultLineParts.
size() < 1 )
2051 if ( resultLineParts.
size() == 1 )
2053 result = resultLineParts[0];
2057 GEOSGeometry **lineArray =
new GEOSGeometry*[resultLineParts.
size()];
2058 for (
int i = 0; i < resultLineParts.
size(); ++i )
2060 lineArray[i] = resultLineParts[i];
2064 GEOSGeometry* multiLineGeom = GEOSGeom_createCollection_r( geosinit.ctxt, GEOS_MULTILINESTRING, lineArray, resultLineParts.
size() );
2065 delete [] lineArray;
2068 result = GEOSLineMerge_r( geosinit.ctxt, multiLineGeom );
2069 GEOSGeom_destroy_r( geosinit.ctxt, multiLineGeom );
2073 if ( GEOSGeomTypeId_r( geosinit.ctxt, result ) != GEOS_LINESTRING )
2075 GEOSGeom_destroy_r( geosinit.ctxt, result );
2082 GEOSGeometry* QgsGeos::reshapePolygon(
const GEOSGeometry* polygon,
const GEOSGeometry* reshapeLineGeos,
double precision )
2085 int nIntersections = 0;
2086 int lastIntersectingRing = -2;
2087 const GEOSGeometry* lastIntersectingGeom =
nullptr;
2089 int nRings = GEOSGetNumInteriorRings_r( geosinit.ctxt, polygon );
2094 const GEOSGeometry* outerRing = GEOSGetExteriorRing_r( geosinit.ctxt, polygon );
2095 if ( GEOSIntersects_r( geosinit.ctxt, outerRing, reshapeLineGeos ) == 1 )
2098 lastIntersectingRing = -1;
2099 lastIntersectingGeom = outerRing;
2103 const GEOSGeometry **innerRings =
new const GEOSGeometry*[nRings];
2107 for (
int i = 0; i < nRings; ++i )
2109 innerRings[i] = GEOSGetInteriorRingN_r( geosinit.ctxt, polygon, i );
2110 if ( GEOSIntersects_r( geosinit.ctxt, innerRings[i], reshapeLineGeos ) == 1 )
2113 lastIntersectingRing = i;
2114 lastIntersectingGeom = innerRings[i];
2118 catch ( GEOSException &e )
2124 if ( nIntersections != 1 )
2126 delete [] innerRings;
2131 GEOSGeometry* reshapeResult = reshapeLine( lastIntersectingGeom, reshapeLineGeos, precision );
2132 if ( !reshapeResult )
2134 delete [] innerRings;
2139 GEOSGeometry* newRing =
nullptr;
2140 const GEOSCoordSequence* reshapeSequence = GEOSGeom_getCoordSeq_r( geosinit.ctxt, reshapeResult );
2141 GEOSCoordSequence* newCoordSequence = GEOSCoordSeq_clone_r( geosinit.ctxt, reshapeSequence );
2143 GEOSGeom_destroy_r( geosinit.ctxt, reshapeResult );
2145 newRing = GEOSGeom_createLinearRing_r( geosinit.ctxt, newCoordSequence );
2148 delete [] innerRings;
2152 GEOSGeometry* newOuterRing =
nullptr;
2153 if ( lastIntersectingRing == -1 )
2154 newOuterRing = newRing;
2156 newOuterRing = GEOSGeom_clone_r( geosinit.ctxt, outerRing );
2162 GEOSGeometry* outerRingPoly = GEOSGeom_createPolygon_r( geosinit.ctxt, GEOSGeom_clone_r( geosinit.ctxt, newOuterRing ),
nullptr, 0 );
2163 if ( outerRingPoly )
2165 GEOSGeometry* currentRing =
nullptr;
2166 for (
int i = 0; i < nRings; ++i )
2168 if ( lastIntersectingRing == i )
2169 currentRing = newRing;
2171 currentRing = GEOSGeom_clone_r( geosinit.ctxt, innerRings[i] );
2174 if ( GEOSContains_r( geosinit.ctxt, outerRingPoly, currentRing ) == 1 )
2177 GEOSGeom_destroy_r( geosinit.ctxt, currentRing );
2180 GEOSGeom_destroy_r( geosinit.ctxt, outerRingPoly );
2183 GEOSGeometry** newInnerRings =
new GEOSGeometry*[ringList.
size()];
2184 for (
int i = 0; i < ringList.
size(); ++i )
2185 newInnerRings[i] = ringList.
at( i );
2187 delete [] innerRings;
2189 GEOSGeometry* reshapedPolygon = GEOSGeom_createPolygon_r( geosinit.ctxt, newOuterRing, newInnerRings, ringList.
size() );
2190 delete[] newInnerRings;
2192 return reshapedPolygon;
2195 int QgsGeos::lineContainedInLine(
const GEOSGeometry* line1,
const GEOSGeometry* line2 )
2197 if ( !line1 || !line2 )
2202 double bufferDistance = pow( 10.0L, geomDigits( line2 ) - 11 );
2208 GEOSGeometry* intersectionGeom = GEOSIntersection_r( geosinit.ctxt, bufferGeom, line1 );
2211 double intersectGeomLength;
2214 GEOSLength_r( geosinit.ctxt, intersectionGeom, &intersectGeomLength );
2215 GEOSLength_r( geosinit.ctxt, line1, &line1Length );
2217 GEOSGeom_destroy_r( geosinit.ctxt, bufferGeom );
2218 GEOSGeom_destroy_r( geosinit.ctxt, intersectionGeom );
2220 double intersectRatio = line1Length / intersectGeomLength;
2221 if ( intersectRatio > 0.9 && intersectRatio < 1.1 )
2227 int QgsGeos::pointContainedInLine(
const GEOSGeometry* point,
const GEOSGeometry* line )
2229 if ( !point || !line )
2232 double bufferDistance = pow( 10.0L, geomDigits( line ) - 11 );
2234 GEOSGeometry* lineBuffer = GEOSBuffer_r( geosinit.ctxt, line, bufferDistance, 8 );
2238 bool contained =
false;
2239 if ( GEOSContains_r( geosinit.ctxt, lineBuffer, point ) == 1 )
2242 GEOSGeom_destroy_r( geosinit.ctxt, lineBuffer );
2246 int QgsGeos::geomDigits(
const GEOSGeometry* geom )
2252 const GEOSGeometry* bBoxRing = GEOSGetExteriorRing_r( geosinit.ctxt, bbox.
get() );
2256 const GEOSCoordSequence* bBoxCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.ctxt, bBoxRing );
2258 if ( !bBoxCoordSeq )
2261 unsigned int nCoords = 0;
2262 if ( !GEOSCoordSeq_getSize_r( geosinit.ctxt, bBoxCoordSeq, &nCoords ) )
2266 for (
unsigned int i = 0; i < nCoords - 1; ++i )
2269 GEOSCoordSeq_getX_r( geosinit.ctxt, bBoxCoordSeq, i, &t );
2272 digits = ceil( log10( fabs( t ) ) );
2273 if ( digits > maxDigits )
2276 GEOSCoordSeq_getY_r( geosinit.ctxt, bBoxCoordSeq, i, &t );
2277 digits = ceil( log10( fabs( t ) ) );
2278 if ( digits > maxDigits )
2287 return geosinit.ctxt;
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
void reset(GEOSGeometry *geom)
const QgsCurveV2 * exteriorRing() const
void setInteriorRings(const QList< QgsCurveV2 *> &rings)
Sets all interior rings (takes ownership)
int numGeometries() const
Returns the number of geometries within the collection.
const QgsCurveV2 * interiorRing(int i) const
QgsAbstractGeometryV2 * combine(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
static QgsPointV2 coordSeqPoint(const GEOSCoordSequence *cs, int i, bool hasZ, bool hasM)
void push_back(const T &value)
bool isEmpty(QString *errorMsg=nullptr) const override
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
bool relatePattern(const QgsAbstractGeometryV2 &geom, const QString &pattern, QString *errorMsg=nullptr) const override
Tests whether two geometries are related by a specified Dimensional Extended 9 Intersection Model (DE...
Multi curve geometry collection.
QgsGeometry shortestLine(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the shortest line joining this geometry to the other geometry.
double area(QString *errorMsg=nullptr) const override
const_iterator constEnd() const
const T & at(int i) const
static bool isMultiType(Type type)
Returns true if the WKB type is a multi type.
Abstract base class for all geometries.
double length(QString *errorMsg=nullptr) const override
GEOSGeometry * get() const
A geometry is the spatial representation of a feature.
static QgsAbstractGeometryV2 * fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
void setX(double x)
Sets the point's x-coordinate.
QgsAbstractGeometryV2 * symDifference(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
bool isValid(QString *errorMsg=nullptr) const override
QgsGeos(const QgsAbstractGeometryV2 *geometry, double precision=0)
GEOS geometry engine constructor.
Multi point geometry collection.
QgsAbstractGeometryV2 * simplify(double tolerance, QString *errorMsg=nullptr) const override
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
double z() const
Returns the point's z-coordinate.
double y() const
Returns the point's y-coordinate.
QgsGeometry closestPoint(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the closest point on the geometry to the other geometry.
Multi line string geometry collection.
QString tr(const char *sourceText, const char *disambiguation, int n)
void setY(double y)
Sets the point's y-coordinate.
int splitGeometry(const QgsLineStringV2 &splitLine, QList< QgsAbstractGeometryV2 *> &newGeometries, bool topological, QgsPointSequenceV2 &topologyTestPoints, QString *errorMsg=nullptr) const override
Splits this geometry according to a given line.
static GEOSContextHandle_t getGEOSHandler()
QgsAbstractGeometryV2 * interpolate(double distance, QString *errorMsg=nullptr) const override
GEOSGeomScopedPtr(GEOSGeometry *geom=nullptr)
bool within(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
bool contains(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
bool intersects(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
#define CATCH_GEOS_WITH_ERRMSG(r)
double qgsRound(double x)
const QgsAbstractGeometryV2 * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
QString fromUtf8(const char *str, int size)
virtual void setExteriorRing(QgsCurveV2 *ring) override
Sets the exterior ring of the polygon.
static QgsPolygonV2 * fromGeosPolygon(const GEOSGeometry *geos)
Line string geometry type, with support for z-dimension and m-values.
void setPoints(const QgsPointSequenceV2 &points)
Resets the line string to match the specified list of points.
bool isMeasure() const
Returns true if the geometry contains m values.
void prepareGeometry() override
Point geometry type, with support for z-dimension and m-values.
QgsAbstractGeometryV2 * intersection(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
const char * constData() const
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
virtual QgsLineStringV2 * clone() const override
Clones the geometry by performing a deep copy.
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
double x() const
Returns the point's x-coordinate.
QgsAbstractGeometryV2 * envelope(QString *errorMsg=nullptr) const override
bool disjoint(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
const QgsAbstractGeometryV2 * mGeometry
QString relate(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Returns the Dimensional Extended 9 Intersection Model (DE-9IM) representation of the relationship bet...
bool touches(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
QByteArray toLocal8Bit() const
static GEOSGeometry * asGeos(const QgsAbstractGeometryV2 *geom, double precision=0)
QgsAbstractGeometryV2 * reshapeGeometry(const QgsLineStringV2 &reshapeWithLine, int *errorCode, QString *errorMsg=nullptr) const
virtual QString geometryType() const =0
Returns a unique string representing the geometry type.
void geometryChanged() override
Removes caches.
bool crosses(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
void addVertex(const QgsPointV2 &pt)
Adds a new vertex to the end of the line string.
virtual QgsLineStringV2 * curveToLine() const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
const_iterator constBegin() const
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
bool centroid(QgsPointV2 &pt, QString *errorMsg=nullptr) 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.
virtual QgsPolygonV2 * toPolygon() const
int count(const T &value) const
bool isEqual(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
bool pointOnSurface(QgsPointV2 &pt, QString *errorMsg=nullptr) const override
double distance(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
Multi polygon geometry collection.
Contains geometry relation and modification algorithms.
Curve polygon geometry type.
bool overlaps(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
QgsAbstractGeometryV2 * difference(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
virtual QgsAbstractGeometryV2 * clone() const =0
Clones the geometry by performing a deep copy.
Abstract base class for curved geometry type.
QgsAbstractGeometryV2 * offsetCurve(double distance, int segments, int joinStyle, double mitreLimit, QString *errorMsg=nullptr) const override
#define DEFAULT_QUADRANT_SEGMENTS
double m() const
Returns the point's m value.
QgsAbstractGeometryV2 * convexHull(QString *errorMsg=nullptr) const override
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
QgsAbstractGeometryV2 * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
int numPoints() const override
Returns the number of points in the curve.
int numInteriorRings() const
QgsPointV2 pointN(int i) const
Returns the specified point from inside the line string.