mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-19 00:04:52 -04:00
Merge pull request #7120 from nyalldawson/opts
Optimise geometry conversion to/from geos
This commit is contained in:
commit
497abfe797
@ -89,6 +89,8 @@ Returns the specified point from inside the line string.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
double zAt( int index ) const;
|
||||
%Docstring
|
||||
Returns the z-coordinate of the specified node in the line string.
|
||||
|
@ -1205,35 +1205,29 @@ std::unique_ptr<QgsLineString> QgsGeos::sequenceToLinestring( const GEOSGeometry
|
||||
const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit.ctxt, geos );
|
||||
unsigned int nPoints;
|
||||
GEOSCoordSeq_getSize_r( geosinit.ctxt, cs, &nPoints );
|
||||
QVector< double > xOut;
|
||||
xOut.reserve( nPoints );
|
||||
QVector< double > yOut;
|
||||
yOut.reserve( nPoints );
|
||||
QVector< double > xOut( nPoints );
|
||||
QVector< double > yOut( nPoints );
|
||||
QVector< double > zOut;
|
||||
if ( hasZ )
|
||||
zOut.reserve( nPoints );
|
||||
zOut.resize( nPoints );
|
||||
QVector< double > mOut;
|
||||
if ( hasM )
|
||||
mOut.reserve( nPoints );
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double z = 0;
|
||||
double m = 0;
|
||||
mOut.resize( nPoints );
|
||||
double *x = xOut.data();
|
||||
double *y = yOut.data();
|
||||
double *z = zOut.data();
|
||||
double *m = mOut.data();
|
||||
for ( unsigned int i = 0; i < nPoints; ++i )
|
||||
{
|
||||
GEOSCoordSeq_getX_r( geosinit.ctxt, cs, i, &x );
|
||||
xOut << x;
|
||||
GEOSCoordSeq_getY_r( geosinit.ctxt, cs, i, &y );
|
||||
yOut << y;
|
||||
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 );
|
||||
zOut << z;
|
||||
GEOSCoordSeq_getZ_r( geosinit.ctxt, cs, i, z++ );
|
||||
}
|
||||
if ( hasM )
|
||||
{
|
||||
GEOSCoordSeq_getOrdinate_r( geosinit.ctxt, cs, i, 3, &m );
|
||||
mOut << m;
|
||||
GEOSCoordSeq_getOrdinate_r( geosinit.ctxt, cs, i, 3, m++ );
|
||||
}
|
||||
}
|
||||
std::unique_ptr< QgsLineString > line( new QgsLineString( xOut, yOut, zOut, mOut ) );
|
||||
@ -1769,19 +1763,33 @@ GEOSCoordSequence *QgsGeos::createCoordinateSequence( const QgsCurve *curve, dou
|
||||
QgsDebugMsg( QStringLiteral( "GEOS Exception: Could not create coordinate sequence for %1 points in %2 dimensions" ).arg( numPoints ).arg( coordDims ) );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const double *xData = line->xData();
|
||||
const double *yData = line->yData();
|
||||
const double *zData = hasZ ? line->zData() : nullptr;
|
||||
const double *mData = hasM ? line->mData() : nullptr;
|
||||
|
||||
if ( precision > 0. )
|
||||
{
|
||||
for ( int i = 0; i < numOutPoints; ++i )
|
||||
{
|
||||
GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, i, std::round( line->xAt( i % numPoints ) / precision ) * precision );
|
||||
GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, i, std::round( line->yAt( i % numPoints ) / precision ) * precision );
|
||||
if ( i >= numPoints )
|
||||
{
|
||||
// start reading back from start of line
|
||||
xData = line->xData();
|
||||
yData = line->yData();
|
||||
zData = hasZ ? line->zData() : nullptr;
|
||||
mData = hasM ? line->mData() : nullptr;
|
||||
}
|
||||
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( line->zAt( i % numPoints ) / precision ) * precision );
|
||||
GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 2, std::round( *zData++ / precision ) * precision );
|
||||
}
|
||||
if ( hasM )
|
||||
{
|
||||
GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 3, line->mAt( i % numPoints ) );
|
||||
GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 3, line->mAt( *mData++ ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1789,15 +1797,23 @@ GEOSCoordSequence *QgsGeos::createCoordinateSequence( const QgsCurve *curve, dou
|
||||
{
|
||||
for ( int i = 0; i < numOutPoints; ++i )
|
||||
{
|
||||
GEOSCoordSeq_setX_r( geosinit.ctxt, coordSeq, i, line->xAt( i % numPoints ) );
|
||||
GEOSCoordSeq_setY_r( geosinit.ctxt, coordSeq, i, line->yAt( i % numPoints ) );
|
||||
if ( i >= numPoints )
|
||||
{
|
||||
// start reading back from start of line
|
||||
xData = line->xData();
|
||||
yData = line->yData();
|
||||
zData = hasZ ? line->zData() : nullptr;
|
||||
mData = hasM ? line->mData() : nullptr;
|
||||
}
|
||||
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, line->zAt( i % numPoints ) );
|
||||
GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 2, *zData++ );
|
||||
}
|
||||
if ( hasM )
|
||||
{
|
||||
GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 3, line->mAt( i % numPoints ) );
|
||||
GEOSCoordSeq_setOrdinate_r( geosinit.ctxt, coordSeq, i, 3, *mData++ );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -560,6 +560,22 @@ const double *QgsLineString::yData() const
|
||||
return mY.constData();
|
||||
}
|
||||
|
||||
const double *QgsLineString::zData() const
|
||||
{
|
||||
if ( mZ.empty() )
|
||||
return nullptr;
|
||||
else
|
||||
return mZ.constData();
|
||||
}
|
||||
|
||||
const double *QgsLineString::mData() const
|
||||
{
|
||||
if ( mM.empty() )
|
||||
return nullptr;
|
||||
else
|
||||
return mM.constData();
|
||||
}
|
||||
|
||||
double QgsLineString::zAt( int index ) const
|
||||
{
|
||||
if ( index >= 0 && index < mZ.size() )
|
||||
|
@ -112,6 +112,26 @@ class CORE_EXPORT QgsLineString: public QgsCurve
|
||||
*/
|
||||
const double *yData() const SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Returns a const pointer to the z vertex data, or a nullptr if the linestring does
|
||||
* not have z values.
|
||||
* \note Not available in Python bindings
|
||||
* \see xData()
|
||||
* \see yData()
|
||||
* \since QGIS 3.2
|
||||
*/
|
||||
const double *zData() const SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Returns a const pointer to the m vertex data, or a nullptr if the linestring does
|
||||
* not have m values.
|
||||
* \note Not available in Python bindings
|
||||
* \see xData()
|
||||
* \see yData()
|
||||
* \since QGIS 3.2
|
||||
*/
|
||||
const double *mData() const SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Returns the z-coordinate of the specified node in the line string.
|
||||
* \param index index of node, where the first node in the line is 0
|
||||
|
@ -2796,6 +2796,19 @@ void TestQgsGeometry::lineString()
|
||||
QCOMPARE( fromArray8.zAt( 2 ), 23.0 );
|
||||
QCOMPARE( fromArray8.mAt( 2 ), 33.0 );
|
||||
|
||||
QCOMPARE( *fromArray8.xData(), 1.0 );
|
||||
QCOMPARE( *( fromArray8.xData() + 1 ), 2.0 );
|
||||
QCOMPARE( *( fromArray8.xData() + 2 ), 3.0 );
|
||||
QCOMPARE( *fromArray8.yData(), 11.0 );
|
||||
QCOMPARE( *( fromArray8.yData() + 1 ), 12.0 );
|
||||
QCOMPARE( *( fromArray8.yData() + 2 ), 13.0 );
|
||||
QCOMPARE( *fromArray8.zData(), 21.0 );
|
||||
QCOMPARE( *( fromArray8.zData() + 1 ), 22.0 );
|
||||
QCOMPARE( *( fromArray8.zData() + 2 ), 23.0 );
|
||||
QCOMPARE( *fromArray8.mData(), 31.0 );
|
||||
QCOMPARE( *( fromArray8.mData() + 1 ), 32.0 );
|
||||
QCOMPARE( *( fromArray8.mData() + 2 ), 33.0 );
|
||||
|
||||
// from QList<QgsPointXY>
|
||||
QgsLineString fromPtsA = QgsLineString( QVector< QgsPoint >() );
|
||||
QVERIFY( fromPtsA.isEmpty() );
|
||||
|
Loading…
x
Reference in New Issue
Block a user