Skip to content

Commit

Permalink
Merge pull request #44766 from nirvn/snapper_more_speed
Browse files Browse the repository at this point in the history
More optimization to the geometry snapper
  • Loading branch information
nirvn committed Aug 31, 2021
2 parents e445fd4 + 75c8eb7 commit ae7db99
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 191 deletions.
@@ -0,0 +1,16 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>lines_t_shape_snapped</Name>
<ElementPath>lines_t_shape_snapped</ElementPath>
<!--MULTILINESTRING-->
<GeometryType>5</GeometryType>
<SRSName>urn:ogc:def:crs:EPSG::4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>3</FeatureCount>
<ExtentXMin>0.75573</ExtentXMin>
<ExtentXMax>8.21641</ExtentXMax>
<ExtentYMin>-2.23951</ExtentYMin>
<ExtentYMax>5.12878</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy><gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"><gml:lowerCorner>-2.23950504124656 0.755728689275893</gml:lowerCorner><gml:upperCorner>5.12878093492209 8.21640696608616</gml:upperCorner></gml:Envelope></gml:boundedBy>

<ogr:featureMember>
<ogr:lines_t_shape_snapped gml:id="lines_t_shape.0">
<gml:boundedBy><gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"><gml:lowerCorner>-2.23950504124656 0.755728689275893</gml:lowerCorner><gml:upperCorner>5.12878093492209 7.0730522456462</gml:upperCorner></gml:Envelope></gml:boundedBy>
<ogr:geometryProperty><gml:MultiCurve srsName="urn:ogc:def:crs:EPSG::4326"><gml:curveMember><gml:LineString><gml:posList>-2.23950504124656 0.755728689275893 1.43703755953514 3.90787414793983 5.12878093492209 7.0730522456462</gml:posList></gml:LineString></gml:curveMember></gml:MultiCurve></ogr:geometryProperty>
</ogr:lines_t_shape_snapped>
</ogr:featureMember>
<ogr:featureMember>
<ogr:lines_t_shape_snapped gml:id="lines_t_shape.1">
<gml:boundedBy><gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"><gml:lowerCorner>-1.90458295142072 3.90787414793983</gml:lowerCorner><gml:upperCorner>5.12878093492209 8.21640696608616</gml:upperCorner></gml:Envelope></gml:boundedBy>
<ogr:geometryProperty><gml:MultiCurve srsName="urn:ogc:def:crs:EPSG::4326"><gml:curveMember><gml:LineString><gml:posList>5.12878093492209 7.0730522456462 1.43703755953514 3.90787414793983 -1.90458295142072 8.21640696608616</gml:posList></gml:LineString></gml:curveMember></gml:MultiCurve></ogr:geometryProperty>
</ogr:lines_t_shape_snapped>
</ogr:featureMember>
<ogr:featureMember>
<ogr:lines_t_shape_snapped gml:id="lines_t_shape.2">
<gml:boundedBy><gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"><gml:lowerCorner>-2.23950504124656 0.755728689275893</gml:lowerCorner><gml:upperCorner>1.43703755953514 8.21640696608616</gml:upperCorner></gml:Envelope></gml:boundedBy>
<ogr:geometryProperty><gml:MultiCurve srsName="urn:ogc:def:crs:EPSG::4326"><gml:curveMember><gml:LineString><gml:posList>-2.23950504124656 0.755728689275893 1.43703755953514 3.90787414793983 -1.90458295142072 8.21640696608616</gml:posList></gml:LineString></gml:curveMember></gml:MultiCurve></ogr:geometryProperty>
</ogr:lines_t_shape_snapped>
</ogr:featureMember>
</ogr:FeatureCollection>
16 changes: 16 additions & 0 deletions python/plugins/processing/tests/testdata/lines_t_shape.gfs
@@ -0,0 +1,16 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>lines_t_shape</Name>
<ElementPath>lines_t_shape</ElementPath>
<!--MULTILINESTRING-->
<GeometryType>5</GeometryType>
<SRSName>urn:ogc:def:crs:EPSG::4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>3</FeatureCount>
<ExtentXMin>0.75573</ExtentXMin>
<ExtentXMax>8.21641</ExtentXMax>
<ExtentYMin>-2.33190</ExtentYMin>
<ExtentYMax>5.12878</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>
25 changes: 25 additions & 0 deletions python/plugins/processing/tests/testdata/lines_t_shape.gml
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy><gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"><gml:lowerCorner>-2.33189734188818 0.755728689275893</gml:lowerCorner><gml:upperCorner>5.12878093492209 8.21640696608616</gml:upperCorner></gml:Envelope></gml:boundedBy>

