Skip to content

Commit f5ace5e

Browse files
committed
feat: merge 001-bike-impedance-column add bike impedance support
2 parents c8f37c9 + d9dfb47 commit f5ace5e

File tree

6 files changed

+354
-80
lines changed

6 files changed

+354
-80
lines changed

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Changelog
2+
3+
## Unreleased
4+
5+
### Breaking Changes
6+
7+
- **`AddWalkImpedanceColumn` toolbox tool removed** — The `AddWalkImpedanceColumn` ArcGIS Pro toolbox tool has been removed and replaced by `AddImpedanceColumn`. Any `.aprx` project or ArcGIS Catalog reference to `AddWalkImpedanceColumn` will no longer resolve. Update references to use `AddImpedanceColumn` instead, selecting `"walk"` as the modality.
8+
9+
- **`add_impedance_column` requires explicit `modality_prefix`** — The `modality_prefix` parameter of `add_impedance_column()` no longer has a default value. Callers that previously relied on the `"walk"` default must now pass `modality_prefix="walk"` explicitly:
10+
11+
```python
12+
# Before (no longer works)
13+
add_impedance_column(edge_features)
14+
15+
# After
16+
add_impedance_column(edge_features, modality_prefix="walk")
17+
```
18+
19+
### New Features
20+
21+
- **`bike_impedance` column**`add_impedance_column()` now supports `modality_prefix="bike"`, adding a `bike_impedance` field populated from `IMPEDANCE_TYPE_COEFFICIENTS_BIKE`.
22+
23+
- **`modalities` parameter on `create_network_dataset()`** — The function now accepts an optional `modalities` list (default `["walk", "bike"]`). Both `walk_impedance` and `bike_impedance` are added to segment features by default. Pass `modalities=["walk"]` to restrict to walk-only as before.
24+
25+
- **`AddImpedanceColumn` toolbox tool** — New ArcGIS Pro toolbox tool replacing `AddWalkImpedanceColumn`. Features a modality combo-box (predefined options: walk, bike; custom names supported) and an editable coefficient table that pre-populates when a predefined modality is selected.
26+
27+
- **`SUPPORTED_MODALITIES`** — New public constant (`list[str]`) exported from `overture_to_arcgis.utils._arcgis_routing` listing all registered modality names.
28+
29+
- **`_IMPEDANCE_REGISTRY`** — New private module-level dict mapping modality name → coefficient table, serving as the single source of truth for impedance lookups.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<metadata xml:lang="en"><Esri><CreaDate>20260320</CreaDate><CreaTime>00000000</CreaTime><ArcGISFormat>1.0</ArcGISFormat><SyncOnce>TRUE</SyncOnce><ModDate>20260320</ModDate><ModTime>000000</ModTime></Esri><tool name="AddImpedanceColumn" displayname="Add Impedance Column (Segments)" toolboxalias="overture_to_arcgis" category="Add Parsed Fields"><summary>Calculate an impedance cost multiplier for each segment feature based on its road class and subtype for a chosen routing modality (e.g. walk or bike). Values below 1.0 indicate modality-friendly segments; values above 1.0 penalise segments less suitable for that modality. A value of -1 marks segments where the chosen modality is prohibited (e.g. water, rail). Replaces the removed AddWalkImpedanceColumn tool — any existing references to AddWalkImpedanceColumn must be updated to use this tool instead.</summary><usage><bullet_item>The input features must contain class and subtype text fields, typically present on Overture segment features.</bullet_item><bullet_item>Select a predefined modality (walk or bike) from the Modality dropdown. The Coefficients table is pre-populated with the default values for that modality and can be edited before running.</bullet_item><bullet_item>Type a custom modality name to define a new impedance field (e.g. &quot;horse&quot; produces a horse_impedance field). Supply all coefficient rows manually when using a custom modality.</bullet_item><bullet_item>The tool adds or overwrites a &lt;modality&gt;_impedance float field. The value acts as a multiplier on segment length when computing routing costs for that modality.</bullet_item><bullet_item>Segments whose class and subtype do not match any coefficient row receive a default impedance of 1.0 (neutral cost).</bullet_item></usage><parameters><param name="input_features" displayname="Input Features" type="Required" direction="Input" datatype="GPFeatureLayer"><dialogReference>The segment feature layer or feature class to which the impedance field will be added.</dialogReference></param><param name="modality" displayname="Modality" type="Required" direction="Input" datatype="GPString"><dialogReference>The routing modality for which the impedance column is calculated. Predefined options are walk and bike. Selecting a predefined modality pre-populates the Coefficients table with default values. A custom modality name can be typed to create a new impedance field with user-supplied coefficients.</dialogReference></param><param name="coefficients" displayname="Coefficients" type="Required" direction="Input" datatype="GPValueTable"><dialogReference>A table of impedance multiplier rules. Each row contains three values: Field Name (either class or subtype), Value (the field value to match, e.g. cycleway), and Multiplier (the numeric cost multiplier for matching features). Rows are pre-populated when a predefined modality is selected and can be edited. At least one row is required to run the tool.</dialogReference></param></parameters></tool></metadata>

