Files
cdsl-cad/backend/tests/test_engine_loft_geometry.py
T
likang 038d38ed98 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、运行时和几何回归测试
2026-09-07 18:21:07 +08:00

118 lines
4.5 KiB
Python

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()