Skip to content
Permalink
Browse files

Optimise storage/calculation of geometry bounding boxes

- removes storage of bounding box from QgsPointV2 (gives significant
decrease in size of object)
- more efficient calculation of bounding box for linestrings

Additionally, this commit moves the bounding box invalidation to a
virtual QgsAbstractGeometryV2::clearCache() method, so that other
non-bounding box caches can also be cleared when the geometry
is modified.
  • Loading branch information
nyalldawson committed Feb 21, 2016
1 parent fef9c93 commit 50f01a2ac8e760f940f572b94739bdc17145511e
@@ -85,12 +85,7 @@ class QgsAbstractGeometryV2

/** Returns the minimal bounding box for the geometry
*/
QgsRectangle boundingBox() const;

/** Calculates the minimal bounding box for the geometry. Derived classes should override this method
* to return the correct bounding box.
*/
virtual QgsRectangle calculateBoundingBox() const;
virtual QgsRectangle boundingBox() const = 0;

//mm-sql interface
/** Returns the inherent dimension of the geometry. For example, this is 0 for a point geometry,
@@ -373,4 +368,13 @@ class QgsAbstractGeometryV2
/** Updates the geometry type based on whether sub geometries contain z or m values.
*/
void setZMTypeFromSubGeometry( const QgsAbstractGeometryV2* subggeom, QgsWKBTypes::Type baseGeomType );

/** Default calculator for the minimal bounding box for the geometry. Derived classes should override this method
* if a more efficient bounding box calculation is available.
*/
virtual QgsRectangle calculateBoundingBox() const;

/** Clears any cached parameters associated with the geometry, eg bounding boxes
*/
virtual void clearCache() const;
};
@@ -16,8 +16,6 @@ class QgsCircularStringV2: public QgsCurveV2
virtual QgsCircularStringV2* clone() const;
virtual void clear();

virtual QgsRectangle calculateBoundingBox() const;

virtual bool fromWkb( QgsConstWkbPtr wkb );
virtual bool fromWkt( const QString& wkt );

@@ -109,6 +107,10 @@ class QgsCircularStringV2: public QgsCurveV2
virtual bool dropZValue();
virtual bool dropMValue();

protected:

virtual QgsRectangle calculateBoundingBox() const;

private:
//helper methods for curveToLine
void segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QList<QgsPointV2>& points ) const;
@@ -18,8 +18,6 @@ class QgsCompoundCurveV2: public QgsCurveV2
virtual QgsCompoundCurveV2* clone() const;
virtual void clear();

virtual QgsRectangle calculateBoundingBox() const;

virtual bool fromWkb( QgsConstWkbPtr wkb );
virtual bool fromWkt( const QString& wkt );

@@ -96,4 +94,8 @@ class QgsCompoundCurveV2: public QgsCurveV2
virtual bool dropZValue();
virtual bool dropMValue();

protected:

virtual QgsRectangle calculateBoundingBox() const;

};
@@ -15,8 +15,6 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
virtual QgsCurvePolygonV2* clone() const;
void clear();


virtual QgsRectangle calculateBoundingBox() const;
virtual bool fromWkb( QgsConstWkbPtr wkb );
virtual bool fromWkt( const QString& wkt );

@@ -88,4 +86,8 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
virtual bool addMValue( double mValue = 0 );
virtual bool dropZValue();
virtual bool dropMValue();

protected:

virtual QgsRectangle calculateBoundingBox() const;
};
@@ -81,6 +81,8 @@ class QgsCurveV2: public QgsAbstractGeometryV2
virtual int partCount() const;
virtual QgsPointV2 vertexAt( QgsVertexId id ) const;

virtual QgsRectangle boundingBox() const;

/** Drops any Z dimensions which exist in the geometry.
* @returns true if Z values were present and have been removed
* @see dropMValue()
@@ -94,4 +96,9 @@ class QgsCurveV2: public QgsAbstractGeometryV2
* @note added in QGIS 2.14
*/
virtual bool dropMValue() = 0;

protected:

virtual void clearCache() const;

};
@@ -66,7 +66,7 @@ class QgsGeometryCollectionV2: public QgsAbstractGeometryV2
QDomElement asGML3( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const;
QString asJSON( int precision = 17 ) const;

virtual QgsRectangle calculateBoundingBox() const;
virtual QgsRectangle boundingBox() const;

virtual void coordinateSequence( QList< QList< QList< QgsPointV2 > > >& coord /Out/ ) const;
virtual double closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const;
@@ -113,4 +113,7 @@ class QgsGeometryCollectionV2: public QgsAbstractGeometryV2
*/
bool fromCollectionWkt( const QString &wkt, const QList<QgsAbstractGeometryV2*>& subtypes, const QString& defaultChildWkbType = QString() );

virtual QgsRectangle calculateBoundingBox() const;
virtual void clearCache() const;

};
@@ -162,4 +162,8 @@ class QgsLineStringV2: public QgsCurveV2

