int QgsGeometryEditUtils::addRing( QgsAbstractGeometryV2* geom, QgsCurveV2* ring ) { if ( !ring ) { return 1; } QList< QgsCurvePolygonV2* > polygonList; QgsCurvePolygonV2* curvePoly = dynamic_cast< QgsCurvePolygonV2* >( geom ); QgsGeometryCollectionV2* multiGeom = dynamic_cast< QgsGeometryCollectionV2* >( geom ); if ( curvePoly ) { polygonList.append( curvePoly ); } else if ( multiGeom ) { for ( int i = 0; i < multiGeom->numGeometries(); ++i ) { polygonList.append( dynamic_cast< QgsCurvePolygonV2* >( multiGeom->geometryN( i ) ) ); } } else { delete ring; return 1; //not polygon / multipolygon; } //ring must be closed if ( !ring->isClosed() ) { delete ring; return 2; } else if ( !ring->isRing() ) { delete ring; return 3; } QScopedPointer<QgsGeometryEngine> ringGeom( QgsGeometry::createGeometryEngine( ring ) ); ringGeom->prepareGeometry(); //for each polygon, test if inside outer ring and no intersection with other interior ring QList< QgsCurvePolygonV2* >::iterator polyIter = polygonList.begin(); for ( ; polyIter != polygonList.end(); ++polyIter ) { if ( ringGeom->within( **polyIter ) ) { //check if disjoint with other interior rings int nInnerRings = ( *polyIter )->numInteriorRings(); for ( int i = 0; i < nInnerRings; ++i ) { if ( !ringGeom->disjoint( *( *polyIter )->interiorRing( i ) ) ) { delete ring; return 4; } } ( *polyIter )->addInteriorRing( ring ); return 0; //success } } delete ring; return 5; //not contained in any outer ring }
QgsGeometry::OperationResult QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, std::unique_ptr<QgsCurve> ring ) { if ( !ring ) { return QgsGeometry::InvalidInput; } QList< QgsCurvePolygon * > polygonList; QgsCurvePolygon *curvePoly = qgsgeometry_cast< QgsCurvePolygon * >( geom ); QgsGeometryCollection *multiGeom = qgsgeometry_cast< QgsGeometryCollection * >( geom ); if ( curvePoly ) { polygonList.append( curvePoly ); } else if ( multiGeom ) { polygonList.reserve( multiGeom->numGeometries() ); for ( int i = 0; i < multiGeom->numGeometries(); ++i ) { polygonList.append( qgsgeometry_cast< QgsCurvePolygon * >( multiGeom->geometryN( i ) ) ); } } else { return QgsGeometry::InvalidInput; //not polygon / multipolygon; } //ring must be closed if ( !ring->isClosed() ) { return QgsGeometry::AddRingNotClosed; } else if ( !ring->isRing() ) { return QgsGeometry::AddRingNotValid; } std::unique_ptr<QgsGeometryEngine> ringGeom( QgsGeometry::createGeometryEngine( ring.get() ) ); ringGeom->prepareGeometry(); //for each polygon, test if inside outer ring and no intersection with other interior ring QList< QgsCurvePolygon * >::const_iterator polyIter = polygonList.constBegin(); for ( ; polyIter != polygonList.constEnd(); ++polyIter ) { if ( ringGeom->within( *polyIter ) ) { //check if disjoint with other interior rings int nInnerRings = ( *polyIter )->numInteriorRings(); for ( int i = 0; i < nInnerRings; ++i ) { if ( !ringGeom->disjoint( ( *polyIter )->interiorRing( i ) ) ) { return QgsGeometry::AddRingCrossesExistingRings; } } //make sure dimensionality of ring matches geometry if ( QgsWkbTypes::hasZ( geom->wkbType() ) ) ring->addZValue( 0 ); if ( QgsWkbTypes::hasM( geom->wkbType() ) ) ring->addMValue( 0 ); ( *polyIter )->addInteriorRing( ring.release() ); return QgsGeometry::Success; //success } } return QgsGeometry::AddRingNotInExistingFeature; //not contained in any outer ring }