Skip to content

Commit e503c70

Browse files
committed
change QgsAbstractGeometryV2::coordinateSequence() to return a
implicitly shared copy of an internal cache instead of recreating the coordinate sequence again and again. Improves performance of the nodetool on large features a lot (refs #13963) Also introduce Qgs(Coordinate|Ring|Point)SequenceV2 typedefs.
1 parent 4485d3a commit e503c70

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+365
-346
lines changed

python/core/geometry/qgsabstractgeometryv2.sip

+2-2
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,9 @@ class QgsAbstractGeometryV2
221221
virtual bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const = 0;
222222

223223
/** Retrieves the sequence of geometries, rings and nodes.
224-
* @param coord destination for coordinate sequence.
224+
* @return coordinate sequence
225225
*/
226-
virtual void coordinateSequence( QList< QList< QList< QgsPointV2 > > >& coord /Out/ ) const = 0;
226+
virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const = 0;
227227

228228
/** Returns the number of nodes contained in the geometry
229229
*/

python/core/geometry/qgscircularstringv2.sip

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class QgsCircularStringV2: public QgsCurveV2
8282
/**
8383
* @copydoc QgsCurveV2::pointAt()
8484
*/
85-
bool pointAt( int i, QgsPointV2& vertex, QgsVertexId::VertexType& type ) const;
85+
bool pointAt( int node, QgsPointV2& point, QgsVertexId::VertexType& type ) const;
8686

8787
/**
8888
* @copydoc QgsCurveV2::sumUpArea()

python/core/geometry/qgscurvepolygonv2.sip

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
6464
virtual bool moveVertex( QgsVertexId position, const QgsPointV2& newPos );
6565
virtual bool deleteVertex( QgsVertexId position );
6666

67-
virtual void coordinateSequence( QList< QList< QList< QgsPointV2 > > >& coord /Out/ ) const;
67+
virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const;
6868
double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const;
6969
bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const;
7070

python/core/geometry/qgscurvev2.sip

+3-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class QgsCurveV2: public QgsAbstractGeometryV2
5757
*/
5858
virtual void sumUpArea( double& sum ) const = 0;
5959

60-
virtual void coordinateSequence( QList< QList< QList< QgsPointV2 > > >& coord /Out/ ) const;
60+
virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const;
6161
virtual bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const;
6262

6363
/** Returns the point and vertex id of a point within the curve.
@@ -76,8 +76,8 @@ class QgsCurveV2: public QgsAbstractGeometryV2
7676
/** Returns a geometry without curves. Caller takes ownership*/
7777
virtual QgsCurveV2* segmentize() const /Factory/;
7878

79-
virtual int vertexCount(int part = 0, int ring = 0) const;
80-
virtual int ringCount(int part = 0) const;
79+
virtual int vertexCount( int part = 0, int ring = 0 ) const;
80+
virtual int ringCount( int part = 0 ) const;
8181
virtual int partCount() const;
8282
virtual QgsPointV2 vertexAt( QgsVertexId id ) const;
8383

python/core/geometry/qgsgeometry.sip

+8
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,13 @@ class QgsGeometry
279279
/** Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
280280
@return 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
281281
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*/
282+
// TODO QGIS 3.0 returns an enum instead of a magic constant
282283
int addRing( const QList<QgsPoint>& ring );
283284

284285
/** Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
285286
@return 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
286287
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*/
288+
// TODO QGIS 3.0 returns an enum instead of a magic constant
287289
int addRing( QgsCurveV2* ring );
288290

289291
/** Adds a new part to a the geometry.
@@ -292,6 +294,7 @@ class QgsGeometry
292294
* @returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
293295
* not disjoint with existing polygons of the feature
294296
*/
297+
// TODO QGIS 3.0 returns an enum instead of a magic constant
295298
int addPart( const QList<QgsPoint> &points, QGis::GeometryType geomType = QGis::UnknownGeometry );
296299

297300
/** Adds a new part to a the geometry.
@@ -300,6 +303,7 @@ class QgsGeometry
300303
* @returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
301304
* not disjoint with existing polygons of the feature
302305
*/
306+
// TODO QGIS 3.0 returns an enum instead of a magic constant
303307
int addPart( const QList<QgsPointV2> &points, QGis::GeometryType geomType = QGis::UnknownGeometry );
304308

305309
/** Adds a new part to this geometry.
@@ -308,6 +312,7 @@ class QgsGeometry
308312
* @returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
309313
* not disjoint with existing polygons of the feature
310314
*/
315+
// TODO QGIS 3.0 returns an enum instead of a magic constant
311316
int addPart( QgsAbstractGeometryV2* part /Transfer/, QGis::GeometryType geomType = QGis::UnknownGeometry );
312317

313318
/** Adds a new island polygon to a multipolygon feature
@@ -316,13 +321,15 @@ class QgsGeometry
316321
* not disjoint with existing polygons of the feature
317322
* @note not available in python bindings
318323
*/
324+
// TODO QGIS 3.0 returns an enum instead of a magic constant
319325
// int addPart( GEOSGeometry *newPart );
320326

321327
/** Adds a new island polygon to a multipolygon feature
322328
@return 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
323329
not disjoint with existing polygons of the feature
324330
@note available in python bindings as addPartGeometry (added in 2.2)
325331
*/
332+
// TODO QGIS 3.0 returns an enum instead of a magic constant
326333
int addPart( const QgsGeometry *newPart /Transfer/ ) /PyName=addPartGeometry/;
327334

328335
/** Translate this geometry by dx, dy
@@ -351,6 +358,7 @@ class QgsGeometry
351358
@param topological true if topological editing is enabled
352359
@param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
353360
@return 0 in case of success, 1 if geometry has not been split, error else*/
361+
// TODO QGIS 3.0 returns an enum instead of a magic constant
354362
int splitGeometry( const QList<QgsPoint>& splitLine,
355363
QList<QgsGeometry*>&newGeometries /Out/,
356364
bool topological,

python/core/geometry/qgsgeometrycollectionv2.sip

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class QgsGeometryCollectionV2: public QgsAbstractGeometryV2
6868

6969
virtual QgsRectangle boundingBox() const;
7070

71-
virtual void coordinateSequence( QList< QList< QList< QgsPointV2 > > >& coord /Out/ ) const;
71+
virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const;
7272
virtual double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const;
7373
bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const;
7474

python/core/geometry/qgspointv2.sip

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class QgsPointV2: public QgsAbstractGeometryV2
155155
void draw( QPainter& p ) const;
156156
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform );
157157
void transform( const QTransform& t );
158-
virtual void coordinateSequence( QList< QList< QList< QgsPointV2 > > >& coord /Out/ ) const;
158+
virtual QList< QList< QList< QgsPointV2 > > > coordinateSequence() const;
159159

160160
//low-level editing
161161
virtual bool insertVertex( QgsVertexId position, const QgsPointV2& vertex );

python/core/qgsvectorlayereditutils.sip

+7
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class QgsVectorLayerEditUtils
5454
* 4 ring crosses existing rings,
5555
* 5 no feature found where ring can be inserted
5656
*/
57+
// TODO QGIS 3.0 returns an enum instead of a magic constant
5758
int addRing( const QList<QgsPoint>& ring, const QgsFeatureIds& targetFeatureIds = QgsFeatureIds(), QgsFeatureId* modifiedFeatureId = 0 );
5859

5960
/** Adds a ring to polygon/multipolygon features
@@ -70,6 +71,7 @@ class QgsVectorLayerEditUtils
7071
* 5 no feature found where ring can be inserted
7172
* @note available in python bindings as addCurvedRing
7273
*/
74+
// TODO QGIS 3.0 returns an enum instead of a magic constant
7375
int addRing( QgsCurveV2* ring, const QgsFeatureIds& targetFeatureIds = QgsFeatureIds(), QgsFeatureId* modifiedFeatureId = nullptr ) /PyName=addCurvedRing/;
7476

7577
/** Adds a new part polygon to a multipart feature
@@ -82,6 +84,7 @@ class QgsVectorLayerEditUtils
8284
* 5 if several features are selected,
8385
* 6 if selected geometry not found
8486
*/
87+
// TODO QGIS 3.0 returns an enum instead of a magic constant
8588
int addPart( const QList<QgsPoint>& ring, QgsFeatureId featureId );
8689

8790
/** Adds a new part polygon to a multipart feature
@@ -95,9 +98,11 @@ class QgsVectorLayerEditUtils
9598
* 6 if selected geometry not found
9699
* @note available in python bindings as addPartV2
97100
*/
101+
// TODO QGIS 3.0 returns an enum instead of a magic constant
98102
int addPart( const QList<QgsPointV2>& ring, QgsFeatureId featureId ) /PyName=addPartV2/;
99103

100104
// @note available in python bindings as addCurvedPart
105+
// TODO QGIS 3.0 returns an enum instead of a magic constant
101106
int addPart( QgsCurveV2* ring, QgsFeatureId featureId ) /PyName=addCurvedPart/;
102107

103108
/** Translates feature by dx, dy
@@ -115,6 +120,7 @@ class QgsVectorLayerEditUtils
115120
* 0 in case of success,
116121
* 4 if there is a selection but no feature split
117122
*/
123+
// TODO QGIS 3.0 returns an enum instead of a magic constant
118124
int splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing = false );
119125

