Skip to content

Latest commit

 

History

History
190 lines (143 loc) · 7.16 KB

File metadata and controls

190 lines (143 loc) · 7.16 KB

ApexVelocity in QGIS — Analyst Workflow

This guide walks a GIS analyst through using ApexVelocity's outputs in QGIS (3.22 LTR or newer, including QGIS 4.x). Everything here also applies to ArcGIS Pro and other OGC-compatible tools, since the data is standard GeoPackage / GeoJSON in EPSG:4326.


1. Get the data

Generate the bundled sample datasets, styles and map renders:

pip install -r requirements.txt          # geopandas, shapely, fiona, contextily…
python python/examples/generate_gis_assets.py

This writes, under the repo root:

data/
  stelvio.gpkg     stelvio.geojson
  dragon.gpkg      dragon.geojson
  sf_urban.gpkg    sf_urban.geojson
qgis/styles/
  <route>_<metric>.qml      # stand-alone QGIS styles
assets/maps/
  *.png                      # cartographic renders

To make your own from any start/end pair:

from apexvelocity import RouteRequest
from apexvelocity.gis import route_to_geopackage

route_to_geopackage(
    RouteRequest(start=(46.6178, 10.5894), end=(46.5285, 10.4543)),
    "stelvio.gpkg",
    default_metric="lateral_g",   # the style QGIS applies on open
)

2. Load a GeoPackage in QGIS

  • Layer → Add Layer → Add Vector Layer…, browse to data/dragon.gpkg, and add the apex_segments layer (and optionally apex_segments_nodes); or
  • drag data/dragon.gpkg from the Browser panel onto the canvas.

The line layer loads already styled as a graduated choropleth — ApexVelocity embeds the style in the GeoPackage's layer_styles table and marks one as the default. No manual symbology needed.

3. The data model

apex_segments — one LineString feature per OSM road edge:

Field Meaning
seg_index Ordinal position along the route
distance_along_m, segment_length_m Chainage and edge length (m)
speed_kmh, physics_limit_speed_kmh, speed_limit_kmh Achieved speed, physics cornering limit, posted limit
lateral_g, longitudinal_g, total_accel_g Cornering / accel / combined load (g)
friction_usage Fraction of available grip used, 0–1
safety_margin 1 − friction_usage, 0–1 (higher = safer)
difficulty_score Composite per-segment difficulty, 0–1
energy_kwh_per_km, regen_potential_j Energy intensity and regen potential
comfort_score, is_uncomfortable Ride comfort
curvature_1pm, curve_radius_m, grade_percent, turn_type Geometry
surface_type, road_type, recommended_action Semantics

apex_segments_nodes — the route vertices as Point features, handy for labeling and graduated-point maps.

4. Styling & switching metrics

The GeoPackage ships six styles (speed, friction usage, safety margin, difficulty, lateral-G, energy). To switch the active metric:

  • Layer Properties → Symbology → Style (bottom) → Load Style… → From Database and pick e.g. ApexVelocity – Safety_margin; or
  • load a stand-alone style: Load Style…qgis/styles/dragon_safety_margin.qml.

To re-class on the fly, open Symbology → Graduated, set Value to any numeric field (e.g. friction_usage), choose a color ramp, and click Classify. Quantile or Natural Breaks (Jenks) work well for skewed metrics like friction usage.

5. Analysis recipes

Find the high-risk segments (grip nearly exhausted) — Select by Expression:

"friction_usage" > 0.85

or flag tight, fast corners:

"curve_radius_m" < 50 AND "speed_kmh" > 40

Hot-spot the dangerous corners — load apex_segments_nodes, then Processing → Interpolation → Heatmap (Kernel Density Estimation) weighted by friction_usage.

Per-segment energy budgetField Calculator, new virtual field:

"energy_kwh_per_km" * ("segment_length_m" / 1000)

Join to your own assets — spatially join the segments to a points-of-interest or jurisdiction layer (Processing → Join attributes by location) to summarise average difficulty or grip usage per zone.

Aggregate to route statsProcessing → Statistics by categories grouped by road_type over lateral_g gives mean/percentile cornering load by road class.

6. The Processing plugin

Annotate any line layer without leaving QGIS:

  1. Copy qgis/apexvelocity_plugin/ into your QGIS profile's python/plugins/ directory (find it via Settings → User Profiles → Open Active Profile Folder), or zip the folder and use Plugins → Manage and Install Plugins → Install from ZIP.
  2. Enable ApexVelocity in the Plugin Manager.
  3. Open Processing Toolbox → ApexVelocity → Annotate route with physics.
  4. Choose your route line layer, set road condition (dry/wet), an optional posted speed limit, and vehicle mass. Run.

You get a styled, physics-annotated segment layer. For full-fidelity physics, put the apexvelocity package on the QGIS Python path by setting an environment variable before launching QGIS:

export APEXVELOCITY_PATH=/path/to/ApexVelocity/python

Without it, the algorithm uses a built-in cornering model so it still runs.

7. CRS & measurement notes

  • All layers are EPSG:4326 (WGS-84). For accurate length/area measurement or buffering, reproject to a local projected CRS first (Processing → Reproject layer, e.g. UTM or a state plane / national grid).
  • segment_length_m and distance_along_m are computed geodesically by ApexVelocity, so they are already metric and CRS-independent.
  • Web-Mercator (EPSG:3857) is fine for display over XYZ basemaps but overstates true distances at high latitude — don't measure in it.

8. Print layouts & reproducible rendering

The repository includes a PyQGIS script that builds QGIS print layouts (map + legend + scale bar + title) over a satellite/dark basemap and exports them to assets/qgis/:

bash qgis/run_render.sh        # macOS; uses the QGIS app's bundled Python

The script (qgis/render_layouts.py) is a clean reference for headless QGIS rendering: it initializes a QgsApplication, loads each GeoPackage (with its embedded style), adds an XYZ basemap, composes a QgsPrintLayout, and exports via QgsLayoutExporter. Adapt the ROUTES list to your own data.

9. Interop: ArcGIS / web maps

  • ArcGIS Pro: GeoPackage and GeoJSON load natively. Export the QGIS style to SLD (Symbology → Style → Save Style → SLD) for portable symbology.

  • Web maps (Leaflet / MapLibre / deck.gl): use the .geojson directly; the numeric attributes drive client-side choropleths.

  • Databases: ogr2ogr the GeoPackage straight into PostGIS:

    ogr2ogr -f PostgreSQL "PG:dbname=gis" data/dragon.gpkg apex_segments