diff --git a/valhalla/common/matrix_core.py b/valhalla/common/matrix_core.py
index 2f94b4a..657d6a9 100644
--- a/valhalla/common/matrix_core.py
+++ b/valhalla/common/matrix_core.py
@@ -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"):
@@ -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.
@@ -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]
@@ -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
diff --git a/valhalla/gui/ValhallaDialog.py b/valhalla/gui/ValhallaDialog.py
index 67e23d5..7d6b5d8 100644
--- a/valhalla/gui/ValhallaDialog.py
+++ b/valhalla/gui/ValhallaDialog.py
@@ -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':
diff --git a/valhalla/gui/ValhallaDialogConfigUI_ui.py b/valhalla/gui/ValhallaDialogConfigUI_ui.py
index 6476bcf..1e1a078 100644
--- a/valhalla/gui/ValhallaDialogConfigUI_ui.py
+++ b/valhalla/gui/ValhallaDialogConfigUI_ui.py
@@ -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.
diff --git a/valhalla/gui/ValhallaDialogUI.ui b/valhalla/gui/ValhallaDialogUI.ui
index 981fe6c..313232c 100644
--- a/valhalla/gui/ValhallaDialogUI.ui
+++ b/valhalla/gui/ValhallaDialogUI.ui
@@ -548,7 +548,7 @@
Method configuration
- true
+ false
false
@@ -762,6 +762,35 @@
+ -
+
+
+ Matrix
+
+
+ true
+
+
+
-
+
+
+ Geometries
+
+
+
+ -
+
+
+
+
+
+ true
+
+
+
+
+
+
-
@@ -829,6 +858,9 @@
Locate
+
+ true
+
-
@@ -1838,7 +1870,7 @@
16777215
- 27
+ 24
@@ -1943,7 +1975,7 @@
16777215
- 27
+ 24
diff --git a/valhalla/gui/ValhallaDialogUI_ui.py b/valhalla/gui/ValhallaDialogUI_ui.py
index 70e1d2b..7d0987c 100644
--- a/valhalla/gui/ValhallaDialogUI_ui.py
+++ b/valhalla/gui/ValhallaDialogUI_ui.py
@@ -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.
@@ -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)
@@ -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")
@@ -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")
@@ -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)
@@ -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)
@@ -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!!"))
diff --git a/valhalla/gui/ValhallaExtraParamsDialogUI_ui.py b/valhalla/gui/ValhallaExtraParamsDialogUI_ui.py
index 12b0587..538d9c1 100644
--- a/valhalla/gui/ValhallaExtraParamsDialogUI_ui.py
+++ b/valhalla/gui/ValhallaExtraParamsDialogUI_ui.py
@@ -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.
diff --git a/valhalla/gui/ValhallaLocateDialog_ui.py b/valhalla/gui/ValhallaLocateDialog_ui.py
index 1beb39c..93ee805 100644
--- a/valhalla/gui/ValhallaLocateDialog_ui.py
+++ b/valhalla/gui/ValhallaLocateDialog_ui.py
@@ -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.
diff --git a/valhalla/metadata.txt b/valhalla/metadata.txt
index a35a89b..644833e 100644
--- a/valhalla/metadata.txt
+++ b/valhalla/metadata.txt
@@ -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
@@ -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
diff --git a/valhalla/proc/matrix/matrix_auto.py b/valhalla/proc/matrix/matrix_auto.py
index 0c15703..f807ef6 100644
--- a/valhalla/proc/matrix/matrix_auto.py
+++ b/valhalla/proc/matrix/matrix_auto.py
@@ -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
@@ -309,6 +309,7 @@ def processAlgorithm(self, parameters, context, feedback):
response,
self.PROFILE,
costing_params,
+ False,
source_attributes,
destination_attributes
)