Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[processing] Skip redundant and potentially expensive duplicate inter…
…section

test in Split With Lines algorithm
  • Loading branch information
nyalldawson committed Oct 15, 2020
1 parent 710230c commit f8222f0
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 17 deletions.
2 changes: 1 addition & 1 deletion python/core/auto_generated/geometry/qgsgeometry.sip.in
Expand Up @@ -857,7 +857,7 @@ Splits this geometry according to a given line.
- will be removed in QGIS 4.0. Use the variant which accepts QgsPoint objects instead of QgsPointXY.
%End

OperationResult splitGeometry( const QgsPointSequence &splitLine, QVector<QgsGeometry> &newGeometries /Out/, bool topological, QgsPointSequence &topologyTestPoints /Out/, bool splitFeature = true );
OperationResult splitGeometry( const QgsPointSequence &splitLine, QVector<QgsGeometry> &newGeometries /Out/, bool topological, QgsPointSequence &topologyTestPoints /Out/, bool splitFeature = true);
%Docstring
Splits this geometry according to a given line.

Expand Down
4 changes: 3 additions & 1 deletion python/core/auto_generated/geometry/qgsgeometryengine.sip.in
Expand Up @@ -240,7 +240,7 @@ Determines whether the geometry is simple (according to OGC definition).
virtual QgsGeometryEngine::EngineOperationResult splitGeometry( const QgsLineString &splitLine,
QVector<QgsGeometry > &newGeometries /Out/,
bool topological,
QgsPointSequence &topologyTestPoints, QString *errorMsg = 0 ) const;
QgsPointSequence &topologyTestPoints, QString *errorMsg = 0, bool skipIntersectionCheck = false ) const;
%Docstring
Splits this geometry according to a given line.

Expand All @@ -249,6 +249,8 @@ Splits this geometry according to a given line.
:param topological: ``True`` if topological editing is enabled
\param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
\param[out] errorMsg error messages emitted, if any
:param skipIntersectionCheck: set to ``True`` to skip the potentially expensive initial intersection check. Only set this flag if an intersection
test has already been performed by the caller!

