mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-30 00:29:39 -05:00
Optimise QgsLineString::snappedToGrid
The old approach was quite inefficient and resulted in many reallocations and array resizing
This commit is contained in:
parent
08b9624f74
commit
fbdc9cd5c3
@ -328,15 +328,72 @@ bool QgsLineString::isValid( QString &error, Qgis::GeometryValidityFlags flags )
|
||||
|
||||
QgsLineString *QgsLineString::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing ) const
|
||||
{
|
||||
// prepare result
|
||||
std::unique_ptr<QgsLineString> result { createEmptyWithSameType() };
|
||||
|
||||
bool res = snapToGridPrivate( hSpacing, vSpacing, dSpacing, mSpacing, mX, mY, mZ, mM,
|
||||
result->mX, result->mY, result->mZ, result->mM );
|
||||
if ( res )
|
||||
return result.release();
|
||||
else
|
||||
const int length = numPoints();
|
||||
if ( length < 2 )
|
||||
return nullptr;
|
||||
|
||||
const bool hasZ = is3D();
|
||||
const bool hasM = isMeasure();
|
||||
|
||||
QVector< double > outX;
|
||||
outX.reserve( length );
|
||||
QVector< double > outY;
|
||||
outY.reserve( length );
|
||||
QVector< double > outZ;
|
||||
if ( hasZ )
|
||||
outZ.reserve( length );
|
||||
QVector< double > outM;
|
||||
if ( hasM )
|
||||
outM.reserve( length );
|
||||
|
||||
const double *xIn = mX.constData();
|
||||
const double *yIn = mY.constData();
|
||||
const double *zIn = hasZ ? mZ.constData() : nullptr;
|
||||
const double *mIn = hasM ? mM.constData() : nullptr;
|
||||
|
||||
double previousX = 0;
|
||||
double previousY = 0;
|
||||
double previousZ = 0;
|
||||
double previousM = 0;
|
||||
for ( int i = 0; i < length; ++i )
|
||||
{
|
||||
const double currentX = *xIn++;
|
||||
const double currentY = *yIn++;
|
||||
const double currentZ = zIn ? *zIn++ : 0;
|
||||
const double currentM = mIn ? *mIn++ : 0;
|
||||
|
||||
const double roundedX = hSpacing > 0 ? ( std::round( currentX / hSpacing ) * hSpacing ) : currentX;
|
||||
const double roundedY = vSpacing > 0 ? ( std::round( currentY / vSpacing ) * vSpacing ) : currentY;
|
||||
const double roundedZ = hasZ && dSpacing > 0 ? ( std::round( currentZ / dSpacing ) * dSpacing ) : currentZ;
|
||||
const double roundedM = hasM && mSpacing > 0 ? ( std::round( currentM / mSpacing ) * mSpacing ) : currentM;
|
||||
|
||||
if ( i > 0 )
|
||||
{
|
||||
const bool isPointEqual = qgsDoubleNear( roundedX, previousX )
|
||||
&& qgsDoubleNear( roundedY, previousY )
|
||||
&& ( !hasZ || dSpacing <= 0 || qgsDoubleNear( roundedZ, previousZ ) )
|
||||
&& ( !hasM || mSpacing <= 0 || qgsDoubleNear( roundedM, previousM ) );
|
||||
if ( isPointEqual )
|
||||
continue;
|
||||
}
|
||||
|
||||
outX.append( roundedX );
|
||||
outY.append( roundedY );
|
||||
if ( hasZ )
|
||||
outZ.append( roundedZ );
|
||||
if ( hasM )
|
||||
outM.append( roundedM );
|
||||
|
||||
previousX = roundedX;
|
||||
previousY = roundedY;
|
||||
previousZ = roundedZ;
|
||||
previousM = roundedM;
|
||||
}
|
||||
|
||||
if ( outX.length() < 2 || ( isClosed() && outX.length() < 4 ) )
|
||||
return nullptr;
|
||||
|
||||
return new QgsLineString( outX, outY, outZ, outM );
|
||||
}
|
||||
|
||||
bool QgsLineString::removeDuplicateNodes( double epsilon, bool useZValues )
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user