Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix matrix & add optional matrix geometries and time options #21

Merged
merged 1 commit into from Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 16 additions & 5 deletions valhalla/common/matrix_core.py
Expand Up @@ -29,7 +29,11 @@

from qgis.core import (QgsFeature,
QgsFields,
QgsField)
QgsField,
QgsPointXY,
QgsGeometry)

from valhalla.utils import convert, logger


def get_fields(from_type=QVariant.String, to_type=QVariant.String, from_name="FROM_ID", to_name="TO_ID"):
Expand Down Expand Up @@ -63,7 +67,7 @@ def get_fields(from_type=QVariant.String, to_type=QVariant.String, from_name="FR
return fields


def get_output_features_matrix(response, profile, options={}, source_attrs=[], destination_attrs=[]):
def get_output_features_matrix(response, profile, options={}, matrix_geometries=False, source_attrs=[], destination_attrs=[]):
"""
Build output feature based on response attributes for directions endpoint.

Expand All @@ -76,19 +80,22 @@ def get_output_features_matrix(response, profile, options={}, source_attrs=[], d
:param options: Costing options being used.
:type options: dict

:param matrix_geometries: Whether we want geometries for each connection.
:type matrix_geometries: bool

:param source_attrs: Attribute values of the source features.
:type source_attrs: list of any

:param destination_attrs: Attribute values of the destination features.
:type destination_attrs: list of any

:returns: Ouput features with attributes and geometry set.
:returns: Output features with attributes and geometry set.
:rtype: list of QgsFeature
"""

feats = []
sources = response['sources'][0]
targets = response['targets'][0]
sources = response['sources']
targets = response['targets']
for o, origin in enumerate(response['sources_to_targets']):
try:
from_id = source_attrs[o]
Expand Down Expand Up @@ -117,6 +124,10 @@ def get_output_features_matrix(response, profile, options={}, source_attrs=[], d
json.dumps(options),
]
)
if matrix_geometries and destination.get("shape"):
shape = destination.get("shape", "")
qgis_coords = [QgsPointXY(x, y) for y, x in convert.decode_polyline6(shape)]
feat.setGeometry(QgsGeometry.fromPolylineXY(qgis_coords))
feats.append(feat)

return feats
10 changes: 8 additions & 2 deletions valhalla/gui/ValhallaDialog.py
Expand Up @@ -364,22 +364,28 @@ def run_gui_control(self):
self.project.addMapLayer(point_layer)

elif method == 'sources_to_targets':
layer_out = QgsVectorLayer("None", 'Matrix_Valhalla', "memory")
matrix_geometries = self.dlg.matrix_geometries.isChecked()
layer_out = QgsVectorLayer("LineString?crs=EPSG:4326" if matrix_geometries else "None", f'Matrix {profile.capitalize()}', "memory")
layer_out.dataProvider().addAttributes(matrix_core.get_fields())
layer_out.updateFields()

matrix = matrix_gui.Matrix(self.dlg)
params = matrix.get_parameters()
params.update(extra_params)
params.update(time_params)
if matrix_geometries:
params["shape_format"] = "polyline6"
response = clnt.request('/sources_to_targets', post_json=params)
feats = matrix_core.get_output_features_matrix(
response,
profile,
matrix.costing_options
matrix.costing_options,
matrix_geometries
)
for feat in feats:
layer_out.dataProvider().addFeature(feat)

layer_out.updateExtents()
self.project.addMapLayer(layer_out)

elif method == 'locate':
Expand Down
2 changes: 1 addition & 1 deletion valhalla/gui/ValhallaDialogConfigUI_ui.py
Expand Up @@ -2,7 +2,7 @@