:return: 0 in case of success, 1 if geometry has not been split, error else
%End
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/processing/qgsalgorithmsplitwithlines.cpp
Expand Up @@ -215,7 +215,7 @@ QVariantMap QgsSplitWithLinesAlgorithm::processAlgorithm( const QVariantMap &par

QVector< QgsGeometry > newGeometries;
QgsPointSequence topologyTestPoints;
QgsGeometry::OperationResult result = inGeom.splitGeometry( splitterPList, newGeometries, false, topologyTestPoints );
QgsGeometry::OperationResult result = inGeom.splitGeometry( splitterPList, newGeometries, false, topologyTestPoints, true );

// splitGeometry: If there are several intersections
// between geometry and splitLine, only the first one is considered.
Expand Down
4 changes: 2 additions & 2 deletions src/core/geometry/qgsgeometry.cpp
Expand Up @@ -837,7 +837,7 @@ QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QVector<QgsPointX
convertPointList( topology, topologyTestPoints );
return result;
}
QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QgsPointSequence &splitLine, QVector<QgsGeometry> &newGeometries, bool topological, QgsPointSequence &topologyTestPoints, bool splitFeature )
QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QgsPointSequence &splitLine, QVector<QgsGeometry> &newGeometries, bool topological, QgsPointSequence &topologyTestPoints, bool splitFeature, bool skipIntersectionTest )
{
if ( !d->geometry )
{
Expand All @@ -860,7 +860,7 @@ QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QgsPointSequence

QgsGeos geos( d->geometry.get() );
mLastError.clear();
QgsGeometryEngine::EngineOperationResult result = geos.splitGeometry( splitLineString, newGeoms, topological, topologyTestPoints, &mLastError );
QgsGeometryEngine::EngineOperationResult result = geos.splitGeometry( splitLineString, newGeoms, topological, topologyTestPoints, &mLastError, skipIntersectionTest );

if ( result == QgsGeometryEngine::Success )
{
Expand Down
4 changes: 3 additions & 1 deletion src/core/geometry/qgsgeometry.h
Expand Up @@ -899,6 +899,8 @@ class CORE_EXPORT QgsGeometry
* \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?
* \param skipIntersectionTest set to TRUE to skip the potentially expensive initial intersection check. Only set this flag if an intersection
* test has already been performed by the caller! Not available in Python bindings.
* \returns OperationResult a result code: success or reason of failure
*
* Example:
Expand All @@ -910,7 +912,7 @@ class CORE_EXPORT QgsGeometry
* > 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 );
OperationResult splitGeometry( const QgsPointSequence &splitLine, QVector<QgsGeometry> &newGeometries SIP_OUT, bool topological, QgsPointSequence &topologyTestPoints SIP_OUT, bool splitFeature = true, bool skipIntersectionTest SIP_PYARGREMOVE = false );

/**
* Splits this geometry according to a given curve.
Expand Down
5 changes: 4 additions & 1 deletion src/core/geometry/qgsgeometryengine.h
Expand Up @@ -253,18 +253,21 @@ class CORE_EXPORT QgsGeometryEngine
* \param topological TRUE if topological editing is enabled
* \param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
* \param[out] errorMsg error messages emitted, if any
* \param skipIntersectionCheck set to TRUE to skip the potentially expensive initial intersection check. Only set this flag if an intersection
* test has already been performed by the caller!
* \returns 0 in case of success, 1 if geometry has not been split, error else
*/
virtual QgsGeometryEngine::EngineOperationResult splitGeometry( const QgsLineString &splitLine,
QVector<QgsGeometry > &newGeometries SIP_OUT,
bool topological,
QgsPointSequence &topologyTestPoints, QString *errorMsg = nullptr ) const
QgsPointSequence &topologyTestPoints, QString *errorMsg = nullptr, bool skipIntersectionCheck = false ) const
{
Q_UNUSED( splitLine )
Q_UNUSED( newGeometries )
Q_UNUSED( topological )
Q_UNUSED( topologyTestPoints )
Q_UNUSED( errorMsg )
Q_UNUSED( skipIntersectionCheck )
return MethodNotImplemented;
}

Expand Down
14 changes: 7 additions & 7 deletions src/core/geometry/qgsgeos.cpp
Expand Up @@ -620,7 +620,7 @@ QgsGeometryEngine::EngineOperationResult QgsGeos::splitGeometry( const QgsLineSt
QVector<QgsGeometry> &newGeometries,
bool topological,
QgsPointSequence &topologyTestPoints,
QString *errorMsg ) const
QString *errorMsg, bool skipIntersectionCheck ) const
{

EngineOperationResult returnCode = Success;
Expand Down Expand Up @@ -678,11 +678,11 @@ QgsGeometryEngine::EngineOperationResult QgsGeos::splitGeometry( const QgsLineSt
//call split function depending on geometry type
if ( mGeometry->dimension() == 1 )
{
returnCode = splitLinearGeometry( splitLineGeos.get(), newGeometries );
returnCode = splitLinearGeometry( splitLineGeos.get(), newGeometries, skipIntersectionCheck );
}
else if ( mGeometry->dimension() == 2 )
{
returnCode = splitPolygonGeometry( splitLineGeos.get(), newGeometries );
returnCode = splitPolygonGeometry( splitLineGeos.get(), newGeometries, skipIntersectionCheck );
}
else
{
Expand Down Expand Up @@ -817,7 +817,7 @@ geos::unique_ptr QgsGeos::linePointDifference( GEOSGeometry *GEOSsplitPoint ) co
return asGeos( &lines, mPrecision );
}

QgsGeometryEngine::EngineOperationResult QgsGeos::splitLinearGeometry( GEOSGeometry *splitLine, QVector<QgsGeometry> &newGeometries ) const
QgsGeometryEngine::EngineOperationResult QgsGeos::splitLinearGeometry( GEOSGeometry *splitLine, QVector<QgsGeometry> &newGeometries, bool skipIntersectionCheck ) const
{
if ( !splitLine )
return InvalidInput;
Expand All @@ -826,7 +826,7 @@ QgsGeometryEngine::EngineOperationResult QgsGeos::splitLinearGeometry( GEOSGeome
return InvalidBaseGeometry;

//first test if linestring intersects geometry. If not, return straight away
if ( !GEOSIntersects_r( geosinit()->ctxt, splitLine, mGeos.get() ) )
if ( !skipIntersectionCheck && !GEOSIntersects_r( geosinit()->ctxt, splitLine, mGeos.get() ) )
return NothingHappened;

//check that split line has no linear intersection
Expand Down Expand Up @@ -872,7 +872,7 @@ QgsGeometryEngine::EngineOperationResult QgsGeos::splitLinearGeometry( GEOSGeome
return Success;
}

QgsGeometryEngine::EngineOperationResult QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QVector<QgsGeometry> &newGeometries ) const
QgsGeometryEngine::EngineOperationResult QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QVector<QgsGeometry> &newGeometries, bool skipIntersectionCheck ) const
{
if ( !splitLine )
return InvalidInput;
Expand All @@ -886,7 +886,7 @@ QgsGeometryEngine::EngineOperationResult QgsGeos::splitPolygonGeometry( GEOSGeom
return EngineError;

//first test if linestring intersects geometry. If not, return straight away
if ( !GEOSPreparedIntersects_r( geosinit()->ctxt, mGeosPrepared.get(), splitLine ) )
if ( !skipIntersectionCheck && !GEOSPreparedIntersects_r( geosinit()->ctxt, mGeosPrepared.get(), splitLine ) )
return NothingHappened;

//first union all the polygon rings together (to get them noded, see JTS developer guide)
Expand Down
6 changes: 3 additions & 3 deletions src/core/geometry/qgsgeos.h
Expand Up @@ -227,7 +227,7 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
QVector<QgsGeometry> &newGeometries,
bool topological,
QgsPointSequence &topologyTestPoints,
QString *errorMsg = nullptr ) const override;
QString *errorMsg = nullptr, bool skipIntersectionCheck = false ) const override;

QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = nullptr ) const override;

Expand Down Expand Up @@ -406,8 +406,8 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
//utils for geometry split
bool topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPointSequence &testPoints, QString *errorMsg = nullptr ) const;
geos::unique_ptr linePointDifference( GEOSGeometry *GEOSsplitPoint ) const;
EngineOperationResult splitLinearGeometry( GEOSGeometry *splitLine, QVector<QgsGeometry > &newGeometries ) const;
EngineOperationResult splitPolygonGeometry( GEOSGeometry *splitLine, QVector<QgsGeometry > &newGeometries ) const;
EngineOperationResult splitLinearGeometry( GEOSGeometry *splitLine, QVector<QgsGeometry > &newGeometries, bool skipIntersectionCheck ) const;
EngineOperationResult splitPolygonGeometry( GEOSGeometry *splitLine, QVector<QgsGeometry > &newGeometries, bool skipIntersectionCheck ) const;

//utils for reshape
static geos::unique_ptr reshapeLine( const GEOSGeometry *line, const GEOSGeometry *reshapeLineGeos, double precision );
Expand Down

0 comments on commit f8222f0

Please sign in to comment.