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:
@@ -0,0 +1,117 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from engine.cdsl_engine.runtime import rebuild_cdsl
|
||||
|
||||
|
||||
def _spline_profile(sketch_id: str, z: float) -> dict:
|
||||
return {
|
||||
"id": sketch_id,
|
||||
"workplane": {"origin_mm": [0, 0, z], "x_dir": [1, 0, 0], "normal": [0, 0, 1]},
|
||||
"profile": {
|
||||
"type": "analytic_contours",
|
||||
"contours": [{
|
||||
"role": "outer",
|
||||
"closed": True,
|
||||
"segments": [{
|
||||
"type": "bspline",
|
||||
"start": [0, 0],
|
||||
"end": [0, 0],
|
||||
"points": [[0, 0], [20, 0], [25, 10], [15, 18], [0, 10], [0, 0]],
|
||||
}],
|
||||
}],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class LoftGeometryTests(unittest.TestCase):
|
||||
def test_open_bspline_segment_can_close_with_other_contour_edges(self):
|
||||
cdsl = {
|
||||
"schema": "cad.cdsl.llm.v1",
|
||||
"schema_version": "1.1.0",
|
||||
"kind": "part",
|
||||
"part_id": "open-bspline-contour",
|
||||
"meta": {"unit": "mm"},
|
||||
"geometry": {"sketches": [{
|
||||
"id": "profile",
|
||||
"workplane": {"origin_mm": [0, 0, 0], "x_dir": [1, 0, 0], "normal": [0, 0, 1]},
|
||||
"profile": {"type": "analytic_contours", "contours": [{
|
||||
"role": "outer", "closed": True,
|
||||
"segments": [
|
||||
{"type": "line", "start": [0, 0], "end": [0, 10]},
|
||||
{
|
||||
"type": "bspline", "start": [0, 10], "end": [0, 0],
|
||||
"points": [[0, 10], [4, 10], [4, 0], [0, 0]],
|
||||
},
|
||||
],
|
||||
}]},
|
||||
}]},
|
||||
"features": [{
|
||||
"id": "add", "atomic_id": "extrude_add_blind", "depends_on": [],
|
||||
"sketch_id": "profile", "params": {"distance_mm": 5},
|
||||
}],
|
||||
}
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
rebuilt = rebuild_cdsl(cdsl, Path(tmp) / "open-bspline-contour.step")
|
||||
self.assertGreater(rebuilt["volume_mm3"], 1.0)
|
||||
|
||||
def test_bspline_loft_and_mirror_replay_produce_step(self):
|
||||
cdsl = {
|
||||
"schema": "cad.cdsl.llm.v1",
|
||||
"schema_version": "1.1.0",
|
||||
"kind": "part",
|
||||
"part_id": "bspline-loft-mirror",
|
||||
"meta": {"unit": "mm"},
|
||||
"geometry": {"sketches": [_spline_profile("lower", 0), _spline_profile("upper", 20)]},
|
||||
"features": [
|
||||
{
|
||||
"id": "mirror_plane",
|
||||
"atomic_id": "reference_plane",
|
||||
"depends_on": [],
|
||||
"params": {"plane": {"origin_mm": [35, 0, 0], "x_dir": [0, 1, 0], "normal": [1, 0, 0]}},
|
||||
"execution_status": "supported",
|
||||
},
|
||||
{
|
||||
"id": "loft",
|
||||
"atomic_id": "loft_add",
|
||||
"depends_on": [],
|
||||
"params": {"profile_sketch_ids": ["lower", "upper"]},
|
||||
"execution_status": "supported",
|
||||
},
|
||||
{
|
||||
"id": "mirror",
|
||||
"atomic_id": "pattern_mirror",
|
||||
"depends_on": ["mirror_plane", "loft"],
|
||||
"params": {
|
||||
"source_feature_ids": ["loft"],
|
||||
"mirror_plane": {
|
||||
"kind": "plane",
|
||||
"owner_feature_id": "mirror_plane",
|
||||
"stable_id": "mirror-plane",
|
||||
"source": "runtime_snapshot",
|
||||
"confidence": 1.0,
|
||||
},
|
||||
},
|
||||
"selectors": [{
|
||||
"kind": "plane",
|
||||
"owner_feature_id": "mirror_plane",
|
||||
"stable_id": "mirror-plane",
|
||||
"source": "runtime_snapshot",
|
||||
"confidence": 1.0,
|
||||
}],
|
||||
"execution_status": "supported",
|
||||
},
|
||||
],
|
||||
}
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
rebuilt = rebuild_cdsl(cdsl, Path(tmp) / "loft.step")
|
||||
self.assertGreater(rebuilt["volume_mm3"], 1.0)
|
||||
self.assertEqual(rebuilt["solid_count"], 2)
|
||||
self.assertEqual([item["feature_id"] for item in rebuilt["feature_results"]], ["mirror_plane", "loft", "mirror.m.loft", "mirror"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user