static bool lwcollection_make_geos_friendly( QgsGeometryCollection &g ) { for ( int i = 0; i < g.numGeometries(); i++ ) { if ( !lwgeom_make_geos_friendly( *g.geometryN( i ) ) ) return false; } return true; }
QgsGeometry::OperationResult QgsGeometryEditUtils::addPart( QgsAbstractGeometry *geom, std::unique_ptr<QgsAbstractGeometry> part ) { if ( !geom ) { return QgsGeometry::InvalidBaseGeometry; } if ( !part ) { return QgsGeometry::InvalidInput; } //multitype? QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( geom ); if ( !geomCollection ) { return QgsGeometry::AddPartNotMultiGeometry; } bool added = false; if ( QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::MultiSurface || QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::MultiPolygon ) { QgsCurve *curve = qgsgeometry_cast<QgsCurve *>( part.get() ); if ( curve && curve->isClosed() && curve->numPoints() >= 4 ) { std::unique_ptr<QgsCurvePolygon> poly; if ( QgsWkbTypes::flatType( curve->wkbType() ) == QgsWkbTypes::LineString ) { poly = qgis::make_unique< QgsPolygonV2 >(); } else { poly = qgis::make_unique< QgsCurvePolygon >(); } // Ownership is still with part, curve points to the same object and is transferred // to poly here. part.release(); poly->setExteriorRing( curve ); added = geomCollection->addGeometry( poly.release() ); } else if ( QgsWkbTypes::flatType( part->wkbType() ) == QgsWkbTypes::Polygon ) { added = geomCollection->addGeometry( part.release() ); } else if ( QgsWkbTypes::flatType( part->wkbType() ) == QgsWkbTypes::MultiPolygon ) { std::unique_ptr<QgsGeometryCollection> parts( static_cast<QgsGeometryCollection *>( part.release() ) ); int i; int n = geomCollection->numGeometries(); for ( i = 0; i < parts->numGeometries() && geomCollection->addGeometry( parts->geometryN( i )->clone() ); i++ ) ; added = i == parts->numGeometries(); if ( !added ) { while ( geomCollection->numGeometries() > n ) geomCollection->removeGeometry( n ); return QgsGeometry::InvalidInput; } } else { return QgsGeometry::InvalidInput; } } else { added = geomCollection->addGeometry( part.release() ); } return added ? QgsGeometry::Success : QgsGeometry::InvalidInput; }
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 }