From 4306f558b4e5c9cc57dd00293f64128af8d5b757 Mon Sep 17 00:00:00 2001 From: Brad Richardson Date: Tue, 13 Jan 2026 11:55:51 -0500 Subject: [PATCH 1/7] Update docs with more clarity on linear referencing --- .../by-theme/transportation/index.mdx | 2 +- .../transportation/linear-referencing.mdx | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 docs/schema/concepts/by-theme/transportation/linear-referencing.mdx diff --git a/docs/schema/concepts/by-theme/transportation/index.mdx b/docs/schema/concepts/by-theme/transportation/index.mdx index fd9686d7c..00f1e6014 100644 --- a/docs/schema/concepts/by-theme/transportation/index.mdx +++ b/docs/schema/concepts/by-theme/transportation/index.mdx @@ -60,7 +60,7 @@ properties: ### Destinations The destination property in the `segment` feature type supports routing use cases. It describes the transitions from one segment to another on the way to a specified location. In turn-by-turn routing applications, this is what is known as “follow signs for” — the human-readable directions and signposts along a road, highway, or interstate that get us from point A to point Z, by way of any number of paths in between. We designed the `destinations` property with a flexible schema that will allow us to capture and model navigation data from many different sources. -### Linear referencing +### [Linear referencing](/schema/concepts/by-theme/transportation/linear-referencing) The `segment` feature type uses linear referencing to describe the properties of specific sections of a road along a road segment. To avoid splitting road segments at any and every property change, we added linear referencing, which defines how some properties apply to portions of a segment can change along a segment that is generally understood to be the same 'road'. Segment splits are then reserved for more significant intersections so that we don't have to version the entire road any time any piece of the road changes. Other than some expected challenges learning how Linear Referencing worked, we noticed that the main difficulty really arises is when people want to convert the transportation data into a routing graph. Many routing engines want the data to be split at every 'decision point' where each decision is what amounts to a connector between segments the routing engine would consider routing on (e.g. vehicle routing would eliminate sidewalks). However that decision of what segments would be considered for routing someone varies significantly by application, even within similar 'types' of routing, so we could not identify a common subset of splitting rules that would meet all or even most of the various use cases of the members, much less the community at large. ### [Scoped and rule-based properties](/schema/concepts/scoping-rules) diff --git a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx new file mode 100644 index 000000000..0949dcefa --- /dev/null +++ b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx @@ -0,0 +1,68 @@ +--- +title: Linear Referencing +--- + +Linear referencing allows properties to apply to portions of a segment +without splitting the geometry. This promotes shape stability and reduces +versioning when only part of a road changes. + +## Linear reference values + +A linear reference is a **normalized position** from `0.0` (start of segment) to `1.0` (end of segment). + +## `at` vs `between` + +| Property | Purpose | Example | +|----------|---------|---------| +| `at` | Single point location | `at: 0.3` — 30% along segment | +| `between` | Range along segment | `between: [0.2, 0.7]` — 20% to 70% | + +## Calculation method + +Linear references use **WGS84 geodetic distance** in meters: + +``` +linear_ref = geodetic_distance_from_start / total_geodetic_length +``` + +Both distances must be computed on the WGS84 ellipsoid—not planar distance on raw lon/lat coordinates. + +### Example: Apache Sedona + +```sql +-- Correct: geodetic distance using Sedona's geography functions +SELECT + ST_LineLocatePoint( + ST_SetSRID(segment_geom, 4326)::geography, + ST_SetSRID(point_geom, 4326)::geography + ) as linear_ref +FROM segments; +``` + +### Reference implementation + +The [transportation-splitter](https://github.com/OvertureMaps/transportation-splitter) +uses `pyproj.Geod(ellps="WGS84")` for geodetic calculations: + +```python +from pyproj import Geod + +geod = Geod(ellps="WGS84") +segment_length = geod.geometry_length(line_geometry) # meters +``` + +## Why geodetic distance matters + +Using planar distance (treating lon/lat as Cartesian x/y) produces incorrect linear references, +especially at high latitudes or for long segments. For a 10 km east-west segment at 60°N latitude, +planar calculations can underestimate length by ~50%. + +If a consumer calculates linear references using planar distance while Overture uses geodetic distance, +connector positions will be misaligned—potentially causing routing failures. + +## Edge cases + +For very short segments (< 1m), floating-point precision may be limited. +Treat `at ≈ 0.0` or `at ≈ 1.0` as equivalent to endpoints. +When a connector doesn't fall exactly on the geometry, the linear reference +corresponds to the closest point on the segment. From 8e285411e4efac709f1aa5d8962d3db335ac5996 Mon Sep 17 00:00:00 2001 From: Brad Richardson Date: Tue, 13 Jan 2026 12:12:11 -0500 Subject: [PATCH 2/7] Fixes --- .../transportation/linear-referencing.mdx | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx index 0949dcefa..a4776a72e 100644 --- a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx +++ b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx @@ -2,9 +2,7 @@ title: Linear Referencing --- -Linear referencing allows properties to apply to portions of a segment -without splitting the geometry. This promotes shape stability and reduces -versioning when only part of a road changes. +Linear referencing allows properties to apply to portions of a segment without splitting the geometry. This promotes shape stability and reduces versioning when only part of a road changes. ## Linear reference values @@ -17,32 +15,30 @@ A linear reference is a **normalized position** from `0.0` (start of segment) to | `at` | Single point location | `at: 0.3` — 30% along segment | | `between` | Range along segment | `between: [0.2, 0.7]` — 20% to 70% | +When `between` is not provided (null), the attribute applies to the full segment. + ## Calculation method -Linear references use **WGS84 geodetic distance** in meters: +Overture computes linear references using **WGS84 geodetic distance** in meters: ``` linear_ref = geodetic_distance_from_start / total_geodetic_length ``` -Both distances must be computed on the WGS84 ellipsoid—not planar distance on raw lon/lat coordinates. +Both distances must be computed on the WGS84 ellipsoid—not planar distance on raw lon/lat coordinates. Other approaches exist (e.g., projected coordinates), but geodetic distance provides consistent accuracy globally. ### Example: Apache Sedona ```sql --- Correct: geodetic distance using Sedona's geography functions -SELECT - ST_LineLocatePoint( - ST_SetSRID(segment_geom, 4326)::geography, - ST_SetSRID(point_geom, 4326)::geography - ) as linear_ref +SELECT ST_LENGTHSPHEROID(segment_geom) AS segment_length_m FROM segments; ``` +**Warning:** Functions like `ST_LINELOCATEPOINT` can produce incorrect results on geometries that cross over themselves in 2D (curved on-ramps, mountain switchbacks, cul-de-sacs). These functions may pick the wrong location when the line passes over itself—even though the geometry is valid because crossings occur at different elevations or positions along the segment. + ### Reference implementation -The [transportation-splitter](https://github.com/OvertureMaps/transportation-splitter) -uses `pyproj.Geod(ellps="WGS84")` for geodetic calculations: +The [transportation-splitter](https://github.com/OvertureMaps/transportation-splitter) uses `pyproj.Geod(ellps="WGS84")` for geodetic calculations: ```python from pyproj import Geod @@ -53,16 +49,10 @@ segment_length = geod.geometry_length(line_geometry) # meters ## Why geodetic distance matters -Using planar distance (treating lon/lat as Cartesian x/y) produces incorrect linear references, -especially at high latitudes or for long segments. For a 10 km east-west segment at 60°N latitude, -planar calculations can underestimate length by ~50%. +Using planar distance (treating lon/lat as Cartesian x/y) produces incorrect linear references, especially at high latitudes or for long segments. For a 10 km east-west segment at 60°N latitude, planar calculations can underestimate length by ~50%. -If a consumer calculates linear references using planar distance while Overture uses geodetic distance, -connector positions will be misaligned—potentially causing routing failures. +If a consumer calculates linear references using planar distance while Overture uses geodetic distance, connector positions will be misaligned—potentially causing routing failures. ## Edge cases -For very short segments (< 1m), floating-point precision may be limited. -Treat `at ≈ 0.0` or `at ≈ 1.0` as equivalent to endpoints. -When a connector doesn't fall exactly on the geometry, the linear reference -corresponds to the closest point on the segment. +For very short segments (< 1m), floating-point precision may be limited. Treat `at ≈ 0.0` or `at ≈ 1.0` as equivalent to endpoints. When a connector doesn't fall exactly on the geometry, the linear reference corresponds to the closest point on the segment. From 31144c9ce1dceb64678e756a8e3feb320d5d979e Mon Sep 17 00:00:00 2001 From: Brad Richardson Date: Tue, 13 Jan 2026 13:47:12 -0500 Subject: [PATCH 3/7] Wording tweaks --- .../transportation/linear-referencing.mdx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx index a4776a72e..e914ce619 100644 --- a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx +++ b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx @@ -27,18 +27,16 @@ linear_ref = geodetic_distance_from_start / total_geodetic_length Both distances must be computed on the WGS84 ellipsoid—not planar distance on raw lon/lat coordinates. Other approaches exist (e.g., projected coordinates), but geodetic distance provides consistent accuracy globally. -### Example: Apache Sedona +### Examples + +**Apache Sedona (SQL):** ```sql SELECT ST_LENGTHSPHEROID(segment_geom) AS segment_length_m FROM segments; ``` -**Warning:** Functions like `ST_LINELOCATEPOINT` can produce incorrect results on geometries that cross over themselves in 2D (curved on-ramps, mountain switchbacks, cul-de-sacs). These functions may pick the wrong location when the line passes over itself—even though the geometry is valid because crossings occur at different elevations or positions along the segment. - -### Reference implementation - -The [transportation-splitter](https://github.com/OvertureMaps/transportation-splitter) uses `pyproj.Geod(ellps="WGS84")` for geodetic calculations: +**pyproj (Python):** ```python from pyproj import Geod @@ -47,11 +45,15 @@ geod = Geod(ellps="WGS84") segment_length = geod.geometry_length(line_geometry) # meters ``` +See the [transportation-splitter](https://github.com/OvertureMaps/transportation-splitter) for a complete implementation. + +**Warning:** Functions like `ST_LINELOCATEPOINT` can produce incorrect results on geometries that cross over themselves in 2D (curved on-ramps, mountain switchbacks, cul-de-sacs). These functions may pick the wrong location when the line passes over itself—even though the geometry is valid because crossings occur at different elevations or positions along the segment. + ## Why geodetic distance matters Using planar distance (treating lon/lat as Cartesian x/y) produces incorrect linear references, especially at high latitudes or for long segments. For a 10 km east-west segment at 60°N latitude, planar calculations can underestimate length by ~50%. -If a consumer calculates linear references using planar distance while Overture uses geodetic distance, connector positions will be misaligned—potentially causing routing failures. +If a consumer calculates linear references using planar distance while Overture uses geodetic distance, connector positions will be misaligned—potentially causing visual discrepancies on rendered maps or routing failures. ## Edge cases From 080de2d0dd1d0b461f057bca680059978de2367a Mon Sep 17 00:00:00 2001 From: Brad Richardson Date: Tue, 13 Jan 2026 13:49:21 -0500 Subject: [PATCH 4/7] Full examples --- .../concepts/by-theme/transportation/linear-referencing.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx index e914ce619..884d8b39e 100644 --- a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx +++ b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx @@ -32,7 +32,7 @@ Both distances must be computed on the WGS84 ellipsoid—not planar distance on **Apache Sedona (SQL):** ```sql -SELECT ST_LENGTHSPHEROID(segment_geom) AS segment_length_m +SELECT ST_LENGTHSPHEROID(ST_GEOMFROMWKB(geometry)) AS segment_length_m FROM segments; ``` @@ -40,8 +40,10 @@ FROM segments; ```python from pyproj import Geod +from shapely import wkb geod = Geod(ellps="WGS84") +line_geometry = wkb.loads(geometry) # geometry is WKB bytes segment_length = geod.geometry_length(line_geometry) # meters ``` From 91c6e347e9bd3e47eb94a4b16dc2e2f922f81afe Mon Sep 17 00:00:00 2001 From: Brad Richardson Date: Tue, 13 Jan 2026 15:27:29 -0500 Subject: [PATCH 5/7] Update docs/schema/concepts/by-theme/transportation/linear-referencing.mdx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../concepts/by-theme/transportation/linear-referencing.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx index 884d8b39e..5bb0569ee 100644 --- a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx +++ b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx @@ -15,7 +15,7 @@ A linear reference is a **normalized position** from `0.0` (start of segment) to | `at` | Single point location | `at: 0.3` — 30% along segment | | `between` | Range along segment | `between: [0.2, 0.7]` — 20% to 70% | -When `between` is not provided (null), the attribute applies to the full segment. +When `between` is not provided (or is null), the attribute applies to the full segment. ## Calculation method From 8778308ab0b415c6ee66240b14260de630e8bd6c Mon Sep 17 00:00:00 2001 From: Brad Richardson Date: Tue, 13 Jan 2026 15:28:04 -0500 Subject: [PATCH 6/7] Update docs/schema/concepts/by-theme/transportation/index.mdx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/schema/concepts/by-theme/transportation/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/schema/concepts/by-theme/transportation/index.mdx b/docs/schema/concepts/by-theme/transportation/index.mdx index 00f1e6014..314d0aa03 100644 --- a/docs/schema/concepts/by-theme/transportation/index.mdx +++ b/docs/schema/concepts/by-theme/transportation/index.mdx @@ -61,7 +61,7 @@ properties: The destination property in the `segment` feature type supports routing use cases. It describes the transitions from one segment to another on the way to a specified location. In turn-by-turn routing applications, this is what is known as “follow signs for” — the human-readable directions and signposts along a road, highway, or interstate that get us from point A to point Z, by way of any number of paths in between. We designed the `destinations` property with a flexible schema that will allow us to capture and model navigation data from many different sources. ### [Linear referencing](/schema/concepts/by-theme/transportation/linear-referencing) -The `segment` feature type uses linear referencing to describe the properties of specific sections of a road along a road segment. To avoid splitting road segments at any and every property change, we added linear referencing, which defines how some properties apply to portions of a segment can change along a segment that is generally understood to be the same 'road'. Segment splits are then reserved for more significant intersections so that we don't have to version the entire road any time any piece of the road changes. Other than some expected challenges learning how Linear Referencing worked, we noticed that the main difficulty really arises is when people want to convert the transportation data into a routing graph. Many routing engines want the data to be split at every 'decision point' where each decision is what amounts to a connector between segments the routing engine would consider routing on (e.g. vehicle routing would eliminate sidewalks). However that decision of what segments would be considered for routing someone varies significantly by application, even within similar 'types' of routing, so we could not identify a common subset of splitting rules that would meet all or even most of the various use cases of the members, much less the community at large. +The `segment` feature type uses linear referencing to describe the properties of specific sections of a road along a road segment. To avoid splitting road segments at any and every property change, we added linear referencing, which defines how some properties apply to portions of a segment can change along a segment that is generally understood to be the same 'road'. Segment splits are then reserved for more significant intersections so that we don't have to version the entire road any time any piece of the road changes. Other than some expected challenges learning how Linear Referencing worked, we noticed that the main difficulty really arises is when people want to convert the transportation data into a routing graph. Many routing engines want the data to be split at every 'decision point' where each decision is what amounts to a connector between segments the routing engine would consider routing on (e.g. vehicle routing would eliminate sidewalks). However that decision of what segments would be considered for routing someone varies significantly by application, even within similar 'types' of routing, so we could not identify a common subset of splitting rules that would meet all or even most of the various use cases of the members, much less the community at large. ### [Scoped and rule-based properties](/schema/concepts/scoping-rules) The schema allows the values of properties to be specified at the sub-feature level. For example: From 9703684f9588bbe0283910ce6bd238d85f5a5f92 Mon Sep 17 00:00:00 2001 From: Brad Richardson Date: Tue, 13 Jan 2026 15:54:15 -0500 Subject: [PATCH 7/7] Clarify differences in results, wording --- docs/schema/concepts/by-theme/transportation/index.mdx | 2 +- .../by-theme/transportation/linear-referencing.mdx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/schema/concepts/by-theme/transportation/index.mdx b/docs/schema/concepts/by-theme/transportation/index.mdx index 314d0aa03..7c17c1595 100644 --- a/docs/schema/concepts/by-theme/transportation/index.mdx +++ b/docs/schema/concepts/by-theme/transportation/index.mdx @@ -61,7 +61,7 @@ properties: The destination property in the `segment` feature type supports routing use cases. It describes the transitions from one segment to another on the way to a specified location. In turn-by-turn routing applications, this is what is known as “follow signs for” — the human-readable directions and signposts along a road, highway, or interstate that get us from point A to point Z, by way of any number of paths in between. We designed the `destinations` property with a flexible schema that will allow us to capture and model navigation data from many different sources. ### [Linear referencing](/schema/concepts/by-theme/transportation/linear-referencing) -The `segment` feature type uses linear referencing to describe the properties of specific sections of a road along a road segment. To avoid splitting road segments at any and every property change, we added linear referencing, which defines how some properties apply to portions of a segment can change along a segment that is generally understood to be the same 'road'. Segment splits are then reserved for more significant intersections so that we don't have to version the entire road any time any piece of the road changes. Other than some expected challenges learning how Linear Referencing worked, we noticed that the main difficulty really arises is when people want to convert the transportation data into a routing graph. Many routing engines want the data to be split at every 'decision point' where each decision is what amounts to a connector between segments the routing engine would consider routing on (e.g. vehicle routing would eliminate sidewalks). However that decision of what segments would be considered for routing someone varies significantly by application, even within similar 'types' of routing, so we could not identify a common subset of splitting rules that would meet all or even most of the various use cases of the members, much less the community at large. +The `segment` feature type uses linear referencing to describe the properties of specific sections of a road along a road segment. To avoid splitting road segments at any and every property change, we added linear referencing, which defines how properties that apply to portions of a segment can vary along that segment while it is generally understood to be the same 'road'. Segment splits are then reserved for more significant intersections so that we don't have to version the entire road any time any piece of the road changes. Other than some expected challenges learning how linear referencing worked, we noticed that the main difficulty really arises when people want to convert the transportation data into a routing graph. Many routing engines want the data to be split at every 'decision point' where each decision is what amounts to a connector between segments the routing engine would consider routing on (e.g. vehicle routing would eliminate sidewalks). However that decision of what segments would be considered for routing varies significantly by application, even within similar 'types' of routing, so we could not identify a common subset of splitting rules that would meet all or even most of the various use cases of the members, much less the community at large. ### [Scoped and rule-based properties](/schema/concepts/scoping-rules) The schema allows the values of properties to be specified at the sub-feature level. For example: diff --git a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx index 5bb0569ee..ac55f38cc 100644 --- a/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx +++ b/docs/schema/concepts/by-theme/transportation/linear-referencing.mdx @@ -22,7 +22,7 @@ When `between` is not provided (or is null), the attribute applies to the full s Overture computes linear references using **WGS84 geodetic distance** in meters: ``` -linear_ref = geodetic_distance_from_start / total_geodetic_length +linear_ref = geodetic_distance_along_segment_from_start / total_geodetic_length ``` Both distances must be computed on the WGS84 ellipsoid—not planar distance on raw lon/lat coordinates. Other approaches exist (e.g., projected coordinates), but geodetic distance provides consistent accuracy globally. @@ -49,13 +49,13 @@ segment_length = geod.geometry_length(line_geometry) # meters See the [transportation-splitter](https://github.com/OvertureMaps/transportation-splitter) for a complete implementation. -**Warning:** Functions like `ST_LINELOCATEPOINT` can produce incorrect results on geometries that cross over themselves in 2D (curved on-ramps, mountain switchbacks, cul-de-sacs). These functions may pick the wrong location when the line passes over itself—even though the geometry is valid because crossings occur at different elevations or positions along the segment. +**Warning:** Functions like `ST_LINELOCATEPOINT` can produce incorrect results on geometries that cross over or near themselves in 2D (curved on-ramps, mountain switchbacks, cul-de-sacs). These functions may pick the wrong location when the line passes over or close to itself—even though the geometry is valid because crossings occur at different elevations or positions along the segment. Note that Overture [disallows self-intersecting segments](/schema/concepts/by-theme/transportation/shape-connectivity#loops) in its own data. ## Why geodetic distance matters -Using planar distance (treating lon/lat as Cartesian x/y) produces incorrect linear references, especially at high latitudes or for long segments. For a 10 km east-west segment at 60°N latitude, planar calculations can underestimate length by ~50%. +Using planar distance (treating lon/lat as Cartesian x/y) can produce incorrect linear references, especially at high latitudes or for long segments. For a 10 km east-west segment at 60°N latitude, planar calculations can underestimate length by ~50%. Some map projections (e.g., EPSG:3857) yield reasonable results for short, straight segments, but accuracy degrades with segment length and curvature. -If a consumer calculates linear references using planar distance while Overture uses geodetic distance, connector positions will be misaligned—potentially causing visual discrepancies on rendered maps or routing failures. +If a consumer calculates linear references differently than Overture, attribution or connector positions may be misaligned—potentially causing visual discrepancies on rendered maps or routing failures. ## Edge cases