Skip to content

Commit

Permalink
Merge pull request #4541 Add qgsgeometry_cast
Browse files Browse the repository at this point in the history
Because it

* is faster than dynamic_cast
* doesn't rely on RTTI
* encapsulates type checking in one place
  • Loading branch information
m-kuhn committed Aug 13, 2017
2 parents 20a54b1 + 3da4c33 commit ee3ab4d
Show file tree
Hide file tree
Showing 48 changed files with 513 additions and 210 deletions.
27 changes: 14 additions & 13 deletions python/core/geometry/qgsabstractgeometry.sip
Expand Up @@ -26,31 +26,31 @@ class QgsAbstractGeometry
%End

%ConvertToSubClassCode
if ( dynamic_cast<QgsPoint *>( sipCpp ) != NULL )
if ( qgsgeometry_cast<QgsPoint *>( sipCpp ) != nullptr )
sipType = sipType_QgsPoint;
else if ( dynamic_cast<QgsLineString *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsLineString *>( sipCpp ) != nullptr )
sipType = sipType_QgsLineString;
else if ( dynamic_cast<QgsCircularString *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsCircularString *>( sipCpp ) != nullptr )
sipType = sipType_QgsCircularString;
else if ( dynamic_cast<QgsCompoundCurve *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsCompoundCurve *>( sipCpp ) != nullptr )
sipType = sipType_QgsCompoundCurve;
else if ( dynamic_cast<QgsTriangle *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsTriangle *>( sipCpp ) != nullptr )
sipType = sipType_QgsTriangle;
else if ( dynamic_cast<QgsPolygonV2 *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsPolygonV2 *>( sipCpp ) != nullptr )
sipType = sipType_QgsPolygonV2;
else if ( dynamic_cast<QgsCurvePolygon *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsCurvePolygon *>( sipCpp ) != nullptr )
sipType = sipType_QgsCurvePolygon;
else if ( dynamic_cast<QgsMultiPointV2 *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsMultiPointV2 *>( sipCpp ) != nullptr )
sipType = sipType_QgsMultiPointV2;
else if ( dynamic_cast<QgsMultiLineString *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsMultiLineString *>( sipCpp ) != nullptr )
sipType = sipType_QgsMultiLineString;
else if ( dynamic_cast<QgsMultiPolygonV2 *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsMultiPolygonV2 *>( sipCpp ) != nullptr )
sipType = sipType_QgsMultiPolygonV2;
else if ( dynamic_cast<QgsMultiSurface *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsMultiSurface *>( sipCpp ) != nullptr )
sipType = sipType_QgsMultiSurface;
else if ( dynamic_cast<QgsMultiCurve *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsMultiCurve *>( sipCpp ) != nullptr )
sipType = sipType_QgsMultiCurve;
else if ( dynamic_cast<QgsGeometryCollection *>( sipCpp ) != NULL )
else if ( qgsgeometry_cast<QgsGeometryCollection *>( sipCpp ) != nullptr )
sipType = sipType_QgsGeometryCollection;
else
sipType = 0;
Expand Down Expand Up @@ -527,6 +527,7 @@ struct QgsVertexId
VertexType type;
};


