Skip to content

Commit

Permalink
[processing] Shortest path handling for multipoint layers
Browse files Browse the repository at this point in the history
Fixes shortest path algorithms fail for multipoint source layers
or layers with null geometries

Refs #17325
  • Loading branch information
nyalldawson committed Oct 31, 2017
1 parent 4149da0 commit 5ffd721
Show file tree
Hide file tree
Showing 17 changed files with 242 additions and 11 deletions.
14 changes: 9 additions & 5 deletions python/plugins/processing/algs/qgis/ShortestPathLayerToPoint.py
Expand Up @@ -37,9 +37,8 @@
QgsFeatureRequest,
QgsFeatureSink,
QgsGeometry,
QgsFields,
QgsField,
QgsMessageLog,
QgsPointXY,
QgsProcessing,
QgsProcessingParameterEnum,
QgsProcessingParameterPoint,
Expand Down Expand Up @@ -224,11 +223,16 @@ def processAlgorithm(self, parameters, context, feedback):
if feedback.isCanceled():
break

points.append(f.geometry().asPoint())
source_attributes[i] = f.attributes()
if not f.hasGeometry():
continue

for p in f.geometry().vertices():
points.append(QgsPointXY(p))
source_attributes[i] = f.attributes()
i += 1

feedback.setProgress(int(current * total))
i += 1


feedback.pushInfo(self.tr('Building graph...'))
snappedPoints = director.makeGraph(builder, points, feedback)
Expand Down
16 changes: 10 additions & 6 deletions python/plugins/processing/algs/qgis/ShortestPathPointToLayer.py
Expand Up @@ -31,15 +31,15 @@
from qgis.PyQt.QtCore import QVariant
from qgis.PyQt.QtGui import QIcon