arcgis/overture_to_arcgis.AddWalkImpedanceColumn.pyt.xml

Lines changed: 0 additions & 2 deletions
This file was deleted.

arcgis/overture_to_arcgis.pyt

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class Toolbox:
6060
SplitSegmentsIntoSubclassFeatures,
6161
SplitSegmentsIntoLevelFeatures,
6262
SplitSegmentsAtConnectors,
63-
AddWalkImpedanceColumn,
63+
AddImpedanceColumn,
6464
CreateNetworkDataset
6565
]
6666

@@ -828,38 +828,94 @@ class SplitSegmentsIntoLevelFeatures:
828828
return
829829

830830

831-
class AddWalkImpedanceColumn:
832-
"""Tool to add walk impedance column to a feature class."""
831+
class AddImpedanceColumn:
832+
"""Tool to add an impedance cost-multiplier field to edge features for a chosen routing modality."""
833+
833834
def __init__(self):
834-
self.label = "Add Walk Impedance Column (Segments)"
835+
self.label = "Add Impedance Column (Segments)"
835836
self.description = (
836-
"Add walk impedance column to a feature class to using features for walk network routing."
837+
"Add an impedance cost-multiplier field to edge features for a chosen routing modality. "
838+
"Supports predefined modalities (walk, bike) with editable coefficients and custom "
839+
"modality names."
837840
)
838841
self.category = "Add Parsed Fields"
839842

840843
def getParameterInfo(self):
841844

842-
# create a parameter to set the input feature layer
843845
input_features = arcpy.Parameter(
844846
displayName="Input Features",
845847
name="input_features",
846848
datatype="GPFeatureLayer",
847849
parameterType="Required",
848-
direction="Input"
850+
direction="Input",
849851
)
850852

851-
params = [input_features]
853+
modality = arcpy.Parameter(
854+
displayName="Modality",
855+
name="modality",
856+
datatype="GPString",
857+
parameterType="Required",
858+
direction="Input",
859+
)
860+
modality.filter.type = "ValueList"
861+
modality.filter.list = overture_to_arcgis.utils._arcgis_routing.SUPPORTED_MODALITIES
862+
modality.value = "walk"
863+
864+
coefficients = arcpy.Parameter(
865+
displayName="Coefficients",
866+
name="coefficients",
867+
datatype="GPValueTable",
868+
parameterType="Required",
869+
direction="Input",
870+
)
871+
coefficients.columns = [
872+
["GPString", "Field Name"],
873+
["GPString", "Value"],
874+
["GPDouble", "Multiplier"],
875+
]
852876

853-
return params
877+
return [input_features, modality, coefficients]
878+
879+
def updateParameters(self, parameters):
880+
"""Pre-populate the coefficient table when the modality selection changes."""
881+
if parameters[1].altered:
882+
from overture_to_arcgis.utils._core import slugify
883+
mod = slugify(parameters[1].valueAsText or "")
884+
registry = overture_to_arcgis.utils._arcgis_routing._IMPEDANCE_REGISTRY
885+
if mod in registry:
886+
rows = []
887+
for field_name, mapping in registry[mod].items():
888+
for value, multiplier in mapping.items():
889+
rows.append([field_name, value, multiplier])
890+
parameters[2].value = rows
891+
else:
892+
parameters[2].value = None
893+
894+
def updateMessages(self, parameters):
895+
"""Block execution when the coefficient table is empty."""
896+
if parameters[2].value is None or len(parameters[2].values or []) == 0:
897+
parameters[2].setErrorMessage(
898+
"Coefficients table must have at least one row before running."
899+
)
854900

855901
def execute(self, parameters, messages):
856902
"""The source code of the tool."""
857-
858-
# retrieve the data directory path from parameters
859903
input_features = parameters[0].valueAsText
904+
modality = parameters[1].valueAsText
860905

861-
# add walk impedance column
862-
overture_to_arcgis.utils.add_impedance_column(input_features, modality_prefix="walk")
906+
# reconstruct the nested coefficients dict from the GPValueTable rows
907+
coefficients = {}
908+
for row in parameters[2].values:
909+
field_name = str(row[0])
910+
value = str(row[1])
911+
multiplier = float(row[2])
912+
coefficients.setdefault(field_name, {})[value] = multiplier
913+
914+
overture_to_arcgis.utils.add_impedance_column(
915+
input_features,
916+
modality_prefix=modality,
917+
coefficients=coefficients,
918+
)
863919

864920
return
865921

0 commit comments

Comments
 (0)