From fe296fa95da08b63d85b20d81bbdcd283be1396e Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 12 Oct 2019 05:53:43 +1000 Subject: [PATCH] Use optimised point getters/setters on GEOS >= 3.8 --- src/core/geometry/qgsgeos.cpp | 49 ++++++++++++++++++++++++++++++++++- src/core/pal/feature.cpp | 8 ++++++ src/core/pal/geomfunction.cpp | 20 ++++++++++++++ src/core/pal/layer.cpp | 12 +++++++++ src/core/pal/pointset.cpp | 29 ++++++++++++++++++++- 5 files changed, 116 insertions(+), 2 deletions(-) diff --git a/src/core/geometry/qgsgeos.cpp b/src/core/geometry/qgsgeos.cpp index 293a1d8c816..980f4f9c897 100644 --- a/src/core/geometry/qgsgeos.cpp +++ b/src/core/geometry/qgsgeos.cpp @@ -1225,12 +1225,19 @@ std::unique_ptr QgsGeos::sequenceToLinestring( const GEOSGeometry double *m = mOut.data(); for ( unsigned int i = 0; i < nPoints; ++i ) { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + if ( hasZ ) + GEOSCoordSeq_getXYZ_r( geosinit.ctxt, cs, i, x++, y++, z++ ); + else + GEOSCoordSeq_getXY_r( geosinit.ctxt, cs, i, x++, y++ ); +#else GEOSCoordSeq_getX_r( geosinit.ctxt, cs, i, x++ ); GEOSCoordSeq_getY_r( geosinit.ctxt, cs, i, y++ ); if ( hasZ ) { GEOSCoordSeq_getZ_r( geosinit.ctxt, cs, i, z++ ); } +#endif if ( hasM ) { GEOSCoordSeq_getOrdinate_r( geosinit.ctxt, cs, i, 3, m++ ); @@ -1264,12 +1271,19 @@ QgsPoint QgsGeos::coordSeqPoint( const GEOSCoordSequence *cs, int i, bool hasZ, double x, y; double z = 0; double m = 0; +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + if ( hasZ ) + GEOSCoordSeq_getXYZ_r( geosinit.ctxt, cs, i, &x, &y, &z ); + else + GEOSCoordSeq_getXY_r( geosinit.ctxt, cs, i, &x, &y ); +#else GEOSCoordSeq_getX_r( geosinit.ctxt, cs, i, &x ); GEOSCoordSeq_getY_r( geosinit.ctxt, cs, i, &y ); if ( hasZ ) { GEOSCoordSeq_getZ_r( geosinit.ctxt, cs, i, &z ); } +#endif if ( hasM ) { GEOSCoordSeq_getOrdinate_r( geosinit.ctxt, cs, i, 3, &m ); @@ -1831,12 +1845,23 @@ GEOSCoordSequence *QgsGeos::createCoordinateSequence( const QgsCurve *curve, dou zData = hasZ ? line->zData() : nullptr; mData = hasM ? line->mData() : nullptr; } +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + if ( hasZ ) + { + GEOSCoordSeq_setXYZ_r( geosinit.ctxt, coordSeq, i, std::round( *xData++ / precision ) * precision, std::round( *yData++ / precision ) * precision, std::round( *zData++ / precision ) * precision ); + } + else + { + GEOSCoordSeq_setXY_r( geosinit.ctxt, coordSeq, i, std::round( *xData++ / precision ) * precision, std::round( *yData++ / precision ) * precision ); + } +#else GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, i, std::round( *xData++ / precision ) * precision ); GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, i, std::round( *yData++ / precision ) * precision ); if ( hasZ ) { GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 2, std::round( *zData++ / precision ) * precision ); } +#endif if ( hasM ) { GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 3, line->mAt( *mData++ ) ); @@ -1855,12 +1880,23 @@ GEOSCoordSequence *QgsGeos::createCoordinateSequence( const QgsCurve *curve, dou zData = hasZ ? line->zData() : nullptr; mData = hasM ? line->mData() : nullptr; } +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + if ( hasZ ) + { + GEOSCoordSeq_setXYZ_r( geosinit.ctxt, coordSeq, i, *xData++, *yData++, *zData++ ); + } + else + { + GEOSCoordSeq_setXY_r( geosinit.ctxt, coordSeq, i, *xData++, *yData++ ); + } +#else GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, i, *xData++ ); GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, i, *yData++ ); if ( hasZ ) { GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 2, *zData++ ); } +#endif if ( hasM ) { GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 3, *mData++ ); @@ -1888,9 +1924,20 @@ geos::unique_ptr QgsGeos::createGeosPointXY( double x, double y, bool hasZ, doub Q_UNUSED( m ) geos::unique_ptr geosPoint; - try { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + if ( coordDims == 2 ) + { + // optimised constructor + if ( precision > 0. ) + geosPoint.reset( GEOSGeom_createPointFromXY_r( geosinit.ctxt, std::round( x / precision ) * precision, std::round( y / precision ) * precision ) ); + else + geosPoint.reset( GEOSGeom_createPointFromXY_r( geosinit.ctxt, x, y ) ); + return geosPoint; + } +#endif + GEOSCoordSequence *coordSeq = GEOSCoordSeq_create_r( geosinit.ctxt, 1, coordDims ); if ( !coordSeq ) { diff --git a/src/core/pal/feature.cpp b/src/core/pal/feature.cpp index f857dc39ae1..694b609a181 100644 --- a/src/core/pal/feature.cpp +++ b/src/core/pal/feature.cpp @@ -132,8 +132,12 @@ void FeaturePart::extractCoords( const GEOSGeometry *geom ) for ( int i = 0; i < nbPoints; ++i ) { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_getXY_r( geosctxt, coordSeq, i, &x[i], &y[i] ); +#else GEOSCoordSeq_getX_r( geosctxt, coordSeq, i, &x[i] ); GEOSCoordSeq_getY_r( geosctxt, coordSeq, i, &y[i] ); +#endif xmax = x[i] > xmax ? x[i] : xmax; xmin = x[i] < xmin ? x[i] : xmin; @@ -320,8 +324,12 @@ std::unique_ptr FeaturePart::createCandidatePointOnSurface( Point if ( pointGeom ) { const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() ); +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py ); +#else GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px ); GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py ); +#endif } } catch ( GEOSException &e ) diff --git a/src/core/pal/geomfunction.cpp b/src/core/pal/geomfunction.cpp index dff57eb5669..3e78db7ffbd 100644 --- a/src/core/pal/geomfunction.cpp +++ b/src/core/pal/geomfunction.cpp @@ -326,8 +326,12 @@ bool GeomFunction::containsCandidate( const GEOSPreparedGeometry *geom, double x GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler(); GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 5, 2 ); +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_setXY_r( geosctxt, coord, 0, x, y ); +#else GEOSCoordSeq_setX_r( geosctxt, coord, 0, x ); GEOSCoordSeq_setY_r( geosctxt, coord, 0, y ); +#endif if ( !qgsDoubleNear( alpha, 0.0 ) ) { double beta = alpha + M_PI_2; @@ -335,25 +339,41 @@ bool GeomFunction::containsCandidate( const GEOSPreparedGeometry *geom, double x double dy1 = std::sin( alpha ) * width; double dx2 = std::cos( beta ) * height; double dy2 = std::sin( beta ) * height; +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_setXY_r( geosctxt, coord, 1, x + dx1, y + dy1 ); + GEOSCoordSeq_setXY_r( geosctxt, coord, 2, x + dx1 + dx2, y + dy1 + dy2 ); + GEOSCoordSeq_setXY_r( geosctxt, coord, 3, x + dx2, y + dy2 ); +#else GEOSCoordSeq_setX_r( geosctxt, coord, 1, x + dx1 ); GEOSCoordSeq_setY_r( geosctxt, coord, 1, y + dy1 ); GEOSCoordSeq_setX_r( geosctxt, coord, 2, x + dx1 + dx2 ); GEOSCoordSeq_setY_r( geosctxt, coord, 2, y + dy1 + dy2 ); GEOSCoordSeq_setX_r( geosctxt, coord, 3, x + dx2 ); GEOSCoordSeq_setY_r( geosctxt, coord, 3, y + dy2 ); +#endif } else { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_setXY_r( geosctxt, coord, 1, x + width, y ); + GEOSCoordSeq_setXY_r( geosctxt, coord, 2, x + width, y + height ); + GEOSCoordSeq_setXY_r( geosctxt, coord, 3, x, y + height ); +#else GEOSCoordSeq_setX_r( geosctxt, coord, 1, x + width ); GEOSCoordSeq_setY_r( geosctxt, coord, 1, y ); GEOSCoordSeq_setX_r( geosctxt, coord, 2, x + width ); GEOSCoordSeq_setY_r( geosctxt, coord, 2, y + height ); GEOSCoordSeq_setX_r( geosctxt, coord, 3, x ); GEOSCoordSeq_setY_r( geosctxt, coord, 3, y + height ); +#endif } //close ring +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_setXY_r( geosctxt, coord, 4, x, y ); +#else GEOSCoordSeq_setX_r( geosctxt, coord, 4, x ); GEOSCoordSeq_setY_r( geosctxt, coord, 4, y ); +#endif try { diff --git a/src/core/pal/layer.cpp b/src/core/pal/layer.cpp index f07617bb8ef..6b4539320b8 100644 --- a/src/core/pal/layer.cpp +++ b/src/core/pal/layer.cpp @@ -435,8 +435,12 @@ void Layer::chopFeaturesAtRepeatDistance() std::vector points( n ); for ( unsigned int i = 0; i < n; ++i ) { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_getXY_r( geosctxt, cs, i, &points[i].x, &points[i].y ); +#else GEOSCoordSeq_getX_r( geosctxt, cs, i, &points[i].x ); GEOSCoordSeq_getY_r( geosctxt, cs, i, &points[i].y ); +#endif } // Cumulative length vector @@ -469,8 +473,12 @@ void Layer::chopFeaturesAtRepeatDistance() GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, part.size(), 2 ); for ( int i = 0; i < part.size(); ++i ) { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y ); +#else GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x ); GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y ); +#endif } GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq ); FeaturePart *newfpart = new FeaturePart( fpart->feature(), newgeom ); @@ -489,8 +497,12 @@ void Layer::chopFeaturesAtRepeatDistance() GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, part.size(), 2 ); for ( int i = 0; i < part.size(); ++i ) { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y ); +#else GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x ); GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y ); +#endif } GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq ); diff --git a/src/core/pal/pointset.cpp b/src/core/pal/pointset.cpp index ee6f1560ff8..aed1e8f136c 100644 --- a/src/core/pal/pointset.cpp +++ b/src/core/pal/pointset.cpp @@ -127,15 +127,23 @@ void PointSet::createGeosGeom() const GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, nbPoints + ( needClose ? 1 : 0 ), 2 ); for ( int i = 0; i < nbPoints; ++i ) { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_setXY_r( geosctxt, coord, i, x[i], y[i] ); +#else GEOSCoordSeq_setX_r( geosctxt, coord, i, x[i] ); GEOSCoordSeq_setY_r( geosctxt, coord, i, y[i] ); +#endif } //close ring if needed if ( needClose ) { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_setXY_r( geosctxt, coord, nbPoints, x[0], y[0] ); +#else GEOSCoordSeq_setX_r( geosctxt, coord, nbPoints, x[0] ); GEOSCoordSeq_setY_r( geosctxt, coord, nbPoints, y[0] ); +#endif } switch ( type ) @@ -239,10 +247,14 @@ bool PointSet::containsPoint( double x, double y ) const GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler(); try { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + geos::unique_ptr point( GEOSGeom_createPointFromXY_r( geosctxt, x, y ) ); +#else GEOSCoordSequence *seq = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, seq, 0, x ); GEOSCoordSeq_setY_r( geosctxt, seq, 0, y ); geos::unique_ptr point( GEOSGeom_createPoint_r( geosctxt, seq ) ); +#endif bool result = ( GEOSPreparedContainsProperly_r( geosctxt, preparedGeom(), point.get() ) == 1 ); return result; @@ -783,11 +795,14 @@ double PointSet::minDistanceToPoint( double px, double py, double *rx, double *r GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler(); try { +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + geos::unique_ptr geosPt( GEOSGeom_createPointFromXY_r( geosctxt, px, py ) ); +#else GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, coord, 0, px ); GEOSCoordSeq_setY_r( geosctxt, coord, 0, py ); geos::unique_ptr geosPt( GEOSGeom_createPoint_r( geosctxt, coord ) ); - +#endif int type = GEOSGeomTypeId_r( geosctxt, mGeos ); const GEOSGeometry *extRing = nullptr; if ( type != GEOS_POLYGON ) @@ -802,8 +817,12 @@ double PointSet::minDistanceToPoint( double px, double py, double *rx, double *r geos::coord_sequence_unique_ptr nearestCoord( GEOSNearestPoints_r( geosctxt, extRing, geosPt.get() ) ); double nx; double ny; +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + ( void )GEOSCoordSeq_getXY_r( geosctxt, nearestCoord.get(), 0, &nx, &ny ); +#else ( void )GEOSCoordSeq_getX_r( geosctxt, nearestCoord.get(), 0, &nx ); ( void )GEOSCoordSeq_getY_r( geosctxt, nearestCoord.get(), 0, &ny ); +#endif if ( rx ) *rx = nx; @@ -834,8 +853,12 @@ void PointSet::getCentroid( double &px, double &py, bool forceInside ) const if ( centroidGeom ) { const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, centroidGeom.get() ); +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py ); +#else GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px ); GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py ); +#endif } // check if centroid inside in polygon @@ -846,8 +869,12 @@ void PointSet::getCentroid( double &px, double &py, bool forceInside ) const if ( pointGeom ) { const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() ); +#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 + GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py ); +#else GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px ); GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py ); +#endif } } }