Handoff: ingesting the asphalt-edge exchange files

2026-09-04 · for a colleague's agent (no iolabs tooling assumed) · generated by Claude (Fable 5.1)

Summary

Goal: load the detected asphalt edges of Abschnitt 1, branch_000, segments 060–064 as 3D polylines, in the same coordinate frame as the existing run7 lane model, into your own tooling (CAD, GIS, viewer, or further processing).

You need only: any XML or JSON parser in the language of your choice. No iolabs packages, no repository access, no special tooling. The format is plain XML (UTF-8, no namespaces, no schema file needed) with a JSON twin of identical content; both are described completely below.

Key facts: 20 polylines (4 per segment: outer left/right, inner left/right of the median), one vertex every 0.25 m along the road, XYZ in a local frame; add the Geoshift values to get EPSG:25832 (UTM 32N) metres.

Files

Folder on the shared drive (new, created 2026-09-04):

N:\02_Modelling\05_Rink\02_AI 3D modeling\03_Working folder\260702_ML_Abschnitt_1\260904_asphalt_edges_A1_seg060-064\
FileWhat it is
asphalt_edges.xmlHighwayData schema 1.1 document, 1.5 MB, 20 Features each holding one Polyline. Primary exchange file.
asphalt_edges.jsonSame content as JSON (the producer dict the XML writer was fed). Use it if JSON is easier for you; keys map one-to-one to the XML elements.
README.txtProvenance and colour key of the renders.
overview_topdown.pngTop-down render of all five segments over the point cloud with the lane model, for orientation.

Videos and per-segment stills of the same data: N:\02_Modelling\05_Rink\02_AI 3D modeling\02_OUT\260716_videos\260904_asphalt_edges_A1_seg060-064\.

The lane model the edges were checked against: N:\02_Modelling\05_Rink\02_AI 3D modeling\03_Working folder\260702_ML_Abschnitt_1\260722_run7_line_width\run7_lanes_branch_000_20260722-092426.xml (same schema family, same geoshift).

Format

XML tree (only the elements you need)

HighwayData
├─ MetaData
│  ├─ CreationDate, Source, SoftwareVersion
│  └─ SchemaVersion            "1.1"
├─ Geoshift                    X, Y, Z  (metres; ADD to every coordinate to get absolute EPSG:25832)
└─ Features
   └─ Feature                  (×20)
      ├─ Type                  "Paving Edge"
      ├─ ID                    e.g. asphalt_edge_060_left_01   = asphalt_edge_<segment>_<side>_<run>
      ├─ LaneID                "0"  (not lane-bound)
      ├─ Lines/ NumberOfLines, Points/ NumberOfPoints   (always empty / 0 for this producer)
      ├─ Polylines
      │  └─ Polyline           (exactly one per Feature)
      │     ├─ ID              e.g. asphalt_edge_060_left_01-1
      │     ├─ LaneID          "0"
      │     ├─ RoadPoint       From, To   = station interval on the segment axis (m), informational
      │     ├─ Vertices
      │     │  └─ Vertex (×~400)  ID, X, Y, Z   (local metres, Z = surface height at the edge)
      │     ├─ Annotation      Display=false   (no label to draw)
      │     └─ Attributes
      │        └─ Attribute name="…" type="string|integer|float"  (see table)
      ├─ NumberOfPolylines     "1"
      └─ Splines/ NumberOfSplines   (empty / 0)

Attributes on every Polyline

nametypemeaning
segmentintegerSegment index of the dataset (060…064).
sidestringleft, right, inner_left, inner_right. Left/right are relative to the road axis direction (increasing station).
edge_classstringouter = pavement/verge boundary; inner = pavement edge facing the central median.
runinteger1-based index of the contiguous run within (segment, side). Here always 1; a segment with a gap in detection would have several runs.
station_start_m, station_end_mfloatStation interval covered, on the local segment axis (0 at the segment start plane, ~105 m long). Same numbers as RoadPoint.
length_mfloatPolyline length in XY.
n_stationsintegerVertex count (0.25 m spacing).
measured_fraction, interpolated_fractionfloatShare of vertices measured directly vs. bridged across short unobserved stretches (these sum to 1). All 20 runs are ≥ 0.90 measured.

Coordinates

JSON twin

{
  "metadata": {"creation_date": "…", "source": "…", "software_version": "…", "schema_version": "1.1"},
  "geoshift": {"x": 694541.4427999306, "y": 5386372.36858739, "z": 467.408348358761},
  "features": [
    {"type": "Paving Edge", "id": "asphalt_edge_060_left_01", "lane_id": "0",
     "polylines": [
       {"id": "asphalt_edge_060_left_01-1", "lane_id": "0",
        "road_point": [0.75, 102.75],
        "vertices": [[229.499, -117.989, -12.807], [229.714, -117.862, -12.802], …],
        "annotation": {"display": false},
        "attributes": {"segment": 60, "side": "left", "edge_class": "outer", "run": 1,
                       "station_start_m": 0.75, "station_end_m": 102.75, "length_m": 100.746,
                       "n_stations": 409, "measured_fraction": 0.971, "interpolated_fraction": 0.029}}
     ]}
  ]
}

Real excerpt (first feature, vertices 3–408 elided)