# Form implementation generated from reading ui file 'valhalla/gui/ValhallaDialogConfigUI.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
# Created by: PyQt5 UI code generator 5.15.10
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
Expand Down
38 changes: 35 additions & 3 deletions valhalla/gui/ValhallaDialogUI.ui
Expand Up @@ -548,7 +548,7 @@
<string>Method configuration</string>
</property>
<property name="collapsed">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="saveCollapsedState">
<bool>false</bool>
Expand Down Expand Up @@ -762,6 +762,35 @@
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="matrix_group">
<property name="title">
<string>Matrix</string>
</property>
<property name="collapsed">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_51">
<property name="text">
<string>Geometries</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="matrix_geometries">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="mGroupBox_12">
<property name="toolTip">
Expand Down Expand Up @@ -829,6 +858,9 @@
<property name="title">
<string>Locate</string>
</property>
<property name="collapsed">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="2" column="0">
<widget class="QLabel" name="label_43">
Expand Down Expand Up @@ -1838,7 +1870,7 @@
<property name="maximumSize">
<size>
<width>16777215</width>
<height>27</height>
<height>24</height>
</size>
</property>
<property name="toolTip">
Expand Down Expand Up @@ -1943,7 +1975,7 @@
<property name="maximumSize">
<size>
<width>16777215</width>
<height>27</height>
<height>24</height>
</size>
</property>
<property name="title">
Expand Down
25 changes: 21 additions & 4 deletions valhalla/gui/ValhallaDialogUI_ui.py
Expand Up @@ -2,7 +2,7 @@

# Form implementation generated from reading ui file 'valhalla/gui/ValhallaDialogUI.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
# Created by: PyQt5 UI code generator 5.15.10
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
Expand Down Expand Up @@ -267,7 +267,7 @@ def setupUi(self, ValhallaDialogBase):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.mGroupBox_11.sizePolicy().hasHeightForWidth())
self.mGroupBox_11.setSizePolicy(sizePolicy)
self.mGroupBox_11.setCollapsed(True)
self.mGroupBox_11.setCollapsed(False)
self.mGroupBox_11.setSaveCollapsedState(False)
self.mGroupBox_11.setObjectName("mGroupBox_11")
self.verticalLayout_9 = QtWidgets.QVBoxLayout(self.mGroupBox_11)
Expand Down Expand Up @@ -332,6 +332,20 @@ def setupUi(self, ValhallaDialogBase):
self.contours_distance.setObjectName("contours_distance")
self.gridLayout_16.addWidget(self.contours_distance, 3, 1, 1, 5)
self.verticalLayout_9.addWidget(self.isochrone_group)
self.matrix_group = gui.QgsCollapsibleGroupBox(self.mGroupBox_11)
self.matrix_group.setCollapsed(True)
self.matrix_group.setObjectName("matrix_group")
self.formLayout_3 = QtWidgets.QFormLayout(self.matrix_group)
self.formLayout_3.setObjectName("formLayout_3")
self.label_51 = QtWidgets.QLabel(self.matrix_group)
self.label_51.setObjectName("label_51")
self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_51)
self.matrix_geometries = QtWidgets.QCheckBox(self.matrix_group)
self.matrix_geometries.setText("")
self.matrix_geometries.setChecked(True)
self.matrix_geometries.setObjectName("matrix_geometries")
self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.matrix_geometries)
self.verticalLayout_9.addWidget(self.matrix_group)
self.mGroupBox_12 = gui.QgsCollapsibleGroupBox(self.mGroupBox_11)
self.mGroupBox_12.setCollapsed(True)
self.mGroupBox_12.setObjectName("mGroupBox_12")
Expand All @@ -351,6 +365,7 @@ def setupUi(self, ValhallaDialogBase):
self.verticalLayout.addWidget(self.widget_3)
self.verticalLayout_9.addWidget(self.mGroupBox_12)
self.mGroupBox_13 = gui.QgsCollapsibleGroupBox(self.mGroupBox_11)
self.mGroupBox_13.setCollapsed(True)
self.mGroupBox_13.setObjectName("mGroupBox_13")
self.formLayout = QtWidgets.QFormLayout(self.mGroupBox_13)
self.formLayout.setObjectName("formLayout")
Expand Down Expand Up @@ -838,7 +853,7 @@ def setupUi(self, ValhallaDialogBase):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.avoidlocation_group.sizePolicy().hasHeightForWidth())
self.avoidlocation_group.setSizePolicy(sizePolicy)
self.avoidlocation_group.setMaximumSize(QtCore.QSize(16777215, 27))
self.avoidlocation_group.setMaximumSize(QtCore.QSize(16777215, 24))
self.avoidlocation_group.setCheckable(True)
self.avoidlocation_group.setChecked(False)
self.avoidlocation_group.setCollapsed(True)
Expand Down Expand Up @@ -877,7 +892,7 @@ def setupUi(self, ValhallaDialogBase):
sizePolicy.setHeightForWidth(self.valhalla_log_group.sizePolicy().hasHeightForWidth())
self.valhalla_log_group.setSizePolicy(sizePolicy)
self.valhalla_log_group.setMinimumSize(QtCore.QSize(0, 0))
self.valhalla_log_group.setMaximumSize(QtCore.QSize(16777215, 27))
self.valhalla_log_group.setMaximumSize(QtCore.QSize(16777215, 24))
self.valhalla_log_group.setFlat(True)
self.valhalla_log_group.setCollapsed(True)
self.valhalla_log_group.setSaveCollapsedState(False)
Expand Down Expand Up @@ -1017,6 +1032,8 @@ def retranslateUi(self, ValhallaDialogBase):
self.contours_distance.setStatusTip(_translate("ValhallaDialogBase", "Comma separated list of decimal distances in kilometers for the contours."))
self.contours_distance.setWhatsThis(_translate("ValhallaDialogBase", "Comma separated list of decimal distances in kilometers for the contours."))
self.contours_distance.setPlaceholderText(_translate("ValhallaDialogBase", "Experimental"))
self.matrix_group.setTitle(_translate("ValhallaDialogBase", "Matrix"))
self.label_51.setText(_translate("ValhallaDialogBase", "Geometries"))
self.mGroupBox_12.setToolTip(_translate("ValhallaDialogBase", "Extract OSM roads and their attributes from a locally available OSM PBF file. Needs osmium!!"))
self.mGroupBox_12.setStatusTip(_translate("ValhallaDialogBase", "Extract OSM roads and their attributes from a locally available OSM PBF file. Needs osmium!!"))
self.mGroupBox_12.setWhatsThis(_translate("ValhallaDialogBase", "Extract OSM roads and their attributes from a locally available OSM PBF file. Needs osmium!!"))
Expand Down
2 changes: 1 addition & 1 deletion valhalla/gui/ValhallaExtraParamsDialogUI_ui.py
Expand Up @@ -2,7 +2,7 @@

