Skip to content

Commit

Permalink
Merge pull request #36514 from lbartoletti/fix_interpolation_split
Browse files Browse the repository at this point in the history
[BUGFIX] Fix interpolation on split geometry
  • Loading branch information
m-kuhn committed Jun 15, 2020
2 parents b5d6159 + 04c3c01 commit 91f1485
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 2 deletions.
11 changes: 10 additions & 1 deletion python/core/auto_generated/geometry/qgsgeometry.sip.in
Expand Up @@ -866,13 +866,22 @@ Splits this geometry according to a given line.
Splits this geometry according to a given line.

:param splitLine: the line that splits the geometry
\param[out] newGeometries list of new geometries that have been created with the split
\param[out] newGeometries list of new geometries that have been created with the ``splitLine``. If the geometry is 3D, a linear interpolation of the z value is performed on the geometry at split points, see example.
:param topological: ``True`` if topological editing is enabled
\param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
:param splitFeature: Set to True if you want to split a feature, otherwise set to False to split parts
fix this bug?

:return: OperationResult a result code: success or reason of failure

* Example:
.. code-block:: python

geometry = QgsGeometry.fromWkt('CompoundCurveZ ((2749546.2003820720128715 1262904.45356595050543547 100, 2749557.82053794478997588 1262920.05570670193992555 200))')
split_line = [QgsPoint(2749544.19, 1262914.79), QgsPoint(2749557.64, 1262897.30)]
result, new_geometries, point_xy = geometry.splitGeometry(split_line, False)
print(geometry.asWkt(2))
> LineStringZ (2749549.12 1262908.38 125.14, 2749557.82 1262920.06 200)
%End

OperationResult reshapeGeometry( const QgsLineString &reshapeLineString );
Expand Down
11 changes: 11 additions & 0 deletions src/core/geometry/qgsgeometry.cpp
Expand Up @@ -833,6 +833,17 @@ QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QgsPointSequence
QVector<QgsGeometry > newGeoms;
QgsLineString splitLineString( splitLine );

/**
* QGIS uses GEOS algorithm to split geometries.
* Using 3D points in GEOS will returns an interpolation value which is the
* mean between geometries.
* On the contrary, in our logic, the interpolation is a linear interpolation
* on the split point. By dropping Z/M value, GEOS will returns the expected
* result. See https://github.com/qgis/QGIS/issues/33489
*/
splitLineString.dropZValue();
splitLineString.dropMValue();

QgsGeos geos( d->geometry.get() );
mLastError.clear();
QgsGeometryEngine::EngineOperationResult result = geos.splitGeometry( splitLineString, newGeoms, topological, topologyTestPoints, &mLastError );
Expand Down
11 changes: 10 additions & 1 deletion src/core/geometry/qgsgeometry.h
Expand Up @@ -893,12 +893,21 @@ class CORE_EXPORT QgsGeometry
/**
* Splits this geometry according to a given line.
* \param splitLine the line that splits the geometry
* \param[out] newGeometries list of new geometries that have been created with the split
* \param[out] newGeometries list of new geometries that have been created with the ``splitLine``. If the geometry is 3D, a linear interpolation of the z value is performed on the geometry at split points, see example.
* \param topological TRUE if topological editing is enabled
* \param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
* \param splitFeature Set to True if you want to split a feature, otherwise set to False to split parts
* fix this bug?
* \returns OperationResult a result code: success or reason of failure
*
* * Example:
* \code{.py}
* geometry = QgsGeometry.fromWkt('CompoundCurveZ ((2749546.2003820720128715 1262904.45356595050543547 100, 2749557.82053794478997588 1262920.05570670193992555 200))')
* split_line = [QgsPoint(2749544.19, 1262914.79), QgsPoint(2749557.64, 1262897.30)]
* result, new_geometries, point_xy = geometry.splitGeometry(split_line, False)
* print(geometry.asWkt(2))
* > LineStringZ (2749549.12 1262908.38 125.14, 2749557.82 1262920.06 200)
* \endcode
*/
OperationResult splitGeometry( const QgsPointSequence &splitLine, QVector<QgsGeometry> &newGeometries SIP_OUT, bool topological, QgsPointSequence &topologyTestPoints SIP_OUT, bool splitFeature = true );

Expand Down
8 changes: 8 additions & 0 deletions tests/src/core/testqgsgeometry.cpp
Expand Up @@ -17660,6 +17660,14 @@ void TestQgsGeometry::splitGeometry()
QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 493825.46541286131832749, 7082214.02779923938214779 ) << QgsPoint( 492955.04876351181883365, 7082338.06309300474822521 ),
newGeoms, false, testPoints ), QgsGeometry::NothingHappened );
QVERIFY( newGeoms.isEmpty() );

// Bug https://github.com/qgis/QGIS/issues/33489
QgsGeometry g2 = QgsGeometry::fromWkt( "CompoundCurveZ ((2749546.2003820720128715 1262904.45356595050543547 100, 2749557.82053794478997588 1262920.05570670193992555 200))" );
testPoints.clear();
newGeoms.clear();
QCOMPARE( g2.splitGeometry( QgsPointSequence() << QgsPoint( 2749544.19, 1262914.79, 0 ) << QgsPoint( 2749557.64, 1262897.30, 0 ), newGeoms, false, testPoints ), QgsGeometry::Success );
QVERIFY( newGeoms.count() == 1 );
QCOMPARE( newGeoms[0].asWkt( 2 ), QStringLiteral( "LineStringZ (2749549.12 1262908.38 125.14, 2749557.82 1262920.06 200)" ) );
}

void TestQgsGeometry::snappedToGrid()
Expand Down

0 comments on commit 91f1485

Please sign in to comment.