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
  • Loading branch information
nyalldawson committed Oct 26, 2016
1 parent 5798a82 commit 49432a84683e99bdc2592e7ae808e81fa3bc40cd
@@ -248,7 +248,7 @@ class QgsAbstractGeometry

/** 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
*/
@@ -68,6 +68,7 @@ class QgsCurvePolygon: public QgsSurface
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;

@@ -67,6 +67,7 @@ class QgsGeometryCollection: public QgsAbstractGeometry
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;

@@ -120,6 +120,7 @@ class QgsLineString: public QgsCurve
virtual QgsLineString* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) 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 QgsGeometryCollection
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( QgsAbstractGeometry* g /Transfer/ );
@@ -157,6 +157,7 @@ class QgsPointV2: public QgsAbstractGeometry
bool transformZ = false );
void transform( const QTransform& t );
virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const;
virtual int nCoordinates() const;
virtual QgsAbstractGeometry* boundary() const /Factory/;

//low-level editing
@@ -233,7 +233,7 @@ class CORE_EXPORT QgsAbstractGeometry

/** 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
*/
@@ -632,6 +632,27 @@ QgsCoordinateSequence QgsCurvePolygon::coordinateSequence() const
return mCoordinateSequence;
}

int QgsCurvePolygon::nCoordinates() const
{
if ( !mCoordinateSequence.isEmpty() )
return QgsAbstractGeometry::nCoordinates();

int count = 0;

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

QList<QgsCurve*>::const_iterator it = mInteriorRings.constBegin();

This comment has been minimized.

Copy link
@m-kuhn

m-kuhn Oct 26, 2016

Member

Is there a reason you are prefering this over Q_FOREACH (or for ( ring : mInteriorRings ))?

This comment has been minimized.

Copy link
@nyalldawson

nyalldawson Oct 26, 2016

Author Collaborator

Just laziness and a copy and paste from a couple of lines above ;)

for ( ; it != mInteriorRings.constEnd(); ++it )
{
count += ( *it )->nCoordinates();
}

return count;
}

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

virtual QgsCoordinateSequence 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;

@@ -369,6 +369,22 @@ QgsCoordinateSequence QgsGeometryCollection::coordinateSequence() const
return mCoordinateSequence;
}

int QgsGeometryCollection::nCoordinates() const
{
if ( !mCoordinateSequence.isEmpty() )
return QgsAbstractGeometry::nCoordinates();

int count = 0;

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

return count;
}

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

virtual QgsCoordinateSequence 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;

@@ -148,6 +148,7 @@ class CORE_EXPORT QgsLineString: public QgsCurve
virtual QgsLineString* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override;

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

void draw( QPainter& p ) const override;
@@ -40,6 +40,7 @@ class CORE_EXPORT QgsMultiPointV2: public QgsGeometryCollection
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( QgsAbstractGeometry* g ) override;
@@ -170,6 +170,7 @@ class CORE_EXPORT QgsPointV2: public QgsAbstractGeometry
bool transformZ = false ) override;
void transform( const QTransform& t ) override;
virtual QgsCoordinateSequence coordinateSequence() const override;
virtual int nCoordinates() const override { return 1; }
virtual QgsAbstractGeometry* boundary() const override;

//low-level editing

0 comments on commit 49432a8

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