Skip to content
Permalink
Browse files

Merge pull request #4541 Add qgsgeometry_cast

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 ee3ab4da1b52fae49662f7514362379bb637a31e
Showing with 513 additions and 210 deletions.
  1. +14 −13 python/core/geometry/qgsabstractgeometry.sip
  2. +1 −0 python/core/geometry/qgscurve.sip
  3. +9 −3 python/core/geometry/qgsgeometry.sip
  4. +1 −0 python/core/geometry/qgsgeometrycollection.sip
  5. +1 −0 python/core/geometry/qgsmulticurve.sip
  6. +3 −1 python/core/geometry/qgsmultisurface.sip
  7. +5 −5 src/analysis/vector/qgsgeometrysnapper.cpp
  8. +2 −2 src/app/nodetool/qgsnodetool.cpp
  9. +1 −1 src/app/qgsmaptooladdpart.cpp
  10. +27 −27 src/core/expression/qgsexpressionfunction.cpp
  11. +22 −14 src/core/geometry/qgsabstractgeometry.h
  12. +16 −0 src/core/geometry/qgscircularstring.h
  13. +2 −2 src/core/geometry/qgscompoundcurve.cpp
  14. +16 −0 src/core/geometry/qgscompoundcurve.h
  15. +23 −0 src/core/geometry/qgscurve.h
  16. +2 −2 src/core/geometry/qgscurvepolygon.cpp
  17. +22 −0 src/core/geometry/qgscurvepolygon.h
  18. +28 −31 src/core/geometry/qgsgeometry.cpp
  19. +7 −1 src/core/geometry/qgsgeometry.h
  20. +1 −1 src/core/geometry/qgsgeometrycollection.cpp
  21. +17 −0 src/core/geometry/qgsgeometrycollection.h
  22. +8 −8 src/core/geometry/qgsgeometryeditutils.cpp
  23. +36 −36 src/core/geometry/qgsgeometrymakevalid.cpp
  24. +1 −1 src/core/geometry/qgsgeometrymakevalid.h
  25. +3 −3 src/core/geometry/qgsgeometryutils.cpp
  26. +8 −8 src/core/geometry/qgsgeos.cpp
  27. +9 −9 src/core/geometry/qgsinternalgeometryengine.cpp
  28. +1 −1 src/core/geometry/qgslinestring.cpp
  29. +16 −0 src/core/geometry/qgslinestring.h
  30. +6 −6 src/core/geometry/qgsmulticurve.cpp
  31. +22 −0 src/core/geometry/qgsmulticurve.h
  32. +3 −3 src/core/geometry/qgsmultilinestring.cpp
  33. +16 −0 src/core/geometry/qgsmultilinestring.h
  34. +4 −4 src/core/geometry/qgsmultipoint.cpp
  35. +16 −0 src/core/geometry/qgsmultipoint.h
  36. +7 −7 src/core/geometry/qgsmultipolygon.cpp
  37. +16 −0 src/core/geometry/qgsmultipolygon.h
  38. +5 −5 src/core/geometry/qgsmultisurface.cpp
  39. +25 −1 src/core/geometry/qgsmultisurface.h
  40. +16 −0 src/core/geometry/qgspoint.h
  41. +2 −2 src/core/geometry/qgspolygon.cpp
  42. +22 −0 src/core/geometry/qgspolygon.h
  43. +22 −0 src/core/geometry/qgssurface.h
  44. +16 −0 src/core/geometry/qgstriangle.h
  45. +5 −5 src/core/qgsdistancearea.cpp
  46. +3 −3 src/core/qgsmaptopixelgeometrysimplifier.cpp
  47. +4 −4 src/core/qgsvectordataprovider.cpp
  48. +1 −1 src/gui/qgsmaptoolidentify.cpp
@@ -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;
@@ -527,6 +527,7 @@ struct QgsVertexId
VertexType type;
};


/************************************************************************
* This file has been generated automatically from *
* *
@@ -156,6 +156,7 @@ class QgsCurve: QgsAbstractGeometry
%End



protected:

virtual void clearCache() const;
@@ -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
@@ -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;
@@ -49,6 +49,7 @@ Adds a geometry and takes ownership. Returns true in case of success

virtual QgsAbstractGeometry *boundary() const /Factory/;


};

/************************************************************************
@@ -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/;


};

/************************************************************************
@@ -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--;
@@ -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 );
@@ -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 )
@@ -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 ) );
@@ -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;
@@ -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;
@@ -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();
@@ -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();
}
@@ -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();
}
@@ -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();

@@ -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();

@@ -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;

@@ -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 )
{
@@ -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 ) );
@@ -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();

@@ -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 ) ) );
}
@@ -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 ) ) );
}
@@ -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 );

@@ -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;

@@ -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;

@@ -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();

@@ -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();

@@ -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();

@@ -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 )
{
@@ -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 )
@@ -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;
@@ -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 );

0 comments on commit ee3ab4d

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