feat: implement S-52 shoreline construction presentation

This commit is contained in:
OpenAI Codex
2026-09-17 10:32:23 +08:00
parent 3c2612faee
commit 47a5358718
3 changed files with 253 additions and 0 deletions

View File

@@ -14,6 +14,7 @@ class S52MarinerSettings:
safety_depth_m: float = 3.0
deep_contour_m: float = 6.0
two_shades: bool = False
symbolized_boundaries: bool = False
def _float(attrs: dict[str, Any], key: str, default: float) -> float:
@@ -632,6 +633,129 @@ def resolve_wrecks02_instruction(
instruction += ";" + udw
return instruction, extra
def resolve_quapnt01_instruction(attrs: dict[str, Any]) -> str:
quapos = _int_attr(attrs, "QUAPOS", 10)
if not (2 <= quapos < 10):
return ""
if quapos == 4:
return "SY(QUAPOS01)"
if quapos == 5:
return "SY(QUAPOS02)"
if quapos in {7, 8}:
return "SY(QUAPOS03)"
return "SY(LOWACC03)"
def resolve_qualin01_instruction(
object_class: str,
attrs: dict[str, Any],
) -> str:
quapos_present = attrs.get("QUAPOS") is not None
quapos = _int_attr(attrs, "QUAPOS", 0)
if quapos_present:
if 2 <= quapos < 10:
return "LC(LOWACC21)"
return ""
if object_class == "COALNE":
conrad = _int_attr(attrs, "CONRAD", 0)
if conrad == 1:
return "LS(SOLD,3,CHMGF);LS(SOLD,1,CSTLN)"
return "LS(SOLD,1,CSTLN)"
def resolve_quapos01_instruction(
object_class: str,
geometry_type: str,
attrs: dict[str, Any],
) -> str:
if str(geometry_type).upper() == "LINE":
return resolve_qualin01_instruction(object_class, attrs)
return resolve_quapnt01_instruction(attrs)
def resolve_slcons03_instruction(
geometry_type: str,
attrs: dict[str, Any],
) -> str:
geom = str(geometry_type).upper()
quapos_present = attrs.get("QUAPOS") is not None
quapos = _int_attr(attrs, "QUAPOS", 0)
if geom == "POINT":
if quapos_present and 2 <= quapos < 10:
return "SY(LOWACC01)"
return ""
instructions: list[str] = []
if geom == "AREA":
instructions.append("AP(CROSSX01)")
if quapos_present and 2 <= quapos < 10:
instructions.append("LC(LOWACC01)")
return ";".join(instructions)
condtn = _int_attr(attrs, "CONDTN", 0)
catslc = _int_attr(attrs, "CATSLC", 0)
watlev = _int_attr(attrs, "WATLEV", 0)
if condtn in {1, 2}:
instructions.append("LS(DASH,1,CSTLN)")
elif catslc in {6, 15, 16}:
instructions.append("LS(SOLD,4,CSTLN)")
elif watlev == 2:
instructions.append("LS(SOLD,2,CSTLN)")
elif watlev in {3, 4}:
instructions.append("LS(DASH,2,CSTLN)")
else:
instructions.append("LS(SOLD,2,CSTLN)")
return ";".join(instructions)
def resolve_restrn01_instruction(attrs: dict[str, Any]) -> str:
restrn = set(_int_list(attrs.get("RESTRN")))
if not restrn:
return ""
if restrn & {7, 8, 14}:
symbol = "ENTRES61" if restrn & {1, 2, 3, 4, 5, 6} else "ENTRES71" if restrn & {9, 10, 11, 12, 13, 14, 15} else "ENTRES51"
elif restrn & {1, 2}:
symbol = "ACHRES61" if restrn & {3, 4, 5, 6} else "ACHRES71" if restrn & {9, 10, 11, 12, 13, 14, 15} else "ACHRES51"
elif restrn & {3, 4, 5, 6}:
symbol = "FSHRES71" if restrn & {9, 10, 11, 12, 13, 14, 15} else "FSHRES51"
else:
symbol = "INFARE51" if restrn & {9, 10, 11, 12, 13, 14, 15} else "RSRDEF51"
return f"SY({symbol})"
def resolve_resare02_instruction(
attrs: dict[str, Any], settings: S52MarinerSettings
) -> str:
restrn = set(_int_list(attrs.get("RESTRN")))
catrea = set(_int_list(attrs.get("CATREA")))
group_a = {1, 8, 9, 12, 14, 19, 21, 25}
group_b = {4, 5, 6, 7, 10, 18, 20, 22, 23, 24}
priority = False
if restrn:
if restrn & {7, 8, 14}:
symbol = "ENTRES61" if (restrn & {1,2,3,4,5,6} or catrea & group_a) else "ENTRES71" if (restrn & {9,10,11,12,13,14,15} or catrea & group_b) else "ENTRES51"
line_code = "RESARE51"; priority = True
elif restrn & {1, 2}:
symbol = "ACHRES61" if (restrn & {3,4,5,6} or catrea & group_a) else "ACHRES71" if (restrn & {9,10,11,12,13,14,15} or catrea & group_b) else "RESTRN51"
line_code = "RESARE51"; priority = True
elif restrn & {3,4,5,6}:
symbol = "FSHRES51" if catrea & group_a else "FSHRES71" if (restrn & {9,10,11,12,13,14,15} or catrea & group_b) else "FSHRES51"
line_code = "FSHRES51"; priority = True
else:
symbol = "INFARE51" if restrn & {9,10,11,12,13,14,15} else "RSRDEF51"
line_code = "CTYARE51"
else:
symbol = "CTYARE71" if (catrea & group_a and catrea & group_b) else "CTYARE51" if catrea & group_a else "INFARE51" if catrea & group_b else "RSRDEF51"
line_code = "CTYARE51"
line = f"LC({line_code})" if settings.symbolized_boundaries else "LS(DASH,2,CHMGD)"
parts = [line, f"SY({symbol})"]
if priority:
parts.insert(0, "OP(6---)")
return ";".join(parts)
def resolve_csp_hints(
csp_name: str,
object_class: str,
@@ -679,6 +803,14 @@ def resolve_csp_hints(
geometry_type, attrs, settings, associated_depth_ranges=associated_depth_ranges
)
extra.update(hazard_extra)
elif name == "QUAPOS01":
instruction = resolve_quapos01_instruction(object_class, geometry_type, attrs)
elif name == "SLCONS03":
instruction = resolve_slcons03_instruction(geometry_type, attrs)
elif name == "RESTRN01":
instruction = resolve_restrn01_instruction(attrs)
elif name == "RESARE02":
instruction = resolve_resare02_instruction(attrs, settings)
else:
return {}