virtual bool convertTo( QgsWKBTypes::Type type );

protected:

virtual QgsRectangle calculateBoundingBox() const;

};
@@ -139,6 +139,7 @@ class QgsPointV2: public QgsAbstractGeometryV2
QPointF toQPointF() const;

//implementation of inherited methods
virtual QgsRectangle boundingBox() const;
virtual QString geometryType() const;
virtual int dimension() const;
virtual QgsPointV2* clone() const /Factory/;
@@ -151,7 +152,6 @@ class QgsPointV2: public QgsAbstractGeometryV2
QDomElement asGML2( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const;
QDomElement asGML3( QDomDocument& doc, int precision = 17, const QString& ns = "gml" ) const;
QString asJSON( int precision = 17 ) const;
virtual QgsRectangle calculateBoundingBox() const;
void draw( QPainter& p ) const;
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform );
void transform( const QTransform& t );
@@ -7,4 +7,11 @@ class QgsSurfaceV2: public QgsAbstractGeometryV2
public:

virtual QgsPolygonV2* surfaceToPolygon() const = 0;

virtual QgsRectangle boundingBox() const;

protected:

virtual void clearCache() const;

};
@@ -45,15 +45,6 @@ QgsAbstractGeometryV2& QgsAbstractGeometryV2::operator=( const QgsAbstractGeomet
return *this;
}

QgsRectangle QgsAbstractGeometryV2::boundingBox() const
{
if ( mBoundingBox.isNull() )
{
mBoundingBox = calculateBoundingBox();
}
return mBoundingBox;
}

bool QgsAbstractGeometryV2::is3D() const
{
return QgsWKBTypes::hasZ( mWkbType );
@@ -56,12 +56,7 @@ class CORE_EXPORT QgsAbstractGeometryV2

/** Returns the minimal bounding box for the geometry
*/
QgsRectangle boundingBox() const;

/** Calculates the minimal bounding box for the geometry. Derived classes should override this method
* to return the correct bounding box.
*/
virtual QgsRectangle calculateBoundingBox() const;
virtual QgsRectangle boundingBox() const = 0;

//mm-sql interface
/** Returns the inherent dimension of the geometry. For example, this is 0 for a point geometry,
@@ -353,11 +348,20 @@ class CORE_EXPORT QgsAbstractGeometryV2

protected:
QgsWKBTypes::Type mWkbType;
mutable QgsRectangle mBoundingBox;

/** Updates the geometry type based on whether sub geometries contain z or m values.
*/
void setZMTypeFromSubGeometry( const QgsAbstractGeometryV2* subggeom, QgsWKBTypes::Type baseGeomType );

/** Default calculator for the minimal bounding box for the geometry. Derived classes should override this method
* if a more efficient bounding box calculation is available.
*/
virtual QgsRectangle calculateBoundingBox() const;

/** Clears any cached parameters associated with the geometry, eg bounding boxes
*/
virtual void clearCache() const {}

};


@@ -723,7 +723,7 @@ bool QgsCircularStringV2::insertVertex( QgsVertexId position, const QgsPointV2&
{
insertVertexBetween( position.vertex, position.vertex + 1, position.vertex - 1 );
}
mBoundingBox = QgsRectangle(); //set bounding box invalid
clearCache(); //set bounding box invalid
return true;
}

@@ -744,7 +744,7 @@ bool QgsCircularStringV2::moveVertex( QgsVertexId position, const QgsPointV2& ne
{
mM[position.vertex] = newPos.m();
}
mBoundingBox = QgsRectangle(); //set bounding box invalid
clearCache(); //set bounding box invalid
return true;
}

@@ -772,7 +772,7 @@ bool QgsCircularStringV2::deleteVertex( QgsVertexId position )
deleteVertex( position.vertex - 1 );
}

mBoundingBox = QgsRectangle(); //set bounding box invalid
clearCache(); //set bounding box invalid
return true;
}

@@ -41,8 +41,6 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
virtual QgsCircularStringV2* clone() const override;
virtual void clear() override;

virtual QgsRectangle calculateBoundingBox() const override;

virtual bool fromWkb( QgsConstWkbPtr wkb ) override;
virtual bool fromWkt( const QString& wkt ) override;

@@ -134,6 +132,10 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
virtual bool dropZValue() override;
virtual bool dropMValue() override;

protected:

virtual QgsRectangle calculateBoundingBox() const override;

private:
QVector<double> mX;
QVector<double> mY;
@@ -152,6 +154,7 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon );
void insertVertexBetween( int after, int before, int pointOnCircle );
void deleteVertex( int i );

};

#endif // QGSCIRCULARSTRING_H
@@ -89,10 +89,10 @@ QgsRectangle QgsCompoundCurveV2::calculateBoundingBox() const
return QgsRectangle();
}

QgsRectangle bbox = mCurves.at( 0 )->calculateBoundingBox();
QgsRectangle bbox = mCurves.at( 0 )->boundingBox();
for ( int i = 1; i < mCurves.size(); ++i )
{
QgsRectangle curveBox = mCurves.at( i )->calculateBoundingBox();
QgsRectangle curveBox = mCurves.at( i )->boundingBox();
bbox.combineExtentWith( &curveBox );
}
return bbox;
@@ -497,7 +497,7 @@ bool QgsCompoundCurveV2::insertVertex( QgsVertexId position, const QgsPointV2& v
bool success = mCurves.at( curveId )->insertVertex( curveIds.at( 0 ).second, vertex );
if ( success )
{
mBoundingBox = QgsRectangle(); //bbox changed
clearCache(); //bbox changed
}
return success;
}
@@ -514,7 +514,7 @@ bool QgsCompoundCurveV2::moveVertex( QgsVertexId position, const QgsPointV2& new
bool success = !curveIds.isEmpty();
if ( success )
{
mBoundingBox = QgsRectangle(); //bbox changed
clearCache(); //bbox changed
}
return success;
}
@@ -531,7 +531,7 @@ bool QgsCompoundCurveV2::deleteVertex( QgsVertexId position )
bool success = !curveIds.isEmpty();
if ( success )
{
mBoundingBox = QgsRectangle(); //bbox changed
clearCache(); //bbox changed
}
return success;
}
@@ -42,8 +42,6 @@ class CORE_EXPORT QgsCompoundCurveV2: public QgsCurveV2
virtual QgsCompoundCurveV2* clone() const override;
virtual void clear() override;

virtual QgsRectangle calculateBoundingBox() const override;

virtual bool fromWkb( QgsConstWkbPtr wkb ) override;
virtual bool fromWkt( const QString& wkt ) override;

@@ -120,11 +118,16 @@ class CORE_EXPORT QgsCompoundCurveV2: public QgsCurveV2
virtual bool dropZValue() override;
virtual bool dropMValue() override;

protected:

virtual QgsRectangle calculateBoundingBox() const override;

private:
QList< QgsCurveV2* > mCurves;
/** Turns a vertex id for the compound curve into one or more ids for the subcurves
@return the index of the subcurve or -1 in case of error*/
QList< QPair<int, QgsVertexId> > curveVertexId( QgsVertexId id ) const;

};

#endif // QGSCOMPOUNDCURVEV2_H
@@ -209,7 +209,7 @@ QgsRectangle QgsCurvePolygonV2::calculateBoundingBox() const
{
if ( mExteriorRing )
{
return mExteriorRing->calculateBoundingBox();
return mExteriorRing->boundingBox();
}
return QgsRectangle();
}
@@ -666,7 +666,7 @@ bool QgsCurvePolygonV2::insertVertex( QgsVertexId vId, const QgsPointV2& vertex
else if ( vId.vertex == n )
ring->moveVertex( QgsVertexId( 0, 0, 0 ), vertex );

mBoundingBox = QgsRectangle();
clearCache();
return true;
}

@@ -687,7 +687,7 @@ bool QgsCurvePolygonV2::moveVertex( QgsVertexId vId, const QgsPointV2& newPos )
ring->moveVertex( QgsVertexId( vId.part, vId.ring, n - 1 ), newPos );
else if ( vId.vertex == n - 1 )
ring->moveVertex( QgsVertexId( vId.part, vId.ring, 0 ), newPos );
mBoundingBox = QgsRectangle();
clearCache();
}
return success;
}
@@ -717,7 +717,7 @@ bool QgsCurvePolygonV2::deleteVertex( QgsVertexId vId )
{
removeInteriorRing( vId.ring - 1 );
}
mBoundingBox = QgsRectangle();
clearCache();
return true;
}

@@ -729,7 +729,7 @@ bool QgsCurvePolygonV2::deleteVertex( QgsVertexId vId )
ring->moveVertex( QgsVertexId( 0, 0, n - 2 ), ring->vertexAt( QgsVertexId( 0, 0, 0 ) ) );
else if ( vId.vertex == n - 1 )
ring->moveVertex( QgsVertexId( 0, 0, 0 ), ring->vertexAt( QgsVertexId( 0, 0, n - 2 ) ) );
mBoundingBox = QgsRectangle();
clearCache();
}
return success;
}
@@ -41,8 +41,6 @@ class CORE_EXPORT QgsCurvePolygonV2: public QgsSurfaceV2
virtual QgsCurvePolygonV2* clone() const override;
void clear() override;


virtual QgsRectangle calculateBoundingBox() const override;
virtual bool fromWkb( QgsConstWkbPtr wkb ) override;
virtual bool fromWkt( const QString& wkt ) override;

@@ -120,6 +118,7 @@ class CORE_EXPORT QgsCurvePolygonV2: public QgsSurfaceV2
QgsCurveV2* mExteriorRing;
QList<QgsCurveV2*> mInteriorRings;

virtual QgsRectangle calculateBoundingBox() const override;
};

#endif // QGSCURVEPOLYGONV2_H

0 comments on commit 50f01a2

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