120126
/** Splits features cut by the given line
@@ -124,6 +130,7 @@ class QgsVectorLayerEditUtils
124130
* 0 in case of success,
125131
* 4 if there is a selection but no feature split
126132
*/
133+
// TODO QGIS 3.0 returns an enum instead of a magic constant
127134
int splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing = false );
128135

129136
/** Adds topological points for every vertex of the geometry.

src/app/qgsmaptooladdcircularstring.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ void QgsMapToolAddCircularString::activate()
161161
mTempRubberBand->show();
162162
}
163163
QgsCircularStringV2* c = new QgsCircularStringV2();
164-
QList< QgsPointV2 > rubberBandPoints = mPoints;
164+
QgsPointSequenceV2 rubberBandPoints = mPoints;
165165
rubberBandPoints.append( QgsPointV2( mapPoint ) );
166166
c->setPoints( rubberBandPoints );
167167
mTempRubberBand->setGeometry( c );
@@ -208,7 +208,7 @@ void QgsMapToolAddCircularString::updateCenterPointRubberBand( const QgsPointV2&
208208

209209
//create circular string
210210
QgsCircularStringV2* cs = new QgsCircularStringV2();
211-
QList< QgsPointV2 > csPoints;
211+
QgsPointSequenceV2 csPoints;
212212
csPoints.append( mPoints.at( mPoints.size() - 2 ) );
213213
csPoints.append( mPoints.at( mPoints.size() - 1 ) );
214214
csPoints.append( pt );

src/app/qgsmaptooladdcircularstring.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class QgsMapToolAddCircularString: public QgsMapToolCapture
4545
* */
4646
QgsMapToolCapture* mParentTool;
4747
/** Circular string points (in map coordinates)*/
48-
QList< QgsPointV2 > mPoints;
48+
QgsPointSequenceV2 mPoints;
4949
//! The rubberband to show the already completed circular strings
5050
QgsGeometryRubberBand* mRubberBand;
5151
//! The rubberband to show the circular string currently working on

