31 #define DEFAULT_QUADRANT_SEGMENTS 8
33 #define CATCH_GEOS(r) \
34 catch (GEOSException &) \
39 #define CATCH_GEOS_WITH_ERRMSG(r) \
40 catch (GEOSException &e) \
44 *errorMsg = e.what(); \
51 static void throwGEOSException(
const char *fmt, ... )
57 vsnprintf( buffer,
sizeof buffer, fmt, ap );
60 QString message = QString::fromUtf8( buffer );
70 throw GEOSException( message );
78 throw GEOSException( message );
83 static void printGEOSNotice(
const char *fmt, ... )
85 #if defined(QGISDEBUG)
90 vsnprintf( buffer,
sizeof buffer, fmt, ap );
100 GEOSContextHandle_t ctxt;
104 ctxt = initGEOS_r( printGEOSNotice, throwGEOSException );
109 finishGEOS_r( ctxt );
112 GEOSInit(
const GEOSInit &rh ) =
delete;
113 GEOSInit &operator=(
const GEOSInit &rh ) =
delete;
120 GEOSGeom_destroy_r( geosinit()->ctxt, geom );
125 GEOSPreparedGeom_destroy_r( geosinit()->ctxt, geom );
130 GEOSBufferParams_destroy_r( geosinit()->ctxt, params );
135 GEOSCoordSeq_destroy_r( geosinit()->ctxt, sequence );
184 std::unique_ptr< QgsAbstractGeometry > geom =
fromGeos( newPart );
191 mGeosPrepared.reset();
197 mGeosPrepared.reset();
200 mGeosPrepared.reset( GEOSPrepare_r( geosinit()->ctxt, mGeos.get() ) );
204 void QgsGeos::cacheGeos()
const
216 return overlay( geom, OverlayIntersection, errorMsg ).release();
221 return overlay( geom, OverlayDifference, errorMsg ).release();
236 catch ( GEOSException &e )
238 logError( QStringLiteral(
"GEOS" ), e.what() );
241 *errorMsg = e.what();
252 int partType = GEOSGeomTypeId_r( geosinit()->ctxt, currentPart );
255 if ( partType == GEOS_POINT )
266 if ( partType == GEOS_MULTILINESTRING || partType == GEOS_MULTIPOLYGON || partType == GEOS_GEOMETRYCOLLECTION )
268 int partCount = GEOSGetNumGeometries_r( geosinit()->ctxt, currentPart );
269 for (
int i = 0; i < partCount; ++i )
271 subdivideRecursive( GEOSGetGeometryN_r( geosinit()->ctxt, currentPart, i ), maxNodes, depth, parts, clipRect );
282 int vertexCount = GEOSGetNumCoordinates_r( geosinit()->ctxt, currentPart );
283 if ( vertexCount == 0 )
287 else if ( vertexCount < maxNodes )
294 double width = clipRect.
width();
295 double height = clipRect.
height();
298 if ( width > height )
311 halfClipRect1.
setYMinimum( halfClipRect1.
yMinimum() - std::numeric_limits<double>::epsilon() );
312 halfClipRect2.
setYMinimum( halfClipRect2.
yMinimum() - std::numeric_limits<double>::epsilon() );
313 halfClipRect1.
setYMaximum( halfClipRect1.
yMaximum() + std::numeric_limits<double>::epsilon() );
314 halfClipRect2.
setYMaximum( halfClipRect2.
yMaximum() + std::numeric_limits<double>::epsilon() );
318 halfClipRect1.
setXMinimum( halfClipRect1.
xMinimum() - std::numeric_limits<double>::epsilon() );
319 halfClipRect2.
setXMinimum( halfClipRect2.
xMinimum() - std::numeric_limits<double>::epsilon() );
320 halfClipRect1.
setXMaximum( halfClipRect1.
xMaximum() + std::numeric_limits<double>::epsilon() );
321 halfClipRect2.
setXMaximum( halfClipRect2.
xMaximum() + std::numeric_limits<double>::epsilon() );
331 subdivideRecursive( clipPart1.get(), maxNodes, depth, parts, halfClipRect1 );
335 subdivideRecursive( clipPart2.get(), maxNodes, depth, parts, halfClipRect2 );
347 maxNodes = std::max( maxNodes, 8 );
356 return std::move( parts );
361 return overlay( geom, OverlayUnion, errorMsg ).release();
366 QVector< GEOSGeometry * > geosGeometries;
367 geosGeometries.reserve( geomList.size() );
373 geosGeometries <<
asGeos( g, mPrecision ).release();
379 geos::unique_ptr geomCollection = createGeosCollection( GEOS_GEOMETRYCOLLECTION, geosGeometries );
380 geomUnion.reset( GEOSUnaryUnion_r( geosinit()->ctxt, geomCollection.get() ) );
384 std::unique_ptr< QgsAbstractGeometry > result =
fromGeos( geomUnion.get() );
385 return result.release();
390 QVector< GEOSGeometry * > geosGeometries;
391 geosGeometries.reserve( geomList.size() );
397 geosGeometries <<
asGeos( g.constGet(), mPrecision ).release();
403 geos::unique_ptr geomCollection = createGeosCollection( GEOS_GEOMETRYCOLLECTION, geosGeometries );
404 geomUnion.reset( GEOSUnaryUnion_r( geosinit()->ctxt, geomCollection.get() ) );
408 std::unique_ptr< QgsAbstractGeometry > result =
fromGeos( geomUnion.get() );
409 return result.release();
414 return overlay( geom, OverlaySymDifference, errorMsg ).release();
426 if ( !otherGeosGeom )
433 #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 )
436 GEOSPreparedDistance_r( geosinit()->ctxt, mGeosPrepared.get(), otherGeosGeom.get(), &
distance );
440 GEOSDistance_r( geosinit()->ctxt, mGeos.get(), otherGeosGeom.get(), &
distance );
443 GEOSDistance_r( geosinit()->ctxt, mGeos.get(), otherGeosGeom.get(), &
distance );
460 if ( !otherGeosGeom )
467 GEOSHausdorffDistance_r( geosinit()->ctxt, mGeos.get(), otherGeosGeom.get(), &
distance );
483 if ( !otherGeosGeom )
490 GEOSHausdorffDistanceDensify_r( geosinit()->ctxt, mGeos.get(), otherGeosGeom.get(), densifyFraction, &
distance );
499 return relation( geom, RelationIntersects, errorMsg );
504 return relation( geom, RelationTouches, errorMsg );
509 return relation( geom, RelationCrosses, errorMsg );
514 return relation( geom, RelationWithin, errorMsg );
519 return relation( geom, RelationOverlaps, errorMsg );
524 return relation( geom, RelationContains, errorMsg );
529 return relation( geom, RelationDisjoint, errorMsg );
548 char *r = GEOSRelate_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() );
551 result = QString( r );
552 GEOSFree_r( geosinit()->ctxt, r );
555 catch ( GEOSException &e )
557 logError( QStringLiteral(
"GEOS" ), e.what() );
560 *errorMsg = e.what();
569 if ( !mGeos || !geom )
583 result = ( GEOSRelatePattern_r( geosinit()->ctxt, mGeos.get(), geosGeom.get(), pattern.toLocal8Bit().constData() ) == 1 );
585 catch ( GEOSException &e )
587 logError( QStringLiteral(
"GEOS" ), e.what() );
590 *errorMsg = e.what();
607 if ( GEOSArea_r( geosinit()->ctxt, mGeos.get(), &
area ) != 1 )
623 if ( GEOSLength_r( geosinit()->ctxt, mGeos.get(), &
length ) != 1 )
631 QVector<QgsGeometry> &newGeometries,
634 QString *errorMsg,
bool skipIntersectionCheck )
const
649 if ( !GEOSisValid_r( geosinit()->ctxt, mGeos.get() ) )
657 newGeometries.clear();
664 splitLineGeos = createGeosLinestring( &splitLine, mPrecision );
668 splitLineGeos = createGeosPointXY( splitLine.
xAt( 0 ), splitLine.
yAt( 0 ),
false, 0,
false, 0, 2, mPrecision );
675 if ( !GEOSisValid_r( geosinit()->ctxt, splitLineGeos.get() ) || !GEOSisSimple_r( geosinit()->ctxt, splitLineGeos.get() ) )
683 if ( !topologicalTestPointsSplit( splitLineGeos.get(), topologyTestPoints ) )
692 returnCode = splitLinearGeometry( splitLineGeos.get(), newGeometries, skipIntersectionCheck );
696 returnCode = splitPolygonGeometry( splitLineGeos.get(), newGeometries, skipIntersectionCheck );
710 bool QgsGeos::topologicalTestPointsSplit(
const GEOSGeometry *splitLine,
QgsPointSequence &testPoints, QString *errorMsg )
const
724 geos::unique_ptr intersectionGeom( GEOSIntersection_r( geosinit()->ctxt, mGeos.get(), splitLine ) );
725 if ( !intersectionGeom )
729 int nIntersectGeoms = 1;
730 if ( GEOSGeomTypeId_r( geosinit()->ctxt, intersectionGeom.get() ) == GEOS_LINESTRING
731 || GEOSGeomTypeId_r( geosinit()->ctxt, intersectionGeom.get() ) == GEOS_POINT )
735 nIntersectGeoms = GEOSGetNumGeometries_r( geosinit()->ctxt, intersectionGeom.get() );
737 for (
int i = 0; i < nIntersectGeoms; ++i )
739 const GEOSGeometry *currentIntersectGeom =
nullptr;
741 currentIntersectGeom = intersectionGeom.get();
743 currentIntersectGeom = GEOSGetGeometryN_r( geosinit()->ctxt, intersectionGeom.get(), i );
745 const GEOSCoordSequence *lineSequence = GEOSGeom_getCoordSeq_r( geosinit()->ctxt, currentIntersectGeom );
746 unsigned int sequenceSize = 0;
748 if ( GEOSCoordSeq_getSize_r( geosinit()->ctxt, lineSequence, &sequenceSize ) != 0 )
750 for (
unsigned int i = 0; i < sequenceSize; ++i )
752 if ( GEOSCoordSeq_getX_r( geosinit()->ctxt, lineSequence, i, &x ) != 0 )
754 if ( GEOSCoordSeq_getY_r( geosinit()->ctxt, lineSequence, i, &y ) != 0 )
756 testPoints.push_back(
QgsPoint( x, y ) );
770 int type = GEOSGeomTypeId_r( geosinit()->ctxt, mGeos.get() );
772 std::unique_ptr< QgsMultiCurve > multiCurve;
773 if ( type == GEOS_MULTILINESTRING )
775 multiCurve.reset( qgsgeometry_cast<QgsMultiCurve *>(
mGeometry->
clone() ) );
777 else if ( type == GEOS_LINESTRING )
793 std::unique_ptr< QgsAbstractGeometry > splitGeom(
fromGeos( GEOSsplitPoint ) );
794 QgsPoint *splitPoint = qgsgeometry_cast<QgsPoint *>( splitGeom.get() );
803 for (
int i = 0; i < multiCurve->numGeometries(); ++i )
805 const QgsLineString *line = qgsgeometry_cast<const QgsLineString *>( multiCurve->geometryN( i ) );
812 for (
int j = 1; j < ( nVertices - 1 ); ++j )
816 if ( currentPoint == *splitPoint )
828 return asGeos( &lines, mPrecision );
840 if ( !skipIntersectionCheck && !GEOSIntersects_r( geosinit()->ctxt, splitLine, mGeos.get() ) )
844 int linearIntersect = GEOSRelatePattern_r( geosinit()->ctxt, mGeos.get(), splitLine,
"1********" );
845 if ( linearIntersect > 0 )
848 int splitGeomType = GEOSGeomTypeId_r( geosinit()->ctxt, splitLine );
851 if ( splitGeomType == GEOS_POINT )
853 splitGeom = linePointDifference( splitLine );
857 splitGeom.reset( GEOSDifference_r( geosinit()->ctxt, mGeos.get(), splitLine ) );
859 QVector<GEOSGeometry *> lineGeoms;
861 int splitType = GEOSGeomTypeId_r( geosinit()->ctxt, splitGeom.get() );
862 if ( splitType == GEOS_MULTILINESTRING )
864 int nGeoms = GEOSGetNumGeometries_r( geosinit()->ctxt, splitGeom.get() );
865 lineGeoms.reserve( nGeoms );
866 for (
int i = 0; i < nGeoms; ++i )
867 lineGeoms << GEOSGeom_clone_r( geosinit()->ctxt, GEOSGetGeometryN_r( geosinit()->ctxt, splitGeom.get(), i ) );
872 lineGeoms << GEOSGeom_clone_r( geosinit()->ctxt, splitGeom.get() );
875 mergeGeometriesMultiTypeSplit( lineGeoms );
877 for (
int i = 0; i < lineGeoms.size(); ++i )
880 GEOSGeom_destroy_r( geosinit()->ctxt, lineGeoms[i] );
896 if ( !mGeosPrepared )
900 if ( !skipIntersectionCheck && !GEOSPreparedIntersects_r( geosinit()->ctxt, mGeosPrepared.get(), splitLine ) )
905 if ( !nodedGeometry )
908 const GEOSGeometry *noded = nodedGeometry.get();
909 geos::unique_ptr polygons( GEOSPolygonize_r( geosinit()->ctxt, &noded, 1 ) );
910 if ( !polygons || numberOfGeometries( polygons.get() ) == 0 )
917 QVector<GEOSGeometry *> testedGeometries;
922 for (
int i = 0; i < numberOfGeometries( polygons.get() ); i++ )
924 const GEOSGeometry *polygon = GEOSGetGeometryN_r( geosinit()->ctxt, polygons.get(), i );
928 testedGeometries << GEOSGeom_clone_r( geosinit()->ctxt, polygon );
931 int nGeometriesThis = numberOfGeometries( mGeos.get() );
932 if ( testedGeometries.empty() || testedGeometries.size() == nGeometriesThis )
935 for (
int i = 0; i < testedGeometries.size(); ++i )
937 GEOSGeom_destroy_r( geosinit()->ctxt, testedGeometries[i] );
946 mergeGeometriesMultiTypeSplit( testedGeometries );
949 for ( i = 0; i < testedGeometries.size() && GEOSisValid_r( geosinit()->ctxt, testedGeometries[i] ); ++i )
952 if ( i < testedGeometries.size() )
954 for ( i = 0; i < testedGeometries.size(); ++i )
955 GEOSGeom_destroy_r( geosinit()->ctxt, testedGeometries[i] );
960 for ( i = 0; i < testedGeometries.size(); ++i )
963 GEOSGeom_destroy_r( geosinit()->ctxt, testedGeometries[i] );
969 geos::unique_ptr QgsGeos::nodeGeometries(
const GEOSGeometry *splitLine,
const GEOSGeometry *geom )
971 if ( !splitLine || !geom )
975 if ( GEOSGeomTypeId_r( geosinit()->ctxt, geom ) == GEOS_POLYGON || GEOSGeomTypeId_r( geosinit()->ctxt, geom ) == GEOS_MULTIPOLYGON )
976 geometryBoundary.reset( GEOSBoundary_r( geosinit()->ctxt, geom ) );
978 geometryBoundary.reset( GEOSGeom_clone_r( geosinit()->ctxt, geom ) );
980 geos::unique_ptr splitLineClone( GEOSGeom_clone_r( geosinit()->ctxt, splitLine ) );
981 geos::unique_ptr unionGeometry( GEOSUnion_r( geosinit()->ctxt, splitLineClone.get(), geometryBoundary.get() ) );
983 return unionGeometry;
986 int QgsGeos::mergeGeometriesMultiTypeSplit( QVector<GEOSGeometry *> &splitResult )
const
992 int type = GEOSGeomTypeId_r( geosinit()->ctxt, mGeos.get() );
993 if ( type != GEOS_GEOMETRYCOLLECTION &&
994 type != GEOS_MULTILINESTRING &&
995 type != GEOS_MULTIPOLYGON &&
996 type != GEOS_MULTIPOINT )
999 QVector<GEOSGeometry *> copyList = splitResult;
1000 splitResult.clear();
1003 QVector<GEOSGeometry *> unionGeom;
1005 for (
int i = 0; i < copyList.size(); ++i )
1008 bool isPart =
false;
1009 for (
int j = 0; j < GEOSGetNumGeometries_r( geosinit()->ctxt, mGeos.get() ); j++ )
1011 if ( GEOSEquals_r( geosinit()->ctxt, copyList[i], GEOSGetGeometryN_r( geosinit()->ctxt, mGeos.get(), j ) ) )
1020 unionGeom << copyList[i];
1024 QVector<GEOSGeometry *> geomVector;
1025 geomVector << copyList[i];
1027 if ( type == GEOS_MULTILINESTRING )
1028 splitResult << createGeosCollection( GEOS_MULTILINESTRING, geomVector ).release();
1029 else if ( type == GEOS_MULTIPOLYGON )
1030 splitResult << createGeosCollection( GEOS_MULTIPOLYGON, geomVector ).release();
1032 GEOSGeom_destroy_r( geosinit()->ctxt, copyList[i] );
1037 if ( !unionGeom.isEmpty() )
1039 if ( type == GEOS_MULTILINESTRING )
1040 splitResult << createGeosCollection( GEOS_MULTILINESTRING, unionGeom ).release();
1041 else if ( type == GEOS_MULTIPOLYGON )
1042 splitResult << createGeosCollection( GEOS_MULTIPOLYGON, unionGeom ).release();
1052 geos::unique_ptr QgsGeos::createGeosCollection(
int typeId,
const QVector<GEOSGeometry *> &geoms )
1054 int nNullGeoms = geoms.count(
nullptr );
1055 int nNotNullGeoms = geoms.size() - nNullGeoms;
1057 GEOSGeometry **geomarr =
new GEOSGeometry*[ nNotNullGeoms ];
1064 QVector<GEOSGeometry *>::const_iterator geomIt = geoms.constBegin();
1065 for ( ; geomIt != geoms.constEnd(); ++geomIt )
1069 if ( GEOSisEmpty_r( geosinit()->ctxt, *geomIt ) )
1074 GEOSGeom_destroy_r( geosinit()->ctxt, *geomIt );
1078 geomarr[i] = *geomIt;
1087 geom.reset( GEOSGeom_createCollection_r( geosinit()->ctxt, typeId, geomarr, nNotNullGeoms ) );
1089 catch ( GEOSException & )
1105 int nCoordDims = GEOSGeom_getCoordinateDimension_r( geosinit()->ctxt,
geos );
1106 int nDims = GEOSGeom_getDimensions_r( geosinit()->ctxt,
geos );
1107 bool hasZ = ( nCoordDims == 3 );
1108 bool hasM = ( ( nDims - nCoordDims ) == 1 );
1110 switch ( GEOSGeomTypeId_r( geosinit()->ctxt,
geos ) )
1114 if ( GEOSisEmpty_r( geosinit()->ctxt,
geos ) )
1117 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit()->ctxt,
geos );
1118 unsigned int nPoints = 0;
1119 GEOSCoordSeq_getSize_r( geosinit()->ctxt, cs, &nPoints );
1120 return nPoints > 0 ? std::unique_ptr<QgsAbstractGeometry>(
coordSeqPoint( cs, 0, hasZ, hasM ).clone() ) : qgis::make_unique< QgsPoint >();
1122 case GEOS_LINESTRING:
1124 return sequenceToLinestring(
geos, hasZ, hasM );
1130 case GEOS_MULTIPOINT:
1132 std::unique_ptr< QgsMultiPoint > multiPoint(
new QgsMultiPoint() );
1133 int nParts = GEOSGetNumGeometries_r( geosinit()->ctxt,
geos );
1134 multiPoint->reserve( nParts );
1135 for (
int i = 0; i < nParts; ++i )
1137 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit()->ctxt, GEOSGetGeometryN_r( geosinit()->ctxt,
geos, i ) );
1140 unsigned int nPoints = 0;
1141 GEOSCoordSeq_getSize_r( geosinit()->ctxt, cs, &nPoints );
1143 multiPoint->addGeometry(
coordSeqPoint( cs, 0, hasZ, hasM ).clone() );
1146 return std::move( multiPoint );
1148 case GEOS_MULTILINESTRING:
1151 int nParts = GEOSGetNumGeometries_r( geosinit()->ctxt,
geos );
1152 multiLineString->reserve( nParts );
1153 for (
int i = 0; i < nParts; ++i )
1155 std::unique_ptr< QgsLineString >line( sequenceToLinestring( GEOSGetGeometryN_r( geosinit()->ctxt,
geos, i ), hasZ, hasM ) );
1158 multiLineString->addGeometry( line.release() );
1161 return std::move( multiLineString );
1163 case GEOS_MULTIPOLYGON:
1165 std::unique_ptr< QgsMultiPolygon > multiPolygon(
new QgsMultiPolygon() );
1167 int nParts = GEOSGetNumGeometries_r( geosinit()->ctxt,
geos );
1168 multiPolygon->reserve( nParts );
1169 for (
int i = 0; i < nParts; ++i )
1171 std::unique_ptr< QgsPolygon > poly =
fromGeosPolygon( GEOSGetGeometryN_r( geosinit()->ctxt,
geos, i ) );
1174 multiPolygon->addGeometry( poly.release() );
1177 return std::move( multiPolygon );
1179 case GEOS_GEOMETRYCOLLECTION:
1182 int nParts = GEOSGetNumGeometries_r( geosinit()->ctxt,
geos );
1183 geomCollection->reserve( nParts );
1184 for (
int i = 0; i < nParts; ++i )
1186 std::unique_ptr< QgsAbstractGeometry > geom(
fromGeos( GEOSGetGeometryN_r( geosinit()->ctxt,
geos, i ) ) );
1189 geomCollection->addGeometry( geom.release() );
1192 return std::move( geomCollection );
1200 if ( GEOSGeomTypeId_r( geosinit()->ctxt,
geos ) != GEOS_POLYGON )
1205 int nCoordDims = GEOSGeom_getCoordinateDimension_r( geosinit()->ctxt,
geos );
1206 int nDims = GEOSGeom_getDimensions_r( geosinit()->ctxt,
geos );
1207 bool hasZ = ( nCoordDims == 3 );
1208 bool hasM = ( ( nDims - nCoordDims ) == 1 );
1210 std::unique_ptr< QgsPolygon > polygon(
new QgsPolygon() );
1212 const GEOSGeometry *ring = GEOSGetExteriorRing_r( geosinit()->ctxt,
geos );
1215 polygon->setExteriorRing( sequenceToLinestring( ring, hasZ, hasM ).release() );
1218 QVector<QgsCurve *> interiorRings;
1219 const int ringCount = GEOSGetNumInteriorRings_r( geosinit()->ctxt,
geos );
1220 interiorRings.reserve( ringCount );
1221 for (
int i = 0; i < ringCount; ++i )
1223 ring = GEOSGetInteriorRingN_r( geosinit()->ctxt,
geos, i );
1226 interiorRings.push_back( sequenceToLinestring( ring, hasZ, hasM ).release() );
1229 polygon->setInteriorRings( interiorRings );
1234 std::unique_ptr<QgsLineString> QgsGeos::sequenceToLinestring(
const GEOSGeometry *
geos,
bool hasZ,
bool hasM )
1236 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit()->ctxt,
geos );
1237 unsigned int nPoints;
1238 GEOSCoordSeq_getSize_r( geosinit()->ctxt, cs, &nPoints );
1239 QVector< double > xOut( nPoints );
1240 QVector< double > yOut( nPoints );
1241 QVector< double > zOut;
1243 zOut.resize( nPoints );
1244 QVector< double > mOut;
1246 mOut.resize( nPoints );
1247 double *x = xOut.data();
1248 double *y = yOut.data();
1249 double *z = zOut.data();
1250 double *m = mOut.data();
1251 for (
unsigned int i = 0; i < nPoints; ++i )
1253 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
1255 GEOSCoordSeq_getXYZ_r( geosinit()->ctxt, cs, i, x++, y++, z++ );
1257 GEOSCoordSeq_getXY_r( geosinit()->ctxt, cs, i, x++, y++ );
1259 GEOSCoordSeq_getX_r( geosinit()->ctxt, cs, i, x++ );
1260 GEOSCoordSeq_getY_r( geosinit()->ctxt, cs, i, y++ );
1263 GEOSCoordSeq_getZ_r( geosinit()->ctxt, cs, i, z++ );
1268 GEOSCoordSeq_getOrdinate_r( geosinit()->ctxt, cs, i, 3, m++ );
1271 std::unique_ptr< QgsLineString > line(
new QgsLineString( xOut, yOut, zOut, mOut ) );
1275 int QgsGeos::numberOfGeometries( GEOSGeometry *g )
1280 int geometryType = GEOSGeomTypeId_r( geosinit()->ctxt, g );
1281 if ( geometryType == GEOS_POINT || geometryType == GEOS_LINESTRING || geometryType == GEOS_LINEARRING
1282 || geometryType == GEOS_POLYGON )
1286 return GEOSGetNumGeometries_r( geosinit()->ctxt, g );
1299 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
1301 GEOSCoordSeq_getXYZ_r( geosinit()->ctxt, cs, i, &x, &y, &z );
1303 GEOSCoordSeq_getXY_r( geosinit()->ctxt, cs, i, &x, &y );
1305 GEOSCoordSeq_getX_r( geosinit()->ctxt, cs, i, &x );
1306 GEOSCoordSeq_getY_r( geosinit()->ctxt, cs, i, &y );
1309 GEOSCoordSeq_getZ_r( geosinit()->ctxt, cs, i, &z );
1314 GEOSCoordSeq_getOrdinate_r( geosinit()->ctxt, cs, i, 3, &m );
1350 int geosType = GEOS_GEOMETRYCOLLECTION;
1357 geosType = GEOS_MULTIPOINT;
1361 geosType = GEOS_MULTILINESTRING;
1365 geosType = GEOS_MULTIPOLYGON;
1380 QVector< GEOSGeometry * > geomVector(
c->numGeometries() );
1381 for (
int i = 0; i <
c->numGeometries(); ++i )
1385 return createGeosCollection( geosType, geomVector );
1392 return createGeosPoint(
static_cast<const QgsPoint *
>( geom ), coordDims,
precision );
1408 std::unique_ptr<QgsAbstractGeometry> QgsGeos::overlay(
const QgsAbstractGeometry *geom, Overlay op, QString *errorMsg )
const
1410 if ( !mGeos || !geom )
1426 case OverlayIntersection:
1427 opGeom.reset( GEOSIntersection_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) );
1430 case OverlayDifference:
1431 opGeom.reset( GEOSDifference_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) );
1436 geos::unique_ptr unionGeometry( GEOSUnion_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) );
1438 if ( unionGeometry && GEOSGeomTypeId_r( geosinit()->ctxt, unionGeometry.get() ) == GEOS_MULTILINESTRING )
1440 geos::unique_ptr mergedLines( GEOSLineMerge_r( geosinit()->ctxt, unionGeometry.get() ) );
1443 unionGeometry = std::move( mergedLines );
1447 opGeom = std::move( unionGeometry );
1451 case OverlaySymDifference:
1452 opGeom.reset( GEOSSymDifference_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) );
1457 catch ( GEOSException &e )
1459 logError( QStringLiteral(
"GEOS" ), e.what() );
1462 *errorMsg = e.what();
1468 bool QgsGeos::relation(
const QgsAbstractGeometry *geom, Relation r, QString *errorMsg )
const
1470 if ( !mGeos || !geom )
1481 bool result =
false;
1484 if ( mGeosPrepared )
1488 case RelationIntersects:
1489 result = ( GEOSPreparedIntersects_r( geosinit()->ctxt, mGeosPrepared.get(), geosGeom.get() ) == 1 );
1491 case RelationTouches:
1492 result = ( GEOSPreparedTouches_r( geosinit()->ctxt, mGeosPrepared.get(), geosGeom.get() ) == 1 );
1494 case RelationCrosses:
1495 result = ( GEOSPreparedCrosses_r( geosinit()->ctxt, mGeosPrepared.get(), geosGeom.get() ) == 1 );
1497 case RelationWithin:
1498 result = ( GEOSPreparedWithin_r( geosinit()->ctxt, mGeosPrepared.get(), geosGeom.get() ) == 1 );
1500 case RelationContains:
1501 result = ( GEOSPreparedContains_r( geosinit()->ctxt, mGeosPrepared.get(), geosGeom.get() ) == 1 );
1503 case RelationDisjoint:
1504 result = ( GEOSPreparedDisjoint_r( geosinit()->ctxt, mGeosPrepared.get(), geosGeom.get() ) == 1 );
1506 case RelationOverlaps:
1507 result = ( GEOSPreparedOverlaps_r( geosinit()->ctxt, mGeosPrepared.get(), geosGeom.get() ) == 1 );
1515 case RelationIntersects:
1516 result = ( GEOSIntersects_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) == 1 );
1518 case RelationTouches:
1519 result = ( GEOSTouches_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) == 1 );
1521 case RelationCrosses:
1522 result = ( GEOSCrosses_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) == 1 );
1524 case RelationWithin:
1525 result = ( GEOSWithin_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) == 1 );
1527 case RelationContains:
1528 result = ( GEOSContains_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) == 1 );
1530 case RelationDisjoint:
1531 result = ( GEOSDisjoint_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) == 1 );
1533 case RelationOverlaps:
1534 result = ( GEOSOverlaps_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() ) == 1 );
1538 catch ( GEOSException &e )
1540 logError( QStringLiteral(
"GEOS" ), e.what() );
1543 *errorMsg = e.what();
1561 geos.reset( GEOSBuffer_r( geosinit()->ctxt, mGeos.get(),
distance, segments ) );
1577 geos.reset( GEOSBufferWithStyle_r( geosinit()->ctxt, mGeos.get(),
distance, segments, endCapStyle, joinStyle, miterLimit ) );
1592 geos.reset( GEOSTopologyPreserveSimplify_r( geosinit()->ctxt, mGeos.get(), tolerance ) );
1607 geos.reset( GEOSInterpolate_r( geosinit()->ctxt, mGeos.get(),
distance ) );
1626 geos.reset( GEOSGetCentroid_r( geosinit()->ctxt, mGeos.get() ) );
1631 GEOSGeomGetX_r( geosinit()->ctxt,
geos.get(), &x );
1632 GEOSGeomGetY_r( geosinit()->ctxt,
geos.get(), &y );
1648 geos.reset( GEOSEnvelope_r( geosinit()->ctxt, mGeos.get() ) );
1667 geos.reset( GEOSPointOnSurface_r( geosinit()->ctxt, mGeos.get() ) );
1669 if ( !
geos || GEOSisEmpty_r( geosinit()->ctxt,
geos.get() ) != 0 )
1674 GEOSGeomGetX_r( geosinit()->ctxt,
geos.get(), &x );
1675 GEOSGeomGetY_r( geosinit()->ctxt,
geos.get(), &y );
1691 geos::unique_ptr cHull( GEOSConvexHull_r( geosinit()->ctxt, mGeos.get() ) );
1692 std::unique_ptr< QgsAbstractGeometry > cHullGeom =
fromGeos( cHull.get() );
1693 return cHullGeom.release();
1707 GEOSGeometry *g1 =
nullptr;
1709 char res = GEOSisValidDetail_r( geosinit()->ctxt, mGeos.get(), allowSelfTouchingHoles ? GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE : 0, &r, &g1 );
1710 const bool invalid = res != 1;
1715 error = QString( r );
1716 GEOSFree_r( geosinit()->ctxt, r );
1719 if ( invalid && errorMsg )
1723 if ( translatedErrors.empty() )
1726 translatedErrors.insert( QStringLiteral(
"topology validation error" ), QObject::tr(
"Topology validation error",
"GEOS Error" ) );
1727 translatedErrors.insert( QStringLiteral(
"repeated point" ), QObject::tr(
"Repeated point",
"GEOS Error" ) );
1728 translatedErrors.insert( QStringLiteral(
"hole lies outside shell" ), QObject::tr(
"Hole lies outside shell",
"GEOS Error" ) );
1729 translatedErrors.insert( QStringLiteral(
"holes are nested" ), QObject::tr(
"Holes are nested",
"GEOS Error" ) );
1730 translatedErrors.insert( QStringLiteral(
"interior is disconnected" ), QObject::tr(
"Interior is disconnected",
"GEOS Error" ) );
1731 translatedErrors.insert( QStringLiteral(
"self-intersection" ), QObject::tr(
"Self-intersection",
"GEOS Error" ) );
1732 translatedErrors.insert( QStringLiteral(
"ring self-intersection" ), QObject::tr(
"Ring self-intersection",
"GEOS Error" ) );
1733 translatedErrors.insert( QStringLiteral(
"nested shells" ), QObject::tr(
"Nested shells",
"GEOS Error" ) );
1734 translatedErrors.insert( QStringLiteral(
"duplicate rings" ), QObject::tr(
"Duplicate rings",
"GEOS Error" ) );
1735 translatedErrors.insert( QStringLiteral(
"too few points in geometry component" ), QObject::tr(
"Too few points in geometry component",
"GEOS Error" ) );
1736 translatedErrors.insert( QStringLiteral(
"invalid coordinate" ), QObject::tr(
"Invalid coordinate",
"GEOS Error" ) );
1737 translatedErrors.insert( QStringLiteral(
"ring is not closed" ), QObject::tr(
"Ring is not closed",
"GEOS Error" ) );
1740 *errorMsg = translatedErrors.value( error.toLower(), error );
1742 if ( g1 && errorLoc )
1748 GEOSGeom_destroy_r( geosinit()->ctxt, g1 );
1758 if ( !mGeos || !geom )
1770 bool equal = GEOSEquals_r( geosinit()->ctxt, mGeos.get(), geosGeom.get() );
1785 return GEOSisEmpty_r( geosinit()->ctxt, mGeos.get() );
1799 return GEOSisSimple_r( geosinit()->ctxt, mGeos.get() );
1804 GEOSCoordSequence *QgsGeos::createCoordinateSequence(
const QgsCurve *curve,
double precision,
bool forceClose )
1806 std::unique_ptr< QgsLineString > segmentized;
1807 const QgsLineString *line = qgsgeometry_cast<const QgsLineString *>( curve );
1812 line = segmentized.get();
1820 bool hasZ = line->
is3D();
1834 int numOutPoints = numPoints;
1835 if ( forceClose && ( line->
pointN( 0 ) != line->
pointN( numPoints - 1 ) ) )
1840 GEOSCoordSequence *coordSeq =
nullptr;
1843 coordSeq = GEOSCoordSeq_create_r( geosinit()->ctxt, numOutPoints, coordDims );
1846 QgsDebugMsg( QStringLiteral(
"GEOS Exception: Could not create coordinate sequence for %1 points in %2 dimensions" ).arg( numPoints ).arg( coordDims ) );
1850 const double *xData = line->
xData();
1851 const double *yData = line->
yData();
1852 const double *zData = hasZ ? line->
zData() :
nullptr;
1853 const double *mData = hasM ? line->
mData() :
nullptr;
1857 for (
int i = 0; i < numOutPoints; ++i )
1859 if ( i >= numPoints )
1862 xData = line->
xData();
1863 yData = line->
yData();
1864 zData = hasZ ? line->
zData() :
nullptr;
1865 mData = hasM ? line->
mData() :
nullptr;
1867 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
1877 GEOSCoordSeq_setX_r( geosinit()->ctxt, coordSeq, i, std::round( *xData++ /
precision ) *
precision );
1878 GEOSCoordSeq_setY_r( geosinit()->ctxt, coordSeq, i, std::round( *yData++ /
precision ) *
precision );
1881 GEOSCoordSeq_setOrdinate_r( geosinit()->ctxt, coordSeq, i, 2, std::round( *zData++ /
precision ) *
precision );
1886 GEOSCoordSeq_setOrdinate_r( geosinit()->ctxt, coordSeq, i, 3, line->
mAt( *mData++ ) );
1892 for (
int i = 0; i < numOutPoints; ++i )
1894 if ( i >= numPoints )
1897 xData = line->
xData();
1898 yData = line->
yData();
1899 zData = hasZ ? line->
zData() :
nullptr;
1900 mData = hasM ? line->
mData() :
nullptr;
1902 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
1905 GEOSCoordSeq_setXYZ_r( geosinit()->ctxt, coordSeq, i, *xData++, *yData++, *zData++ );
1909 GEOSCoordSeq_setXY_r( geosinit()->ctxt, coordSeq, i, *xData++, *yData++ );
1912 GEOSCoordSeq_setX_r( geosinit()->ctxt, coordSeq, i, *xData++ );
1913 GEOSCoordSeq_setY_r( geosinit()->ctxt, coordSeq, i, *yData++ );
1916 GEOSCoordSeq_setOrdinate_r( geosinit()->ctxt, coordSeq, i, 2, *zData++ );
1921 GEOSCoordSeq_setOrdinate_r( geosinit()->ctxt, coordSeq, i, 3, *mData++ );
1933 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( point );
1940 geos::unique_ptr QgsGeos::createGeosPointXY(
double x,
double y,
bool hasZ,
double z,
bool hasM,
double m,
int coordDims,
double precision )
1948 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
1949 if ( coordDims == 2 )
1955 geosPoint.reset( GEOSGeom_createPointFromXY_r( geosinit()->ctxt, x, y ) );
1960 GEOSCoordSequence *coordSeq = GEOSCoordSeq_create_r( geosinit()->ctxt, 1, coordDims );
1963 QgsDebugMsg( QStringLiteral(
"GEOS Exception: Could not create coordinate sequence for point with %1 dimensions" ).arg( coordDims ) );
1968 GEOSCoordSeq_setX_r( geosinit()->ctxt, coordSeq, 0, std::round( x /
precision ) *
precision );
1969 GEOSCoordSeq_setY_r( geosinit()->ctxt, coordSeq, 0, std::round( y /
precision ) *
precision );
1972 GEOSCoordSeq_setOrdinate_r( geosinit()->ctxt, coordSeq, 0, 2, std::round( z /
precision ) *
precision );
1977 GEOSCoordSeq_setX_r( geosinit()->ctxt, coordSeq, 0, x );
1978 GEOSCoordSeq_setY_r( geosinit()->ctxt, coordSeq, 0, y );
1981 GEOSCoordSeq_setOrdinate_r( geosinit()->ctxt, coordSeq, 0, 2, z );
1987 GEOSCoordSeq_setOrdinate_r( geosinit()->ctxt, coordSeq, 0, 3, m );
1990 geosPoint.reset( GEOSGeom_createPoint_r( geosinit()->ctxt, coordSeq ) );
1998 const QgsCurve *
c = qgsgeometry_cast<const QgsCurve *>( curve );
2002 GEOSCoordSequence *coordSeq = createCoordinateSequence(
c,
precision );
2009 geosGeom.reset( GEOSGeom_createLineString_r( geosinit()->ctxt, coordSeq ) );
2017 const QgsCurvePolygon *polygon = qgsgeometry_cast<const QgsCurvePolygon *>( poly );
2022 if ( !exteriorRing )
2030 geos::unique_ptr exteriorRingGeos( GEOSGeom_createLinearRing_r( geosinit()->ctxt, createCoordinateSequence( exteriorRing,
precision,
true ) ) );
2033 GEOSGeometry **holes =
nullptr;
2036 holes =
new GEOSGeometry*[ nHoles ];
2039 for (
int i = 0; i < nHoles; ++i )
2042 holes[i] = GEOSGeom_createLinearRing_r( geosinit()->ctxt, createCoordinateSequence( interiorRing,
precision,
true ) );
2044 geosPolygon.reset( GEOSGeom_createPolygon_r( geosinit()->ctxt, exteriorRingGeos.release(), holes, nHoles ) );
2060 offset.reset( GEOSOffsetCurve_r( geosinit()->ctxt, mGeos.get(),
distance, segments, joinStyle, miterLimit ) );
2063 std::unique_ptr< QgsAbstractGeometry > offsetGeom =
fromGeos( offset.get() );
2064 return offsetGeom.release();
2078 GEOSBufferParams_setSingleSided_r( geosinit()->ctxt, bp.get(), 1 );
2079 GEOSBufferParams_setQuadrantSegments_r( geosinit()->ctxt, bp.get(), segments );
2080 GEOSBufferParams_setJoinStyle_r( geosinit()->ctxt, bp.get(), joinStyle );
2081 GEOSBufferParams_setMitreLimit_r( geosinit()->ctxt, bp.get(), miterLimit );
2087 geos.reset( GEOSBufferWithParams_r( geosinit()->ctxt, mGeos.get(), bp.get(),
distance ) );
2107 geos::unique_ptr reshapeLineGeos = createGeosLinestring( &reshapeWithLine, mPrecision );
2110 int numGeoms = GEOSGetNumGeometries_r( geosinit()->ctxt, mGeos.get() );
2111 if ( numGeoms == -1 )
2120 bool isMultiGeom =
false;
2121 int geosTypeId = GEOSGeomTypeId_r( geosinit()->ctxt, mGeos.get() );
2122 if ( geosTypeId == GEOS_MULTILINESTRING || geosTypeId == GEOS_MULTIPOLYGON )
2132 reshapedGeometry = reshapeLine( mGeos.get(), reshapeLineGeos.get(), mPrecision );
2136 reshapedGeometry = reshapePolygon( mGeos.get(), reshapeLineGeos.get(), mPrecision );
2141 std::unique_ptr< QgsAbstractGeometry > reshapeResult =
fromGeos( reshapedGeometry.get() );
2142 return reshapeResult;
2149 bool reshapeTookPlace =
false;
2152 GEOSGeometry **newGeoms =
new GEOSGeometry*[numGeoms];
2154 for (
int i = 0; i < numGeoms; ++i )
2157 currentReshapeGeometry = reshapeLine( GEOSGetGeometryN_r( geosinit()->ctxt, mGeos.get(), i ), reshapeLineGeos.get(), mPrecision );
2159 currentReshapeGeometry = reshapePolygon( GEOSGetGeometryN_r( geosinit()->ctxt, mGeos.get(), i ), reshapeLineGeos.get(), mPrecision );
2161 if ( currentReshapeGeometry )
2163 newGeoms[i] = currentReshapeGeometry.release();
2164 reshapeTookPlace =
true;
2168 newGeoms[i] = GEOSGeom_clone_r( geosinit()->ctxt, GEOSGetGeometryN_r( geosinit()->ctxt, mGeos.get(), i ) );
2175 newMultiGeom.reset( GEOSGeom_createCollection_r( geosinit()->ctxt, GEOS_MULTILINESTRING, newGeoms, numGeoms ) );
2179 newMultiGeom.reset( GEOSGeom_createCollection_r( geosinit()->ctxt, GEOS_MULTIPOLYGON, newGeoms, numGeoms ) );
2183 if ( !newMultiGeom )
2189 if ( reshapeTookPlace )
2193 std::unique_ptr< QgsAbstractGeometry > reshapedMultiGeom =
fromGeos( newMultiGeom.get() );
2194 return reshapedMultiGeom;
2216 if ( GEOSGeomTypeId_r( geosinit()->ctxt, mGeos.get() ) != GEOS_MULTILINESTRING )
2222 geos.reset( GEOSLineMerge_r( geosinit()->ctxt, mGeos.get() ) );
2245 #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 )
2247 if ( mGeosPrepared )
2249 nearestCoord.reset( GEOSPreparedNearestPoints_r( geosinit()->ctxt, mGeosPrepared.get(), otherGeom.get() ) );
2253 nearestCoord.reset( GEOSNearestPoints_r( geosinit()->ctxt, mGeos.get(), otherGeom.get() ) );
2259 ( void )GEOSCoordSeq_getX_r( geosinit()->ctxt, nearestCoord.get(), 0, &nx );
2260 ( void )GEOSCoordSeq_getY_r( geosinit()->ctxt, nearestCoord.get(), 0, &ny );
2262 catch ( GEOSException &e )
2264 logError( QStringLiteral(
"GEOS" ), e.what() );
2267 *errorMsg = e.what();
2277 if ( !mGeos || other.
isNull() )
2296 ( void )GEOSCoordSeq_getX_r( geosinit()->ctxt, nearestCoord.get(), 0, &nx1 );
2297 ( void )GEOSCoordSeq_getY_r( geosinit()->ctxt, nearestCoord.get(), 0, &ny1 );
2298 ( void )GEOSCoordSeq_getX_r( geosinit()->ctxt, nearestCoord.get(), 1, &nx2 );
2299 ( void )GEOSCoordSeq_getY_r( geosinit()->ctxt, nearestCoord.get(), 1, &ny2 );
2301 catch ( GEOSException &e )
2303 logError( QStringLiteral(
"GEOS" ), e.what() );
2306 *errorMsg = e.what();
2333 distance = GEOSProject_r( geosinit()->ctxt, mGeos.get(), otherGeom.get() );
2335 catch ( GEOSException &e )
2337 logError( QStringLiteral(
"GEOS" ), e.what() );
2340 *errorMsg = e.what();
2350 GEOSGeometry **
const lineGeosGeometries =
new GEOSGeometry*[ geometries.size()];
2357 lineGeosGeometries[validLines] = l.release();
2364 geos::unique_ptr result( GEOSPolygonize_r( geosinit()->ctxt, lineGeosGeometries, validLines ) );
2365 for (
int i = 0; i < validLines; ++i )
2367 GEOSGeom_destroy_r( geosinit()->ctxt, lineGeosGeometries[i] );
2369 delete[] lineGeosGeometries;
2372 catch ( GEOSException &e )
2376 *errorMsg = e.what();
2378 for (
int i = 0; i < validLines; ++i )
2380 GEOSGeom_destroy_r( geosinit()->ctxt, lineGeosGeometries[i] );
2382 delete[] lineGeosGeometries;
2397 extentGeosGeom =
asGeos( extent, mPrecision );
2398 if ( !extentGeosGeom )
2407 geos.reset( GEOSVoronoiDiagram_r( geosinit()->ctxt, mGeos.get(), extentGeosGeom.get(), tolerance, edgesOnly ) );
2409 if ( !
geos || GEOSisEmpty_r( geosinit()->ctxt,
geos.get() ) != 0 )
2429 geos.reset( GEOSDelaunayTriangulation_r( geosinit()->ctxt, mGeos.get(), tolerance, edgesOnly ) );
2431 if ( !
geos || GEOSisEmpty_r( geosinit()->ctxt,
geos.get() ) != 0 )
2443 static bool _linestringEndpoints(
const GEOSGeometry *linestring,
double &x1,
double &y1,
double &x2,
double &y2 )
2445 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosinit()->ctxt, linestring );
2449 unsigned int coordSeqSize;
2450 if ( GEOSCoordSeq_getSize_r( geosinit()->ctxt, coordSeq, &coordSeqSize ) == 0 )
2453 if ( coordSeqSize < 2 )
2456 GEOSCoordSeq_getX_r( geosinit()->ctxt, coordSeq, 0, &x1 );
2457 GEOSCoordSeq_getY_r( geosinit()->ctxt, coordSeq, 0, &y1 );
2458 GEOSCoordSeq_getX_r( geosinit()->ctxt, coordSeq, coordSeqSize - 1, &x2 );
2459 GEOSCoordSeq_getY_r( geosinit()->ctxt, coordSeq, coordSeqSize - 1, &y2 );
2465 static geos::unique_ptr _mergeLinestrings(
const GEOSGeometry *line1,
const GEOSGeometry *line2,
const QgsPointXY &intersectionPoint )
2467 double x1, y1, x2, y2;
2468 if ( !_linestringEndpoints( line1, x1, y1, x2, y2 ) )
2471 double rx1, ry1, rx2, ry2;
2472 if ( !_linestringEndpoints( line2, rx1, ry1, rx2, ry2 ) )
2475 bool intersectionAtOrigLineEndpoint =
2476 ( intersectionPoint.
x() == x1 && intersectionPoint.
y() == y1 ) !=
2477 ( intersectionPoint.
x() == x2 && intersectionPoint.
y() == y2 );
2478 bool intersectionAtReshapeLineEndpoint =
2479 ( intersectionPoint.
x() == rx1 && intersectionPoint.
y() == ry1 ) ||
2480 ( intersectionPoint.
x() == rx2 && intersectionPoint.
y() == ry2 );
2483 if ( intersectionAtOrigLineEndpoint && intersectionAtReshapeLineEndpoint )
2487 GEOSGeometry *geoms[2] = { g1.release(), g2.release() };
2488 geos::unique_ptr multiGeom( GEOSGeom_createCollection_r( geosinit()->ctxt, GEOS_MULTILINESTRING, geoms, 2 ) );
2489 geos::unique_ptr res( GEOSLineMerge_r( geosinit()->ctxt, multiGeom.get() ) );
2497 geos::unique_ptr QgsGeos::reshapeLine(
const GEOSGeometry *line,
const GEOSGeometry *reshapeLineGeos,
double precision )
2499 if ( !line || !reshapeLineGeos )
2502 bool atLeastTwoIntersections =
false;
2503 bool oneIntersection =
false;
2509 geos::unique_ptr intersectGeom( GEOSIntersection_r( geosinit()->ctxt, line, reshapeLineGeos ) );
2510 if ( intersectGeom )
2512 const int geomType = GEOSGeomTypeId_r( geosinit()->ctxt, intersectGeom.get() );
2513 atLeastTwoIntersections = ( geomType == GEOS_MULTIPOINT && GEOSGetNumGeometries_r( geosinit()->ctxt, intersectGeom.get() ) > 1 )
2514 || ( geomType == GEOS_GEOMETRYCOLLECTION && GEOSGetNumGeometries_r( geosinit()->ctxt, intersectGeom.get() ) > 0 )
2515 || ( geomType == GEOS_MULTILINESTRING && GEOSGetNumGeometries_r( geosinit()->ctxt, intersectGeom.get() ) > 0 );
2517 if ( GEOSGeomTypeId_r( geosinit()->ctxt, intersectGeom.get() ) == GEOS_POINT )
2519 const GEOSCoordSequence *intersectionCoordSeq = GEOSGeom_getCoordSeq_r( geosinit()->ctxt, intersectGeom.get() );
2521 GEOSCoordSeq_getX_r( geosinit()->ctxt, intersectionCoordSeq, 0, &xi );
2522 GEOSCoordSeq_getY_r( geosinit()->ctxt, intersectionCoordSeq, 0, &yi );
2523 oneIntersection =
true;
2528 catch ( GEOSException & )
2530 atLeastTwoIntersections =
false;
2534 if ( oneIntersection )
2535 return _mergeLinestrings( line, reshapeLineGeos, oneIntersectionPoint );
2537 if ( !atLeastTwoIntersections )
2541 double x1, y1, x2, y2;
2542 if ( !_linestringEndpoints( line, x1, y1, x2, y2 ) )
2548 bool isRing =
false;
2549 if ( GEOSGeomTypeId_r( geosinit()->ctxt, line ) == GEOS_LINEARRING
2550 || GEOSEquals_r( geosinit()->ctxt, beginLineVertex.get(), endLineVertex.get() ) == 1 )
2555 if ( !nodedGeometry )
2561 geos::unique_ptr mergedLines( GEOSLineMerge_r( geosinit()->ctxt, nodedGeometry.get() ) );
2567 int numMergedLines = GEOSGetNumGeometries_r( geosinit()->ctxt, mergedLines.get() );
2568 if ( numMergedLines < 2 )
2570 if ( numMergedLines == 1 )
2572 geos::unique_ptr result( GEOSGeom_clone_r( geosinit()->ctxt, reshapeLineGeos ) );
2579 QVector<GEOSGeometry *> resultLineParts;
2580 QVector<GEOSGeometry *> probableParts;
2582 for (
int i = 0; i < numMergedLines; ++i )
2584 const GEOSGeometry *currentGeom = GEOSGetGeometryN_r( geosinit()->ctxt, mergedLines.get(), i );
2587 bool alreadyAdded =
false;
2589 double bufferDistance = std::pow( 10.0L, geomDigits( currentGeom ) - 11 );
2590 for (
const GEOSGeometry *other : qgis::as_const( resultLineParts ) )
2592 GEOSHausdorffDistance_r( geosinit()->ctxt, currentGeom, other, &
distance );
2595 alreadyAdded =
true;
2602 const GEOSCoordSequence *currentCoordSeq = GEOSGeom_getCoordSeq_r( geosinit()->ctxt, currentGeom );
2603 unsigned int currentCoordSeqSize;
2604 GEOSCoordSeq_getSize_r( geosinit()->ctxt, currentCoordSeq, ¤tCoordSeqSize );
2605 if ( currentCoordSeqSize < 2 )
2609 double xBegin, xEnd, yBegin, yEnd;
2610 GEOSCoordSeq_getX_r( geosinit()->ctxt, currentCoordSeq, 0, &xBegin );
2611 GEOSCoordSeq_getY_r( geosinit()->ctxt, currentCoordSeq, 0, &yBegin );
2612 GEOSCoordSeq_getX_r( geosinit()->ctxt, currentCoordSeq, currentCoordSeqSize - 1, &xEnd );
2613 GEOSCoordSeq_getY_r( geosinit()->ctxt, currentCoordSeq, currentCoordSeqSize - 1, &yEnd );
2618 int nEndpointsOnOriginalLine = 0;
2619 if ( pointContainedInLine( beginCurrentGeomVertex.get(), line ) == 1 )
2620 nEndpointsOnOriginalLine += 1;
2622 if ( pointContainedInLine( endCurrentGeomVertex.get(), line ) == 1 )
2623 nEndpointsOnOriginalLine += 1;
2626 int nEndpointsSameAsOriginalLine = 0;
2627 if ( GEOSEquals_r( geosinit()->ctxt, beginCurrentGeomVertex.get(), beginLineVertex.get() ) == 1
2628 || GEOSEquals_r( geosinit()->ctxt, beginCurrentGeomVertex.get(), endLineVertex.get() ) == 1 )
2629 nEndpointsSameAsOriginalLine += 1;
2631 if ( GEOSEquals_r( geosinit()->ctxt, endCurrentGeomVertex.get(), beginLineVertex.get() ) == 1
2632 || GEOSEquals_r( geosinit()->ctxt, endCurrentGeomVertex.get(), endLineVertex.get() ) == 1 )
2633 nEndpointsSameAsOriginalLine += 1;
2636 bool currentGeomOverlapsOriginalGeom =
false;
2637 bool currentGeomOverlapsReshapeLine =
false;
2638 if ( lineContainedInLine( currentGeom, line ) == 1 )
2639 currentGeomOverlapsOriginalGeom =
true;
2641 if ( lineContainedInLine( currentGeom, reshapeLineGeos ) == 1 )
2642 currentGeomOverlapsReshapeLine =
true;
2645 if ( !isRing && nEndpointsSameAsOriginalLine == 1 && nEndpointsOnOriginalLine == 2 && currentGeomOverlapsOriginalGeom )
2647 resultLineParts.push_back( GEOSGeom_clone_r( geosinit()->ctxt, currentGeom ) );
2650 else if ( isRing && nEndpointsOnOriginalLine == 2 && currentGeomOverlapsOriginalGeom )
2652 probableParts.push_back( GEOSGeom_clone_r( geosinit()->ctxt, currentGeom ) );
2654 else if ( nEndpointsOnOriginalLine == 2 && !currentGeomOverlapsOriginalGeom )
2656 resultLineParts.push_back( GEOSGeom_clone_r( geosinit()->ctxt, currentGeom ) );
2658 else if ( nEndpointsSameAsOriginalLine == 2 && !currentGeomOverlapsOriginalGeom )
2660 resultLineParts.push_back( GEOSGeom_clone_r( geosinit()->ctxt, currentGeom ) );
2662 else if ( currentGeomOverlapsOriginalGeom && currentGeomOverlapsReshapeLine )
2664 resultLineParts.push_back( GEOSGeom_clone_r( geosinit()->ctxt, currentGeom ) );
2669 if ( isRing && !probableParts.isEmpty() )
2672 GEOSGeometry *currentGeom =
nullptr;
2673 double maxLength = -std::numeric_limits<double>::max();
2674 double currentLength = 0;
2675 for (
int i = 0; i < probableParts.size(); ++i )
2677 currentGeom = probableParts.at( i );
2678 GEOSLength_r( geosinit()->ctxt, currentGeom, ¤tLength );
2679 if ( currentLength > maxLength )
2681 maxLength = currentLength;
2682 maxGeom.reset( currentGeom );
2686 GEOSGeom_destroy_r( geosinit()->ctxt, currentGeom );
2689 resultLineParts.push_back( maxGeom.release() );
2693 if ( resultLineParts.empty() )
2696 if ( resultLineParts.size() == 1 )
2698 result.reset( resultLineParts[0] );
2702 GEOSGeometry **lineArray =
new GEOSGeometry*[resultLineParts.size()];
2703 for (
int i = 0; i < resultLineParts.size(); ++i )
2705 lineArray[i] = resultLineParts[i];
2709 geos::unique_ptr multiLineGeom( GEOSGeom_createCollection_r( geosinit()->ctxt, GEOS_MULTILINESTRING, lineArray, resultLineParts.size() ) );
2710 delete [] lineArray;
2713 result.reset( GEOSLineMerge_r( geosinit()->ctxt, multiLineGeom.get() ) );
2717 if ( GEOSGeomTypeId_r( geosinit()->ctxt, result.get() ) != GEOS_LINESTRING )
2725 geos::unique_ptr QgsGeos::reshapePolygon(
const GEOSGeometry *polygon,
const GEOSGeometry *reshapeLineGeos,
double precision )
2728 int nIntersections = 0;
2729 int lastIntersectingRing = -2;
2730 const GEOSGeometry *lastIntersectingGeom =
nullptr;
2732 int nRings = GEOSGetNumInteriorRings_r( geosinit()->ctxt, polygon );
2737 const GEOSGeometry *outerRing = GEOSGetExteriorRing_r( geosinit()->ctxt, polygon );
2738 if ( GEOSIntersects_r( geosinit()->ctxt, outerRing, reshapeLineGeos ) == 1 )
2741 lastIntersectingRing = -1;
2742 lastIntersectingGeom = outerRing;
2746 const GEOSGeometry **innerRings =
new const GEOSGeometry*[nRings];
2750 for (
int i = 0; i < nRings; ++i )
2752 innerRings[i] = GEOSGetInteriorRingN_r( geosinit()->ctxt, polygon, i );
2753 if ( GEOSIntersects_r( geosinit()->ctxt, innerRings[i], reshapeLineGeos ) == 1 )
2756 lastIntersectingRing = i;
2757 lastIntersectingGeom = innerRings[i];
2761 catch ( GEOSException & )
2766 if ( nIntersections != 1 )
2768 delete [] innerRings;
2774 if ( !reshapeResult )
2776 delete [] innerRings;
2781 GEOSGeometry *newRing =
nullptr;
2782 const GEOSCoordSequence *reshapeSequence = GEOSGeom_getCoordSeq_r( geosinit()->ctxt, reshapeResult.get() );
2783 GEOSCoordSequence *newCoordSequence = GEOSCoordSeq_clone_r( geosinit()->ctxt, reshapeSequence );
2785 reshapeResult.reset();
2787 newRing = GEOSGeom_createLinearRing_r( geosinit()->ctxt, newCoordSequence );
2790 delete [] innerRings;
2794 GEOSGeometry *newOuterRing =
nullptr;
2795 if ( lastIntersectingRing == -1 )
2796 newOuterRing = newRing;
2798 newOuterRing = GEOSGeom_clone_r( geosinit()->ctxt, outerRing );
2801 QVector<GEOSGeometry *> ringList;
2804 GEOSGeometry *outerRingPoly = GEOSGeom_createPolygon_r( geosinit()->ctxt, GEOSGeom_clone_r( geosinit()->ctxt, newOuterRing ),
nullptr, 0 );
2805 if ( outerRingPoly )
2807 ringList.reserve( nRings );
2808 GEOSGeometry *currentRing =
nullptr;
2809 for (
int i = 0; i < nRings; ++i )
2811 if ( lastIntersectingRing == i )
2812 currentRing = newRing;
2814 currentRing = GEOSGeom_clone_r( geosinit()->ctxt, innerRings[i] );
2817 if ( GEOSContains_r( geosinit()->ctxt, outerRingPoly, currentRing ) == 1 )
2818 ringList.push_back( currentRing );
2820 GEOSGeom_destroy_r( geosinit()->ctxt, currentRing );
2823 GEOSGeom_destroy_r( geosinit()->ctxt, outerRingPoly );
2826 GEOSGeometry **newInnerRings =
new GEOSGeometry*[ringList.size()];
2827 for (
int i = 0; i < ringList.size(); ++i )
2828 newInnerRings[i] = ringList.at( i );
2830 delete [] innerRings;
2832 geos::unique_ptr reshapedPolygon( GEOSGeom_createPolygon_r( geosinit()->ctxt, newOuterRing, newInnerRings, ringList.size() ) );
2833 delete[] newInnerRings;
2835 return reshapedPolygon;
2838 int QgsGeos::lineContainedInLine(
const GEOSGeometry *line1,
const GEOSGeometry *line2 )
2840 if ( !line1 || !line2 )
2845 double bufferDistance = std::pow( 10.0L, geomDigits( line2 ) - 11 );
2851 geos::unique_ptr intersectionGeom( GEOSIntersection_r( geosinit()->ctxt, bufferGeom.get(), line1 ) );
2854 double intersectGeomLength;
2857 GEOSLength_r( geosinit()->ctxt, intersectionGeom.get(), &intersectGeomLength );
2858 GEOSLength_r( geosinit()->ctxt, line1, &line1Length );
2860 double intersectRatio = line1Length / intersectGeomLength;
2861 if ( intersectRatio > 0.9 && intersectRatio < 1.1 )
2867 int QgsGeos::pointContainedInLine(
const GEOSGeometry *point,
const GEOSGeometry *line )
2869 if ( !point || !line )
2872 double bufferDistance = std::pow( 10.0L, geomDigits( line ) - 11 );
2874 geos::unique_ptr lineBuffer( GEOSBuffer_r( geosinit()->ctxt, line, bufferDistance, 8 ) );
2878 bool contained =
false;
2879 if ( GEOSContains_r( geosinit()->ctxt, lineBuffer.get(), point ) == 1 )
2885 int QgsGeos::geomDigits(
const GEOSGeometry *geom )
2891 const GEOSGeometry *bBoxRing = GEOSGetExteriorRing_r( geosinit()->ctxt, bbox.get() );
2895 const GEOSCoordSequence *bBoxCoordSeq = GEOSGeom_getCoordSeq_r( geosinit()->ctxt, bBoxRing );
2897 if ( !bBoxCoordSeq )
2900 unsigned int nCoords = 0;
2901 if ( !GEOSCoordSeq_getSize_r( geosinit()->ctxt, bBoxCoordSeq, &nCoords ) )
2905 for (
unsigned int i = 0; i < nCoords - 1; ++i )
2908 GEOSCoordSeq_getX_r( geosinit()->ctxt, bBoxCoordSeq, i, &t );
2911 digits = std::ceil( std::log10( std::fabs( t ) ) );
2912 if ( digits > maxDigits )
2915 GEOSCoordSeq_getY_r( geosinit()->ctxt, bBoxCoordSeq, i, &t );
2916 digits = std::ceil( std::log10( std::fabs( t ) ) );
2917 if ( digits > maxDigits )
2926 return geosinit()->ctxt;
Abstract base class for all geometries.
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
virtual QgsRectangle boundingBox() const =0
Returns the minimal bounding box for the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
virtual int dimension() const =0
Returns the inherent dimension of the geometry.
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
Curve polygon geometry type.
const QgsCurve * interiorRing(int i) const SIP_HOLDGIL
Retrieves an interior ring from the curve polygon.
const QgsCurve * exteriorRing() const SIP_HOLDGIL
Returns the curve polygon's exterior ring.
int numInteriorRings() const SIP_HOLDGIL
Returns the number of interior rings contained with the curve polygon.
Abstract base class for curved geometry type.
virtual QgsLineString * 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.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
static QgsGeometry::OperationResult addPart(QgsAbstractGeometry *geometry, std::unique_ptr< QgsAbstractGeometry > part)
Add a part to multi type geometry.
Contains geometry relation and modification algorithms.
const QgsAbstractGeometry * mGeometry
EngineOperationResult
Success or failure of a geometry operation.
@ NothingHappened
Nothing happened, without any error.
@ InvalidBaseGeometry
The geometry on which the operation occurs is not valid.
@ InvalidInput
The input is not valid.
@ NodedGeometryError
Error occurred while creating a noded geometry.
@ EngineError
Error occurred in the geometry engine.
@ SplitCannotSplitPoint
Points cannot be split.
@ Success
Operation succeeded.
void logError(const QString &engineName, const QString &message) const
Logs an error message encountered during an operation.
static std::unique_ptr< QgsGeometryCollection > createCollectionOfType(QgsWkbTypes::Type type)
Returns a new geometry collection matching a specified WKB type.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
OperationResult
Success or failure of a geometry operation.
@ InvalidBaseGeometry
The base geometry on which the operation is done is invalid or empty.
@ AddPartNotMultiGeometry
The source geometry is not multi.
Does vector analysis using the geos library and handles import, export, exception handling*.
QgsGeometry delaunayTriangulation(double tolerance=0.0, bool edgesOnly=false, QString *errorMsg=nullptr) const
Returns the Delaunay triangulation for the vertices of the geometry.
QgsAbstractGeometry * intersection(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Calculate the intersection of this and geom.
bool touches(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Checks if geom touches this.
double hausdorffDistanceDensify(const QgsAbstractGeometry *geom, double densifyFraction, QString *errorMsg=nullptr) const
Returns the Hausdorff distance between this geometry and geom.
bool isValid(QString *errorMsg=nullptr, bool allowSelfTouchingHoles=false, QgsGeometry *errorLoc=nullptr) const override
Returns true if the geometry is valid.
double hausdorffDistance(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const
Returns the Hausdorff distance between this geometry and geom.
static geos::unique_ptr asGeos(const QgsGeometry &geometry, double precision=0)
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
QgsAbstractGeometry * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
std::unique_ptr< QgsAbstractGeometry > reshapeGeometry(const QgsLineString &reshapeWithLine, EngineOperationResult *errorCode, QString *errorMsg=nullptr) const
Reshapes the geometry using a line.
QgsAbstractGeometry * combine(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Calculate the combination of this and geom.
EngineOperationResult splitGeometry(const QgsLineString &splitLine, QVector< QgsGeometry > &newGeometries, bool topological, QgsPointSequence &topologyTestPoints, QString *errorMsg=nullptr, bool skipIntersectionCheck=false) const override
Splits this geometry according to a given line.
std::unique_ptr< QgsAbstractGeometry > clip(const QgsRectangle &rectangle, QString *errorMsg=nullptr) const
Performs a fast, non-robust intersection between the geometry and a rectangle.
bool contains(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Checks if geom contains this.
bool disjoint(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Checks if geom is disjoint from this.
QgsGeos(const QgsAbstractGeometry *geometry, double precision=0)
GEOS geometry engine constructor.
static QgsGeometry::OperationResult addPart(QgsGeometry &geometry, GEOSGeometry *newPart)
Adds a new island polygon to a multipolygon feature.
QgsGeometry shortestLine(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the shortest line joining this geometry to the other geometry.
QgsAbstractGeometry * offsetCurve(double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg=nullptr) const override
QgsAbstractGeometry * simplify(double tolerance, QString *errorMsg=nullptr) const override
QgsGeometry closestPoint(const QgsGeometry &other, QString *errorMsg=nullptr) const
Returns the closest point on the geometry to the other geometry.
static std::unique_ptr< QgsPolygon > fromGeosPolygon(const GEOSGeometry *geos)
QgsAbstractGeometry * envelope(QString *errorMsg=nullptr) const override
QString relate(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Returns the Dimensional Extended 9 Intersection Model (DE-9IM) representation of the relationship bet...
bool crosses(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Checks if geom crosses this.
QgsAbstractGeometry * convexHull(QString *errorMsg=nullptr) const override
Calculate the convex hull of this.
double distance(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Calculates the distance between this and geom.
QgsAbstractGeometry * symDifference(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Calculate the symmetric difference of this and geom.
bool isSimple(QString *errorMsg=nullptr) const override
Determines whether the geometry is simple (according to OGC definition).
bool within(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Checks if geom is within this.
void prepareGeometry() override
Prepares the geometry, so that subsequent calls to spatial relation methods are much faster.
std::unique_ptr< QgsAbstractGeometry > singleSidedBuffer(double distance, int segments, int side, int joinStyle, double miterLimit, QString *errorMsg=nullptr) const
Returns a single sided buffer for a geometry.
static std::unique_ptr< QgsAbstractGeometry > fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
QgsAbstractGeometry * interpolate(double distance, QString *errorMsg=nullptr) const override
bool isEqual(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Checks if this is equal to geom.
QgsGeometry mergeLines(QString *errorMsg=nullptr) const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
static QgsGeometry polygonize(const QVector< const QgsAbstractGeometry * > &geometries, QString *errorMsg=nullptr)
Creates a GeometryCollection geometry containing possible polygons formed from the constituent linewo...
bool relatePattern(const QgsAbstractGeometry *geom, const QString &pattern, QString *errorMsg=nullptr) const override
Tests whether two geometries are related by a specified Dimensional Extended 9 Intersection Model (DE...
static GEOSContextHandle_t getGEOSHandler()
QgsPoint * centroid(QString *errorMsg=nullptr) const override
Calculates the centroid of this.
double lineLocatePoint(const QgsPoint &point, QString *errorMsg=nullptr) const
Returns a distance representing the location along this linestring of the closest point on this lines...
bool isEmpty(QString *errorMsg=nullptr) const override
std::unique_ptr< QgsAbstractGeometry > subdivide(int maxNodes, QString *errorMsg=nullptr) const
Subdivides the geometry.
QgsGeometry voronoiDiagram(const QgsAbstractGeometry *extent=nullptr, double tolerance=0.0, bool edgesOnly=false, QString *errorMsg=nullptr) const
Creates a Voronoi diagram for the nodes contained within the geometry.
bool intersects(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Checks if geom intersects this.
void geometryChanged() override
Should be called whenever the geometry associated with the engine has been modified and the engine mu...
bool overlaps(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Checks if geom overlaps this.
double area(QString *errorMsg=nullptr) const override
double length(QString *errorMsg=nullptr) const override
QgsAbstractGeometry * difference(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Calculate the difference of this and geom.
static QgsPoint coordSeqPoint(const GEOSCoordSequence *cs, int i, bool hasZ, bool hasM)
QgsPoint * pointOnSurface(QString *errorMsg=nullptr) const override
Calculate a point that is guaranteed to be on the surface of this.
static QgsGeometry geometryFromGeos(GEOSGeometry *geos)
Creates a new QgsGeometry object, feeding in a geometry in GEOS format.
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
int numPoints() const override SIP_HOLDGIL
Returns the number of points in the curve.
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
const double * mData() const
Returns a const pointer to the m vertex data, or nullptr if the linestring does not have m values.
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
double mAt(int index) const
Returns the m value of the specified node in the line string.
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
const double * xData() const
Returns a const pointer to the x vertex data.
const double * zData() const
Returns a const pointer to the z vertex data, or nullptr if the linestring does not have z values.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
Multi curve geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Multi line string geometry collection.
Multi point geometry collection.
Multi polygon geometry collection.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
bool isEmpty() const
Returns true if the rectangle is empty.
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
Type
The WKB type describes the number of dimensions a geometry has.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Contains geos related utilities and functions.
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
std::unique_ptr< GEOSCoordSequence, GeosDeleter > coord_sequence_unique_ptr
Scoped GEOS coordinate sequence pointer.
std::unique_ptr< GEOSBufferParams, GeosDeleter > buffer_params_unique_ptr
Scoped GEOS buffer params pointer.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QMap< QString, QString > QgsStringMap
QVector< QgsPoint > QgsPointSequence
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)
#define DEFAULT_QUADRANT_SEGMENTS
#define CATCH_GEOS_WITH_ERRMSG(r)
void CORE_EXPORT operator()(GEOSGeometry *geom)
Destroys the GEOS geometry geom, using the static QGIS geos context.