Navigation Menu

Skip to content

Commit

Permalink
[feature][processing] Add new "Select within distance" and
Browse files Browse the repository at this point in the history
"Extract within distance" algorithms

These algorithms allow users to select or extract features from one
layer which are within a certain distance of features from another
reference layer.

The distance checking is heavily optimised, using spatial indices
to restrict the number of features retrieved, and also automatically
handing the check off to the database server for postgis layers.

The distance parameter can also be data-defined.

Sponsored by QTIBIA Engineering
  • Loading branch information
nyalldawson committed Aug 6, 2021
1 parent 0eaf3e5 commit cf40573
Show file tree
Hide file tree
Showing 19 changed files with 841 additions and 0 deletions.
@@ -0,0 +1 @@
UTF-8
Binary file not shown.
@@ -0,0 +1 @@
PROJCS["WGS_1984_Web_Mercator_Auxiliary_Sphere",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Mercator_Auxiliary_Sphere"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",0.0],PARAMETER["Standard_Parallel_1",0.0],PARAMETER["Auxiliary_Sphere_Type",0.0],UNIT["Meter",1.0]]
@@ -0,0 +1,26 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="3.21.0-Master">
<identifier></identifier>
<parentidentifier></parentidentifier>
<language></language>
<type>dataset</type>
<title></title>
<abstract></abstract>
<links/>
<fees></fees>
<encoding></encoding>
<crs>
<spatialrefsys>
<wkt></wkt>
<proj4></proj4>
<srsid>0</srsid>
<srid>0</srid>
<authid></authid>
<description></description>
<projectionacronym></projectionacronym>
<ellipsoidacronym></ellipsoidacronym>
<geographicflag>false</geographicflag>
</spatialrefsys>
</crs>
<extent/>
</qgis>
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ lines_within_distance.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
<gml:coord><gml:X>10</gml:X><gml:Y>3</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:lines_within_distance fid="lines.1">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:lines_within_distance>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_within_distance fid="lines.2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 2,2 3,2 3,3</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:lines_within_distance>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_within_distance fid="lines.3">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:lines_within_distance>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_within_distance fid="lines.5">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,-3 10,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:lines_within_distance>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
<xs:complexType name="FeatureCollectionType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureCollectionType">
<xs:attribute name="lockId" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="lines_within_distance" type="ogr:lines_within_distance_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="lines_within_distance_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:LineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ lines_within_distance_transform.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-111319.490793272</gml:X><gml:Y>-318649.196224542</gml:Y></gml:coord>
<gml:coord><gml:X>1136357.53225559</gml:X><gml:Y>238136.038774373</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:lines_within_distance_transform fid="lines.1">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:3857"><gml:lineStringMember><gml:LineString><gml:coordinates>-111319.490793272,-111325.142866386 111319.490793272,-111325.142866386</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:lines_within_distance_transform>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_within_distance_transform fid="lines.2">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:3857"><gml:lineStringMember><gml:LineString><gml:coordinates>222638.981586547,-0.000000000708115 203336.794650833,238136.038774373 246182.324006617,233067.497373915 364841.971476963,202083.784506753</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:lines_within_distance_transform>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_within_distance_transform fid="lines.5">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:3857"><gml:lineStringMember><gml:LineString><gml:coordinates>648614.757823928,-318649.196224542 862884.352006337,-182767.696351667 1012154.59764253,36015.6211455719 1136357.53225559,94594.3964176019</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:lines_within_distance_transform>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
<xs:complexType name="FeatureCollectionType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureCollectionType">
<xs:attribute name="lockId" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="lines_within_distance_transform" type="ogr:lines_within_distance_transform_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="lines_within_distance_transform_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:MultiLineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ points_within_distance.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>0</gml:X><gml:Y>-1</gml:Y></gml:coord>
<gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:points_within_distance fid="points.8">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>9</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:points_within_distance>
</gml:featureMember>
<gml:featureMember>
<ogr:points_within_distance fid="points.1">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>2</ogr:id>
<ogr:id2>1</ogr:id2>
</ogr:points_within_distance>
</gml:featureMember>
<gml:featureMember>
<ogr:points_within_distance fid="points.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>3</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:points_within_distance>
</gml:featureMember>
<gml:featureMember>
<ogr:points_within_distance fid="points.4">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>4,1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>5</ogr:id>
<ogr:id2>1</ogr:id2>
</ogr:points_within_distance>
</gml:featureMember>
<gml:featureMember>
<ogr:points_within_distance fid="points.6">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>7</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:points_within_distance>
</gml:featureMember>
<gml:featureMember>
<ogr:points_within_distance fid="points.7">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>8</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:points_within_distance>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
<xs:complexType name="FeatureCollectionType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureCollectionType">
<xs:attribute name="lockId" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="points_within_distance" type="ogr:points_within_distance_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="points_within_distance_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
<xs:element name="id" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="id2" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ points_within_distance_transform.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>0</gml:X><gml:Y>-1</gml:Y></gml:coord>
<gml:coord><gml:X>8</gml:X><gml:Y>2</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:points_within_distance_transform fid="points.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>3</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:points_within_distance_transform>
</gml:featureMember>
<gml:featureMember>
<ogr:points_within_distance_transform fid="points.6">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>7</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:points_within_distance_transform>
</gml:featureMember>
<gml:featureMember>
<ogr:points_within_distance_transform fid="points.8">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>9</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:points_within_distance_transform>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
<xs:complexType name="FeatureCollectionType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureCollectionType">
<xs:attribute name="lockId" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="points_within_distance_transform" type="ogr:points_within_distance_transform_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="points_within_distance_transform_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
<xs:element name="id" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="id2" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
Expand Up @@ -2725,5 +2725,64 @@ tests:
name: expected/retain_fields_three.gml
type: vector

- algorithm: native:extractwithindistance
name: Points within distance
params:
DISTANCE: 0.8
INPUT:
name: points.gml|layername=points
type: vector
REFERENCE:
name: lines.gml|layername=lines
type: vector
results:
OUTPUT:
name: expected/points_within_distance.gml
type: vector

- algorithm: native:extractwithindistance
name: Lines within distance
params:
DISTANCE: 0.8
INPUT:
name: lines.gml|layername=lines
type: vector
REFERENCE:
name: points.gml|layername=points
type: vector
results:
OUTPUT:
name: expected/lines_within_distance.gml
type: vector

- algorithm: native:extractwithindistance
name: Points within distance reprojected
params:
DISTANCE: 0.7
INPUT:
name: points.gml|layername=points
type: vector
REFERENCE:
name: custom/snap_lines_3857.shp
type: vector
results:
OUTPUT:
name: expected/points_within_distance_transform.gml
type: vector

- algorithm: native:extractwithindistance
name: Lines within distance reprojected
params:
DISTANCE: 50000.0
INPUT:
name: custom/snap_lines_3857.shp
type: vector
REFERENCE:
name: points.gml|layername=points
type: vector
results:
OUTPUT:
name: expected/lines_within_distance_transform.gml
type: vector

# See ../README.md for a description of the file format
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Expand Up @@ -66,6 +66,7 @@ set(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmdetectdatasetchanges.cpp
processing/qgsalgorithmdifference.cpp
processing/qgsalgorithmdissolve.cpp
processing/qgsalgorithmdistancewithin.cpp
processing/qgsalgorithmdrape.cpp
processing/qgsalgorithmdropfields.cpp
processing/qgsalgorithmdropgeometry.cpp
Expand Down

0 comments on commit cf40573

Please sign in to comment.