src/app/qgsmaptooladdpart.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void QgsMapToolAddPart::cadCanvasReleaseEvent( QgsMapMouseEvent * e )
8585
}
8686

8787
vlayer->beginEditCommand( tr( "Part added" ) );
88-
errorCode = vlayer->addPart( QList<QgsPointV2>() << layerPoint );
88+
errorCode = vlayer->addPart( QgsPointSequenceV2() << layerPoint );
8989
}
9090
break;
9191

src/app/qgsmaptoolcircularstringcurvepoint.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ void QgsMapToolCircularStringCurvePoint::cadCanvasReleaseEvent( QgsMapMouseEvent
5252
}
5353

5454
QgsCircularStringV2* c = new QgsCircularStringV2();
55-
QList< QgsPointV2 > rubberBandPoints = mPoints.mid( mPoints.size() - 1 - ( mPoints.size() + 1 ) % 2 );
55+
QgsPointSequenceV2 rubberBandPoints = mPoints.mid( mPoints.size() - 1 - ( mPoints.size() + 1 ) % 2 );
5656
rubberBandPoints.append( mapPoint );
5757
c->setPoints( rubberBandPoints );
5858
mTempRubberBand->setGeometry( c );
@@ -66,7 +66,7 @@ void QgsMapToolCircularStringCurvePoint::cadCanvasReleaseEvent( QgsMapMouseEvent
6666
}
6767

6868
QgsCircularStringV2* c = new QgsCircularStringV2();
69-
QList< QgsPointV2 > rubberBandPoints = mPoints;
69+
QgsPointSequenceV2 rubberBandPoints = mPoints;
7070
rubberBandPoints.append( mapPoint );
7171
c->setPoints( rubberBandPoints );
7272
mRubberBand->setGeometry( c );

