ErrorList topolTest::checkGaps( QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { Q_UNUSED( layer2 ); int i = 0; ErrorList errorList; GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler(); // could be enabled for lines and points too // so duplicate rule may be removed? if ( layer1->geometryType() != QgsWkbTypes::PolygonGeometry ) { return errorList; } QList<FeatureLayer>::iterator it; QgsGeometry g1; QList<GEOSGeometry *> geomList; qDebug() << mFeatureList1.count() << " features in list!"; for ( it = mFeatureList1.begin(); it != mFeatureList1.end(); ++it ) { qDebug() << "reading features-" << i; if ( !( ++i % 100 ) ) { emit progress( i ); } if ( testCanceled() ) { break; } g1 = it->feature.geometry(); if ( g1.isNull() ) { continue; } if ( !_canExportToGeos( g1 ) ) { continue; } if ( !g1.isGeosValid() ) { qDebug() << "invalid geometry found..skipping.." << it->feature.id(); continue; } if ( g1.isMultipart() ) { QgsMultiPolygonXY polys = g1.asMultiPolygon(); for ( int m = 0; m < polys.count(); m++ ) { QgsPolygonXY polygon = polys[m]; QgsGeometry polyGeom = QgsGeometry::fromPolygonXY( polygon ); geomList.push_back( QgsGeos::asGeos( polyGeom ).release() ); } } else { geomList.push_back( QgsGeos::asGeos( g1 ).release() ); } } GEOSGeometry **geomArray = new GEOSGeometry*[geomList.size()]; for ( int i = 0; i < geomList.size(); ++i ) { //qDebug() << "filling geometry array-" << i; geomArray[i] = geomList.at( i ); } qDebug() << "creating geometry collection-"; if ( geomList.isEmpty() ) { //qDebug() << "geometry list is empty!"; delete [] geomArray; return errorList; } GEOSGeometry *collection = nullptr; collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOLYGON, geomArray, geomList.size() ); qDebug() << "performing cascaded union..might take time..-"; GEOSGeometry *unionGeom = GEOSUnionCascaded_r( geosctxt, collection ); //delete[] geomArray; QgsGeometry test = QgsGeos::geometryFromGeos( unionGeom ); //qDebug() << "wktmerged - " << test.exportToWkt(); QString extentWkt = test.boundingBox().asWktPolygon(); QgsGeometry extentGeom = QgsGeometry::fromWkt( extentWkt ); QgsGeometry bufferExtent = extentGeom.buffer( 2, 3 ); //qDebug() << "extent wkt - " << bufferExtent->exportToWkt(); QgsGeometry diffGeoms = bufferExtent.difference( test ); if ( !diffGeoms ) { qDebug() << "difference result 0-"; return errorList; } //qDebug() << "difference gometry - " << diffGeoms->exportToWkt(); QVector<QgsGeometry> geomColl = diffGeoms.asGeometryCollection(); QgsGeometry canvasExtentPoly = QgsGeometry::fromWkt( qgsInterface->mapCanvas()->extent().asWktPolygon() ); for ( int i = 1; i < geomColl.count() ; ++i ) { QgsGeometry conflictGeom = geomColl[i]; if ( isExtent ) { if ( canvasExtentPoly.disjoint( conflictGeom ) ) { continue; } if ( canvasExtentPoly.crosses( conflictGeom ) ) { conflictGeom = conflictGeom.intersection( canvasExtentPoly ); } } QgsRectangle bBox = conflictGeom.boundingBox(); FeatureLayer ftrLayer1; ftrLayer1.layer = layer1; QList<FeatureLayer> errorFtrLayers; errorFtrLayers << ftrLayer1 << ftrLayer1; TopolErrorGaps *err = new TopolErrorGaps( bBox, conflictGeom, errorFtrLayers ); errorList << err; } return errorList; }
void QgsMapToolOffsetCurve::prepareGeometry( const QgsPointLocator::Match &match, QgsFeature &snappedFeature ) { QgsVectorLayer *vl = match.layer(); if ( !vl ) { return; } mOriginalGeometry = QgsGeometry(); mManipulatedGeometry = QgsGeometry(); mModifiedPart = -1; mModifiedRing = -1; //assign feature part by vertex number (snap to vertex) or by before vertex number (snap to segment) QgsGeometry geom = snappedFeature.geometry(); if ( geom.isNull() ) { return; } mOriginalGeometry = geom; QgsWkbTypes::Type geomType = geom.wkbType(); if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::LineGeometry ) { if ( !match.hasEdge() ) { return; } if ( !geom.isMultipart() ) { mManipulatedGeometry = geom; } else { int vertex = match.vertexIndex(); QgsVertexId vertexId; geom.vertexIdFromVertexNr( vertex, vertexId ); mModifiedPart = vertexId.part; QgsMultiPolylineXY multiLine = geom.asMultiPolyline(); mManipulatedGeometry = QgsGeometry::fromPolylineXY( multiLine.at( mModifiedPart ) ); } } else if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::PolygonGeometry ) { if ( !match.hasEdge() && match.hasArea() ) { if ( !geom.isMultipart() ) { mManipulatedGeometry = geom; } else { // get the correct part QgsMultiPolygonXY mpolygon = geom.asMultiPolygon(); for ( int part = 0; part < mpolygon.count(); part++ ) // go through the polygons { const QgsPolygonXY &polygon = mpolygon[part]; QgsGeometry partGeo = QgsGeometry::fromPolygonXY( polygon ); const QgsPointXY layerCoords = match.point(); if ( partGeo.contains( &layerCoords ) ) { mModifiedPart = part; mManipulatedGeometry = partGeo; } } } } else if ( match.hasEdge() ) { int vertex = match.vertexIndex(); QgsVertexId vertexId; geom.vertexIdFromVertexNr( vertex, vertexId ); QgsDebugMsg( QStringLiteral( "%1" ).arg( vertexId.ring ) ); if ( !geom.isMultipart() ) { QgsPolygonXY poly = geom.asPolygon(); // if has rings if ( poly.count() > 0 ) { mModifiedRing = vertexId.ring; mManipulatedGeometry = QgsGeometry::fromPolygonXY( QgsPolygonXY() << poly.at( mModifiedRing ) ); } else { mManipulatedGeometry = QgsGeometry::fromPolygonXY( poly ); } } else { mModifiedPart = vertexId.part; // get part, get ring QgsMultiPolygonXY multiPoly = geom.asMultiPolygon(); // if has rings if ( multiPoly.at( mModifiedPart ).count() > 0 ) { mModifiedRing = vertexId.ring; mManipulatedGeometry = QgsGeometry::fromPolygonXY( QgsPolygonXY() << multiPoly.at( mModifiedPart ).at( mModifiedRing ) ); } else { mManipulatedGeometry = QgsGeometry::fromPolygonXY( multiPoly.at( mModifiedPart ) ); } } } } }
QgsGeometry QgsMapToolDeletePart::partUnderPoint( QPoint point, QgsFeatureId &fid, int &partNum ) { QgsFeature f; QgsGeometry geomPart; switch ( vlayer->geometryType() ) { case QgsWkbTypes::PointGeometry: case QgsWkbTypes::LineGeometry: { QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToCurrentLayer( point, QgsPointLocator::Types( QgsPointLocator::Vertex | QgsPointLocator::Edge ) ); if ( !match.isValid() ) return geomPart; int snapVertex = match.vertexIndex(); vlayer->getFeatures( QgsFeatureRequest().setFilterFid( match.featureId() ) ).nextFeature( f ); QgsGeometry g = f.geometry(); if ( !g.isMultipart() ) { fid = match.featureId(); return QgsGeometry::fromPointXY( match.point() ); } else if ( QgsWkbTypes::geometryType( g.wkbType() ) == QgsWkbTypes::PointGeometry ) { fid = match.featureId(); partNum = snapVertex; return QgsGeometry::fromPointXY( match.point() ); } else if ( QgsWkbTypes::geometryType( g.wkbType() ) == QgsWkbTypes::LineGeometry ) { QgsMultiPolylineXY mline = g.asMultiPolyline(); for ( int part = 0; part < mline.count(); part++ ) { if ( snapVertex < mline[part].count() ) { fid = match.featureId(); partNum = part; return QgsGeometry::fromPolylineXY( mline[part] ); } snapVertex -= mline[part].count(); } } break; } case QgsWkbTypes::PolygonGeometry: { QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToCurrentLayer( point, QgsPointLocator::Area ); if ( !match.isValid() ) return geomPart; vlayer->getFeatures( QgsFeatureRequest().setFilterFid( match.featureId() ) ).nextFeature( f ); QgsGeometry g = f.geometry(); if ( g.isNull() ) return geomPart; QgsPointXY layerCoords = toLayerCoordinates( vlayer, point ); if ( !g.isMultipart() ) { fid = f.id(); return geomPart; } QgsMultiPolygonXY mpolygon = g.asMultiPolygon(); for ( int part = 0; part < mpolygon.count(); part++ ) // go through the polygons { const QgsPolygonXY &polygon = mpolygon[part]; QgsGeometry partGeo = QgsGeometry::fromPolygonXY( polygon ); if ( partGeo.contains( &layerCoords ) ) { fid = f.id(); partNum = part; return partGeo; } } break; } default: { break; } } return geomPart; }
QgsGeometry QgsMapToolDeletePart::partUnderPoint( QPoint point, QgsFeatureId &fid, int &partNum ) { QgsFeature f; QgsGeometry geomPart; switch ( vlayer->geometryType() ) { case QgsWkbTypes::PointGeometry: case QgsWkbTypes::LineGeometry: { QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToCurrentLayer( point, QgsPointLocator::Types( QgsPointLocator::Vertex | QgsPointLocator::Edge ) ); if ( !match.isValid() ) return geomPart; int snapVertex = match.vertexIndex(); vlayer->getFeatures( QgsFeatureRequest().setFilterFid( match.featureId() ) ).nextFeature( f ); QgsGeometry g = f.geometry(); if ( !g.isMultipart() ) { fid = match.featureId(); return QgsGeometry::fromPointXY( match.point() ); } if ( g.wkbType() == QgsWkbTypes::MultiPoint || g.wkbType() == QgsWkbTypes::MultiPoint25D ) { fid = match.featureId(); partNum = snapVertex; return QgsGeometry::fromPointXY( match.point() ); } if ( g.wkbType() == QgsWkbTypes::MultiLineString || g.wkbType() == QgsWkbTypes::MultiLineString25D ) { QgsMultiPolylineXY mline = g.asMultiPolyline(); for ( int part = 0; part < mline.count(); part++ ) { if ( snapVertex < mline[part].count() ) { fid = match.featureId(); partNum = part; return QgsGeometry::fromPolylineXY( mline[part] ); } snapVertex -= mline[part].count(); } } break; } case QgsWkbTypes::PolygonGeometry: { QgsPointXY layerCoords = toLayerCoordinates( vlayer, point ); double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapSettings() ); QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius, layerCoords.x() + searchRadius, layerCoords.y() + searchRadius ); QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectRect ) ); fit.nextFeature( f ); QgsGeometry g = f.geometry(); if ( g.isNull() ) return geomPart; if ( !g.isMultipart() ) { fid = f.id(); return geomPart; } QgsMultiPolygonXY mpolygon = g.asMultiPolygon(); for ( int part = 0; part < mpolygon.count(); part++ ) // go through the polygons { const QgsPolygonXY &polygon = mpolygon[part]; QgsGeometry partGeo = QgsGeometry::fromPolygonXY( polygon ); if ( partGeo.contains( &layerCoords ) ) { fid = f.id(); partNum = part; return partGeo; } } break; } default: { break; } } return geomPart; }