优化生成流程
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
"""Explicit import/rebuild compatibility for retired CDSL profile macros.
|
||||
|
||||
The CDSL runtime accepts only direct geometric profiles. This adapter is for
|
||||
historical artifacts and importers: it expands a legacy shorthand exactly once
|
||||
into an ``analytic_contours`` profile before generic runtime validation.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
from typing import Any
|
||||
|
||||
from .legacy_profiles import LEGACY_PROFILE_GENERATORS
|
||||
|
||||
|
||||
class LegacyProfileError(ValueError):
|
||||
"""A legacy profile could not be lowered to generic CDSL geometry."""
|
||||
|
||||
|
||||
def legacy_profile_types() -> tuple[str, ...]:
|
||||
return tuple(sorted(LEGACY_PROFILE_GENERATORS))
|
||||
|
||||
|
||||
def _segment_from_edge(edge: dict[str, Any]) -> dict[str, Any]:
|
||||
kind = str(edge.get("type") or "")
|
||||
if kind == "line":
|
||||
return {
|
||||
"type": "line",
|
||||
"start": list(edge["start_mm"][:2]),
|
||||
"end": list(edge["end_mm"][:2]),
|
||||
}
|
||||
if kind == "arc":
|
||||
segment = {
|
||||
"type": "arc",
|
||||
"start": list(edge["start_mm"][:2]),
|
||||
"end": list(edge["end_mm"][:2]),
|
||||
"center": list(edge["center_mm"][:2]),
|
||||
"radius_mm": float(edge["radius_mm"]),
|
||||
}
|
||||
if "clockwise" in edge:
|
||||
segment["clockwise"] = bool(edge["clockwise"])
|
||||
return segment
|
||||
raise LegacyProfileError(f"Legacy profile emitted unsupported edge type: {kind}")
|
||||
|
||||
|
||||
def _circle_contour(entity: dict[str, Any]) -> dict[str, Any]:
|
||||
radius = entity.get("radius_mm")
|
||||
if not isinstance(radius, (int, float)) or float(radius) <= 0:
|
||||
raise LegacyProfileError("Legacy circle must have radius_mm > 0")
|
||||
center = entity.get("center") or [0.0, 0.0]
|
||||
if not isinstance(center, list) or len(center) < 2:
|
||||
raise LegacyProfileError("Legacy circle must have a two-dimensional center")
|
||||
return {
|
||||
"role": "outer",
|
||||
"closed": True,
|
||||
"segments": [{"type": "circle", "center": [float(center[0]), float(center[1])], "radius_mm": float(radius)}],
|
||||
}
|
||||
|
||||
|
||||
def _edge_contour(edges: list[dict[str, Any]], *, role: str) -> dict[str, Any]:
|
||||
return {
|
||||
"role": role,
|
||||
"closed": True,
|
||||
"segments": [_segment_from_edge(edge) for edge in edges],
|
||||
}
|
||||
|
||||
|
||||
def lower_legacy_profile(profile: dict[str, Any], *, sketch_id: str = "") -> dict[str, Any]:
|
||||
"""Expand one named legacy profile to a direct analytic contour profile."""
|
||||
kind = str(profile.get("type") or "")
|
||||
generator = LEGACY_PROFILE_GENERATORS.get(kind)
|
||||
if generator is None:
|
||||
raise LegacyProfileError(f"Unsupported legacy profile: {kind!r}")
|
||||
meta: dict[str, Any] = {"id": sketch_id, "_entities": None, "_contour": None}
|
||||
try:
|
||||
entities, contour = generator(copy.deepcopy(profile), meta)
|
||||
except (KeyError, TypeError, ValueError) as error:
|
||||
raise LegacyProfileError(f"Could not lower legacy profile {kind!r}: {error}") from error
|
||||
|
||||
contours: list[dict[str, Any]] = []
|
||||
if contour:
|
||||
contours.append(_edge_contour(contour, role="outer"))
|
||||
for region in meta.get("_regions") or []:
|
||||
if not isinstance(region, dict):
|
||||
continue
|
||||
outer = region.get("outer") or []
|
||||
if outer:
|
||||
contours.append(_edge_contour(outer, role="outer"))
|
||||
for hole in region.get("holes") or []:
|
||||
if hole:
|
||||
contours.append(_edge_contour(hole, role="inner"))
|
||||
for entity in entities or []:
|
||||
if entity.get("type") == "circle" and not entity.get("construction"):
|
||||
contours.append(_circle_contour(entity))
|
||||
if not contours:
|
||||
raise LegacyProfileError(f"Legacy profile {kind!r} did not produce a closed contour")
|
||||
return {"type": "analytic_contours", "contours": contours}
|
||||
|
||||
|
||||
def lower_legacy_profiles(cdsl: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Return a copy with every self-contained legacy sketch lowered.
|
||||
|
||||
This is opt-in. Calling the runtime directly with a legacy profile still
|
||||
returns an unsupported-profile diagnostic.
|
||||
"""
|
||||
lowered = copy.deepcopy(cdsl)
|
||||
sketches = ((lowered.get("geometry") or {}).get("sketches") or [])
|
||||
for sketch in sketches:
|
||||
if not isinstance(sketch, dict):
|
||||
continue
|
||||
profile = sketch.get("profile")
|
||||
if not isinstance(profile, dict):
|
||||
continue
|
||||
if str(profile.get("type") or "") not in LEGACY_PROFILE_GENERATORS:
|
||||
continue
|
||||
sketch["profile"] = lower_legacy_profile(profile, sketch_id=str(sketch.get("id") or ""))
|
||||
return lowered
|
||||
Reference in New Issue
Block a user