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 );
138 , mGeosPrepared( nullptr )
139 , mPrecision( precision )
146 GEOSGeom_destroy_r( geosinit.ctxt, mGeos );
148 GEOSPreparedGeom_destroy_r( geosinit.ctxt, mGeosPrepared );
149 mGeosPrepared =
nullptr;
154 GEOSGeom_destroy_r( geosinit.ctxt, mGeos );
156 GEOSPreparedGeom_destroy_r( geosinit.ctxt, mGeosPrepared );
157 mGeosPrepared =
nullptr;
163 GEOSPreparedGeom_destroy_r( geosinit.ctxt, mGeosPrepared );
164 mGeosPrepared =
nullptr;
167 mGeosPrepared = GEOSPrepare_r( geosinit.ctxt, mGeos );
171 void QgsGeos::cacheGeos()
const 183 return overlay( geom, INTERSECTION, errorMsg );
188 return overlay( geom, DIFFERENCE, errorMsg );
193 return overlay( geom, UNION, errorMsg );
201 for (
int i = 0; i < geomList.
size(); ++i )
203 geosGeometries[i] =
asGeos( geomList.
at( i ), mPrecision );
206 GEOSGeometry* geomUnion =
nullptr;
209 GEOSGeometry* geomCollection = createGeosCollection( GEOS_GEOMETRYCOLLECTION, geosGeometries );
210 geomUnion = GEOSUnaryUnion_r( geosinit.ctxt, geomCollection );
211 GEOSGeom_destroy_r( geosinit.ctxt, geomCollection );
216 GEOSGeom_destroy_r( geosinit.ctxt, geomUnion );
222 return overlay( geom, SYMDIFFERENCE, errorMsg );
233 GEOSGeometry* otherGeosGeom =
asGeos( &geom, mPrecision );
234 if ( !otherGeosGeom )
241 GEOSDistance_r( geosinit.ctxt, mGeos, otherGeosGeom, &distance );
245 GEOSGeom_destroy_r( geosinit.ctxt, otherGeosGeom );
252 return relation( geom, INTERSECTS, errorMsg );
257 return relation( geom, TOUCHES, errorMsg );
262 return relation( geom, CROSSES, errorMsg );
267 return relation( geom, WITHIN, errorMsg );
272 return relation( geom, OVERLAPS, errorMsg );
277 return relation( geom, CONTAINS, errorMsg );
282 return relation( geom, DISJOINT, errorMsg );
301 char* r = GEOSRelate_r( geosinit.ctxt, mGeos, geosGeom.
get() );
305 GEOSFree_r( geosinit.ctxt, r );
308 catch ( GEOSException &e )
312 *errorMsg = e.what();
335 result = ( GEOSRelatePattern_r( geosinit.ctxt, mGeos, geosGeom.
get(), pattern.
toLocal8Bit().
constData() ) == 1 );
337 catch ( GEOSException &e )
341 *errorMsg = e.what();
358 if ( GEOSArea_r( geosinit.ctxt, mGeos, &area ) != 1 )
374 if ( GEOSLength_r( geosinit.ctxt, mGeos, &length ) != 1 )
400 if ( !GEOSisValid_r( geosinit.ctxt, mGeos ) )
408 newGeometries.
clear();
409 GEOSGeometry* splitLineGeos =
nullptr;
415 splitLineGeos = createGeosLinestring( &splitLine, mPrecision );
420 splitLineGeos = createGeosPoint( &pt, 2, mPrecision );
427 if ( !GEOSisValid_r( geosinit.ctxt, splitLineGeos ) || !GEOSisSimple_r( geosinit.ctxt, splitLineGeos ) )
429 GEOSGeom_destroy_r( geosinit.ctxt, splitLineGeos );
436 if ( topologicalTestPointsSplit( splitLineGeos, topologyTestPoints ) != 0 )
443 returnCode = splitLinearGeometry( splitLineGeos, newGeometries );
444 GEOSGeom_destroy_r( geosinit.ctxt, splitLineGeos );
448 returnCode = splitPolygonGeometry( splitLineGeos, newGeometries );
449 GEOSGeom_destroy_r( geosinit.ctxt, splitLineGeos );
463 int QgsGeos::topologicalTestPointsSplit(
const GEOSGeometry* splitLine,
QgsPointSequenceV2 &testPoints,
QString* errorMsg )
const 477 GEOSGeometry* intersectionGeom = GEOSIntersection_r( geosinit.ctxt, mGeos, splitLine );
478 if ( !intersectionGeom )
482 int nIntersectGeoms = 1;
483 if ( GEOSGeomTypeId_r( geosinit.ctxt, intersectionGeom ) == GEOS_LINESTRING
484 || GEOSGeomTypeId_r( geosinit.ctxt, intersectionGeom ) == GEOS_POINT )
488 nIntersectGeoms = GEOSGetNumGeometries_r( geosinit.ctxt, intersectionGeom );
490 for (
int i = 0; i < nIntersectGeoms; ++i )
492 const GEOSGeometry* currentIntersectGeom;
494 currentIntersectGeom = intersectionGeom;
496 currentIntersectGeom = GEOSGetGeometryN_r( geosinit.ctxt, intersectionGeom, i );
498 const GEOSCoordSequence* lineSequence = GEOSGeom_getCoordSeq_r( geosinit.ctxt, currentIntersectGeom );
499 unsigned int sequenceSize = 0;
501 if ( GEOSCoordSeq_getSize_r( geosinit.ctxt, lineSequence, &sequenceSize ) != 0 )
503 for (
unsigned int i = 0; i < sequenceSize; ++i )
505 if ( GEOSCoordSeq_getX_r( geosinit.ctxt, lineSequence, i, &x ) != 0 )
507 if ( GEOSCoordSeq_getY_r( geosinit.ctxt, lineSequence, i, &y ) != 0 )
515 GEOSGeom_destroy_r( geosinit.ctxt, intersectionGeom );
522 GEOSGeometry* QgsGeos::linePointDifference( GEOSGeometry* GEOSsplitPoint )
const 524 int type = GEOSGeomTypeId_r( geosinit.ctxt, mGeos );
527 if ( type == GEOS_MULTILINESTRING )
531 else if ( type == GEOS_LINESTRING )
567 for (
int j = 1; j < ( nVertices - 1 ); ++j )
571 if ( currentPoint == *splitPoint )
585 return asGeos( &lines, mPrecision );
597 if ( !GEOSIntersects_r( geosinit.ctxt, splitLine, mGeos ) )
601 int linearIntersect = GEOSRelatePattern_r( geosinit.ctxt, mGeos, splitLine,
"1********" );
602 if ( linearIntersect > 0 )
605 int splitGeomType = GEOSGeomTypeId_r( geosinit.ctxt, splitLine );
607 GEOSGeometry* splitGeom;
608 if ( splitGeomType == GEOS_POINT )
610 splitGeom = linePointDifference( splitLine );
614 splitGeom = GEOSDifference_r( geosinit.ctxt, mGeos, splitLine );
618 int splitType = GEOSGeomTypeId_r( geosinit.ctxt, splitGeom );
619 if ( splitType == GEOS_MULTILINESTRING )
621 int nGeoms = GEOSGetNumGeometries_r( geosinit.ctxt, splitGeom );
623 for (
int i = 0; i < nGeoms; ++i )
624 lineGeoms << GEOSGeom_clone_r( geosinit.ctxt, GEOSGetGeometryN_r( geosinit.ctxt, splitGeom, i ) );
629 lineGeoms << GEOSGeom_clone_r( geosinit.ctxt, splitGeom );
632 mergeGeometriesMultiTypeSplit( lineGeoms );
634 for (
int i = 0; i < lineGeoms.
size(); ++i )
636 newGeometries <<
fromGeos( lineGeoms[i] );
637 GEOSGeom_destroy_r( geosinit.ctxt, lineGeoms[i] );
640 GEOSGeom_destroy_r( geosinit.ctxt, splitGeom );
653 if ( !GEOSIntersects_r( geosinit.ctxt, splitLine, mGeos ) )
657 GEOSGeometry *nodedGeometry = nodeGeometries( splitLine, mGeos );
658 if ( !nodedGeometry )
661 GEOSGeometry *polygons = GEOSPolygonize_r( geosinit.ctxt, &nodedGeometry, 1 );
662 if ( !polygons || numberOfGeometries( polygons ) == 0 )
665 GEOSGeom_destroy_r( geosinit.ctxt, polygons );
667 GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
672 GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
677 GEOSGeometry *intersectGeometry =
nullptr;
682 for (
int i = 0; i < numberOfGeometries( polygons ); i++ )
684 const GEOSGeometry *polygon = GEOSGetGeometryN_r( geosinit.ctxt, polygons, i );
685 intersectGeometry = GEOSIntersection_r( geosinit.ctxt, mGeos, polygon );
686 if ( !intersectGeometry )
692 double intersectionArea;
693 GEOSArea_r( geosinit.ctxt, intersectGeometry, &intersectionArea );
696 GEOSArea_r( geosinit.ctxt, polygon, &polygonArea );
698 const double areaRatio = intersectionArea / polygonArea;
699 if ( areaRatio > 0.99 && areaRatio < 1.01 )
700 testedGeometries << GEOSGeom_clone_r( geosinit.ctxt, polygon );
702 GEOSGeom_destroy_r( geosinit.ctxt, intersectGeometry );
704 GEOSGeom_destroy_r( geosinit.ctxt, polygons );
706 bool splitDone =
true;
707 int nGeometriesThis = numberOfGeometries( mGeos );
708 if ( testedGeometries.
size() == nGeometriesThis )
713 mergeGeometriesMultiTypeSplit( testedGeometries );
718 for (
int i = 0; i < testedGeometries.
size(); ++i )
720 GEOSGeom_destroy_r( geosinit.ctxt, testedGeometries[i] );
726 for ( i = 0; i < testedGeometries.
size() && GEOSisValid_r( geosinit.ctxt, testedGeometries[i] ); ++i )
729 if ( i < testedGeometries.
size() )
731 for ( i = 0; i < testedGeometries.
size(); ++i )
732 GEOSGeom_destroy_r( geosinit.ctxt, testedGeometries[i] );
737 for ( i = 0; i < testedGeometries.
size(); ++i )
738 newGeometries <<
fromGeos( testedGeometries[i] );
743 GEOSGeometry* QgsGeos::nodeGeometries(
const GEOSGeometry *splitLine,
const GEOSGeometry *geom )
745 if ( !splitLine || !geom )
748 GEOSGeometry *geometryBoundary =
nullptr;
749 if ( GEOSGeomTypeId_r( geosinit.ctxt, geom ) == GEOS_POLYGON || GEOSGeomTypeId_r( geosinit.ctxt, geom ) == GEOS_MULTIPOLYGON )
750 geometryBoundary = GEOSBoundary_r( geosinit.ctxt, geom );
752 geometryBoundary = GEOSGeom_clone_r( geosinit.ctxt, geom );
754 GEOSGeometry *splitLineClone = GEOSGeom_clone_r( geosinit.ctxt, splitLine );
755 GEOSGeometry *unionGeometry = GEOSUnion_r( geosinit.ctxt, splitLineClone, geometryBoundary );
756 GEOSGeom_destroy_r( geosinit.ctxt, splitLineClone );
758 GEOSGeom_destroy_r( geosinit.ctxt, geometryBoundary );
759 return unionGeometry;
768 int type = GEOSGeomTypeId_r( geosinit.ctxt, mGeos );
769 if ( type != GEOS_GEOMETRYCOLLECTION &&
770 type != GEOS_MULTILINESTRING &&
771 type != GEOS_MULTIPOLYGON &&
772 type != GEOS_MULTIPOINT )
781 for (
int i = 0; i < copyList.
size(); ++i )
785 for (
int j = 0; j < GEOSGetNumGeometries_r( geosinit.ctxt, mGeos ); j++ )
787 if ( GEOSEquals_r( geosinit.ctxt, copyList[i], GEOSGetGeometryN_r( geosinit.ctxt, mGeos, j ) ) )
796 unionGeom << copyList[i];
801 geomVector << copyList[i];
803 if ( type == GEOS_MULTILINESTRING )
804 splitResult << createGeosCollection( GEOS_MULTILINESTRING, geomVector );
805 else if ( type == GEOS_MULTIPOLYGON )
806 splitResult << createGeosCollection( GEOS_MULTIPOLYGON, geomVector );
808 GEOSGeom_destroy_r( geosinit.ctxt, copyList[i] );
815 if ( type == GEOS_MULTILINESTRING )
816 splitResult << createGeosCollection( GEOS_MULTILINESTRING, unionGeom );
817 else if ( type == GEOS_MULTIPOLYGON )
818 splitResult << createGeosCollection( GEOS_MULTIPOLYGON, unionGeom );
830 int nNullGeoms = geoms.
count(
nullptr );
831 int nNotNullGeoms = geoms.
size() - nNullGeoms;
833 GEOSGeometry **geomarr =
new GEOSGeometry*[ nNotNullGeoms ];
841 for ( ; geomIt != geoms.
constEnd(); ++geomIt )
845 geomarr[i] = *geomIt;
849 GEOSGeometry *geom =
nullptr;
853 geom = GEOSGeom_createCollection_r( geosinit.ctxt, typeId, geomarr, nNotNullGeoms );
855 catch ( GEOSException &e )
872 int nCoordDims = GEOSGeom_getCoordinateDimension_r( geosinit.ctxt, geos );
873 int nDims = GEOSGeom_getDimensions_r( geosinit.ctxt, geos );
874 bool hasZ = ( nCoordDims == 3 );
875 bool hasM = (( nDims - nCoordDims ) == 1 );
877 switch ( GEOSGeomTypeId_r( geosinit.ctxt, geos ) )
881 const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r( geosinit.ctxt, geos );
884 case GEOS_LINESTRING:
886 return sequenceToLinestring( geos, hasZ, hasM );
892 case GEOS_MULTIPOINT:
895 int nParts = GEOSGetNumGeometries_r( geosinit.ctxt, geos );
896 for (
int i = 0; i < nParts; ++i )
898 const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r( geosinit.ctxt, GEOSGetGeometryN_r( geosinit.ctxt, geos, i ) );
906 case GEOS_MULTILINESTRING:
909 int nParts = GEOSGetNumGeometries_r( geosinit.ctxt, geos );
910 for (
int i = 0; i < nParts; ++i )
912 QgsLineStringV2* line = sequenceToLinestring( GEOSGetGeometryN_r( geosinit.ctxt, geos, i ), hasZ, hasM );
918 return multiLineString;
920 case GEOS_MULTIPOLYGON:
924 int nParts = GEOSGetNumGeometries_r( geosinit.ctxt, geos );
925 for (
int i = 0; i < nParts; ++i )
935 case GEOS_GEOMETRYCOLLECTION:
938 int nParts = GEOSGetNumGeometries_r( geosinit.ctxt, geos );
939 for (
int i = 0; i < nParts; ++i )
947 return geomCollection;
955 if ( GEOSGeomTypeId_r( geosinit.ctxt, geos ) != GEOS_POLYGON )
960 int nCoordDims = GEOSGeom_getCoordinateDimension_r( geosinit.ctxt, geos );
961 int nDims = GEOSGeom_getDimensions_r( geosinit.ctxt, geos );
962 bool hasZ = ( nCoordDims == 3 );
963 bool hasM = (( nDims - nCoordDims ) == 1 );
967 const GEOSGeometry* ring = GEOSGetExteriorRing_r( geosinit.ctxt, geos );
974 for (
int i = 0; i < GEOSGetNumInteriorRings_r( geosinit.ctxt, geos ); ++i )
976 ring = GEOSGetInteriorRingN_r( geosinit.ctxt, geos, i );
979 interiorRings.
push_back( sequenceToLinestring( ring, hasZ, hasM ) );
987 QgsLineStringV2* QgsGeos::sequenceToLinestring(
const GEOSGeometry* geos,
bool hasZ,
bool hasM )
990 const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r( geosinit.ctxt, geos );
991 unsigned int nPoints;
992 GEOSCoordSeq_getSize_r( geosinit.ctxt, cs, &nPoints );
994 for (
unsigned int i = 0; i < nPoints; ++i )
1003 int QgsGeos::numberOfGeometries( GEOSGeometry* g )
1008 int geometryType = GEOSGeomTypeId_r( geosinit.ctxt, g );
1009 if ( geometryType == GEOS_POINT || geometryType == GEOS_LINESTRING || geometryType == GEOS_LINEARRING
1010 || geometryType == GEOS_POLYGON )
1014 return GEOSGetNumGeometries_r( geosinit.ctxt, g );
1027 GEOSCoordSeq_getX_r( geosinit.ctxt, cs, i, &x );
1028 GEOSCoordSeq_getY_r( geosinit.ctxt, cs, i, &y );
1031 GEOSCoordSeq_getZ_r( geosinit.ctxt, cs, i, &z );
1035 GEOSCoordSeq_getOrdinate_r( geosinit.ctxt, cs, i, 3, &m );
1071 geosType = GEOS_GEOMETRYCOLLECTION;
1077 geosType = GEOS_MULTIPOINT;
1081 geosType = GEOS_MULTILINESTRING;
1085 geosType = GEOS_MULTIPOLYGON;
1105 return createGeosCollection( geosType, geomVector );
1112 return createGeosPoint( static_cast<const QgsPointV2*>( geom ), coordDims, precision );
1116 return createGeosLinestring( static_cast<const QgsLineStringV2*>( geom ), precision );
1120 return createGeosPolygon( static_cast<const QgsPolygonV2*>( geom ), precision );
1151 opGeom.
reset( GEOSIntersection_r( geosinit.ctxt, mGeos, geosGeom.
get() ) );
1154 opGeom.
reset( GEOSDifference_r( geosinit.ctxt, mGeos, geosGeom.
get() ) );
1158 GEOSGeometry *unionGeometry = GEOSUnion_r( geosinit.ctxt, mGeos, geosGeom.
get() );
1160 if ( unionGeometry && GEOSGeomTypeId_r( geosinit.ctxt, unionGeometry ) == GEOS_MULTILINESTRING )
1162 GEOSGeometry *mergedLines = GEOSLineMerge_r( geosinit.ctxt, unionGeometry );
1165 GEOSGeom_destroy_r( geosinit.ctxt, unionGeometry );
1166 unionGeometry = mergedLines;
1170 opGeom.
reset( unionGeometry );
1174 opGeom.
reset( GEOSSymDifference_r( geosinit.ctxt, mGeos, geosGeom.
get() ) );
1182 catch ( GEOSException &e )
1186 *errorMsg = e.what();
1205 bool result =
false;
1208 if ( mGeosPrepared )
1213 result = ( GEOSPreparedIntersects_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1216 result = ( GEOSPreparedTouches_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1219 result = ( GEOSPreparedCrosses_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1222 result = ( GEOSPreparedWithin_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1225 result = ( GEOSPreparedContains_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1228 result = ( GEOSPreparedDisjoint_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1231 result = ( GEOSPreparedOverlaps_r( geosinit.ctxt, mGeosPrepared, geosGeom.
get() ) == 1 );
1242 result = ( GEOSIntersects_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1245 result = ( GEOSTouches_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1248 result = ( GEOSCrosses_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1251 result = ( GEOSWithin_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1254 result = ( GEOSContains_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1257 result = ( GEOSDisjoint_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1260 result = ( GEOSOverlaps_r( geosinit.ctxt, mGeos, geosGeom.
get() ) == 1 );
1266 catch ( GEOSException &e )
1270 *errorMsg = e.what();
1288 geos.
reset( GEOSBuffer_r( geosinit.ctxt, mGeos, distance, segments ) );
1301 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ 1302 ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3))) 1307 geos.
reset( GEOSBufferWithStyle_r( geosinit.ctxt, mGeos, distance, segments, endCapStyle, joinStyle, mitreLimit ) );
1325 geos.
reset( GEOSTopologyPreserveSimplify_r( geosinit.ctxt, mGeos, tolerance ) );
1340 geos.
reset( GEOSInterpolate_r( geosinit.ctxt, mGeos, distance ) );
1356 geos.
reset( GEOSGetCentroid_r( geosinit.ctxt, mGeos ) );
1366 GEOSGeomGetX_r( geosinit.ctxt, geos.
get(), &x );
1367 GEOSGeomGetY_r( geosinit.ctxt, geos.
get(), &y );
1382 geos.
reset( GEOSEnvelope_r( geosinit.ctxt, mGeos ) );
1398 geos.
reset( GEOSPointOnSurface_r( geosinit.ctxt, mGeos ) );
1400 if ( !geos || GEOSisEmpty_r( geosinit.ctxt, geos.
get() ) != 0 )
1406 GEOSGeomGetX_r( geosinit.ctxt, geos.
get(), &x );
1407 GEOSGeomGetY_r( geosinit.ctxt, geos.
get(), &y );
1426 GEOSGeometry* cHull = GEOSConvexHull_r( geosinit.ctxt, mGeos );
1428 GEOSGeom_destroy_r( geosinit.ctxt, cHull );
1443 return GEOSisValid_r( geosinit.ctxt, mGeos );
1462 bool equal = GEOSEquals_r( geosinit.ctxt, mGeos, geosGeom.
get() );
1477 return GEOSisEmpty_r( geosinit.ctxt, mGeos );
1482 GEOSCoordSequence* QgsGeos::createCoordinateSequence(
const QgsCurveV2* curve,
double precision,
bool forceClose )
1484 bool segmentize =
false;
1498 bool hasZ = line->
is3D();
1512 int numOutPoints = numPoints;
1513 if ( forceClose && ( line->
pointN( 0 ) != line->
pointN( numPoints - 1 ) ) )
1518 GEOSCoordSequence* coordSeq =
nullptr;
1521 coordSeq = GEOSCoordSeq_create_r( geosinit.ctxt, numOutPoints, coordDims );
1527 if ( precision > 0. )
1529 for (
int i = 0; i < numOutPoints; ++i )
1532 GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, i,
qgsRound( pt.
x() / precision ) * precision );
1533 GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, i,
qgsRound( pt.
y() / precision ) * precision );
1536 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 2,
qgsRound( pt.
z() / precision ) * precision );
1540 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 3, pt.
m() );
1546 for (
int i = 0; i < numOutPoints; ++i )
1549 GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, i, pt.
x() );
1550 GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, i, pt.
y() );
1553 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 2, pt.
z() );
1557 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 3, pt.
m() );
1571 GEOSGeometry* QgsGeos::createGeosPoint(
const QgsAbstractGeometryV2* point,
int coordDims,
double precision )
1577 GEOSGeometry* geosPoint =
nullptr;
1581 GEOSCoordSequence* coordSeq = GEOSCoordSeq_create_r( geosinit.ctxt, 1, coordDims );
1587 if ( precision > 0. )
1589 GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, 0,
qgsRound( pt->
x() / precision ) * precision );
1590 GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, 0,
qgsRound( pt->
y() / precision ) * precision );
1593 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, 0, 2,
qgsRound( pt->
z() / precision ) * precision );
1598 GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, 0, pt->
x() );
1599 GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, 0, pt->
y() );
1602 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, 0, 2, pt->
z() );
1605 #if 0 //disabled until geos supports m-coordinates 1608 GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, 0, 3, pt->
m() );
1611 geosPoint = GEOSGeom_createPoint_r( geosinit.ctxt, coordSeq );
1617 GEOSGeometry* QgsGeos::createGeosLinestring(
const QgsAbstractGeometryV2* curve ,
double precision )
1623 GEOSCoordSequence* coordSeq = createCoordinateSequence( c, precision );
1627 GEOSGeometry* geosGeom =
nullptr;
1630 geosGeom = GEOSGeom_createLineString_r( geosinit.ctxt, coordSeq );
1643 if ( !exteriorRing )
1648 GEOSGeometry* geosPolygon =
nullptr;
1651 GEOSGeometry* exteriorRingGeos = GEOSGeom_createLinearRing_r( geosinit.ctxt, createCoordinateSequence( exteriorRing, precision,
true ) );
1655 GEOSGeometry** holes =
nullptr;
1658 holes =
new GEOSGeometry*[ nHoles ];
1661 for (
int i = 0; i < nHoles; ++i )
1664 holes[i] = GEOSGeom_createLinearRing_r( geosinit.ctxt, createCoordinateSequence( interiorRing, precision,
true ) );
1666 geosPolygon = GEOSGeom_createPolygon_r( geosinit.ctxt, exteriorRingGeos, holes, nHoles );
1679 GEOSGeometry* offset =
nullptr;
1682 offset = GEOSOffsetCurve_r( geosinit.ctxt, mGeos, distance, segments, joinStyle, mitreLimit );
1686 GEOSGeom_destroy_r( geosinit.ctxt, offset );
1694 if ( errorCode ) { *errorCode = 1; }
1698 GEOSGeometry* reshapeLineGeos = createGeosLinestring( &reshapeWithLine, mPrecision );
1701 int numGeoms = GEOSGetNumGeometries_r( geosinit.ctxt, mGeos );
1702 if ( numGeoms == -1 )
1704 if ( errorCode ) { *errorCode = 1; }
1705 GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
1709 bool isMultiGeom =
false;
1710 int geosTypeId = GEOSGeomTypeId_r( geosinit.ctxt, mGeos );
1711 if ( geosTypeId == GEOS_MULTILINESTRING || geosTypeId == GEOS_MULTIPOLYGON )
1718 GEOSGeometry* reshapedGeometry;
1721 reshapedGeometry = reshapeLine( mGeos, reshapeLineGeos, mPrecision );
1725 reshapedGeometry = reshapePolygon( mGeos, reshapeLineGeos, mPrecision );
1728 if ( errorCode ) { *errorCode = 0; }
1730 GEOSGeom_destroy_r( geosinit.ctxt, reshapedGeometry );
1731 GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
1732 return reshapeResult;
1739 bool reshapeTookPlace =
false;
1741 GEOSGeometry* currentReshapeGeometry =
nullptr;
1742 GEOSGeometry** newGeoms =
new GEOSGeometry*[numGeoms];
1744 for (
int i = 0; i < numGeoms; ++i )
1747 currentReshapeGeometry = reshapeLine( GEOSGetGeometryN_r( geosinit.ctxt, mGeos, i ), reshapeLineGeos, mPrecision );
1749 currentReshapeGeometry = reshapePolygon( GEOSGetGeometryN_r( geosinit.ctxt, mGeos, i ), reshapeLineGeos, mPrecision );
1751 if ( currentReshapeGeometry )
1753 newGeoms[i] = currentReshapeGeometry;
1754 reshapeTookPlace =
true;
1758 newGeoms[i] = GEOSGeom_clone_r( geosinit.ctxt, GEOSGetGeometryN_r( geosinit.ctxt, mGeos, i ) );
1761 GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
1763 GEOSGeometry* newMultiGeom =
nullptr;
1766 newMultiGeom = GEOSGeom_createCollection_r( geosinit.ctxt, GEOS_MULTILINESTRING, newGeoms, numGeoms );
1770 newMultiGeom = GEOSGeom_createCollection_r( geosinit.ctxt, GEOS_MULTIPOLYGON, newGeoms, numGeoms );
1774 if ( !newMultiGeom )
1776 if ( errorCode ) { *errorCode = 3; }
1780 if ( reshapeTookPlace )
1782 if ( errorCode ) { *errorCode = 0; }
1784 GEOSGeom_destroy_r( geosinit.ctxt, newMultiGeom );
1785 return reshapedMultiGeom;
1789 GEOSGeom_destroy_r( geosinit.ctxt, newMultiGeom );
1790 if ( errorCode ) { *errorCode = 1; }
1805 if ( GEOSGeomTypeId_r( geosinit.ctxt, mGeos ) != GEOS_MULTILINESTRING )
1811 geos.
reset( GEOSLineMerge_r( geosinit.ctxt, mGeos ) );
1819 if ( !mGeos || other.
isEmpty() )
1834 GEOSCoordSequence* nearestCoord = GEOSNearestPoints_r( geosinit.ctxt, mGeos, otherGeom.
get() );
1836 ( void )GEOSCoordSeq_getX_r( geosinit.ctxt, nearestCoord, 0, &nx );
1837 ( void )GEOSCoordSeq_getY_r( geosinit.ctxt, nearestCoord, 0, &ny );
1838 GEOSCoordSeq_destroy_r( geosinit.ctxt, nearestCoord );
1840 catch ( GEOSException &e )
1844 *errorMsg = e.what();
1854 if ( !mGeos || other.
isEmpty() )
1871 GEOSCoordSequence* nearestCoord = GEOSNearestPoints_r( geosinit.ctxt, mGeos, otherGeom.
get() );
1873 ( void )GEOSCoordSeq_getX_r( geosinit.ctxt, nearestCoord, 0, &nx1 );
1874 ( void )GEOSCoordSeq_getY_r( geosinit.ctxt, nearestCoord, 0, &ny1 );
1875 ( void )GEOSCoordSeq_getX_r( geosinit.ctxt, nearestCoord, 1, &nx2 );
1876 ( void )GEOSCoordSeq_getY_r( geosinit.ctxt, nearestCoord, 1, &ny2 );
1878 GEOSCoordSeq_destroy_r( geosinit.ctxt, nearestCoord );
1880 catch ( GEOSException &e )
1884 *errorMsg = e.what();
1911 distance = GEOSProject_r( geosinit.ctxt, mGeos, otherGeom.
get() );
1913 catch ( GEOSException &e )
1917 *errorMsg = e.what();
1929 const GEOSCoordSequence* coordSeq = GEOSGeom_getCoordSeq_r( geosinit.ctxt, linestring );
1933 unsigned int coordSeqSize;
1934 if ( GEOSCoordSeq_getSize_r( geosinit.ctxt, coordSeq, &coordSeqSize ) == 0 )
1937 if ( coordSeqSize < 2 )
1940 GEOSCoordSeq_getX_r( geosinit.ctxt, coordSeq, 0, &x1 );
1941 GEOSCoordSeq_getY_r( geosinit.ctxt, coordSeq, 0, &y1 );
1942 GEOSCoordSeq_getX_r( geosinit.ctxt, coordSeq, coordSeqSize - 1, &x2 );
1943 GEOSCoordSeq_getY_r( geosinit.ctxt, coordSeq, coordSeqSize - 1, &y2 );
1951 double x1, y1, x2, y2;
1955 double rx1, ry1, rx2, ry2;
1959 bool interesectionAtOrigLineEndpoint =
1960 ( interesectionPoint.
x() == x1 && interesectionPoint.
y() == y1 ) ||
1961 ( interesectionPoint.
x() == x2 && interesectionPoint.
y() == y2 );
1962 bool interesectionAtReshapeLineEndpoint =
1963 ( interesectionPoint.
x() == rx1 && interesectionPoint.
y() == ry1 ) ||
1964 ( interesectionPoint.
x() == rx2 && interesectionPoint.
y() == ry2 );
1967 if ( interesectionAtOrigLineEndpoint && interesectionAtReshapeLineEndpoint )
1969 GEOSGeometry* g1 = GEOSGeom_clone_r( geosinit.ctxt, line1 );
1970 GEOSGeometry* g2 = GEOSGeom_clone_r( geosinit.ctxt, line2 );
1971 GEOSGeometry* geoms[2] = { g1, g2 };
1972 GEOSGeometry* multiGeom = GEOSGeom_createCollection_r( geosinit.ctxt, GEOS_MULTILINESTRING, geoms, 2 );
1973 GEOSGeometry* res = GEOSLineMerge_r( geosinit.ctxt, multiGeom );
1974 GEOSGeom_destroy_r( geosinit.ctxt, multiGeom );
1982 GEOSGeometry* QgsGeos::reshapeLine(
const GEOSGeometry* line,
const GEOSGeometry* reshapeLineGeos ,
double precision )
1984 if ( !line || !reshapeLineGeos )
1987 bool atLeastTwoIntersections =
false;
1988 bool oneIntersection =
false;
1994 GEOSGeometry* intersectGeom = GEOSIntersection_r( geosinit.ctxt, line, reshapeLineGeos );
1995 if ( intersectGeom )
1997 atLeastTwoIntersections = ( GEOSGeomTypeId_r( geosinit.ctxt, intersectGeom ) == GEOS_MULTIPOINT
1998 && GEOSGetNumGeometries_r( geosinit.ctxt, intersectGeom ) > 1 );
2000 if ( GEOSGeomTypeId_r( geosinit.ctxt, intersectGeom ) == GEOS_POINT )
2002 const GEOSCoordSequence* intersectionCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.ctxt, intersectGeom );
2004 GEOSCoordSeq_getX_r( geosinit.ctxt, intersectionCoordSeq, 0, &xi );
2005 GEOSCoordSeq_getY_r( geosinit.ctxt, intersectionCoordSeq, 0, &yi );
2006 oneIntersection =
true;
2007 oneIntersectionPoint =
QgsPoint( xi, yi );
2009 GEOSGeom_destroy_r( geosinit.ctxt, intersectGeom );
2012 catch ( GEOSException &e )
2015 atLeastTwoIntersections =
false;
2019 if ( oneIntersection )
2022 if ( !atLeastTwoIntersections )
2026 double x1, y1, x2, y2;
2031 GEOSGeometry* beginLineVertex = createGeosPoint( &beginPoint, 2, precision );
2033 GEOSGeometry* endLineVertex = createGeosPoint( &endPoint, 2, precision );
2035 bool isRing =
false;
2036 if ( GEOSGeomTypeId_r( geosinit.ctxt, line ) == GEOS_LINEARRING
2037 || GEOSEquals_r( geosinit.ctxt, beginLineVertex, endLineVertex ) == 1 )
2041 GEOSGeometry* nodedGeometry = nodeGeometries( reshapeLineGeos, line );
2042 if ( !nodedGeometry )
2044 GEOSGeom_destroy_r( geosinit.ctxt, beginLineVertex );
2045 GEOSGeom_destroy_r( geosinit.ctxt, endLineVertex );
2050 GEOSGeometry *mergedLines = GEOSLineMerge_r( geosinit.ctxt, nodedGeometry );
2051 GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
2054 GEOSGeom_destroy_r( geosinit.ctxt, beginLineVertex );
2055 GEOSGeom_destroy_r( geosinit.ctxt, endLineVertex );
2059 int numMergedLines = GEOSGetNumGeometries_r( geosinit.ctxt, mergedLines );
2060 if ( numMergedLines < 2 )
2062 GEOSGeom_destroy_r( geosinit.ctxt, beginLineVertex );
2063 GEOSGeom_destroy_r( geosinit.ctxt, endLineVertex );
2064 if ( numMergedLines == 1 )
2065 return GEOSGeom_clone_r( geosinit.ctxt, reshapeLineGeos );
2073 for (
int i = 0; i < numMergedLines; ++i )
2075 const GEOSGeometry* currentGeom;
2077 currentGeom = GEOSGetGeometryN_r( geosinit.ctxt, mergedLines, i );
2078 const GEOSCoordSequence* currentCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.ctxt, currentGeom );
2079 unsigned int currentCoordSeqSize;
2080 GEOSCoordSeq_getSize_r( geosinit.ctxt, currentCoordSeq, ¤tCoordSeqSize );
2081 if ( currentCoordSeqSize < 2 )
2085 double xBegin, xEnd, yBegin, yEnd;
2086 GEOSCoordSeq_getX_r( geosinit.ctxt, currentCoordSeq, 0, &xBegin );
2087 GEOSCoordSeq_getY_r( geosinit.ctxt, currentCoordSeq, 0, &yBegin );
2088 GEOSCoordSeq_getX_r( geosinit.ctxt, currentCoordSeq, currentCoordSeqSize - 1, &xEnd );
2089 GEOSCoordSeq_getY_r( geosinit.ctxt, currentCoordSeq, currentCoordSeqSize - 1, &yEnd );
2091 GEOSGeometry* beginCurrentGeomVertex = createGeosPoint( &beginPoint, 2, precision );
2093 GEOSGeometry* endCurrentGeomVertex = createGeosPoint( &endPoint, 2, precision );
2096 int nEndpointsOnOriginalLine = 0;
2097 if ( pointContainedInLine( beginCurrentGeomVertex, line ) == 1 )
2098 nEndpointsOnOriginalLine += 1;
2100 if ( pointContainedInLine( endCurrentGeomVertex, line ) == 1 )
2101 nEndpointsOnOriginalLine += 1;
2104 int nEndpointsSameAsOriginalLine = 0;
2105 if ( GEOSEquals_r( geosinit.ctxt, beginCurrentGeomVertex, beginLineVertex ) == 1
2106 || GEOSEquals_r( geosinit.ctxt, beginCurrentGeomVertex, endLineVertex ) == 1 )
2107 nEndpointsSameAsOriginalLine += 1;
2109 if ( GEOSEquals_r( geosinit.ctxt, endCurrentGeomVertex, beginLineVertex ) == 1
2110 || GEOSEquals_r( geosinit.ctxt, endCurrentGeomVertex, endLineVertex ) == 1 )
2111 nEndpointsSameAsOriginalLine += 1;
2114 bool currentGeomOverlapsOriginalGeom =
false;
2115 bool currentGeomOverlapsReshapeLine =
false;
2116 if ( lineContainedInLine( currentGeom, line ) == 1 )
2117 currentGeomOverlapsOriginalGeom =
true;
2119 if ( lineContainedInLine( currentGeom, reshapeLineGeos ) == 1 )
2120 currentGeomOverlapsReshapeLine =
true;
2123 if ( !isRing && nEndpointsSameAsOriginalLine == 1 && nEndpointsOnOriginalLine == 2 && currentGeomOverlapsOriginalGeom )
2125 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.ctxt, currentGeom ) );
2128 else if ( isRing && nEndpointsOnOriginalLine == 2 && currentGeomOverlapsOriginalGeom )
2130 probableParts.
push_back( GEOSGeom_clone_r( geosinit.ctxt, currentGeom ) );
2132 else if ( nEndpointsOnOriginalLine == 2 && !currentGeomOverlapsOriginalGeom )
2134 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.ctxt, currentGeom ) );
2136 else if ( nEndpointsSameAsOriginalLine == 2 && !currentGeomOverlapsOriginalGeom )
2138 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.ctxt, currentGeom ) );
2140 else if ( currentGeomOverlapsOriginalGeom && currentGeomOverlapsReshapeLine )
2142 resultLineParts.
push_back( GEOSGeom_clone_r( geosinit.ctxt, currentGeom ) );
2145 GEOSGeom_destroy_r( geosinit.ctxt, beginCurrentGeomVertex );
2146 GEOSGeom_destroy_r( geosinit.ctxt, endCurrentGeomVertex );
2150 if ( isRing && !probableParts.
isEmpty() )
2152 GEOSGeometry* maxGeom =
nullptr;
2153 GEOSGeometry* currentGeom =
nullptr;
2155 double currentLength = 0;
2156 for (
int i = 0; i < probableParts.
size(); ++i )
2158 currentGeom = probableParts.
at( i );
2159 GEOSLength_r( geosinit.ctxt, currentGeom, ¤tLength );
2160 if ( currentLength > maxLength )
2162 maxLength = currentLength;
2163 GEOSGeom_destroy_r( geosinit.ctxt, maxGeom );
2164 maxGeom = currentGeom;
2168 GEOSGeom_destroy_r( geosinit.ctxt, currentGeom );
2174 GEOSGeom_destroy_r( geosinit.ctxt, beginLineVertex );
2175 GEOSGeom_destroy_r( geosinit.ctxt, endLineVertex );
2176 GEOSGeom_destroy_r( geosinit.ctxt, mergedLines );
2178 GEOSGeometry* result =
nullptr;
2179 if ( resultLineParts.
size() < 1 )
2182 if ( resultLineParts.
size() == 1 )
2184 result = resultLineParts[0];
2188 GEOSGeometry **lineArray =
new GEOSGeometry*[resultLineParts.
size()];
2189 for (
int i = 0; i < resultLineParts.
size(); ++i )
2191 lineArray[i] = resultLineParts[i];
2195 GEOSGeometry* multiLineGeom = GEOSGeom_createCollection_r( geosinit.ctxt, GEOS_MULTILINESTRING, lineArray, resultLineParts.
size() );
2196 delete [] lineArray;
2199 result = GEOSLineMerge_r( geosinit.ctxt, multiLineGeom );
2200 GEOSGeom_destroy_r( geosinit.ctxt, multiLineGeom );
2204 if ( GEOSGeomTypeId_r( geosinit.ctxt, result ) != GEOS_LINESTRING )
2206 GEOSGeom_destroy_r( geosinit.ctxt, result );
2213 GEOSGeometry* QgsGeos::reshapePolygon(
const GEOSGeometry* polygon,
const GEOSGeometry* reshapeLineGeos,
double precision )
2216 int nIntersections = 0;
2217 int lastIntersectingRing = -2;
2218 const GEOSGeometry* lastIntersectingGeom =
nullptr;
2220 int nRings = GEOSGetNumInteriorRings_r( geosinit.ctxt, polygon );
2225 const GEOSGeometry* outerRing = GEOSGetExteriorRing_r( geosinit.ctxt, polygon );
2226 if ( GEOSIntersects_r( geosinit.ctxt, outerRing, reshapeLineGeos ) == 1 )
2229 lastIntersectingRing = -1;
2230 lastIntersectingGeom = outerRing;
2234 const GEOSGeometry **innerRings =
new const GEOSGeometry*[nRings];
2238 for (
int i = 0; i < nRings; ++i )
2240 innerRings[i] = GEOSGetInteriorRingN_r( geosinit.ctxt, polygon, i );
2241 if ( GEOSIntersects_r( geosinit.ctxt, innerRings[i], reshapeLineGeos ) == 1 )
2244 lastIntersectingRing = i;
2245 lastIntersectingGeom = innerRings[i];
2249 catch ( GEOSException &e )
2255 if ( nIntersections != 1 )
2257 delete [] innerRings;
2262 GEOSGeometry* reshapeResult = reshapeLine( lastIntersectingGeom, reshapeLineGeos, precision );
2263 if ( !reshapeResult )
2265 delete [] innerRings;
2270 GEOSGeometry* newRing =
nullptr;
2271 const GEOSCoordSequence* reshapeSequence = GEOSGeom_getCoordSeq_r( geosinit.ctxt, reshapeResult );
2272 GEOSCoordSequence* newCoordSequence = GEOSCoordSeq_clone_r( geosinit.ctxt, reshapeSequence );
2274 GEOSGeom_destroy_r( geosinit.ctxt, reshapeResult );
2276 newRing = GEOSGeom_createLinearRing_r( geosinit.ctxt, newCoordSequence );
2279 delete [] innerRings;
2283 GEOSGeometry* newOuterRing =
nullptr;
2284 if ( lastIntersectingRing == -1 )
2285 newOuterRing = newRing;
2287 newOuterRing = GEOSGeom_clone_r( geosinit.ctxt, outerRing );
2293 GEOSGeometry* outerRingPoly = GEOSGeom_createPolygon_r( geosinit.ctxt, GEOSGeom_clone_r( geosinit.ctxt, newOuterRing ),
nullptr, 0 );
2294 if ( outerRingPoly )
2296 GEOSGeometry* currentRing =
nullptr;
2297 for (
int i = 0; i < nRings; ++i )
2299 if ( lastIntersectingRing == i )
2300 currentRing = newRing;
2302 currentRing = GEOSGeom_clone_r( geosinit.ctxt, innerRings[i] );
2305 if ( GEOSContains_r( geosinit.ctxt, outerRingPoly, currentRing ) == 1 )
2308 GEOSGeom_destroy_r( geosinit.ctxt, currentRing );
2311 GEOSGeom_destroy_r( geosinit.ctxt, outerRingPoly );
2314 GEOSGeometry** newInnerRings =
new GEOSGeometry*[ringList.
size()];
2315 for (
int i = 0; i < ringList.
size(); ++i )
2316 newInnerRings[i] = ringList.
at( i );
2318 delete [] innerRings;
2320 GEOSGeometry* reshapedPolygon = GEOSGeom_createPolygon_r( geosinit.ctxt, newOuterRing, newInnerRings, ringList.
size() );
2321 delete[] newInnerRings;
2323 return reshapedPolygon;
2326 int QgsGeos::lineContainedInLine(
const GEOSGeometry* line1,
const GEOSGeometry* line2 )
2328 if ( !line1 || !line2 )
2333 double bufferDistance = pow( 10.0L, geomDigits( line2 ) - 11 );
2339 GEOSGeometry* intersectionGeom = GEOSIntersection_r( geosinit.ctxt, bufferGeom, line1 );
2342 double intersectGeomLength;
2345 GEOSLength_r( geosinit.ctxt, intersectionGeom, &intersectGeomLength );
2346 GEOSLength_r( geosinit.ctxt, line1, &line1Length );
2348 GEOSGeom_destroy_r( geosinit.ctxt, bufferGeom );
2349 GEOSGeom_destroy_r( geosinit.ctxt, intersectionGeom );
2351 double intersectRatio = line1Length / intersectGeomLength;
2352 if ( intersectRatio > 0.9 && intersectRatio < 1.1 )
2358 int QgsGeos::pointContainedInLine(
const GEOSGeometry* point,
const GEOSGeometry* line )
2360 if ( !point || !line )
2363 double bufferDistance = pow( 10.0L, geomDigits( line ) - 11 );
2365 GEOSGeometry* lineBuffer = GEOSBuffer_r( geosinit.ctxt, line, bufferDistance, 8 );
2369 bool contained =
false;
2370 if ( GEOSContains_r( geosinit.ctxt, lineBuffer, point ) == 1 )
2373 GEOSGeom_destroy_r( geosinit.ctxt, lineBuffer );
2377 int QgsGeos::geomDigits(
const GEOSGeometry* geom )
2383 const GEOSGeometry* bBoxRing = GEOSGetExteriorRing_r( geosinit.ctxt, bbox.
get() );
2387 const GEOSCoordSequence* bBoxCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.ctxt, bBoxRing );
2389 if ( !bBoxCoordSeq )
2392 unsigned int nCoords = 0;
2393 if ( !GEOSCoordSeq_getSize_r( geosinit.ctxt, bBoxCoordSeq, &nCoords ) )
2397 for (
unsigned int i = 0; i < nCoords - 1; ++i )
2400 GEOSCoordSeq_getX_r( geosinit.ctxt, bBoxCoordSeq, i, &t );
2403 digits = ceil( log10( fabs( t ) ) );
2404 if ( digits > maxDigits )
2407 GEOSCoordSeq_getY_r( geosinit.ctxt, bBoxCoordSeq, i, &t );
2408 digits = ceil( log10( fabs( t ) ) );
2409 if ( digits > maxDigits )
2418 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.
static bool _linestringEndpoints(const GEOSGeometry *linestring, double &x1, double &y1, double &x2, double &y2)
Extract coordinates of linestring's endpoints.
QgsGeometry mergeLines(QString *errorMsg=nullptr) const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
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()
double y() const
Get the y value of the point.
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)
A round function which returns a double to guard against overflows.
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
static GEOSGeometry * _mergeLinestrings(const GEOSGeometry *line1, const GEOSGeometry *line2, const QgsPoint &interesectionPoint)
Merge two linestrings if they meet at the given intersection point, return new geometry or null on er...
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...
A class to represent a point.
bool touches(const QgsAbstractGeometryV2 &geom, QString *errorMsg=nullptr) const override
QByteArray toLocal8Bit() const
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, eg both MultiPolygon and CurvePolygon would have a PolygonG...
static GEOSGeometry * asGeos(const QgsAbstractGeometryV2 *geom, double precision=0)
QgsAbstractGeometryV2 * reshapeGeometry(const QgsLineStringV2 &reshapeWithLine, int *errorCode, QString *errorMsg=nullptr) const
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.
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 QgsLineStringV2 * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
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
static Type flatType(Type type)
Returns the flat type for a WKB type.
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 lineLocatePoint(const QgsPointV2 &point, QString *errorMsg=nullptr) const
Returns a distance representing the location along this linestring of the closest point on this lines...
double m() const
Returns the point's m value.
QgsAbstractGeometryV2 * convexHull(QString *errorMsg=nullptr) const override
double x() const
Get the x value of the point.
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.