feat: consume manifest-driven native roads

This commit is contained in:
2026-08-26 10:55:47 +08:00
parent 5704b51315
commit 620127031e
16 changed files with 349 additions and 97 deletions

View File

@@ -10,6 +10,7 @@ The expected values are derived from the geometry, not captured from the
implementation — a test that just records current output would ratify a bug.
"""
import json
import math
import os
import sys
@@ -30,7 +31,8 @@ from osmassets.geom import (
sample_tree_row,
signed_polygon_area,
)
from osmassets.catalog import NATIVE_ROAD_LAYERS, ROAD_LAYERS
from osmassets.catalog import ROAD_LAYERS
from osmassets.native_road_manifest import CONTRACT, load as load_native_road_manifest
from osmassets.osm import Projector, parse_height, parse_osm, tags
@@ -46,24 +48,6 @@ class RoadLayerCatalogTest(unittest.TestCase):
self.assertNotEqual(layers["road_surface"]["z"],
layers["intersection_surface"]["z"])
def test_native_provider_maps_to_existing_material_layers(self):
layers = {layer["id"] for layer in ROAD_LAYERS}
self.assertEqual(
[(entry["source"], entry["material_layer"])
for entry in NATIVE_ROAD_LAYERS],
[("road_surface", "road_surface"),
("edge_lines", "lane_separators"),
("intersection_surface", "intersection_surface"),
("sidewalk_surface", "sidewalks"),
("lane_separators", "lane_separators"),
("center_lines", "center_lines"),
("direction_arrows", "lane_arrows_webscale"),
("turn_arrows", "lane_arrows_webscale"),
("crosswalks", "crosswalks"),
("vehicle_stop_lines", "vehicle_stop_lines")])
self.assertTrue(all(entry["material_layer"] in layers
for entry in NATIVE_ROAD_LAYERS))
def test_cesium_export_keeps_signal_assets_optional(self):
exporter = os.path.join(os.path.dirname(os.path.abspath(__file__)),
"..", "export_cesium.py")
@@ -72,6 +56,66 @@ class RoadLayerCatalogTest(unittest.TestCase):
self.assertIn('if not args.get(key):\n continue', source)
class NativeRoadManifestTest(unittest.TestCase):
def setUp(self):
self.root = tempfile.TemporaryDirectory()
self.layers_dir = os.path.join(self.root.name, "layers")
os.mkdir(self.layers_dir)
def tearDown(self):
self.root.cleanup()
def write_manifest(self, layers):
with open(os.path.join(self.root.name, "manifest.json"), "w", encoding="utf-8") as handle:
json.dump({"contract": CONTRACT, "areaId": "test", "layers": layers}, handle)
for layer in layers:
with open(os.path.join(self.layers_dir, layer["source"] + ".geojson"), "w",
encoding="utf-8") as handle:
json.dump({"type": "FeatureCollection", "features": []}, handle)
def test_accepts_semantic_and_split_layers(self):
layers = [
{"source": "road_surface", "role": "surface", "materialLayer": "road_surface"},
{"source": "center_lines", "role": "marking", "materialLayer": "center_lines",
"splitBy": {"prop": "color", "cases": [
{"match": "white", "material": "native_center_line_white"},
{"default": True, "material": "center_lines"},
]}},
{"source": "connectors", "role": "semantic"},
]
self.write_manifest(layers)
self.assertEqual(load_native_road_manifest(self.root.name)["layers"], layers)
def test_rejects_undeclared_or_missing_geojson(self):
layers = [{"source": "road_surface", "role": "surface",
"materialLayer": "road_surface"}]
self.write_manifest(layers)
with open(os.path.join(self.layers_dir, "extra.geojson"), "w", encoding="utf-8") as handle:
handle.write("{}")
with self.assertRaisesRegex(RuntimeError, "mismatch"):
load_native_road_manifest(self.root.name)
os.unlink(os.path.join(self.layers_dir, "extra.geojson"))
os.unlink(os.path.join(self.layers_dir, "road_surface.geojson"))
with self.assertRaisesRegex(RuntimeError, "mismatch"):
load_native_road_manifest(self.root.name)
def test_rejects_invalid_semantic_and_split_definitions(self):
self.write_manifest([{"source": "connectors", "role": "semantic",
"materialLayer": "road_surface"}])
with self.assertRaisesRegex(RuntimeError, "semantic"):
load_native_road_manifest(self.root.name)
self.write_manifest([{"source": "center_lines", "role": "marking",
"materialLayer": "center_lines", "splitBy": {
"prop": "color", "cases": [
{"match": "white", "material": "native_center_line_white"},
{"default": True, "material": "center_lines"},
{"default": True, "material": "center_lines"},
]}}])
with self.assertRaisesRegex(RuntimeError, "exactly one default"):
load_native_road_manifest(self.root.name)
class GeometryRingsTest(unittest.TestCase):
def test_polygon_keeps_only_the_exterior_ring(self):
geometry = {"type": "Polygon", "coordinates": [["outer"], ["hole"]]}