/************************************************************************
* This file has been generated automatically from *
* *
Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgscurve.sip
Expand Up @@ -156,6 +156,7 @@ class QgsCurve: QgsAbstractGeometry
%End



protected:

virtual void clearCache() const;
Expand Down
12 changes: 9 additions & 3 deletions python/core/geometry/qgsgeometry.sip
Expand Up @@ -1109,15 +1109,21 @@ Ring 0 is outer ring and can't be deleted.
%Docstring
Attempts to make an invalid geometry valid without losing vertices.

.. note::

Ported from PostGIS ST_MakeValid() and it should return equivalent results.
Already-valid geometries are returned without further intervention.
In case of full or partial dimensional collapses, the output geometry may be a collection
of lower-to-equal dimension geometries or a geometry of lower dimension.
Single polygons may become multi-geometries in case of self-intersections.
It preserves Z values, but M values will be dropped.

If an error was encountered during the process, more information can be retrieved
by calling `error()` on the returned geometry.

:return: new valid QgsGeometry or null geometry on error

.. note::

Ported from PostGIS ST_MakeValid() and it should return equivalent results.

.. versionadded:: 3.0
:rtype: QgsGeometry
%End
Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgsgeometrycollection.sip
Expand Up @@ -141,6 +141,7 @@ Adds a geometry and takes ownership. Returns true in case of success.
virtual bool dropZValue();
virtual bool dropMValue();


protected:

virtual bool wktOmitChildType() const;
Expand Down
1 change: 1 addition & 0 deletions python/core/geometry/qgsmulticurve.sip
Expand Up @@ -49,6 +49,7 @@ Adds a geometry and takes ownership. Returns true in case of success

virtual QgsAbstractGeometry *boundary() const /Factory/;


};

/************************************************************************
Expand Down
4 changes: 3 additions & 1 deletion python/core/geometry/qgsmultisurface.sip
Expand Up @@ -35,13 +35,15 @@ class QgsMultiSurface: QgsGeometryCollection



virtual bool addGeometry( QgsAbstractGeometry *g ) /Transfer/;
virtual bool addGeometry( QgsAbstractGeometry *g /Transfer/ );
%Docstring
Adds a geometry and takes ownership. Returns true in case of success
:rtype: bool
%End

virtual QgsAbstractGeometry *boundary() const /Factory/;


};

/************************************************************************
Expand Down
10 changes: 5 additions & 5 deletions src/analysis/vector/qgsgeometrysnapper.cpp
Expand Up @@ -332,9 +332,9 @@ void QgsSnapIndex::addGeometry( const QgsAbstractGeometry *geom )
{
int nVerts = geom->vertexCount( iPart, iRing );

if ( dynamic_cast< const QgsSurface * >( geom ) )
if ( qgsgeometry_cast< const QgsSurface * >( geom ) )
nVerts--;
else if ( const QgsCurve *curve = dynamic_cast< const QgsCurve * >( geom ) )
else if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom ) )
{
if ( curve->isClosed() )
nVerts--;
Expand Down Expand Up @@ -510,7 +510,7 @@ QgsGeometry QgsGeometrySnapper::snapGeometry( const QgsGeometry &geometry, doubl
( mode == EndPointPreferClosest || mode == EndPointPreferNodes || mode == EndPointToEndPoint ) )
return geometry;

QgsPoint center = dynamic_cast< const QgsPoint * >( geometry.geometry() ) ? *static_cast< const QgsPoint * >( geometry.geometry() ) :
QgsPoint center = qgsgeometry_cast< const QgsPoint * >( geometry.geometry() ) ? *static_cast< const QgsPoint * >( geometry.geometry() ) :
QgsPoint( geometry.geometry()->boundingBox().center() );

QgsSnapIndex refSnapIndex( center, 10 * snapTolerance );
Expand Down Expand Up @@ -607,7 +607,7 @@ QgsGeometry QgsGeometrySnapper::snapGeometry( const QgsGeometry &geometry, doubl
}

//nothing more to do for points
if ( dynamic_cast< const QgsPoint * >( subjGeom ) )
if ( qgsgeometry_cast< const QgsPoint * >( subjGeom ) )
return QgsGeometry( subjGeom );
//or for end point snapping
if ( mode == EndPointPreferClosest || mode == EndPointPreferNodes || mode == EndPointToEndPoint )
Expand Down Expand Up @@ -715,7 +715,7 @@ int QgsGeometrySnapper::polyLineSize( const QgsAbstractGeometry *geom, int iPart
{
int nVerts = geom->vertexCount( iPart, iRing );

if ( dynamic_cast< const QgsSurface * >( geom ) )
if ( qgsgeometry_cast< const QgsSurface * >( geom ) )
{
QgsPoint front = geom->vertexAt( QgsVertexId( iPart, iRing, 0 ) );
QgsPoint back = geom->vertexAt( QgsVertexId( iPart, iRing, nVerts - 1 ) );
Expand Down
4 changes: 2 additions & 2 deletions src/app/nodetool/qgsnodetool.cpp
Expand Up @@ -63,7 +63,7 @@ static bool isEndpointAtVertexIndex( const QgsGeometry &geom, int vertexIndex )
{
for ( int i = 0; i < multiCurve->numGeometries(); ++i )
{
QgsCurve *part = dynamic_cast<QgsCurve *>( multiCurve->geometryN( i ) );
QgsCurve *part = qgsgeometry_cast<QgsCurve *>( multiCurve->geometryN( i ) );
Q_ASSERT( part );
if ( vertexIndex < part->numPoints() )
return vertexIndex == 0 || vertexIndex == part->numPoints() - 1;
Expand Down Expand Up @@ -93,7 +93,7 @@ int adjacentVertexIndexToEndpoint( const QgsGeometry &geom, int vertexIndex )
int offset = 0;
for ( int i = 0; i < multiCurve->numGeometries(); ++i )
{
QgsCurve *part = dynamic_cast<QgsCurve *>( multiCurve->geometryN( i ) );
QgsCurve *part = qgsgeometry_cast<QgsCurve *>( multiCurve->geometryN( i ) );
Q_ASSERT( part );
if ( vertexIndex < part->numPoints() )
return vertexIndex == 0 ? offset + 1 : offset + part->numPoints() - 2;
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgsmaptooladdpart.cpp
Expand Up @@ -157,7 +157,7 @@ void QgsMapToolAddPart::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
QgsGeometry *geom = new QgsGeometry( cp );
geom->avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() );

const QgsCurvePolygon *cpGeom = dynamic_cast<const QgsCurvePolygon *>( geom->geometry() );
const QgsCurvePolygon *cpGeom = qgsgeometry_cast<const QgsCurvePolygon *>( geom->geometry() );
if ( !cpGeom )
{
stopCapturing();
Expand Down
54 changes: 27 additions & 27 deletions src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -1620,7 +1620,7 @@ static QVariant fcnGeomZ( const QVariantList &values, const QgsExpressionContext
//if single point, return the point's z coordinate
if ( geom.type() == QgsWkbTypes::PointGeometry && !geom.isMultipart() )
{
QgsPoint *point = dynamic_cast< QgsPoint * >( geom.geometry() );
QgsPoint *point = qgsgeometry_cast< QgsPoint * >( geom.geometry() );
if ( point )
return point->z();
}
Expand All @@ -1637,7 +1637,7 @@ static QVariant fcnGeomM( const QVariantList &values, const QgsExpressionContext
//if single point, return the point's m value
if ( geom.type() == QgsWkbTypes::PointGeometry && !geom.isMultipart() )
{
QgsPoint *point = dynamic_cast< QgsPoint * >( geom.geometry() );
QgsPoint *point = qgsgeometry_cast< QgsPoint * >( geom.geometry() );
if ( point )
return point->m();
}
Expand Down Expand Up @@ -1769,7 +1769,7 @@ static QVariant fcnInteriorRingN( const QVariantList &values, const QgsExpressio
if ( geom.isNull() )
return QVariant();

QgsCurvePolygon *curvePolygon = dynamic_cast< QgsCurvePolygon * >( geom.geometry() );
QgsCurvePolygon *curvePolygon = qgsgeometry_cast< QgsCurvePolygon * >( geom.geometry() );
if ( !curvePolygon )
return QVariant();

Expand All @@ -1791,7 +1791,7 @@ static QVariant fcnGeometryN( const QVariantList &values, const QgsExpressionCon
if ( geom.isNull() )
return QVariant();

QgsGeometryCollection *collection = dynamic_cast< QgsGeometryCollection * >( geom.geometry() );
QgsGeometryCollection *collection = qgsgeometry_cast< QgsGeometryCollection * >( geom.geometry() );
if ( !collection )
return QVariant();

Expand Down Expand Up @@ -1938,7 +1938,7 @@ static QVariant fcnMakeLine( const QVariantList &values, const QgsExpressionCont
if ( geom.type() != QgsWkbTypes::PointGeometry || geom.isMultipart() )
continue;

QgsPoint *point = dynamic_cast< QgsPoint * >( geom.geometry() );
QgsPoint *point = qgsgeometry_cast< QgsPoint * >( geom.geometry() );
if ( !point )
continue;

Expand All @@ -1961,7 +1961,7 @@ static QVariant fcnMakePolygon( const QVariantList &values, const QgsExpressionC
return QVariant();

QgsPolygonV2 *polygon = new QgsPolygonV2();
polygon->setExteriorRing( dynamic_cast< QgsCurve * >( outerRing.geometry()->clone() ) );
polygon->setExteriorRing( qgsgeometry_cast< QgsCurve * >( outerRing.geometry()->clone() ) );

for ( int i = 1; i < values.count(); ++i )
{
Expand All @@ -1972,7 +1972,7 @@ static QVariant fcnMakePolygon( const QVariantList &values, const QgsExpressionC
if ( ringGeom.type() != QgsWkbTypes::LineGeometry || ringGeom.isMultipart() || ringGeom.isNull() )
continue;

polygon->addInteriorRing( dynamic_cast< QgsCurve * >( ringGeom.geometry()->clone() ) );
polygon->addInteriorRing( qgsgeometry_cast< QgsCurve * >( ringGeom.geometry()->clone() ) );
}

return QVariant::fromValue( QgsGeometry( polygon ) );
Expand All @@ -1993,7 +1993,7 @@ static QVariant fcnMakeTriangle( const QVariantList &values, const QgsExpression
if ( geom.type() != QgsWkbTypes::PointGeometry || geom.isMultipart() )
return QVariant();

QgsPoint *point = dynamic_cast< QgsPoint * >( geom.geometry() );
QgsPoint *point = qgsgeometry_cast< QgsPoint * >( geom.geometry() );
if ( !point )
return QVariant();

Expand Down Expand Up @@ -2022,7 +2022,7 @@ static QVariant fcnMakeCircle( const QVariantList &values, const QgsExpressionCo
parent->setEvalErrorString( QObject::tr( "Segment must be greater than 2" ) );
return QVariant();
}
QgsPoint *point = static_cast< QgsPoint * >( geom.geometry() );
QgsPoint *point = qgsgeometry_cast< QgsPoint * >( geom.geometry() );
QgsCircle circ( *point, radius );
return QVariant::fromValue( QgsGeometry( circ.toPolygon( segment ) ) );
}
Expand All @@ -2045,7 +2045,7 @@ static QVariant fcnMakeEllipse( const QVariantList &values, const QgsExpressionC
parent->setEvalErrorString( QObject::tr( "Segment must be greater than 2" ) );
return QVariant();
}
QgsPoint *point = static_cast< QgsPoint * >( geom.geometry() );
QgsPoint *point = qgsgeometry_cast< QgsPoint * >( geom.geometry() );
QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
return QVariant::fromValue( QgsGeometry( elp.toPolygon( segment ) ) );
}
Expand Down Expand Up @@ -2080,8 +2080,8 @@ static QVariant fcnMakeRegularPolygon( const QVariantList &values, const QgsExpr
parent->setEvalErrorString( QObject::tr( "Option can be 0 (inscribed) or 1 (circumscribed)" ) );
return QVariant();
}
QgsPoint *center = static_cast< QgsPoint * >( pt1.geometry() );
QgsPoint *corner = static_cast< QgsPoint * >( pt2.geometry() );
QgsPoint *center = qgsgeometry_cast< QgsPoint * >( pt1.geometry() );
QgsPoint *corner = qgsgeometry_cast< QgsPoint * >( pt2.geometry() );

QgsRegularPolygon rp = QgsRegularPolygon( *center, *corner, nbEdges, option );

Expand Down Expand Up @@ -2245,17 +2245,17 @@ static QVariant fcnGeomNumInteriorRings( const QVariantList &values, const QgsEx
if ( geom.isNull() )
return QVariant();

QgsCurvePolygon *curvePolygon = dynamic_cast< QgsCurvePolygon * >( geom.geometry() );
QgsCurvePolygon *curvePolygon = qgsgeometry_cast< QgsCurvePolygon * >( geom.geometry() );
if ( curvePolygon )
return QVariant( curvePolygon->numInteriorRings() );

QgsGeometryCollection *collection = dynamic_cast< QgsGeometryCollection * >( geom.geometry() );
QgsGeometryCollection *collection = qgsgeometry_cast< QgsGeometryCollection * >( geom.geometry() );
if ( collection )
{
//find first CurvePolygon in collection
for ( int i = 0; i < collection->numGeometries(); ++i )
{
curvePolygon = dynamic_cast< QgsCurvePolygon *>( collection->geometryN( i ) );
curvePolygon = qgsgeometry_cast< QgsCurvePolygon *>( collection->geometryN( i ) );
if ( !curvePolygon )
continue;

Expand All @@ -2273,19 +2273,19 @@ static QVariant fcnGeomNumRings( const QVariantList &values, const QgsExpression
if ( geom.isNull() )
return QVariant();

QgsCurvePolygon *curvePolygon = dynamic_cast< QgsCurvePolygon * >( geom.geometry() );
QgsCurvePolygon *curvePolygon = qgsgeometry_cast< QgsCurvePolygon * >( geom.geometry() );
if ( curvePolygon )
return QVariant( curvePolygon->ringCount() );

bool foundPoly = false;
int ringCount = 0;
QgsGeometryCollection *collection = dynamic_cast< QgsGeometryCollection * >( geom.geometry() );
QgsGeometryCollection *collection = qgsgeometry_cast< QgsGeometryCollection * >( geom.geometry() );
if ( collection )
{
//find CurvePolygons in collection
for ( int i = 0; i < collection->numGeometries(); ++i )
{
curvePolygon = dynamic_cast< QgsCurvePolygon *>( collection->geometryN( i ) );
curvePolygon = qgsgeometry_cast< QgsCurvePolygon *>( collection->geometryN( i ) );
if ( !curvePolygon )
continue;

Expand Down Expand Up @@ -2350,7 +2350,7 @@ static QVariant fcnIsClosed( const QVariantList &values, const QgsExpressionCont
if ( fGeom.isNull() )
return QVariant();

QgsCurve *curve = dynamic_cast< QgsCurve * >( fGeom.geometry() );
QgsCurve *curve = qgsgeometry_cast< QgsCurve * >( fGeom.geometry() );
if ( !curve )
return QVariant();

Expand Down Expand Up @@ -2544,7 +2544,7 @@ static QVariant fcnReverse( const QVariantList &values, const QgsExpressionConte
if ( fGeom.isNull() )
return QVariant();

QgsCurve *curve = dynamic_cast< QgsCurve * >( fGeom.geometry() );
QgsCurve *curve = qgsgeometry_cast< QgsCurve * >( fGeom.geometry() );
if ( !curve )
return QVariant();

Expand All @@ -2559,7 +2559,7 @@ static QVariant fcnExteriorRing( const QVariantList &values, const QgsExpression
if ( fGeom.isNull() )
return QVariant();

QgsCurvePolygon *curvePolygon = dynamic_cast< QgsCurvePolygon * >( fGeom.geometry() );
QgsCurvePolygon *curvePolygon = qgsgeometry_cast< QgsCurvePolygon * >( fGeom.geometry() );
if ( !curvePolygon || !curvePolygon->exteriorRing() )
return QVariant();

Expand Down Expand Up @@ -2622,8 +2622,8 @@ static QVariant fcnAzimuth( const QVariantList &values, const QgsExpressionConte
QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );

const QgsPoint *pt1 = dynamic_cast<const QgsPoint *>( fGeom1.geometry() );
const QgsPoint *pt2 = dynamic_cast<const QgsPoint *>( fGeom2.geometry() );
const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.geometry() );
const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.geometry() );

if ( !pt1 || !pt2 )
{
Expand Down Expand Up @@ -2705,8 +2705,8 @@ static QVariant fcnInclination( const QVariantList &values, const QgsExpressionC
QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );

const QgsPoint *pt1 = dynamic_cast<const QgsPoint *>( fGeom1.geometry() );
const QgsPoint *pt2 = dynamic_cast<const QgsPoint *>( fGeom2.geometry() );
const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.geometry() );
const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.geometry() );

if ( ( fGeom1.type() != QgsWkbTypes::PointGeometry ) || ( fGeom2.type() != QgsWkbTypes::PointGeometry ) ||
!pt1 || !pt2 )
Expand Down Expand Up @@ -2774,7 +2774,7 @@ static QVariant fcnOrderParts( const QVariantList &values, const QgsExpressionCo
unconstedContext = new QgsExpressionContext();
}

QgsGeometryCollection *collection = dynamic_cast<QgsGeometryCollection *>( fGeom.geometry() );
QgsGeometryCollection *collection = qgsgeometry_cast<QgsGeometryCollection *>( fGeom.geometry() );
Q_ASSERT( collection ); // Should have failed the multipart check above

QgsFeatureRequest::OrderBy orderBy;
Expand All @@ -2791,7 +2791,7 @@ static QVariant fcnOrderParts( const QVariantList &values, const QgsExpressionCo

sorter.sortFeatures( partFeatures, unconstedContext );

QgsGeometryCollection *orderedGeom = dynamic_cast<QgsGeometryCollection *>( fGeom.geometry()->clone() );
QgsGeometryCollection *orderedGeom = qgsgeometry_cast<QgsGeometryCollection *>( fGeom.geometry()->clone() );

Q_ASSERT( orderedGeom );

Expand Down

0 comments on commit ee3ab4d

Please sign in to comment.