Skip to content

Commit

Permalink
Optimise QgsAbstractGeometry
Browse files Browse the repository at this point in the history
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 49432a8
Show file tree
Hide file tree
Showing 14 changed files with 50 additions and 2 deletions.
2 changes: 1 addition & 1 deletion python/core/geometry/qgsabstractgeometry.sip
Expand Up @@ -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
*/
Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgscurvepolygon.sip
Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgsgeometrycollection.sip
Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgslinestring.sip
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgsmultipoint.sip
Expand Up @@ -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/ );
Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgspointv2.sip
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/core/geometry/qgsabstractgeometry.h
Expand Up @@ -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
*/
Expand Down
21 changes: 21 additions & 0 deletions src/core/geometry/qgscurvepolygon.cpp
Expand Up @@ -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 )
Expand Down
1 change: 1 addition & 0 deletions src/core/geometry/qgscurvepolygon.h
Expand Up @@ -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;

Expand Down
16 changes: 16 additions & 0 deletions src/core/geometry/qgsgeometrycollection.cpp
Expand Up @@ -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 );
Expand Down
2 changes: 2 additions & 0 deletions src/core/geometry/qgsgeometrycollection.h
Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions src/core/geometry/qgslinestring.h
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/core/geometry/qgsmultipoint.h
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/core/geometry/qgspointv2.h
Expand Up @@ -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
Expand Down

0 comments on commit 49432a8

Please sign in to comment.