src/app/qgsmaptoolcircularstringradius.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ void QgsMapToolCircularStringRadius::recalculateRubberBand()
122122

123123
void QgsMapToolCircularStringRadius::recalculateTempRubberBand( const QgsPoint& mousePosition )
124124
{
125-
QList<QgsPointV2> rubberBandPoints;
125+
QgsPointSequenceV2 rubberBandPoints;
126126
if ( !( mPoints.size() % 2 ) )
127127
{
128128
//recalculate midpoint on circle segment

src/core/geometry/qgsabstractgeometryv2.cpp

+3-8
Original file line numberDiff line numberDiff line change
@@ -137,18 +137,13 @@ QgsRectangle QgsAbstractGeometryV2::calculateBoundingBox() const
137137

138138
int QgsAbstractGeometryV2::nCoordinates() const
139139
{
140-
QList< QList< QList< QgsPointV2 > > > coordinates;
141-
coordinateSequence( coordinates );
142140
int nCoords = 0;
143141

144-
QList< QList< QList< QgsPointV2 > > >::const_iterator partIt = coordinates.constBegin();
145-
for ( ; partIt != coordinates.constEnd(); ++partIt )
142+
Q_FOREACH ( const QgsRingSequenceV2 &r, coordinateSequence() )
146143
{
147-
const QList< QList< QgsPointV2 > >& part = *partIt;
148-
QList< QList< QgsPointV2 > >::const_iterator ringIt = part.constBegin();
149-
for ( ; ringIt != part.constEnd(); ++ringIt )
144+
Q_FOREACH ( const QgsPointSequenceV2 &p, r )
150145
{
151-
nCoords += ringIt->size();
146+
nCoords += p.size();
152147
}
153148
}
154149

src/core/geometry/qgsabstractgeometryv2.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ class QgsPointV2;
3232
struct QgsVertexId;
3333
class QPainter;
3434

35+
typedef QList< QgsPointV2 > QgsPointSequenceV2;
36+
typedef QList< QgsPointSequenceV2 > QgsRingSequenceV2;
37+
typedef QList< QgsRingSequenceV2 > QgsCoordinateSequenceV2;
3538

3639
/** \ingroup core
3740
* \class QgsAbstractGeometryV2
@@ -204,9 +207,9 @@ class CORE_EXPORT QgsAbstractGeometryV2
204207
virtual bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const = 0;
205208

206209
/** Retrieves the sequence of geometries, rings and nodes.
207-
* @param coord destination for coordinate sequence.
210+
* @return coordinate sequence
208211
*/
209-
virtual void coordinateSequence( QList< QList< QList< QgsPointV2 > > >& coord ) const = 0;
212+
virtual QgsCoordinateSequenceV2 coordinateSequence() const = 0;
210213

211214
/** Returns the number of nodes contained in the geometry
212215
*/

src/core/geometry/qgscircularstringv2.cpp

+12-12
Original file line numberDiff line numberDiff line change
@@ -118,18 +118,18 @@ QgsRectangle QgsCircularStringV2::segmentBoundingBox( const QgsPointV2& pt1, con
118118
QgsRectangle bbox( pt1.x(), pt1.y(), pt1.x(), pt1.y() );
119119
bbox.combineExtentWith( pt3.x(), pt3.y() );
120120

121-
QList<QgsPointV2> compassPoints = compassPointsOnSegment( p1Angle, p2Angle, p3Angle, centerX, centerY, radius );
122-
QList<QgsPointV2>::const_iterator cpIt = compassPoints.constBegin();
121+
QgsPointSequenceV2 compassPoints = compassPointsOnSegment( p1Angle, p2Angle, p3Angle, centerX, centerY, radius );
122+
QgsPointSequenceV2::const_iterator cpIt = compassPoints.constBegin();
123123
for ( ; cpIt != compassPoints.constEnd(); ++cpIt )
124124
{
125125
bbox.combineExtentWith( cpIt->x(), cpIt->y() );
126126
}
127127
return bbox;
128128
}
129129

130-
QList<QgsPointV2> QgsCircularStringV2::compassPointsOnSegment( double p1Angle, double p2Angle, double p3Angle, double centerX, double centerY, double radius )
130+
QgsPointSequenceV2 QgsCircularStringV2::compassPointsOnSegment( double p1Angle, double p2Angle, double p3Angle, double centerX, double centerY, double radius )
131131
{
132-
QList<QgsPointV2> pointList;
132+
QgsPointSequenceV2 pointList;
133133

134134
QgsPointV2 nPoint( centerX, centerY + radius );
135135
QgsPointV2 ePoint( centerX + radius, centerY );
@@ -274,7 +274,7 @@ unsigned char* QgsCircularStringV2::asWkb( int& binarySize ) const
274274
QgsWkbPtr wkb( geomPtr, binarySize );
275275
wkb << static_cast<char>( QgsApplication::endian() );
276276
wkb << static_cast<quint32>( wkbType() );
277-
QList<QgsPointV2> pts;
277+
QgsPointSequenceV2 pts;
278278
points( pts );
279279
QgsGeometryUtils::pointsToWKB( wkb, pts, is3D(), isMeasure() );
280280
return geomPtr;
@@ -283,7 +283,7 @@ unsigned char* QgsCircularStringV2::asWkb( int& binarySize ) const
283283
QString QgsCircularStringV2::asWkt( int precision ) const
284284
{
285285
QString wkt = wktTypeStr() + ' ';
286-
QList<QgsPointV2> pts;
286+
QgsPointSequenceV2 pts;
287287
points( pts );
288288
wkt += QgsGeometryUtils::pointsToWKT( pts, precision, is3D(), isMeasure() );
289289
return wkt;
@@ -300,7 +300,7 @@ QDomElement QgsCircularStringV2::asGML2( QDomDocument& doc, int precision, const
300300

301301
QDomElement QgsCircularStringV2::asGML3( QDomDocument& doc, int precision, const QString& ns ) const
302302
{
303-
QList<QgsPointV2> pts;
303+
QgsPointSequenceV2 pts;
304304
points( pts );
305305

306306
QDomElement elemCurve = doc.createElementNS( ns, "Curve" );
@@ -354,7 +354,7 @@ QgsPointV2 QgsCircularStringV2::endPoint() const
354354
QgsLineStringV2* QgsCircularStringV2::curveToLine() const
355355
{
356356
QgsLineStringV2* line = new QgsLineStringV2();
357-
QList<QgsPointV2> points;
357+
QgsPointSequenceV2 points;
358358
int nPoints = numPoints();
359359

360360
for ( int i = 0; i < ( nPoints - 2 ) ; i += 2 )
@@ -408,7 +408,7 @@ QgsPointV2 QgsCircularStringV2::pointN( int i ) const
408408
return QgsPointV2( t, x, y, z, m );
409409
}
410410

411-
void QgsCircularStringV2::points( QList<QgsPointV2>& pts ) const
411+
void QgsCircularStringV2::points( QgsPointSequenceV2 &pts ) const
412412
{
413413
pts.clear();
414414
int nPts = numPoints();
@@ -418,7 +418,7 @@ void QgsCircularStringV2::points( QList<QgsPointV2>& pts ) const
418418
}
419419
}
420420

421-
void QgsCircularStringV2::setPoints( const QList<QgsPointV2>& points )
421+
void QgsCircularStringV2::setPoints( const QgsPointSequenceV2 &points )
422422
{
423423
clearCache();
424424

@@ -473,7 +473,7 @@ void QgsCircularStringV2::setPoints( const QList<QgsPointV2>& points )
473473
}
474474
}
475475

476-
void QgsCircularStringV2::segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QList<QgsPointV2>& points ) const
476+
void QgsCircularStringV2::segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QgsPointSequenceV2 &points ) const
477477
{
478478
//adapted code from postgis
479479
double radius = 0;
@@ -670,7 +670,7 @@ void QgsCircularStringV2::addToPainterPath( QPainterPath& path ) const
670670

671671
for ( int i = 0; i < ( nPoints - 2 ) ; i += 2 )
672672
{
673-
QList<QgsPointV2> pt;
673+
QgsPointSequenceV2 pt;
674674
segmentize( QgsPointV2( mX[i], mY[i] ), QgsPointV2( mX[i + 1], mY[i + 1] ), QgsPointV2( mX[i + 2], mY[i + 2] ), pt );
675675
for ( int j = 1; j < pt.size(); ++j )
676676
{

0 commit comments

Comments
 (0)