<ogr:featureMember>
<ogr:lines_t_shape gml:id="lines_t_shape.0">
<gml:boundedBy><gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"><gml:lowerCorner>-2.23950504124656 0.755728689275893</gml:lowerCorner><gml:upperCorner>5.12878093492209 7.0730522456462</gml:upperCorner></gml:Envelope></gml:boundedBy>
<ogr:geometryProperty><gml:MultiCurve srsName="urn:ogc:def:crs:EPSG::4326"><gml:curveMember><gml:LineString><gml:posList>-2.23950504124656 0.755728689275893 5.12878093492209 7.0730522456462</gml:posList></gml:LineString></gml:curveMember></gml:MultiCurve></ogr:geometryProperty>
</ogr:lines_t_shape>
</ogr:featureMember>
<ogr:featureMember>
<ogr:lines_t_shape gml:id="lines_t_shape.1">
<gml:boundedBy><gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"><gml:lowerCorner>-1.90458295142072 3.96636113657195</gml:lowerCorner><gml:upperCorner>5.08258478460128 8.21640696608616</gml:upperCorner></gml:Envelope></gml:boundedBy>
<ogr:geometryProperty><gml:MultiCurve srsName="urn:ogc:def:crs:EPSG::4326"><gml:curveMember><gml:LineString><gml:posList>5.08258478460128 7.15389550870761 1.38689275893675 3.96636113657195 -1.90458295142072 8.21640696608616</gml:posList></gml:LineString></gml:curveMember></gml:MultiCurve></ogr:geometryProperty>
</ogr:lines_t_shape>
</ogr:featureMember>
<ogr:featureMember>
<ogr:lines_t_shape gml:id="lines_t_shape.2">
<gml:boundedBy><gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"><gml:lowerCorner>-2.33189734188818 0.882768102658111</gml:lowerCorner><gml:upperCorner>1.30604949587534 8.13556370302475</gml:upperCorner></gml:Envelope></gml:boundedBy>
<ogr:geometryProperty><gml:MultiCurve srsName="urn:ogc:def:crs:EPSG::4326"><gml:curveMember><gml:LineString><gml:posList>-2.33189734188818 0.882768102658111 1.30604949587534 3.94326306141155 -1.93923006416132 8.13556370302475</gml:posList></gml:LineString></gml:curveMember></gml:MultiCurve></ogr:geometryProperty>
</ogr:lines_t_shape>
</ogr:featureMember>
</ogr:FeatureCollection>
Expand Up @@ -630,6 +630,22 @@ tests:
name: expected/snap_geometries.gml
type: vector

- algorithm: native:snapgeometries
name: Snap lines to lines (against itself; ordering check)
params:
BEHAVIOR: '0'
INPUT:
name: lines_t_shape.gml
type: vector
REFERENCE_LAYER:
name: lines_t_shape.gml
type: vector
TOLERANCE: 0.3
results:
OUTPUT:
name: expected/lines_t_shape_snapped.gml
type: vector

- algorithm: native:poleofinaccessibility
name: Pole of inaccessibility (polygons)
params:
Expand Down
48 changes: 38 additions & 10 deletions src/analysis/processing/qgsalgorithmsnapgeometries.cpp
Expand Up @@ -125,11 +125,11 @@ QVariantMap QgsSnapGeometriesAlgorithm::processAlgorithm( const QVariantMap &par
if ( !sink )
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

const double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 1;
QgsFeatureIterator features = source->getFeatures();

if ( parameters.value( QStringLiteral( "INPUT" ) ) != parameters.value( QStringLiteral( "REFERENCE_LAYER" ) ) )
{
const double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 1;
if ( mode == 7 )
throw QgsProcessingException( QObject::tr( "This mode applies when the input and reference layer are the same." ) );

Expand Down Expand Up @@ -166,28 +166,56 @@ QVariantMap QgsSnapGeometriesAlgorithm::processAlgorithm( const QVariantMap &par
else
{
// snapping internally
QgsInternalGeometrySnapper snapper( tolerance, mode );
const double step = source->featureCount() > 0 ? 100.0 / ( source->featureCount() * 2 ) : 1;
long long processed = 0;

QgsInternalGeometrySnapper snapper( tolerance, mode );
QgsFeature f;
QList<QgsFeatureId> editedFeatureIds;
QMap<QgsFeatureId, QgsFeature> editedFeatures;
while ( features.nextFeature( f ) )
{
if ( feedback->isCanceled() )
break;

QgsFeature editedFeature( f );
if ( f.hasGeometry() )
{
QgsFeature outFeature( f );
outFeature.setGeometry( snapper.snapFeature( f ) );
if ( !sink->addFeature( outFeature, QgsFeatureSink::FastInsert ) )
throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
editedFeature.setGeometry( snapper.snapFeature( f ) );
}
else
editedFeatureIds << editedFeature.id();
editedFeatures.insert( editedFeature.id(), editedFeature );
processed += 1;
}

// reversed order snapping round is required to insure geometries are snapped against all features
snapper = QgsInternalGeometrySnapper( tolerance, mode );
std::reverse( editedFeatureIds.begin(), editedFeatureIds.end() );
for ( const QgsFeatureId &fid : editedFeatureIds )
{
if ( feedback->isCanceled() )
break;

QgsFeature editedFeature( editedFeatures.value( fid ) );
if ( editedFeature.hasGeometry() )
{
if ( !sink->addFeature( f ) )
editedFeature.setGeometry( snapper.snapFeature( editedFeature ) );
editedFeatures.insert( editedFeature.id(), editedFeature );
}
}
std::reverse( editedFeatureIds.begin(), editedFeatureIds.end() );
processed += 1;

if ( !feedback->isCanceled() )
{
for ( const QgsFeatureId &fid : editedFeatureIds )
{
QgsFeature outFeature( editedFeatures.value( fid ) );
if ( !sink->addFeature( outFeature ) )
throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );

feedback->setProgress( processed * step );
}
processed += 1;
feedback->setProgress( processed * step );
}
}

Expand Down

0 comments on commit ae7db99

Please sign in to comment.