Skip to content
Permalink
Browse files

Optimise QgsAbstractGeometry

Make nCoordinates virtual, and provide shortcuts for some
geometry types. The base method which calls coordinateSequence()
is quite slow in certain circumstances.

Speeds up rendering point layers by ~25%, also likely to
speed up lots of geometry heavy operations throughout QGIS

Refs #15752

(cherry-picked from 49432a8)
  • Loading branch information
nyalldawson committed Oct 28, 2016
1 parent 68cbf07 commit 5f01a87278eaca8bda625f6e1d52bf3cdf582669
@@ -227,7 +227,7 @@ class QgsAbstractGeometryV2

/** Returns the number of nodes contained in the geometry
*/
int nCoordinates() const;
virtual int nCoordinates() const;

/** Returns the point corresponding to a specified vertex id
*/
@@ -65,6 +65,7 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
virtual bool deleteVertex( QgsVertexId position );

virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const;
virtual int nCoordinates() const;
double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const;
bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const;

@@ -69,6 +69,7 @@ class QgsGeometryCollectionV2: public QgsAbstractGeometryV2
virtual QgsRectangle boundingBox() const;

virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const;
virtual int nCoordinates() const;
virtual double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const;
bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const;

@@ -134,6 +134,7 @@ class QgsLineStringV2: public QgsCurveV2
virtual QgsLineStringV2* curveToLine() const /Factory/;

int numPoints() const;
virtual int nCoordinates() const;
void points( QList<QgsPointV2>& pt ) const;

void draw( QPainter& p ) const;
@@ -16,6 +16,7 @@ class QgsMultiPointV2: public QgsGeometryCollectionV2
QDomElement asGML3( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const;
QString asJSON( int precision = 17 ) const;

virtual int nCoordinates() const;

/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g );
@@ -156,6 +156,7 @@ class QgsPointV2: public QgsAbstractGeometryV2
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform );
void transform( const QTransform& t );
virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const;
virtual int nCoordinates() const;

//low-level editing
virtual bool insertVertex( QgsVertexId position, const QgsPointV2& vertex );
@@ -213,7 +213,7 @@ class CORE_EXPORT QgsAbstractGeometryV2

/** Returns the number of nodes contained in the geometry
*/
int nCoordinates() const;
virtual int nCoordinates() const;

/** Returns the point corresponding to a specified vertex id
*/
@@ -607,6 +607,27 @@ QgsCoordinateSequenceV2 QgsCurvePolygonV2::coordinateSequence() const
return mCoordinateSequence;
}

int QgsCurvePolygonV2::nCoordinates() const
{
if ( !mCoordinateSequence.isEmpty() )
return QgsAbstractGeometryV2::nCoordinates();

int count = 0;

if ( mExteriorRing )
{
count += mExteriorRing->nCoordinates();
}

QList<QgsCurveV2*>::const_iterator it = mInteriorRings.constBegin();
for ( ; it != mInteriorRings.constEnd(); ++it )
{
count += ( *it )->nCoordinates();
}

return count;
}

double QgsCurvePolygonV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
{
if ( !mExteriorRing )
@@ -91,6 +91,7 @@ class CORE_EXPORT QgsCurvePolygonV2: public QgsSurfaceV2
virtual bool deleteVertex( QgsVertexId position ) override;

virtual QgsCoordinateSequenceV2 coordinateSequence() const override;
virtual int nCoordinates() const override;
double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const override;
bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const override;

@@ -361,6 +361,22 @@ QgsCoordinateSequenceV2 QgsGeometryCollectionV2::coordinateSequence() const
return mCoordinateSequence;
}

int QgsGeometryCollectionV2::nCoordinates() const
{
if ( !mCoordinateSequence.isEmpty() )
return QgsAbstractGeometryV2::nCoordinates();

int count = 0;

QVector< QgsAbstractGeometryV2* >::const_iterator geomIt = mGeometries.constBegin();
for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
{
count += ( *geomIt )->nCoordinates();
}

return count;
}

double QgsGeometryCollectionV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
{
return QgsGeometryUtils::closestSegmentFromComponents( mGeometries, QgsGeometryUtils::PART, pt, segmentPt, vertexAfter, leftOf, epsilon );
@@ -93,6 +93,8 @@ class CORE_EXPORT QgsGeometryCollectionV2: public QgsAbstractGeometryV2
virtual QgsRectangle boundingBox() const override;

virtual QgsCoordinateSequenceV2 coordinateSequence() const override;
virtual int nCoordinates() const override;

virtual double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const override;
bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const override;

@@ -159,6 +159,7 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2
virtual QgsLineStringV2* curveToLine() const override;

int numPoints() const override;
virtual int nCoordinates() const override { return mX.size(); }
void points( QgsPointSequenceV2 &pt ) const override;

void draw( QPainter& p ) const override;
@@ -39,6 +39,7 @@ class CORE_EXPORT QgsMultiPointV2: public QgsGeometryCollectionV2
QDomElement asGML3( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const override;
QString asJSON( int precision = 17 ) const override;

virtual int nCoordinates() const override { return mGeometries.size(); }

/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g ) override;
@@ -168,6 +168,7 @@ class CORE_EXPORT QgsPointV2: public QgsAbstractGeometryV2
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) override;
void transform( const QTransform& t ) override;
virtual QgsCoordinateSequenceV2 coordinateSequence() const override;
virtual int nCoordinates() const override { return 1; }

//low-level editing
virtual bool insertVertex( QgsVertexId position, const QgsPointV2& vertex ) override { Q_UNUSED( position ); Q_UNUSED( vertex ); return false; }

0 comments on commit 5f01a87

Please sign in to comment.
You can’t perform that action at this time.