zero2route3d-sdk 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zero2route3d_sdk-0.2.0/CHANGELOG.md +46 -0
- zero2route3d_sdk-0.2.0/LICENSE +21 -0
- zero2route3d_sdk-0.2.0/MANIFEST.in +7 -0
- zero2route3d_sdk-0.2.0/PKG-INFO +251 -0
- zero2route3d_sdk-0.2.0/README.md +210 -0
- zero2route3d_sdk-0.2.0/pyproject.toml +129 -0
- zero2route3d_sdk-0.2.0/setup.cfg +4 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/__init__.py +212 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/accessibility_equity.py +214 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/ahp_engine.py +117 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/api.py +244 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/basemap.py +44 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/cli.py +251 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/copernicus_dem.py +76 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/copernicus_eo_suite.py +443 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/dem_fetcher.py +223 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/environmental_raster.py +411 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/evacuation.py +121 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/html_bundler.py +603 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/input_validation.py +100 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/integrations.py +260 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/isochrone_engine.py +220 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/kinematics.py +383 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/local_server.py +116 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/map_matching_3d.py +374 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/micro_elevation.py +264 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/mobility_profiles.py +517 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/multimodal.py +172 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/network_source.py +512 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/osm_downloader.py +328 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/osm_styling.py +351 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/pareto_router.py +331 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/plotting.py +292 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/profile_dxf.py +231 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/profile_stats.py +648 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/py.typed +1 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/qml_generator.py +189 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/raster_source.py +206 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/report_generator.py +154 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/route_corridor_3d.py +479 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/routing_engine.py +747 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/solar_shadow.py +157 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d/tsp_solver.py +78 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d_sdk.egg-info/PKG-INFO +251 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d_sdk.egg-info/SOURCES.txt +50 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d_sdk.egg-info/dependency_links.txt +1 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d_sdk.egg-info/entry_points.txt +2 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d_sdk.egg-info/requires.txt +15 -0
- zero2route3d_sdk-0.2.0/src/zero2route3d_sdk.egg-info/top_level.txt +1 -0
- zero2route3d_sdk-0.2.0/tests/test_all_features.py +553 -0
- zero2route3d_sdk-0.2.0/tests/test_geotiff_sampling.py +146 -0
- zero2route3d_sdk-0.2.0/tests/test_regressions_0_2_0.py +270 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [0.2.0] - 2026-08-25
|
|
11
|
+
### Added
|
|
12
|
+
- Added `GeoTiffRasterSource` for headless rasterio-backed GeoTIFF sampling with WGS84-to-raster CRS reprojection.
|
|
13
|
+
- Added GeoTIFF DEM integration for `EnvironmentalSurfaceSampler` and `sample_rasterio_dem`.
|
|
14
|
+
- Added file/path GeoJSON network loading for high-level routing calls.
|
|
15
|
+
- Added focused 0.2.0 regression tests for network input, profile resolution, DEM fallback behavior, report generation, multimodal routing, and plotting validation.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Made unknown profile keys fail strictly in high-level APIs while preserving the legacy non-strict `get_profile` fallback.
|
|
19
|
+
- Preserved caller-supplied `MobilityProfile` instances through routing engines.
|
|
20
|
+
- Improved standalone route HTML output so generated reports include their route data, styles, and scripts without external assets.
|
|
21
|
+
- Kept missing DEM/elevation samples as `None` instead of silently treating them as sea level.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- Fixed GeoJSON `oneway=-1` handling so reversed one-way segments are stored in their travel direction.
|
|
25
|
+
- Fixed DEM batch fetch alignment when invalid coordinates or cache misses are present.
|
|
26
|
+
- Fixed multimodal hub selection so access and egress hubs cannot collapse into the same main-leg endpoint.
|
|
27
|
+
- Fixed motorized elevation plots so they do not show pedestrian calorie axes.
|
|
28
|
+
- Fixed Pareto plotting to reject unsupported metric names instead of silently substituting calories.
|
|
29
|
+
|
|
30
|
+
## [0.1.0] - 2026-08-24
|
|
31
|
+
### Added
|
|
32
|
+
- Initial standalone release of `zero2route3d-sdk`.
|
|
33
|
+
- Biomechanical kinematics engine: Tobler's walking speed, Minetti metabolic energy polynomials, cycling aerodynamics, rolling resistance, scooter power, and senior fatigue decay.
|
|
34
|
+
- 15 Calibrated mobility profiles spanning pedestrian, micromobility, vehicle, and emergency modes.
|
|
35
|
+
- 3D Topological graph routing engine with Dijkstra and A* pathfinding.
|
|
36
|
+
- NAMOA* 4D Multi-objective Pareto frontier router (Time, Climb, Heat Dose, Calories).
|
|
37
|
+
- 3D Anisotropic Isochrone wavefront simulation engine.
|
|
38
|
+
- 3D Hidden Markov Model (HMM) Viterbi map-matching for noisy GPS/GPX tracks.
|
|
39
|
+
- Keys' 16-point bicubic convolution spline micro-elevation interpolator.
|
|
40
|
+
- Solar shadow raytracing and thermal irradiance analysis.
|
|
41
|
+
- Multi-Criteria Decision Analysis (AHP) with consistency ratio validation ($CR \le 0.10$).
|
|
42
|
+
- Enhanced 2-Step Floating Catchment Area (E2SFCA) accessibility equity engine with Gini, Lorenz, and Palma scorecards.
|
|
43
|
+
- Dynamic hazard zone evacuation routing and safe haven allocation.
|
|
44
|
+
- Standalone Three.js 60 FPS WebGL 3D Cockpit HTML bundler.
|
|
45
|
+
- AutoCAD DXF 3D Polyline and longitudinal profile drawing exporter.
|
|
46
|
+
- Copernicus GLO-30 DEM COG tile fetcher.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yusuf Eminoğlu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zero2route3d-sdk
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Headless 3D spatial mobility, biomechanical human kinematics, and multi-criteria routing engine.
|
|
5
|
+
Author-email: Yusuf Eminoğlu <yusufeminoglu@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/YusufEminoglu/zero2route3d_sdk
|
|
8
|
+
Project-URL: Repository, https://github.com/YusufEminoglu/zero2route3d_sdk
|
|
9
|
+
Project-URL: Issues, https://github.com/YusufEminoglu/zero2route3d_sdk/issues
|
|
10
|
+
Project-URL: Documentation, https://yusufeminoglu.github.io/zero2route3d/
|
|
11
|
+
Keywords: gis,routing,shortest-path,isochrone,accessibility,walkability,mobility,kinematics,openstreetmap,dem,pareto,map-matching
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
22
|
+
Classifier: Intended Audience :: Science/Research
|
|
23
|
+
Classifier: Intended Audience :: Developers
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: numpy>=1.20.0
|
|
28
|
+
Requires-Dist: scipy>=1.7.0
|
|
29
|
+
Provides-Extra: geo
|
|
30
|
+
Requires-Dist: shapely>=2.0.0; extra == "geo"
|
|
31
|
+
Requires-Dist: rasterio>=1.3.0; extra == "geo"
|
|
32
|
+
Requires-Dist: geopandas>=0.12.0; extra == "geo"
|
|
33
|
+
Requires-Dist: networkx>=2.8.0; extra == "geo"
|
|
34
|
+
Requires-Dist: matplotlib>=3.5.0; extra == "geo"
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
39
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
|
|
42
|
+
# zero2route3d-sdk
|
|
43
|
+
|
|
44
|
+
[](https://github.com/YusufEminoglu/zero2route3d_sdk/actions/workflows/ci.yml)
|
|
45
|
+
[](https://pypi.org/project/zero2route3d-sdk/)
|
|
46
|
+
[](https://pypi.org/project/zero2route3d-sdk/)
|
|
47
|
+
[](LICENSE)
|
|
48
|
+
[](https://docs.astral.sh/ruff/)
|
|
49
|
+
|
|
50
|
+
**zero2route3d-sdk** is a Python library for **3D spatial mobility modeling, biomechanical human kinematics, and multi-criteria routing analytics**.
|
|
51
|
+
|
|
52
|
+
Built for urban planners, mobility researchers, and geospatial developers, it brings physiological human movement equations, terrain-aware 3D graph algorithms, and environmental microclimate impedance surfaces together into a pure-Python, headless package powered by NumPy and SciPy.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 🌟 Key Capabilities
|
|
57
|
+
|
|
58
|
+
1. **Biomechanical Kinematics & Energy Modeling:**
|
|
59
|
+
- Empirical slope-speed curves via **Tobler's hiking function** ($W(s) = 6.0 \cdot e^{-3.5|s+0.05|}$).
|
|
60
|
+
- Exact metabolic energy expenditure via **Minetti's 5th-order polynomial equations** ($J / (kg \cdot m)$).
|
|
61
|
+
- Aerodynamic drag, rolling resistance, and mechanical efficiency for commuter bikes, cargo bikes, and e-scooters.
|
|
62
|
+
- Universal Thermal Comfort Index (**UTCI**) and solar irradiance aspect factors.
|
|
63
|
+
|
|
64
|
+
2. **15 Calibrated Mobility Profiles:**
|
|
65
|
+
- Pedestrian (*Adult, Senior, Child*).
|
|
66
|
+
- Universal accessibility (*Wheelchair ADA, Stroller*).
|
|
67
|
+
- Micromobility (*Commuter Bike, Cargo Bike, E-Bike, E-Scooter, Runner, Hiker*).
|
|
68
|
+
- Vehicles & Emergency (*Emergency EMS, Fire Truck, Logistics Van, Electric Car*).
|
|
69
|
+
|
|
70
|
+
3. **Multi-Objective 4D Pareto Optimization (NAMOA*):**
|
|
71
|
+
- Finds non-dominated Pareto frontiers balancing **Travel Time, Cumulative Climb, Thermal Heat Dose, and Metabolic Calories**.
|
|
72
|
+
|
|
73
|
+
4. **3D Topological Routing & Isochrones:**
|
|
74
|
+
- 3D graph construction with elevation draping, turn penalties, and barrier avoidance.
|
|
75
|
+
- Anisotropic 3D isochrone wavefront propagation.
|
|
76
|
+
|
|
77
|
+
5. **3D Hidden Markov Model (HMM) Map Matching:**
|
|
78
|
+
- Robust Viterbi decoding matching noisy GPS/GPX tracks to 3D networks.
|
|
79
|
+
|
|
80
|
+
6. **Micro-Elevation & Solar Ray-Tracing:**
|
|
81
|
+
- Keys' 16-point bicubic convolution spline interpolation with analytical $\mathcal{C}^1$ slope/aspect derivatives.
|
|
82
|
+
- Solar position calculation (azimuth/elevation) and building shadow casting.
|
|
83
|
+
|
|
84
|
+
7. **Spatial Justice & Evacuation:**
|
|
85
|
+
- Enhanced 2-Step Floating Catchment Area (**E2SFCA**) healthcare/amenity accessibility.
|
|
86
|
+
- Gini coefficients, Lorenz curves, and Palma spatial equity ratios.
|
|
87
|
+
- Dynamic hazard zone evacuation routing and safe haven allocation.
|
|
88
|
+
|
|
89
|
+
8. **Headless & Multi-Format I/O:**
|
|
90
|
+
- Runs everywhere: Jupyter Notebooks, FastAPI/Flask backends, Docker containers, CLI scripts.
|
|
91
|
+
- Exports to GeoJSON 3D, GPX 1.1, AutoCAD DXF (AC1009/AC1015) 3D Polylines, and standalone Three.js 60 FPS WebGL 3D Cockpit HTML bundles.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 📦 Installation
|
|
96
|
+
|
|
97
|
+
Install the core library from PyPI:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install zero2route3d-sdk
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Or install with optional geospatial acceleration libraries:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
pip install "zero2route3d-sdk[geo]"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 🚀 Quickstart
|
|
112
|
+
|
|
113
|
+
### 1. High-Level One-Line Routing & Isochrones
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import zero2route3d as zr3d
|
|
117
|
+
|
|
118
|
+
# Solve 3D Least-Cost Route in 1 line
|
|
119
|
+
route = zr3d.solve_3d_route(
|
|
120
|
+
origin=(27.11, 38.41),
|
|
121
|
+
destination=(27.14, 38.44),
|
|
122
|
+
network="izmir_network.geojson", # Or GeoDataFrame / list of RoadSegments
|
|
123
|
+
profile="wheelchair" # 15 calibrated profiles
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
print(f"Distance: {route.statistics.total_distance_km:.2f} km")
|
|
127
|
+
print(f"Duration: {route.statistics.total_duration_min:.1f} min")
|
|
128
|
+
print(f"Climb: +{route.statistics.elevation_gain_m:.1f} m")
|
|
129
|
+
|
|
130
|
+
# Save or display interactive 3D WebGL Cockpit
|
|
131
|
+
route.to_html("route_viewer.html")
|
|
132
|
+
|
|
133
|
+
# Plot publication-grade elevation & metabolic energy profile with Matplotlib
|
|
134
|
+
route.plot(show_energy=True, save_path="profile.png")
|
|
135
|
+
|
|
136
|
+
# Convert to 3D LineStringZ GeoDataFrame for GIS workflows
|
|
137
|
+
gdf = route.to_geodataframe()
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 2. Multi-Objective 4D Pareto Frontier (NAMOA*)
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
import zero2route3d as zr3d
|
|
144
|
+
|
|
145
|
+
pareto_result = zr3d.solve_4d_pareto_frontier(
|
|
146
|
+
origin=(27.11, 38.41),
|
|
147
|
+
destination=(27.14, 38.44),
|
|
148
|
+
network="izmir_network.geojson",
|
|
149
|
+
profile="commuter_bike"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
for idx, sol in enumerate(pareto_result.solutions, start=1):
|
|
153
|
+
print(f"Solution #{idx}: Time={sol.costs.time_sec/60:.1f}m, Climb={sol.costs.climb_m:.1f}m, Calories={sol.costs.calories_kcal:.0f}kcal")
|
|
154
|
+
|
|
155
|
+
# Plot 2D Pareto trade-off curve
|
|
156
|
+
zr3d.plot_pareto_frontier_2d(pareto_result, save_path="pareto_curve.png")
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 3. GeoPandas & NetworkX Ecosystem Bridges
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
from zero2route3d import to_geodataframe, to_networkx_digraph, from_geodataframe
|
|
163
|
+
import geopandas as gpd
|
|
164
|
+
|
|
165
|
+
# Load standard GeoDataFrame of road centerlines
|
|
166
|
+
gdf = gpd.read_file("streets.geojson")
|
|
167
|
+
|
|
168
|
+
# Convert GeoDataFrame into 3D RoadSegment graph
|
|
169
|
+
segments = from_geodataframe(gdf)
|
|
170
|
+
|
|
171
|
+
# Convert 3D routing graph into NetworkX DiGraph with slope & kinematic weights
|
|
172
|
+
nx_digraph = to_networkx_digraph(segments)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 4. Command Line Interface (CLI)
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Inspect all 15 mobility profiles
|
|
179
|
+
zero2route3d profiles
|
|
180
|
+
|
|
181
|
+
# Run headless 3D route calculation from terminal
|
|
182
|
+
zero2route3d route --origin 27.11,38.41 --dest 27.14,38.44 --network streets.geojson --profile wheelchair --out-geojson route.geojson --out-dxf route.dxf --out-html viewer.html
|
|
183
|
+
|
|
184
|
+
# Compute 3D travel time isochrone bands
|
|
185
|
+
zero2route3d isochrone --center 27.12,38.42 --intervals 5,10,15 --network streets.geojson --out-geojson isochrones.geojson
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 📚 Mobility Profiles Catalog
|
|
191
|
+
|
|
192
|
+
| Key | Profile Name | Base Speed | Max Slope | Stairs Policy | Target Use-Case |
|
|
193
|
+
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
194
|
+
| `adult` | Standard Adult | 5.0 km/h | 25.0% | Allowed (1.2×) | Everyday urban walking |
|
|
195
|
+
| `senior` | Senior / Elderly | 3.2 km/h | 10.0% | Heavy Penalty (8.0×) | Age-friendly routing |
|
|
196
|
+
| `child` | Child / Elementary | 3.8 km/h | 12.0% | Heavy Penalty (5.0×) | Safe routes to school |
|
|
197
|
+
| `wheelchair` | Wheelchair ADA | 3.5 km/h | 5.0% | **Forbidden** (1000×) | Barrier-free ADA routing |
|
|
198
|
+
| `stroller` | Stroller / Pram | 4.0 km/h | 8.0% | **Forbidden** (500×) | Family-friendly walking |
|
|
199
|
+
| `cargo_bike` | Cargo Bike | 14.0 km/h | 8.0% | **Forbidden** (1000×) | Urban freight & logistics |
|
|
200
|
+
| `commuter_bike`| Commuter Bike | 18.0 km/h | 15.0% | Heavy Penalty (20.0×) | Daily bicycle commuting |
|
|
201
|
+
| `ebike` | Electric Assist Bike| 22.0 km/h | 22.0% | Heavy Penalty (20.0×) | Topography-immune cycling |
|
|
202
|
+
| `escooter` | E-Scooter | 16.0 km/h | 10.0% | **Forbidden** (1000×) | First/last-mile micromobility |
|
|
203
|
+
| `runner` | Jogger / Runner | 10.0 km/h | 30.0% | Allowed (1.0×) | Fitness & athletic routing |
|
|
204
|
+
| `hiker` | Mountain Hiker | 4.5 km/h | 50.0% | Allowed (1.0×) | Trail & topographic hiking |
|
|
205
|
+
| `emergency_ems`| Ambulance EMS | 50.0 km/h | 20.0% | **Forbidden** (1000×) | Rapid emergency response |
|
|
206
|
+
| `emergency_fire`| Fire Engine Heavy | 40.0 km/h | 16.0% | **Forbidden** (1000×) | Heavy emergency vehicles |
|
|
207
|
+
| `logistics_van`| Delivery Van | 45.0 km/h | 18.0% | **Forbidden** (1000×) | Courier & parcel delivery |
|
|
208
|
+
| `electric_car` | Electric EV | 50.0 km/h | 25.0% | **Forbidden** (1000×) | Regenerative braking routing |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 🧪 Development & Testing
|
|
213
|
+
|
|
214
|
+
Clone the repository and install in editable mode:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
git clone https://github.com/YusufEminoglu/zero2route3d_sdk.git
|
|
218
|
+
cd zero2route3d_sdk
|
|
219
|
+
pip install -e ".[dev]"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Run test suite with coverage:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
pytest tests/ -v --cov=zero2route3d
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Run linter and type checker:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
ruff check .
|
|
232
|
+
ruff format --check src tests
|
|
233
|
+
mypy src
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 📄 License & Citation
|
|
239
|
+
|
|
240
|
+
Distributed under the **MIT License**. See `LICENSE` for details.
|
|
241
|
+
|
|
242
|
+
If you use this library in scientific research, please cite:
|
|
243
|
+
|
|
244
|
+
```bibtex
|
|
245
|
+
@software{eminoglu2026zero2route3d,
|
|
246
|
+
author = {Eminoğlu, Yusuf},
|
|
247
|
+
title = {zero2route3d-sdk: Headless 3D spatial mobility, biomechanical human kinematics, and multi-criteria routing engine},
|
|
248
|
+
year = {2026},
|
|
249
|
+
url = {https://github.com/YusufEminoglu/zero2route3d_sdk}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# zero2route3d-sdk
|
|
2
|
+
|
|
3
|
+
[](https://github.com/YusufEminoglu/zero2route3d_sdk/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/zero2route3d-sdk/)
|
|
5
|
+
[](https://pypi.org/project/zero2route3d-sdk/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://docs.astral.sh/ruff/)
|
|
8
|
+
|
|
9
|
+
**zero2route3d-sdk** is a Python library for **3D spatial mobility modeling, biomechanical human kinematics, and multi-criteria routing analytics**.
|
|
10
|
+
|
|
11
|
+
Built for urban planners, mobility researchers, and geospatial developers, it brings physiological human movement equations, terrain-aware 3D graph algorithms, and environmental microclimate impedance surfaces together into a pure-Python, headless package powered by NumPy and SciPy.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🌟 Key Capabilities
|
|
16
|
+
|
|
17
|
+
1. **Biomechanical Kinematics & Energy Modeling:**
|
|
18
|
+
- Empirical slope-speed curves via **Tobler's hiking function** ($W(s) = 6.0 \cdot e^{-3.5|s+0.05|}$).
|
|
19
|
+
- Exact metabolic energy expenditure via **Minetti's 5th-order polynomial equations** ($J / (kg \cdot m)$).
|
|
20
|
+
- Aerodynamic drag, rolling resistance, and mechanical efficiency for commuter bikes, cargo bikes, and e-scooters.
|
|
21
|
+
- Universal Thermal Comfort Index (**UTCI**) and solar irradiance aspect factors.
|
|
22
|
+
|
|
23
|
+
2. **15 Calibrated Mobility Profiles:**
|
|
24
|
+
- Pedestrian (*Adult, Senior, Child*).
|
|
25
|
+
- Universal accessibility (*Wheelchair ADA, Stroller*).
|
|
26
|
+
- Micromobility (*Commuter Bike, Cargo Bike, E-Bike, E-Scooter, Runner, Hiker*).
|
|
27
|
+
- Vehicles & Emergency (*Emergency EMS, Fire Truck, Logistics Van, Electric Car*).
|
|
28
|
+
|
|
29
|
+
3. **Multi-Objective 4D Pareto Optimization (NAMOA*):**
|
|
30
|
+
- Finds non-dominated Pareto frontiers balancing **Travel Time, Cumulative Climb, Thermal Heat Dose, and Metabolic Calories**.
|
|
31
|
+
|
|
32
|
+
4. **3D Topological Routing & Isochrones:**
|
|
33
|
+
- 3D graph construction with elevation draping, turn penalties, and barrier avoidance.
|
|
34
|
+
- Anisotropic 3D isochrone wavefront propagation.
|
|
35
|
+
|
|
36
|
+
5. **3D Hidden Markov Model (HMM) Map Matching:**
|
|
37
|
+
- Robust Viterbi decoding matching noisy GPS/GPX tracks to 3D networks.
|
|
38
|
+
|
|
39
|
+
6. **Micro-Elevation & Solar Ray-Tracing:**
|
|
40
|
+
- Keys' 16-point bicubic convolution spline interpolation with analytical $\mathcal{C}^1$ slope/aspect derivatives.
|
|
41
|
+
- Solar position calculation (azimuth/elevation) and building shadow casting.
|
|
42
|
+
|
|
43
|
+
7. **Spatial Justice & Evacuation:**
|
|
44
|
+
- Enhanced 2-Step Floating Catchment Area (**E2SFCA**) healthcare/amenity accessibility.
|
|
45
|
+
- Gini coefficients, Lorenz curves, and Palma spatial equity ratios.
|
|
46
|
+
- Dynamic hazard zone evacuation routing and safe haven allocation.
|
|
47
|
+
|
|
48
|
+
8. **Headless & Multi-Format I/O:**
|
|
49
|
+
- Runs everywhere: Jupyter Notebooks, FastAPI/Flask backends, Docker containers, CLI scripts.
|
|
50
|
+
- Exports to GeoJSON 3D, GPX 1.1, AutoCAD DXF (AC1009/AC1015) 3D Polylines, and standalone Three.js 60 FPS WebGL 3D Cockpit HTML bundles.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 📦 Installation
|
|
55
|
+
|
|
56
|
+
Install the core library from PyPI:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install zero2route3d-sdk
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or install with optional geospatial acceleration libraries:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install "zero2route3d-sdk[geo]"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 🚀 Quickstart
|
|
71
|
+
|
|
72
|
+
### 1. High-Level One-Line Routing & Isochrones
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
import zero2route3d as zr3d
|
|
76
|
+
|
|
77
|
+
# Solve 3D Least-Cost Route in 1 line
|
|
78
|
+
route = zr3d.solve_3d_route(
|
|
79
|
+
origin=(27.11, 38.41),
|
|
80
|
+
destination=(27.14, 38.44),
|
|
81
|
+
network="izmir_network.geojson", # Or GeoDataFrame / list of RoadSegments
|
|
82
|
+
profile="wheelchair" # 15 calibrated profiles
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
print(f"Distance: {route.statistics.total_distance_km:.2f} km")
|
|
86
|
+
print(f"Duration: {route.statistics.total_duration_min:.1f} min")
|
|
87
|
+
print(f"Climb: +{route.statistics.elevation_gain_m:.1f} m")
|
|
88
|
+
|
|
89
|
+
# Save or display interactive 3D WebGL Cockpit
|
|
90
|
+
route.to_html("route_viewer.html")
|
|
91
|
+
|
|
92
|
+
# Plot publication-grade elevation & metabolic energy profile with Matplotlib
|
|
93
|
+
route.plot(show_energy=True, save_path="profile.png")
|
|
94
|
+
|
|
95
|
+
# Convert to 3D LineStringZ GeoDataFrame for GIS workflows
|
|
96
|
+
gdf = route.to_geodataframe()
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 2. Multi-Objective 4D Pareto Frontier (NAMOA*)
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
import zero2route3d as zr3d
|
|
103
|
+
|
|
104
|
+
pareto_result = zr3d.solve_4d_pareto_frontier(
|
|
105
|
+
origin=(27.11, 38.41),
|
|
106
|
+
destination=(27.14, 38.44),
|
|
107
|
+
network="izmir_network.geojson",
|
|
108
|
+
profile="commuter_bike"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
for idx, sol in enumerate(pareto_result.solutions, start=1):
|
|
112
|
+
print(f"Solution #{idx}: Time={sol.costs.time_sec/60:.1f}m, Climb={sol.costs.climb_m:.1f}m, Calories={sol.costs.calories_kcal:.0f}kcal")
|
|
113
|
+
|
|
114
|
+
# Plot 2D Pareto trade-off curve
|
|
115
|
+
zr3d.plot_pareto_frontier_2d(pareto_result, save_path="pareto_curve.png")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 3. GeoPandas & NetworkX Ecosystem Bridges
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from zero2route3d import to_geodataframe, to_networkx_digraph, from_geodataframe
|
|
122
|
+
import geopandas as gpd
|
|
123
|
+
|
|
124
|
+
# Load standard GeoDataFrame of road centerlines
|
|
125
|
+
gdf = gpd.read_file("streets.geojson")
|
|
126
|
+
|
|
127
|
+
# Convert GeoDataFrame into 3D RoadSegment graph
|
|
128
|
+
segments = from_geodataframe(gdf)
|
|
129
|
+
|
|
130
|
+
# Convert 3D routing graph into NetworkX DiGraph with slope & kinematic weights
|
|
131
|
+
nx_digraph = to_networkx_digraph(segments)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 4. Command Line Interface (CLI)
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Inspect all 15 mobility profiles
|
|
138
|
+
zero2route3d profiles
|
|
139
|
+
|
|
140
|
+
# Run headless 3D route calculation from terminal
|
|
141
|
+
zero2route3d route --origin 27.11,38.41 --dest 27.14,38.44 --network streets.geojson --profile wheelchair --out-geojson route.geojson --out-dxf route.dxf --out-html viewer.html
|
|
142
|
+
|
|
143
|
+
# Compute 3D travel time isochrone bands
|
|
144
|
+
zero2route3d isochrone --center 27.12,38.42 --intervals 5,10,15 --network streets.geojson --out-geojson isochrones.geojson
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 📚 Mobility Profiles Catalog
|
|
150
|
+
|
|
151
|
+
| Key | Profile Name | Base Speed | Max Slope | Stairs Policy | Target Use-Case |
|
|
152
|
+
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
153
|
+
| `adult` | Standard Adult | 5.0 km/h | 25.0% | Allowed (1.2×) | Everyday urban walking |
|
|
154
|
+
| `senior` | Senior / Elderly | 3.2 km/h | 10.0% | Heavy Penalty (8.0×) | Age-friendly routing |
|
|
155
|
+
| `child` | Child / Elementary | 3.8 km/h | 12.0% | Heavy Penalty (5.0×) | Safe routes to school |
|
|
156
|
+
| `wheelchair` | Wheelchair ADA | 3.5 km/h | 5.0% | **Forbidden** (1000×) | Barrier-free ADA routing |
|
|
157
|
+
| `stroller` | Stroller / Pram | 4.0 km/h | 8.0% | **Forbidden** (500×) | Family-friendly walking |
|
|
158
|
+
| `cargo_bike` | Cargo Bike | 14.0 km/h | 8.0% | **Forbidden** (1000×) | Urban freight & logistics |
|
|
159
|
+
| `commuter_bike`| Commuter Bike | 18.0 km/h | 15.0% | Heavy Penalty (20.0×) | Daily bicycle commuting |
|
|
160
|
+
| `ebike` | Electric Assist Bike| 22.0 km/h | 22.0% | Heavy Penalty (20.0×) | Topography-immune cycling |
|
|
161
|
+
| `escooter` | E-Scooter | 16.0 km/h | 10.0% | **Forbidden** (1000×) | First/last-mile micromobility |
|
|
162
|
+
| `runner` | Jogger / Runner | 10.0 km/h | 30.0% | Allowed (1.0×) | Fitness & athletic routing |
|
|
163
|
+
| `hiker` | Mountain Hiker | 4.5 km/h | 50.0% | Allowed (1.0×) | Trail & topographic hiking |
|
|
164
|
+
| `emergency_ems`| Ambulance EMS | 50.0 km/h | 20.0% | **Forbidden** (1000×) | Rapid emergency response |
|
|
165
|
+
| `emergency_fire`| Fire Engine Heavy | 40.0 km/h | 16.0% | **Forbidden** (1000×) | Heavy emergency vehicles |
|
|
166
|
+
| `logistics_van`| Delivery Van | 45.0 km/h | 18.0% | **Forbidden** (1000×) | Courier & parcel delivery |
|
|
167
|
+
| `electric_car` | Electric EV | 50.0 km/h | 25.0% | **Forbidden** (1000×) | Regenerative braking routing |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 🧪 Development & Testing
|
|
172
|
+
|
|
173
|
+
Clone the repository and install in editable mode:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
git clone https://github.com/YusufEminoglu/zero2route3d_sdk.git
|
|
177
|
+
cd zero2route3d_sdk
|
|
178
|
+
pip install -e ".[dev]"
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Run test suite with coverage:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
pytest tests/ -v --cov=zero2route3d
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Run linter and type checker:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
ruff check .
|
|
191
|
+
ruff format --check src tests
|
|
192
|
+
mypy src
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## 📄 License & Citation
|
|
198
|
+
|
|
199
|
+
Distributed under the **MIT License**. See `LICENSE` for details.
|
|
200
|
+
|
|
201
|
+
If you use this library in scientific research, please cite:
|
|
202
|
+
|
|
203
|
+
```bibtex
|
|
204
|
+
@software{eminoglu2026zero2route3d,
|
|
205
|
+
author = {Eminoğlu, Yusuf},
|
|
206
|
+
title = {zero2route3d-sdk: Headless 3D spatial mobility, biomechanical human kinematics, and multi-criteria routing engine},
|
|
207
|
+
year = {2026},
|
|
208
|
+
url = {https://github.com/YusufEminoglu/zero2route3d_sdk}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "zero2route3d-sdk"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Yusuf Eminoğlu", email = "yusufeminoglu@gmail.com" }
|
|
10
|
+
]
|
|
11
|
+
description = "Headless 3D spatial mobility, biomechanical human kinematics, and multi-criteria routing engine."
|
|
12
|
+
keywords = [
|
|
13
|
+
"gis",
|
|
14
|
+
"routing",
|
|
15
|
+
"shortest-path",
|
|
16
|
+
"isochrone",
|
|
17
|
+
"accessibility",
|
|
18
|
+
"walkability",
|
|
19
|
+
"mobility",
|
|
20
|
+
"kinematics",
|
|
21
|
+
"openstreetmap",
|
|
22
|
+
"dem",
|
|
23
|
+
"pareto",
|
|
24
|
+
"map-matching",
|
|
25
|
+
]
|
|
26
|
+
readme = "README.md"
|
|
27
|
+
license = "MIT"
|
|
28
|
+
requires-python = ">=3.9"
|
|
29
|
+
classifiers = [
|
|
30
|
+
"Programming Language :: Python :: 3",
|
|
31
|
+
"Programming Language :: Python :: 3.9",
|
|
32
|
+
"Programming Language :: Python :: 3.10",
|
|
33
|
+
"Programming Language :: Python :: 3.11",
|
|
34
|
+
"Programming Language :: Python :: 3.12",
|
|
35
|
+
"Programming Language :: Python :: 3.13",
|
|
36
|
+
"Operating System :: OS Independent",
|
|
37
|
+
"Topic :: Scientific/Engineering :: GIS",
|
|
38
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
39
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
40
|
+
"Intended Audience :: Science/Research",
|
|
41
|
+
"Intended Audience :: Developers",
|
|
42
|
+
]
|
|
43
|
+
dependencies = [
|
|
44
|
+
"numpy>=1.20.0",
|
|
45
|
+
"scipy>=1.7.0",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[project.optional-dependencies]
|
|
49
|
+
geo = [
|
|
50
|
+
"shapely>=2.0.0",
|
|
51
|
+
"rasterio>=1.3.0",
|
|
52
|
+
"geopandas>=0.12.0",
|
|
53
|
+
"networkx>=2.8.0",
|
|
54
|
+
"matplotlib>=3.5.0",
|
|
55
|
+
]
|
|
56
|
+
dev = [
|
|
57
|
+
"pytest>=7.0.0",
|
|
58
|
+
"pytest-cov>=4.0.0",
|
|
59
|
+
"ruff>=0.1.0",
|
|
60
|
+
"mypy>=1.0.0",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[project.scripts]
|
|
64
|
+
zero2route3d = "zero2route3d.cli:main"
|
|
65
|
+
|
|
66
|
+
[project.urls]
|
|
67
|
+
Homepage = "https://github.com/YusufEminoglu/zero2route3d_sdk"
|
|
68
|
+
Repository = "https://github.com/YusufEminoglu/zero2route3d_sdk"
|
|
69
|
+
Issues = "https://github.com/YusufEminoglu/zero2route3d_sdk/issues"
|
|
70
|
+
Documentation = "https://yusufeminoglu.github.io/zero2route3d/"
|
|
71
|
+
|
|
72
|
+
[tool.setuptools]
|
|
73
|
+
package-dir = {"" = "src"}
|
|
74
|
+
|
|
75
|
+
[tool.setuptools.packages.find]
|
|
76
|
+
where = ["src"]
|
|
77
|
+
|
|
78
|
+
[tool.setuptools.package-data]
|
|
79
|
+
zero2route3d = ["py.typed"]
|
|
80
|
+
|
|
81
|
+
[tool.black]
|
|
82
|
+
line-length = 100
|
|
83
|
+
target-version = ['py39']
|
|
84
|
+
|
|
85
|
+
[tool.ruff]
|
|
86
|
+
line-length = 100
|
|
87
|
+
target-version = "py39"
|
|
88
|
+
exclude = [
|
|
89
|
+
"scratch",
|
|
90
|
+
".venv",
|
|
91
|
+
"build",
|
|
92
|
+
"dist",
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
[tool.ruff.lint]
|
|
96
|
+
select = ["E", "F", "W", "I", "B", "C4"]
|
|
97
|
+
ignore = ["E501"]
|
|
98
|
+
|
|
99
|
+
[tool.mypy]
|
|
100
|
+
files = ["src"]
|
|
101
|
+
|
|
102
|
+
[[tool.mypy.overrides]]
|
|
103
|
+
module = [
|
|
104
|
+
"scipy.*",
|
|
105
|
+
"sklearn.*",
|
|
106
|
+
"shapely.*",
|
|
107
|
+
"rasterio.*",
|
|
108
|
+
"geopandas.*",
|
|
109
|
+
"networkx.*",
|
|
110
|
+
"matplotlib.*",
|
|
111
|
+
# QGIS and GDAL are optional, host-provided runtimes: every import of them in
|
|
112
|
+
# this package is lazy and guarded, and they are never installed in CI.
|
|
113
|
+
"qgis.*",
|
|
114
|
+
"osgeo.*",
|
|
115
|
+
]
|
|
116
|
+
ignore_missing_imports = true
|
|
117
|
+
|
|
118
|
+
[tool.pytest.ini_options]
|
|
119
|
+
testpaths = ["tests"]
|
|
120
|
+
# Lets `pytest` run straight from a clone, without an editable install first.
|
|
121
|
+
pythonpath = ["src"]
|
|
122
|
+
|
|
123
|
+
[tool.coverage.run]
|
|
124
|
+
source = ["zero2route3d"]
|
|
125
|
+
branch = true
|
|
126
|
+
|
|
127
|
+
[tool.coverage.report]
|
|
128
|
+
show_missing = true
|
|
129
|
+
fail_under = 50
|