feat(cadfs): 补齐核心建模能力并建立代表性回归

- 新增 loft、双向切除、through-all/up-to-next 等 CADFS lowering 与 engine 支持
- 支持多种 reference plane、B-spline profile 和 circular pattern replay
- 保留 transform 历史,并烘焙安全的单源平移/旋转变换
- 改进 selector 绑定、拓扑快照和 pattern 变换处理
- 建立 17 个代表样本的转换、重建与比较回归工具链
- 补充 schema、author guidance、运行时和几何回归测试
This commit is contained in:
2026-09-07 18:21:07 +08:00
parent 4ad890b7b4
commit 038d38ed98
31 changed files with 2498 additions and 85 deletions
+23 -4
View File
@@ -1,9 +1,9 @@
"""Core CDSL sketch resolver.
The runtime accepts only direct geometric descriptions: circles, straight-edge
polygons, and closed analytic line/arc/circle contours. Semantic shapes and
historical profile macros belong to the importer compatibility layer and must
be lowered before this module is invoked.
polygons, and closed analytic line/arc/circle/B-spline contours. Semantic
shapes and historical profile macros belong to the importer compatibility
layer and must be lowered before this module is invoked.
"""
from __future__ import annotations
@@ -81,6 +81,11 @@ def _transform_contours(contours: list[_Ctx], workplane: _Ctx) -> list[_Ctx]:
if edge["type"] == "arc":
output["center_mm"] = _to_3d(workplane, edge["center_mm"][0], edge["center_mm"][1])
output["normal"] = list(normal)
elif edge["type"] == "bspline":
output["points_mm"] = [
_to_3d(workplane, point[0], point[1])
for point in edge["points_mm"]
]
transformed.append(output)
return transformed
@@ -118,6 +123,8 @@ def _reverse(edge: _Ctx) -> _Ctx:
output["start_mm"], output["end_mm"] = output["end_mm"], output["start_mm"]
if output.get("type") == "arc" and "clockwise" in output:
output["clockwise"] = not bool(output["clockwise"])
if output.get("type") == "bspline":
output["points_mm"] = list(reversed(output["points_mm"]))
return output
@@ -163,7 +170,16 @@ def _segment_edges(segment: _Ctx) -> list[_Ctx]:
if kind == "circle":
return _circle_edges(segment)
if kind == "bspline":
raise ValueError("analytic_contours: bspline requires an explicit approximation capability")
points = segment.get("points") or []
if len(points) < 3:
raise ValueError("analytic_contours: bspline needs at least 3 interpolation points")
converted = [_point(point) for point in points]
return [{
"type": "bspline",
"start_mm": converted[0],
"end_mm": converted[-1],
"points_mm": converted,
}]
raise ValueError(f"analytic_contours: unsupported segment type {kind!r}")
@@ -172,6 +188,9 @@ def _sample_loop(edges: list[_Ctx]) -> list[tuple[float, float]]:
for edge in edges:
start = edge["start_mm"]
points.append((float(start[0]), float(start[1])))
if edge.get("type") == "bspline":
points.extend((float(point[0]), float(point[1])) for point in edge["points_mm"][1:-1])
continue
if edge.get("type") != "arc":
continue
center, end = edge["center_mm"], edge["end_mm"]