Skip to content

Commit

Permalink
Split features: always give largest geometry to original feature
Browse files Browse the repository at this point in the history
  • Loading branch information
JuhoErvasti authored and github-actions[bot] committed Dec 17, 2024
1 parent 918a0dc commit 201b9cf
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 2 deletions.
16 changes: 16 additions & 0 deletions src/core/vector/qgsvectorlayereditutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,22 @@ Qgis::GeometryOperationResult QgsVectorLayerEditUtils::splitFeatures( const QgsC
topologyTestPoints.append( featureTopologyTestPoints );
if ( splitFunctionReturn == Qgis::GeometryOperationResult::Success )
{
//find largest geometry and give that to the original feature
std::function<double( const QgsGeometry & )> size = mLayer->geometryType() == Qgis::GeometryType::Polygon ? &QgsGeometry::area : &QgsGeometry::length;
double featureGeomSize = size( featureGeom );

QVector<QgsGeometry>::iterator largestNewFeature = std::max_element( newGeometries.begin(), newGeometries.end(), [ &size ]( const QgsGeometry & a, const QgsGeometry & b ) -> bool
{
return size( a ) < size( b );
} );

if ( size( *largestNewFeature ) > featureGeomSize )
{
QgsGeometry copy = *largestNewFeature;
*largestNewFeature = featureGeom;
featureGeom = copy;
}

//change this geometry
mLayer->changeGeometry( feat.id(), featureGeom );

Expand Down
60 changes: 58 additions & 2 deletions tests/src/app/testqgsmaptoolsplitfeatures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class TestQgsMapToolSplitFeatures : public QObject
void testSplitSomeOfSelectedLines();
// see https://github.com/qgis/QGIS/issues/29270
void testSplitPolygonSnapToSegment();
void testLargestGeometryToOriginalFeaturePolygon();
void testLargestGeometryToOriginalFeatureLine();

private:
QPoint mapToPoint( double x, double y );
Expand Down Expand Up @@ -146,13 +148,17 @@ void TestQgsMapToolSplitFeatures::testSplitPolygon()
{
mCanvas->setCurrentLayer( mPolygonLayer );

QSet<QgsFeatureId> oldFids = mUtils->existingFeatureIds();

mUtils->mouseClick( 4, 11, Qt::LeftButton );
mUtils->mouseClick( 4, 3, Qt::LeftButton );
mUtils->mouseClick( 4, 3, Qt::RightButton );

QgsFeatureId newFid = mUtils->newFeatureId( oldFids );

QCOMPARE( mPolygonLayer->undoStack()->index(), 1 );
QCOMPARE( mPolygonLayer->featureCount(), 3 );
QCOMPARE( mPolygonLayer->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon Z ((4 10 24, 4 5 14, 0 5 10, 0 10 20, 4 10 24))" ) );
QCOMPARE( mPolygonLayer->getFeature( newFid ).geometry().asWkt(), QStringLiteral( "Polygon Z ((4 10 24, 4 5 14, 0 5 10, 0 10 20, 4 10 24))" ) );
QCOMPARE( mPolygonLayer->getFeature( 2 ).geometry().asWkt(), QStringLiteral( "Polygon Z ((0 0 10, 0 5 20, 10 5 30, 0 0 10))" ) );

// no change to other layers
Expand All @@ -165,13 +171,17 @@ void TestQgsMapToolSplitFeatures::testSplitPolygonTopologicalEditing()
QgsProject::instance()->setTopologicalEditing( true );
mCanvas->setCurrentLayer( mPolygonLayer );

QSet<QgsFeatureId> oldFids = mUtils->existingFeatureIds();

mUtils->mouseClick( 4, 11, Qt::LeftButton );
mUtils->mouseClick( 4, 3, Qt::LeftButton );
mUtils->mouseClick( 4, 3, Qt::RightButton );

QgsFeatureId newFid = mUtils->newFeatureId( oldFids );

QCOMPARE( mPolygonLayer->undoStack()->index(), 1 );
QCOMPARE( mPolygonLayer->featureCount(), 3 );
QCOMPARE( mPolygonLayer->getFeature( 1 ).geometry().asWkt(), QStringLiteral( "Polygon Z ((4 10 24, 4 5 14, 0 5 10, 0 10 20, 4 10 24))" ) );
QCOMPARE( mPolygonLayer->getFeature( newFid ).geometry().asWkt(), QStringLiteral( "Polygon Z ((4 10 24, 4 5 14, 0 5 10, 0 10 20, 4 10 24))" ) );
QCOMPARE( mPolygonLayer->getFeature( 2 ).geometry().asWkt(), QStringLiteral( "Polygon Z ((0 0 10, 0 5 20, 4 5 14, 10 5 30, 0 0 10))" ) );

QCOMPARE( mMultiLineStringLayer->undoStack()->index(), 1 );
Expand Down Expand Up @@ -252,5 +262,51 @@ void TestQgsMapToolSplitFeatures::testSplitPolygonSnapToSegment()
mCanvas->snappingUtils()->setConfig( oldCfg );
}

void TestQgsMapToolSplitFeatures::testLargestGeometryToOriginalFeaturePolygon()
{
mCanvas->setCurrentLayer( mPolygonLayer );

QSet<QgsFeatureId> oldFids = mUtils->existingFeatureIds();

mUtils->mouseClick( 1, 11, Qt::LeftButton );
mUtils->mouseClick( 1, 5, Qt::LeftButton );
mUtils->mouseClick( 1, 5, Qt::RightButton );

QgsFeatureId newFid = mUtils->newFeatureId( oldFids );

QCOMPARE( mPolygonLayer->featureCount(), 3 );

QgsFeature oldFeat = mPolygonLayer->getFeature( 1 );
QgsFeature newFeat = mPolygonLayer->getFeature( newFid );

//larger
QCOMPARE( oldFeat.geometry().asWkt(), QStringLiteral( "Polygon Z ((1 5 10, 1 10 21, 10 10 30, 10 5 20, 1 5 10))" ) );

//smaller
QCOMPARE( newFeat.geometry().asWkt(), QStringLiteral( "Polygon Z ((1 10 21, 1 5 10, 0 5 10, 0 10 20, 1 10 21))" ) );
}

void TestQgsMapToolSplitFeatures::testLargestGeometryToOriginalFeatureLine()
{
mCanvas->setCurrentLayer( mMultiLineStringLayer );

QSet<QgsFeatureId> oldFids = mUtils->existingFeatureIds();

mUtils->mouseClick( 4, 1, Qt::LeftButton );
mUtils->mouseClick( 4, -1, Qt::LeftButton );
mUtils->mouseClick( 4, -1, Qt::RightButton );

QgsFeatureId newFid = mUtils->newFeatureId( oldFids );

QgsFeature oldFeat = mMultiLineStringLayer->getFeature( 1 );
QgsFeature newFeat = mMultiLineStringLayer->getFeature( newFid );

//larger
QCOMPARE( oldFeat.geometry().asWkt(), QStringLiteral( "MultiLineString ((4 0, 10 0))" ) );

//smaller
QCOMPARE( newFeat.geometry().asWkt(), QStringLiteral( "MultiLineString ((0 0, 4 0))" ) );
}

QGSTEST_MAIN( TestQgsMapToolSplitFeatures )
#include "testqgsmaptoolsplitfeatures.moc"

0 comments on commit 201b9cf

Please sign in to comment.