feat: add OSM turn lane arrows

This commit is contained in:
2026-08-05 10:17:34 +08:00
parent 9970e3eeef
commit 9a23f74f0f
34 changed files with 1540 additions and 33 deletions

View File

@@ -152,7 +152,10 @@ def normalize_file(input_path, tolerance):
with input_path.open("r", encoding="utf-8") as handle:
collection = json.load(handle)
for index, feature in enumerate(collection.get("features", [])):
collection["features"] = merge_custom_turn_lane_arrow_components(
collection.get("features", [])
)
for index, feature in enumerate(collection["features"]):
geometry = ogr.CreateGeometryFromJson(json.dumps(feature.get("geometry", {})))
if geometry is None or geometry.IsEmpty():
raise ValueError(f"feature {index} has no usable geometry")
@@ -171,6 +174,49 @@ def normalize_file(input_path, tolerance):
temp_path.replace(input_path)
def merge_custom_turn_lane_arrow_components(features):
"""Restore each imported SVG icon before QGIS assigns its single outline."""
grouped = {}
for feature in features:
properties = feature.get("properties", {})
arrow_id = properties.get("custom_arrow_id")
if properties.get("source") == "osm_turn_lanes" and arrow_id:
grouped.setdefault(arrow_id, []).append(feature)
merged_ids = set()
output = []
for feature in features:
properties = feature.get("properties", {})
arrow_id = properties.get("custom_arrow_id")
if properties.get("source") != "osm_turn_lanes" or not arrow_id:
output.append(feature)
continue
if arrow_id in merged_ids:
continue
merged_ids.add(arrow_id)
components = grouped[arrow_id]
multi = ogr.Geometry(ogr.wkbMultiPolygon)
for component in components:
geometry = ogr.CreateGeometryFromJson(
json.dumps(component.get("geometry", {}))
)
if geometry is None or geometry.IsEmpty() or geometry.GetGeometryName() != "POLYGON":
raise ValueError(f"custom arrow {arrow_id} has an invalid component")
multi.AddGeometry(geometry)
united = multi.UnionCascaded()
if united is None or united.IsEmpty() or united.GetGeometryName() != "POLYGON":
raise ValueError(
f"custom arrow {arrow_id} components did not form one Polygon"
)
merged = dict(components[0])
merged["properties"] = dict(components[0].get("properties", {}))
merged["properties"].pop("arrow_part", None)
merged["properties"]["component_count"] = len(components)
merged["geometry"] = json.loads(united.ExportToJson())
output.append(merged)
return output
def main():
args = cli_args()
if args.outline_simplify_meters < 0: