Skip to content

Commit

Permalink
Merge pull request #2824 from nyalldawson/geombbox
Browse files Browse the repository at this point in the history
Optimise storage/calculation of geometry bounding boxes
  • Loading branch information
jef-n committed Feb 21, 2016
2 parents 959952e + 6116fdc commit 4485d3a
Show file tree
Hide file tree
Showing 28 changed files with 270 additions and 99 deletions.
16 changes: 10 additions & 6 deletions python/core/geometry/qgsabstractgeometryv2.sip
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
};
6 changes: 4 additions & 2 deletions python/core/geometry/qgscircularstringv2.sip
Expand Up @@ -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 );

Expand Down Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions python/core/geometry/qgscompoundcurvev2.sip
Expand Up @@ -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 );

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

protected:

virtual QgsRectangle calculateBoundingBox() const;

};
10 changes: 6 additions & 4 deletions python/core/geometry/qgscurvepolygonv2.sip
Expand Up @@ -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 );

Expand All @@ -34,8 +32,8 @@ class QgsCurvePolygonV2: public QgsSurfaceV2

//curve polygon interface
int numInteriorRings() const;
QgsCurveV2* exteriorRing() const;
QgsCurveV2* interiorRing( int i ) const;
const QgsCurveV2* exteriorRing() const;
const QgsCurveV2* interiorRing( int i ) const;
virtual QgsPolygonV2* toPolygon() const;

/** Sets the exterior ring of the polygon. The CurvePolygon type will be updated to match the dimensionality
Expand Down Expand Up @@ -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;
};
7 changes: 7 additions & 0 deletions python/core/geometry/qgscurvev2.sip
Expand Up @@ -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()
Expand All @@ -94,4 +96,9 @@ class QgsCurveV2: public QgsAbstractGeometryV2
* @note added in QGIS 2.14
*/
virtual bool dropMValue() = 0;

protected:

virtual void clearCache() const;

};
5 changes: 4 additions & 1 deletion python/core/geometry/qgsgeometrycollectionv2.sip
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

};
4 changes: 4 additions & 0 deletions python/core/geometry/qgslinestringv2.sip
Expand Up @@ -162,4 +162,8 @@ class QgsLineStringV2: public QgsCurveV2

virtual bool convertTo( QgsWKBTypes::Type type );

protected:

virtual QgsRectangle calculateBoundingBox() const;

};
2 changes: 1 addition & 1 deletion python/core/geometry/qgspointv2.sip
Expand Up @@ -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/;
Expand All @@ -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 );
Expand Down
7 changes: 7 additions & 0 deletions python/core/geometry/qgssurfacev2.sip
Expand Up @@ -7,4 +7,11 @@ class QgsSurfaceV2: public QgsAbstractGeometryV2
public:

virtual QgsPolygonV2* surfaceToPolygon() const = 0;

virtual QgsRectangle boundingBox() const;

protected:

virtual void clearCache() const;

};
9 changes: 0 additions & 9 deletions src/core/geometry/qgsabstractgeometryv2.cpp
Expand Up @@ -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 );
Expand Down
18 changes: 11 additions & 7 deletions src/core/geometry/qgsabstractgeometryv2.h
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {}

};


Expand Down
22 changes: 19 additions & 3 deletions src/core/geometry/qgscircularstringv2.cpp
Expand Up @@ -62,6 +62,7 @@ void QgsCircularStringV2::clear()
mZ.clear();
mM.clear();
mWkbType = QgsWKBTypes::Unknown;
clearCache();
}

QgsRectangle QgsCircularStringV2::calculateBoundingBox() const
Expand Down Expand Up @@ -216,6 +217,7 @@ bool QgsCircularStringV2::fromWkb( QgsConstWkbPtr wkbPtr )
{
return false;
}
clearCache();
mWkbType = type;

//type
Expand Down Expand Up @@ -418,6 +420,8 @@ void QgsCircularStringV2::points( QList<QgsPointV2>& pts ) const

void QgsCircularStringV2::setPoints( const QList<QgsPointV2>& points )
{
clearCache();

if ( points.size() < 1 )
{
mWkbType = QgsWKBTypes::Unknown;
Expand Down Expand Up @@ -609,6 +613,8 @@ void QgsCircularStringV2::draw( QPainter& p ) const

void QgsCircularStringV2::transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d )
{
clearCache();

double* zArray = mZ.data();

bool hasZ = is3D();
Expand All @@ -630,6 +636,8 @@ void QgsCircularStringV2::transform( const QgsCoordinateTransform& ct, QgsCoordi

void QgsCircularStringV2::transform( const QTransform& t )
{
clearCache();

int nPoints = numPoints();
for ( int i = 0; i < nPoints; ++i )
{
Expand Down Expand Up @@ -723,7 +731,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;
}

Expand All @@ -744,7 +752,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;
}

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

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

Expand All @@ -788,6 +796,7 @@ void QgsCircularStringV2::deleteVertex( int i )
{
mM.remove( i );
}
clearCache();
}

double QgsCircularStringV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
Expand Down Expand Up @@ -975,6 +984,7 @@ void QgsCircularStringV2::insertVertexBetween( int after, int before, int pointO
{
mM.insert( before, ( mM[after] + mM[before] ) / 2.0 );
}
clearCache();
}

double QgsCircularStringV2::vertexAngle( QgsVertexId vId ) const
Expand Down Expand Up @@ -1053,6 +1063,7 @@ bool QgsCircularStringV2::addZValue( double zValue )
if ( QgsWKBTypes::hasZ( mWkbType ) )
return false;

clearCache();
mWkbType = QgsWKBTypes::addZ( mWkbType );

int nPoints = numPoints();
Expand All @@ -1070,6 +1081,7 @@ bool QgsCircularStringV2::addMValue( double mValue )
if ( QgsWKBTypes::hasM( mWkbType ) )
return false;

clearCache();
mWkbType = QgsWKBTypes::addM( mWkbType );

int nPoints = numPoints();
Expand All @@ -1087,6 +1099,8 @@ bool QgsCircularStringV2::dropZValue()
if ( !QgsWKBTypes::hasZ( mWkbType ) )
return false;

clearCache();

mWkbType = QgsWKBTypes::dropZ( mWkbType );
mZ.clear();
return true;
Expand All @@ -1097,6 +1111,8 @@ bool QgsCircularStringV2::dropMValue()
if ( !QgsWKBTypes::hasM( mWkbType ) )
return false;

clearCache();

mWkbType = QgsWKBTypes::dropM( mWkbType );
mM.clear();
return true;
Expand Down
7 changes: 5 additions & 2 deletions src/core/geometry/qgscircularstringv2.h
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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

0 comments on commit 4485d3a

Please sign in to comment.