bool QgsGeometryEditUtils::deleteRing( QgsAbstractGeometryV2* geom, int ringNum, int partNum ) { if ( !geom || partNum < 0 ) { return false; } if ( ringNum < 1 ) //cannot remove exterior ring { return false; } QgsAbstractGeometryV2* g = geom; QgsGeometryCollectionV2* c = dynamic_cast<QgsGeometryCollectionV2*>( geom ); if ( c ) { g = c->geometryN( partNum ); } else if ( partNum > 0 ) { //part num specified, but not a multi part geometry type return false; } QgsCurvePolygonV2* cpoly = dynamic_cast<QgsCurvePolygonV2*>( g ); if ( !cpoly ) { return false; } return cpoly->removeInteriorRing( ringNum - 1 ); }
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 }
void QgsGeometryAreaCheck::collectErrors( QList<QgsGeometryCheckError*>& errors, QStringList &/*messages*/, QAtomicInt* progressCounter , const QgsFeatureIds &ids ) const { const QgsFeatureIds& featureIds = ids.isEmpty() ? mFeaturePool->getFeatureIds() : ids; foreach ( const QgsFeatureId& featureid, featureIds ) { if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 ); QgsFeature feature; if ( !mFeaturePool->get( featureid, feature ) ) { continue; } QgsAbstractGeometryV2* geom = feature.geometry()->geometry(); if ( dynamic_cast<QgsGeometryCollectionV2*>( geom ) ) { QgsGeometryCollectionV2* multiGeom = static_cast<QgsGeometryCollectionV2*>( geom ); for ( int i = 0, n = multiGeom->numGeometries(); i < n; ++i ) { double value; if ( checkThreshold( multiGeom->geometryN( i ), value ) ) { errors.append( new QgsGeometryCheckError( this, featureid, multiGeom->geometryN( i )->centroid(), QgsVertexId( i ), value, QgsGeometryCheckError::ValueArea ) ); } } } else { double value; if ( checkThreshold( geom, value ) ) { errors.append( new QgsGeometryCheckError( this, featureid, geom->centroid(), QgsVertexId( 0 ), value, QgsGeometryCheckError::ValueArea ) ); } } } }
bool QgsGeometryEditUtils::deletePart( QgsAbstractGeometryV2* geom, int partNum ) { if ( !geom ) { return false; } QgsGeometryCollectionV2* c = dynamic_cast<QgsGeometryCollectionV2*>( geom ); if ( !c ) { return false; } return c->removeGeometry( partNum ); }
void QgsGeometryCheck::replaceFeatureGeometryPart( QgsFeature& feature, int partIdx, QgsAbstractGeometryV2* newPartGeom, Changes& changes ) const { QgsAbstractGeometryV2* geom = feature.geometry()->geometry(); if ( dynamic_cast<QgsGeometryCollectionV2*>( geom ) ) { QgsGeometryCollectionV2* GeomCollection = static_cast<QgsGeometryCollectionV2*>( geom ); GeomCollection->removeGeometry( partIdx ); GeomCollection->addGeometry( newPartGeom ); changes[feature.id()].append( Change( ChangeFeature, ChangeRemoved, QgsVertexId( partIdx ) ) ); changes[feature.id()].append( Change( ChangeFeature, ChangeAdded, QgsVertexId( GeomCollection->partCount() - 1 ) ) ); } else { feature.setGeometry( new QgsGeometry( newPartGeom ) ); changes[feature.id()].append( Change( ChangeFeature, ChangeChanged ) ); } mFeaturePool->updateFeature( feature ); }
int QgsGeometryEditUtils::addPart( QgsAbstractGeometryV2* geom, QgsAbstractGeometryV2* part ) { if ( !geom ) { return 1; } if ( !part ) { return 2; } //multitype? QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( geom ); if ( !geomCollection ) { return 1; } bool added = false; if ( QgsWKBTypes::flatType( geom->wkbType() ) == QgsWKBTypes::MultiSurface || QgsWKBTypes::flatType( geom->wkbType() ) == QgsWKBTypes::MultiPolygon ) { QgsCurveV2* curve = dynamic_cast<QgsCurveV2*>( part ); if ( curve && curve->isClosed() && curve->numPoints() >= 4 ) { QgsCurvePolygonV2 *poly = nullptr; if ( QgsWKBTypes::flatType( curve->wkbType() ) == QgsWKBTypes::LineString ) { poly = new QgsPolygonV2(); } else { poly = new QgsCurvePolygonV2(); } poly->setExteriorRing( curve ); added = geomCollection->addGeometry( poly ); } else if ( QgsWKBTypes::flatType( part->wkbType() ) == QgsWKBTypes::Polygon ) { added = geomCollection->addGeometry( part ); } else if ( QgsWKBTypes::flatType( part->wkbType() ) == QgsWKBTypes::MultiPolygon ) { QgsGeometryCollectionV2 *parts = static_cast<QgsGeometryCollectionV2*>( part ); 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 ); delete part; return 2; } delete part; } else { delete part; return 2; } } else { added = geomCollection->addGeometry( part ); } return added ? 0 : 2; }
void QgsGeometryTypeCheck::fixError( QgsGeometryCheckError* error, int method, int /*mergeAttributeIndex*/, Changes &changes ) const { QgsFeature feature; if ( !mFeaturePool->get( error->featureId(), feature ) ) { error->setObsolete(); return; } QgsAbstractGeometryV2* geom = feature.geometry()->geometry(); // Check if error still applies QgsWKBTypes::Type type = QgsWKBTypes::flatType( geom->wkbType() ); if (( mAllowedTypes & ( 1 << type ) ) != 0 ) { error->setObsolete(); return; } // Fix with selected method if ( method == NoChange ) { error->setFixed( method ); } else if ( method == Convert ) { // Check if corresponding single type is allowed if ( QgsWKBTypes::isMultiType( type ) && (( 1 << QgsWKBTypes::singleType( type ) ) & mAllowedTypes ) != 0 ) { // Explode multi-type feature into single-type features for ( int iPart = 1, nParts = geom->partCount(); iPart < nParts; ++iPart ) { QgsFeature newFeature; newFeature.setAttributes( feature.attributes() ); newFeature.setGeometry( new QgsGeometry( QgsGeomUtils::getGeomPart( geom, iPart )->clone() ) ); mFeaturePool->addFeature( newFeature ); changes[newFeature.id()].append( Change( ChangeFeature, ChangeAdded ) ); } // Recycle feature for part 0 feature.setGeometry( new QgsGeometry( QgsGeomUtils::getGeomPart( geom, 0 ) ) ); changes[feature.id()].append( Change( ChangeFeature, ChangeChanged ) ); } // Check if corresponding multi type is allowed else if ( QgsWKBTypes::isSingleType( type ) && (( 1 << QgsWKBTypes::multiType( type ) ) & mAllowedTypes ) != 0 ) { QgsGeometryCollectionV2* geomCollection = nullptr; switch ( QgsWKBTypes::multiType( type ) ) { case QgsWKBTypes::MultiPoint: { geomCollection = new QgsMultiPointV2(); break; } case QgsWKBTypes::MultiLineString: { geomCollection = new QgsMultiLineStringV2(); break; } case QgsWKBTypes::MultiPolygon: { geomCollection = new QgsMultiPolygonV2(); break; } case QgsWKBTypes::MultiCurve: { geomCollection = new QgsMultiCurveV2(); break; } case QgsWKBTypes::MultiSurface: { geomCollection = new QgsMultiSurfaceV2(); break; } default: break; } if ( !geomCollection ) { error->setFixFailed( tr( "Unknown geometry type" ) ); } else { geomCollection->addGeometry( geom->clone() ); feature.setGeometry( new QgsGeometry( geomCollection ) ); mFeaturePool->updateFeature( feature ); changes[feature.id()].append( Change( ChangeFeature, ChangeChanged ) ); } } // Delete feature else { mFeaturePool->deleteFeature( feature ); changes[error->featureId()].append( Change( ChangeFeature, ChangeRemoved ) ); } error->setFixed( method ); } else if ( method == Delete ) { mFeaturePool->deleteFeature( feature ); error->setFixed( method ); changes[error->featureId()].append( Change( ChangeFeature, ChangeRemoved ) ); } else { error->setFixFailed( tr( "Unknown method" ) ); } }