Make gap fixes more robust

This commit is contained in:
Matthias Kuhn 2020-01-14 16:25:28 +01:00
parent 6cdd75bbab
commit d5cc24c0ca

View File

@ -24,6 +24,9 @@
#include "qgsapplication.h" #include "qgsapplication.h"
#include "qgsproject.h" #include "qgsproject.h"
#include "qgsexpressioncontextutils.h" #include "qgsexpressioncontextutils.h"
#include "qgspolygon.h"
#include "qgscurve.h"
#include "qgssnappingutils.h"
#include "geos_c.h" #include "geos_c.h"
@ -304,6 +307,8 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( const QMap<QString, QgsFeaturePool
const QgsAbstractGeometry *errGeometry = QgsGeometryCheckerUtils::getGeomPart( geometry.constGet(), 0 ); const QgsAbstractGeometry *errGeometry = QgsGeometryCheckerUtils::getGeomPart( geometry.constGet(), 0 );
const auto layerIds = err->neighbors().keys(); const auto layerIds = err->neighbors().keys();
QList<QgsFeature> neighbours;
// Search for touching neighboring geometries // Search for touching neighboring geometries
for ( const QString &layerId : layerIds ) for ( const QString &layerId : layerIds )
{ {
@ -316,11 +321,20 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( const QMap<QString, QgsFeaturePool
for ( QgsFeatureId testId : featureIds ) for ( QgsFeatureId testId : featureIds )
{ {
QgsFeature testFeature; QgsFeature feature;
if ( !featurePool->getFeature( testId, testFeature ) ) if ( !featurePool->getFeature( testId, feature ) )
{ {
continue; continue;
} }
QgsGeometry transformedGeometry = feature.geometry();
transformedGeometry.transform( ct );
feature.setGeometry( transformedGeometry );
neighbours.append( feature );
}
for ( const QgsFeature &testFeature : neighbours )
{
const QgsGeometry featureGeom = testFeature.geometry(); const QgsGeometry featureGeom = testFeature.geometry();
const QgsAbstractGeometry *testGeom = featureGeom.constGet(); const QgsAbstractGeometry *testGeom = featureGeom.constGet();
for ( int iPart = 0, nParts = testGeom->partCount(); iPart < nParts; ++iPart ) for ( int iPart = 0, nParts = testGeom->partCount(); iPart < nParts; ++iPart )
@ -353,14 +367,34 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( const QMap<QString, QgsFeaturePool
return false; return false;
} }
QgsSpatialIndex neighbourIndex( QgsSpatialIndex::Flag::FlagStoreFeatureGeometries );
neighbourIndex.addFeatures( neighbours );
QgsPolyline snappedRing;
QgsVertexIterator iterator = errGeometry->vertices();
while ( iterator.hasNext() )
{
QgsPoint pt = iterator.next();
QgsVertexId id;
QgsGeometry closestGeom = neighbourIndex.geometry( neighbourIndex.nearestNeighbor( QgsPointXY( pt ) ).first() );
if ( !closestGeom.isEmpty() )
{
QgsPoint closestPoint = QgsGeometryUtils::closestVertex( *closestGeom.constGet(), pt, id );
snappedRing.append( closestPoint );
}
}
std::unique_ptr<QgsPolygon> snappedErrGeom = qgis::make_unique<QgsPolygon>();
snappedErrGeom->setExteriorRing( new QgsLineString( snappedRing ) );
// Merge geometries // Merge geometries
QgsFeaturePool *featurePool = featurePools[ mergeLayerId ]; QgsFeaturePool *featurePool = featurePools[ mergeLayerId ];
std::unique_ptr<QgsAbstractGeometry> errLayerGeom( errGeometry->clone() ); std::unique_ptr<QgsAbstractGeometry> errLayerGeom( snappedErrGeom->clone() );
QgsCoordinateTransform ct( featurePool->crs(), mContext->mapCrs, mContext->transformContext ); QgsCoordinateTransform ct( featurePool->crs(), mContext->mapCrs, mContext->transformContext );
errLayerGeom->transform( ct, QgsCoordinateTransform::ReverseTransform ); errLayerGeom->transform( ct, QgsCoordinateTransform::ReverseTransform );
const QgsGeometry mergeFeatureGeom = mergeFeature.geometry(); const QgsGeometry mergeFeatureGeom = mergeFeature.geometry();
const QgsAbstractGeometry *mergeGeom = mergeFeatureGeom.constGet(); const QgsAbstractGeometry *mergeGeom = mergeFeatureGeom.constGet();
std::unique_ptr< QgsGeometryEngine > geomEngine = QgsGeometryCheckerUtils::createGeomEngine( errLayerGeom.get(), mContext->reducedTolerance ); std::unique_ptr< QgsGeometryEngine > geomEngine = QgsGeometryCheckerUtils::createGeomEngine( errLayerGeom.get(), 0 );
std::unique_ptr<QgsAbstractGeometry> combinedGeom( geomEngine->combine( QgsGeometryCheckerUtils::getGeomPart( mergeGeom, mergePartIdx ), &errMsg ) ); std::unique_ptr<QgsAbstractGeometry> combinedGeom( geomEngine->combine( QgsGeometryCheckerUtils::getGeomPart( mergeGeom, mergePartIdx ), &errMsg ) );
if ( !combinedGeom || combinedGeom->isEmpty() || !QgsWkbTypes::isSingleType( combinedGeom->wkbType() ) ) if ( !combinedGeom || combinedGeom->isEmpty() || !QgsWkbTypes::isSingleType( combinedGeom->wkbType() ) )
{ {