from qgis.core import (QgsWkbTypes,
from qgis.core import (NULL,
QgsWkbTypes,
QgsUnitTypes,
QgsFeature,
QgsFeatureSink,
QgsGeometry,
QgsFeatureRequest,
QgsFields,
QgsField,
QgsMessageLog,
QgsPointXY,
QgsProcessing,
QgsProcessingParameterEnum,
QgsProcessingParameterPoint,
Expand Down Expand Up @@ -224,11 +224,15 @@ def processAlgorithm(self, parameters, context, feedback):
if feedback.isCanceled():
break

points.append(f.geometry().asPoint())
source_attributes[i] = f.attributes()
if not f.hasGeometry():
continue

for p in f.geometry().vertices():
points.append(QgsPointXY(p))
source_attributes[i] = f.attributes()
i += 1

feedback.setProgress(int(current * total))
i += 1

feedback.pushInfo(self.tr('Building graph...'))
snappedPoints = director.makeGraph(builder, points, feedback)
Expand Down
37 changes: 37 additions & 0 deletions python/plugins/processing/tests/testdata/custom/route_points.gml
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ route_points.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>20.4273694007118</gml:X><gml:Y>-34.03714867571521</gml:Y></gml:coord>
<gml:coord><gml:X>20.45438438930011</gml:X><gml:Y>-34.01428003760926</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:route_points fid="route_points.0">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>20.4273694007118,-34.0371486757152</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:d>1</ogr:d>
</ogr:route_points>
</gml:featureMember>
<gml:featureMember>
<ogr:route_points fid="route_points.1">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>20.4366264365433,-34.0289935170312</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:d>2</ogr:d>
</ogr:route_points>
</gml:featureMember>
<gml:featureMember>
<ogr:route_points fid="route_points.2">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>20.4440686605369,-34.0142800376093</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>20.4543843893001,-34.0209124105391</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:d>3</ogr:d>
</ogr:route_points>
</gml:featureMember>
<gml:featureMember>
<ogr:route_points fid="route_points.3">
<ogr:d>4</ogr:d>
</ogr:route_points>
</gml:featureMember>
</ogr:FeatureCollection>
30 changes: 30 additions & 0 deletions python/plugins/processing/tests/testdata/custom/route_points.xsd
@@ -0,0 +1,30 @@
<?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="route_points" type="ogr:route_points_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="route_points_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:MultiPointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
<xs:element name="d" 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>
Binary file not shown.
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ shortest_path_layer_to_point.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>1001186.34740161</gml:X><gml:Y>6220412.593725896</gml:Y></gml:coord>
<gml:coord><gml:X>1004138.7211059</gml:X><gml:Y>6223142.049559583</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:shortest_path_layer_to_point fid="route_points.0">
<ogr:geometryProperty><gml:LineString srsName="EPSG:32733"><gml:coordinates>1001269.29926109,6220412.5937259 1001186.34740161,6220459.66433954 1001230.60014311,6220497.58606688 1001417.00785562,6220703.65963346 1001474.56242038,6220771.95914347 1001535.25328051,6220851.26299517 1001730.88604383,6221182.3451556 1001806.08518826,6221307.13224234 1001821.61736105,6221332.90322892 1001835.96992268,6221356.72100035 1001891.40736133,6221430.94581986 1001930.78353526,6221467.36521594 1001968.37489204,6221502.13083684 1002137.81278244,6221630.62018051 1002215.13556068,6221689.25446887 1002288.4678461,6221744.85964495 1002334.20638747,6221779.49098284 1002425.63766482,6221848.74446543 1002462.62346654,6221875.38780442 1002518.06990805,6221915.34875741 1002626.85249869,6221993.7562202 1002657.33259138,6222018.20620536 1002781.74783802,6222107.45193255 1002852.18578258,6222162.74032983 1002903.48249244,6222204.64725757 1002916.58033846,6222216.16749784 1002945.17950103,6222241.31856099 1002991.11072264,6222281.72914386 1003040.80096358,6222322.18412711 1003081.26058941,6222355.11171034 1003105.74257399,6222376.7841218 1003153.88971381,6222419.41498029 1003172.94058079,6222436.28679202 1003198.63616199,6222463.1404267 1003261.7338751,6222520.86764589 1003285.57002497,6222541.37125149 1003318.51056419,6222558.84948158 1003416.77290022,6222570.20188393 1003430.63468333,6222565.77529146 1003461.44609399,6222555.86616133 1003536.86501513,6222502.0742548 1003555.31281829,6222483.13439712 1003602.8338769,6222436.67874613 1003647.3751082,6222401.82100567 1003696.4437017,6222455.04866221 1003745.10253898,6222507.54062578 1003852.72754463,6222623.65770678 1004026.21371718,6222810.84939244 1004138.7211059,6222934.89025765 1004027.57619058,6223045.89797913 1004078.05459543,6223104.58501454 1004113.27822798,6223142.04955958</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:d>1</ogr:d>
<ogr:start>1001269.16642, 6220412.35961</ogr:start>
<ogr:end>1004113.23166, 6223142.09335</ogr:end>
<ogr:cost>4509.5154628</ogr:cost>
</ogr:shortest_path_layer_to_point>
</gml:featureMember>
<gml:featureMember>
<ogr:shortest_path_layer_to_point fid="route_points.1">
<ogr:geometryProperty><gml:LineString srsName="EPSG:32733"><gml:coordinates>1002169.82194678,6221268.41390691 1002103.66905047,6221324.68154126 1002275.1898604,6221455.19588041 1002226.82368085,6221517.62843522 1002302.22841804,6221576.64258306 1002310.58466849,6221563.42200322 1002421.46534272,6221674.17571725 1002532.83636772,6221785.38136521 1002462.62346654,6221875.38780442 1002518.06990805,6221915.34875741 1002626.85249869,6221993.7562202 1002657.33259138,6222018.20620536 1002781.74783802,6222107.45193255 1002852.18578258,6222162.74032983 1002903.48249244,6222204.64725757 1002916.58033846,6222216.16749784 1002945.17950103,6222241.31856099 1002991.11072264,6222281.72914386 1003040.80096358,6222322.18412711 1003081.26058941,6222355.11171034 1003105.74257399,6222376.7841218 1003153.88971381,6222419.41498029 1003172.94058079,6222436.28679202 1003198.63616199,6222463.1404267 1003261.7338751,6222520.86764589 1003285.57002497,6222541.37125149 1003318.51056419,6222558.84948158 1003416.77290022,6222570.20188393 1003430.63468333,6222565.77529146 1003461.44609399,6222555.86616133 1003536.86501513,6222502.0742548 1003555.31281829,6222483.13439712 1003602.8338769,6222436.67874613 1003647.3751082,6222401.82100567 1003696.4437017,6222455.04866221 1003745.10253898,6222507.54062578 1003852.72754463,6222623.65770678 1004026.21371718,6222810.84939244 1004138.7211059,6222934.89025765 1004027.57619058,6223045.89797913 1004078.05459543,6223104.58501454 1004113.27822798,6223142.04955958</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:d>2</ogr:d>
<ogr:start>1002173.3505, 6221272.56237</ogr:start>
<ogr:end>1004113.23166, 6223142.09335</ogr:end>
<ogr:cost>3407.7806316</ogr:cost>
</ogr:shortest_path_layer_to_point>
</gml:featureMember>
<gml:featureMember>
<ogr:shortest_path_layer_to_point fid="route_points.2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:32733"><gml:coordinates>1002947.79277674,6222869.79641753 1003002.42639578,6222681.59030886 1002950.16219022,6222560.53103646 1002981.05280059,6222513.31733464 1002988.8334088,6222500.42759959 1003006.76410522,6222480.99306342 1003027.13399838,6222458.25399505 1003105.74257399,6222376.7841218 1003153.88971381,6222419.41498029 1003172.94058079,6222436.28679202 1003198.63616199,6222463.1404267 1003261.7338751,6222520.86764589 1003285.57002497,6222541.37125149 1003318.51056419,6222558.84948158 1003416.77290022,6222570.20188393 1003430.63468333,6222565.77529146 1003461.44609399,6222555.86616133 1003536.86501513,6222502.0742548 1003555.31281829,6222483.13439712 1003602.8338769,6222436.67874613 1003647.3751082,6222401.82100567 1003696.4437017,6222455.04866221 1003745.10253898,6222507.54062578 1003852.72754463,6222623.65770678 1004026.21371718,6222810.84939244 1004138.7211059,6222934.89025765 1004027.57619058,6223045.89797913 1004078.05459543,6223104.58501454 1004113.27822798,6223142.04955958</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:d>3</ogr:d>
<ogr:start>1002948.69578, 6222870.05855</ogr:start>
<ogr:end>1004113.23166, 6223142.09335</ogr:end>
<ogr:cost>2243.3726118</ogr:cost>
</ogr:shortest_path_layer_to_point>
</gml:featureMember>
<gml:featureMember>
<ogr:shortest_path_layer_to_point fid="route_points.2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:32733"><gml:coordinates>1003866.67429938,6222081.06454087 1003835.88711567,6222011.8549713 1003839.54015074,6221908.19492644 1003775.57324976,6221922.76175725 1003645.34240628,6221954.38918302 1003525.93018347,6222064.10735181 1003596.67006395,6222145.79506248 1003745.40906699,6222317.55884368 1003692.73332615,6222357.0841711 1003647.3751082,6222401.82100567 1003696.4437017,6222455.04866221 1003745.10253898,6222507.54062578 1003852.72754463,6222623.65770678 1004026.21371718,6222810.84939244 1004138.7211059,6222934.89025765 1004027.57619058,6223045.89797913 1004078.05459543,6223104.58501454 1004113.27822798,6223142.04955958</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:d>3</ogr:d>
<ogr:start>1003863.44041, 6222082.50311</ogr:start>
<ogr:end>1004113.23166, 6223142.09335</ogr:end>
<ogr:cost>2011.5004590</ogr:cost>
</ogr:shortest_path_layer_to_point>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1 @@
PROJCS["WGS_1984_UTM_Zone_33S",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",15],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",10000000],UNIT["Meter",1]]
@@ -0,0 +1 @@
PROJCS["WGS 84 / UTM zone 33S",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",15],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",10000000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","32733"]]
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,52 @@
<?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="shortest_path_layer_to_point" type="ogr:shortest_path_layer_to_point_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="shortest_path_layer_to_point_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:LineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
<xs:element name="d" 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="start" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="254"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="end" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="254"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="cost" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:totalDigits value="21"/>
<xs:fractionDigits value="7"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
Binary file not shown.
@@ -0,0 +1 @@
PROJCS["WGS_1984_UTM_Zone_33S",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",15],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",10000000],UNIT["Meter",1]]
@@ -0,0 +1 @@
PROJCS["WGS 84 / UTM zone 33S",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",15],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",10000000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","32733"]]
Binary file not shown.
Binary file not shown.
50 changes: 50 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Expand Up @@ -2662,6 +2662,56 @@ tests:
geometry:
precision: 5

- algorithm: qgis:shortestpathlayertopoint
name: Shortest path layer to point
params:
DEFAULT_DIRECTION: 2
DEFAULT_SPEED: 5.0
END_POINT: 1004160.8843928401,6223198.426763908 [EPSG:32733]
INPUT:
name: roads.gml
type: vector
START_POINTS:
name: custom/route_points.gml
type: vector
STRATEGY: 0
TOLERANCE: 0.0
VALUE_BACKWARD: ''
VALUE_BOTH: ''
VALUE_FORWARD: ''
results:
OUTPUT:
name: expected/shortest_path_layer_to_point.shp
type: vector
compare:
geometry:
precision: 5

- algorithm: qgis:shortestpathpointtolayer
name: Shortest path point to layer
params:
DEFAULT_DIRECTION: 2
DEFAULT_SPEED: 5.0
END_POINTS:
name: custom/route_points.gml
type: vector
INPUT:
name: roads.gml
type: vector
START_POINT: 1001285.5030045575,6219636.580449594 [EPSG:32733]
STRATEGY: 0
TOLERANCE: 0.0
VALUE_BACKWARD: ''
VALUE_BOTH: ''
VALUE_FORWARD: ''
results:
OUTPUT:
name: expected/shortest_path_point_to_layer.shp
type: vector
compare:
geometry:
precision: 5

- algorithm: qgis:serviceareafrompoint
name: Service area (from point, shortest)
params:
Expand Down

0 comments on commit 5ffd721

Please sign in to comment.