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 ( 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.
const QgsCurveV2 * exteriorRing() const
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.
void reset(GEOSGeometry *geom)
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
QgsPointV2 pointN(int i) const
Returns the specified point from inside the line string.
QgsAbstractGeometryV2 * combine(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
static QgsPointV2 coordSeqPoint(const GEOSCoordSequence *cs, int i, bool hasZ, bool hasM)
double x() const
Returns the point's x-coordinate.
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...
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
Multi curve geometry collection.
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.
QgsGeometry closestPoint(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the closest point on the geometry to the other geometry.
Abstract base class for all geometries.
double length(QString *errorMsg=nullptr) const override
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.
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.
static GEOSContextHandle_t getGEOSHandler()
GEOSGeometry * get() const
QgsAbstractGeometryV2 * interpolate(double distance, QString *errorMsg=nullptr) const override
GEOSGeomScopedPtr(GEOSGeometry *geom=nullptr)
double y() const
Returns the point's y-coordinate.
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)
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
void setInteriorRings(const QList< QgsCurveV2 * > &rings)
Sets all interior rings (takes ownership)
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)
bool isMeasure() const
Returns true if the geometry contains m values.
double z() const
Returns the point's z-coordinate.
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.
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.
virtual QgsPolygonV2 * toPolygon() const
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)
virtual QString geometryType() const =0
Returns a unique string representing the geometry type.
const QgsCurveV2 * interiorRing(int i) const
void geometryChanged() override
Removes caches.
bool crosses(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
int numGeometries() const
Returns the number of geometries within the collection.
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 * reshapeGeometry(const QgsLineStringV2 &reshapeWithLine, int *errorCode, QString *errorMsg=nullptr) const
bool centroid(QgsPointV2 &pt, QString *errorMsg=nullptr) const override
QgsGeometry shortestLine(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the shortest line joining this geometry to the other geometry.
virtual bool addGeometry(QgsAbstractGeometryV2 *g)
Adds a geometry and takes ownership.
virtual int dimension() const =0
Returns the inherent dimension of the geometry.
int count(const T &value) const
bool isEqual(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
const QgsAbstractGeometryV2 * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
double m() const
Returns the point's m value.
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.
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
Curve polygon geometry type.
bool overlaps(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
QgsAbstractGeometryV2 * difference(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
int numInteriorRings() const
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
QgsAbstractGeometryV2 * convexHull(QString *errorMsg=nullptr) const override
QgsAbstractGeometryV2 * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
int numPoints() const override
Returns the number of points in the curve.