# Form implementation generated from reading ui file 'valhalla/gui/ValhallaExtraParamsDialogUI.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
# Created by: PyQt5 UI code generator 5.15.10
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
Expand Down
2 changes: 1 addition & 1 deletion valhalla/gui/ValhallaLocateDialog_ui.py
Expand Up @@ -2,7 +2,7 @@

# Form implementation generated from reading ui file 'valhalla/gui/ValhallaLocateDialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
# Created by: PyQt5 UI code generator 5.15.10
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
Expand Down
5 changes: 3 additions & 2 deletions valhalla/metadata.txt
Expand Up @@ -4,7 +4,7 @@ qgisMinimumVersion=3.0
qgisMaximumVersion=3.99
description=Valhalla routing, isochrones and matrix calculations for QGIS

version=2.4.2
version=2.5.0
author=GIS • OPS UG
email=nils@gis-ops.com

Expand All @@ -18,7 +18,8 @@ about=Valhalla provides access to most of the functions of the open-source Valha

The plugin accesses remote or local Valhalla HTTP APIs. If you want to quickly get a local setup, try our Valhalla Docker image: https://github.com/gis-ops/docker-valhalla.

changelog=2023/04/29 v2.4.2 Fix some datetime & processing stuff, CAREFUL: will remove iso poly styling
changelog=2024/03/26 v2.5.0 Fix matrix & add optional matrix geometries and time options
2023/04/29 v2.4.2 Fix some datetime & processing stuff, CAREFUL: will remove iso poly styling
2023/04/29 v2.4.1 Bit more logging for isochrone processing algos
2023/03/12 v2.4.0 Add multimodal routing for debugging; fix time options
2022/12/28 v2.3.0 Implement centroid endpoint; fixed #2; avoid_polygons; enhance /locate to accept heading & radius; add time options
Expand Down
3 changes: 2 additions & 1 deletion valhalla/proc/matrix/matrix_auto.py
Expand Up @@ -43,7 +43,7 @@
from .. import HELP_DIR
from ... import RESOURCE_PREFIX, __help__
from ...common import client, matrix_core
from ...utils import configmanager, transform, exceptions,logger
from ...utils import configmanager, transform, exceptions, logger
from ..costing_params import CostingAuto
from ..request_builder import get_locations, get_costing_options, get_avoid_locations

Expand Down Expand Up @@ -309,6 +309,7 @@ def processAlgorithm(self, parameters, context, feedback):
response,
self.PROFILE,
costing_params,
False,
source_attributes,
destination_attributes
)
Expand Down