<Feature>
  <Type>Paving Edge</Type>
  <ID>asphalt_edge_060_left_01</ID>
  <LaneID>0</LaneID>
  <Lines/>
  <NumberOfLines>0</NumberOfLines>
  <Points/>
  <NumberOfPoints>0</NumberOfPoints>
  <Polylines>
    <Polyline>
      <ID>asphalt_edge_060_left_01-1</ID>
      <LaneID>0</LaneID>
      <RoadPoint><From>0.75</From><To>102.75</To></RoadPoint>
      <Vertices>
        <Vertex><ID>asphalt_edge_060_left_01-1-1</ID><X>229.499</X><Y>-117.989</Y><Z>-12.807</Z></Vertex>
        <Vertex><ID>asphalt_edge_060_left_01-1-2</ID><X>229.714</X><Y>-117.862</Y><Z>-12.802</Z></Vertex>
        …
        <Vertex><ID>asphalt_edge_060_left_01-1-409</ID><X>313.637</X><Y>-62.697</Y><Z>-9.031</Z></Vertex>
      </Vertices>
      <Annotation><Display>false</Display></Annotation>
      <Attributes>
        <Attribute name="edge_class" type="string">outer</Attribute>
        <Attribute name="interpolated_fraction" type="float">0.029</Attribute>
        <Attribute name="length_m" type="float">100.746</Attribute>
        <Attribute name="measured_fraction" type="float">0.971</Attribute>
        <Attribute name="n_stations" type="integer">409</Attribute>
        <Attribute name="run" type="integer">1</Attribute>
        <Attribute name="segment" type="integer">60</Attribute>
        <Attribute name="side" type="string">left</Attribute>
        <Attribute name="station_end_m" type="float">102.75</Attribute>
        <Attribute name="station_start_m" type="float">0.75</Attribute>
      </Attributes>
    </Polyline>
  </Polylines>
  <NumberOfPolylines>1</NumberOfPolylines>
  <Splines/>
  <NumberOfSplines>0</NumberOfSplines>
</Feature>

In the real file every element is on its own line with two-space indentation; the excerpt is condensed. Attributes appear in alphabetical order of name.

Ingestion procedure (any language)

Everything is reachable with plain tree navigation. The left column gives the XPath for the XML, the right column the equivalent path in the JSON twin.

StepXML (XPath from the root)JSON (path)
1. Read the geoshift/HighwayData/Geoshift/X, …/Y, …/Z (decimal text)$.geoshift.x, .y, .z (numbers)
2. Iterate features/HighwayData/Features/Feature (20 elements)$.features[*] (20 objects)
3. Filter by classFeature/Type text equals Paving Edgefeature.type == "Paving Edge"
4. Iterate polylinesFeature/Polylines/Polyline (exactly one here; loop anyway)feature.polylines[*]
5. IdentifierPolyline/IDpolyline.id
6. Vertices, in orderPolyline/Vertices/Vertex, each with X, Y, Z decimal text; document order = along the roadpolyline.vertices: array of [x, y, z] number triples
7. Absolute coordinatesFor every vertex: E = X + Geoshift.X, N = Y + Geoshift.Y, H = Z + Geoshift.Z. Result is metres in EPSG:25832 (ETRS89 / UTM zone 32N) plus absolute height. Use 64-bit floating point: the absolute values are ~7 digits before the decimal point and 3 after.
8. Metadata per polylinePolyline/Attributes/Attribute: element attribute name = key, element attribute type ∈ {string, integer, float}, element text = valuepolyline.attributes: object with the same keys, already typed
9. IgnoreLaneID (always "0"), RoadPoint (same numbers as station_start_m/station_end_m), Annotation (Display=false: nothing to label), the empty Lines/Points/Splines containers and their NumberOf… counters, and every Vertex/ID (derived: <polyline id>-<1-based index>).

Parsing notes

Worked example and expected numbers

CheckExpected
Geoshift X / Y / Z694541.4427999306 / 5386372.36858739 / 467.408348358761
Number of Feature elements20 (5 segments × 4 sides)
Feature IDsasphalt_edge_060_left_01, …_060_right_01, …_060_inner_left_01, …_060_inner_right_01, then the same for 061 … 064
Vertices per polyline328 (064 inner_right) to 415 (061 left); total 8070
First vertex of asphalt_edge_060_left_01-1, localX 229.499, Y −117.989, Z −12.807
Same vertex, absolute (local + geoshift)E 694770.942, N 5386254.380, H 454.601
Local XY bounding box of all verticesX 229.5 … 611.6, Y −137.6 … 233.2 (≈ 530 m of road running SW→NE)
Local Z range−12.8 … 2.4 (road climbs ~15 m over the five segments)
Vertex spacing≈ 0.25 m along the road (never simplified)

If your first vertex does not come out at E 694770.942 / N 5386254.380, the geoshift was not added (values around 230 / −118) or was subtracted (values around 694312 / 5386490).

Mapping to CAD / GIS

Relation to the run7 lane model

Verification done

Risks and open questions

Provenance

Produced 2026-09-04 with iolabs-point-cloud-detection-asphaltedge (branch t3code/3abd1a9d, Jira AI3D-384) and the iolabs-point-cloud-modelling-export 0.10.0 writer (HighwayData schema 1.1). The normative schema description lives in that package's docs/xml_schema_1_1_spec.md (Bitbucket, ioholding); the tables above cover everything needed for this document. Questions: Miroslav Simko (iolabs).