revert feat(engine): 鏀寔 annulus/circles profile 鐩存帴閲嶅缓涓?schema 鍚屾
This commit is contained in:
2026-08-31 16:44:59 +08:00
parent d192ac5ccd
commit 52dd2d929a
737 changed files with 6 additions and 216949 deletions
+1 -3
View File
@@ -334,13 +334,11 @@
{"if": {"properties": {"atomic_id": {"const": "hole_wizard"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/holeWizardParams"}}}}
]
},
"profile_type": {"enum": ["circle", "polygon", "analytic_contours", "annulus", "circles"]},
"profile_type": {"enum": ["circle", "polygon", "analytic_contours"]},
"profile": {
"oneOf": [
{"type": "object", "properties": {"type": {"const": "circle"}, "center": {"$ref": "#/$defs/point2"}, "radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "polygon"}, "vertices": {"type": "array", "minItems": 3, "items": {"$ref": "#/$defs/point2"}}}, "required": ["type", "vertices"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "annulus"}, "center": {"$ref": "#/$defs/point2"}, "inner_radius_mm": {"$ref": "#/$defs/positive"}, "outer_radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "inner_radius_mm", "outer_radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "circles"}, "items": {"type": "array", "minItems": 1, "items": {"type": "object", "properties": {"center": {"$ref": "#/$defs/point2"}, "radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["radius_mm"], "additionalProperties": false}}}, "required": ["type", "items"], "additionalProperties": false},
{"$ref": "#/$defs/analyticProfile"}
]
},
+1 -12
View File
@@ -5,7 +5,7 @@
"maintenance_rule": "The CDSL-only runtime contract is limited to direct generic profiles and runtime.py EXECUTORS. Legacy macro profiles are importer compatibility syntax and must be lowered by cdsl_importer.legacy_profile_adapter before generic runtime validation.",
"coordinate_convention": "All profile dimensions use millimetres. Two-dimensional points are [u, v] in the sketch workplane.",
"runtime_supported_atomic_ids": ["extrude_add_blind", "extrude_add_two_sided", "extrude_cut_blind", "revolve_add", "revolve_cut", "hole_blind", "hole_countersink", "hole_counterbore", "sphere_add", "reference_plane", "reference_axis", "hole_wizard", "fillet", "chamfer", "pattern_linear", "pattern_mirror"],
"runtime_supported_profiles": ["circle", "polygon", "analytic_contours", "annulus", "circles"],
"runtime_supported_profiles": ["circle", "polygon", "analytic_contours"],
"feature_atomic_ids": {
"extrude_add_blind": {"summary": "Add the closed profile by one signed extrusion distance.", "required_params": ["distance_mm"], "optional_params": ["reverse"], "requires_sketch": true},
"extrude_add_two_sided": {"summary": "Add the closed profile with independently captured forward and reverse terminations.", "required_params": ["distance_mm", "reverse_distance_mm"], "optional_params": ["reverse", "end_condition", "reverse_end_condition"], "requires_sketch": true},
@@ -38,17 +38,6 @@
},
"analytic_contours": {
"summary": "Closed direct line, arc and circle contours. B-splines are unsupported."
},
"annulus": {
"summary": "A concentric ring: an outer circular boundary with an inner circular hole.",
"required": ["inner_radius_mm", "outer_radius_mm"],
"optional": ["center"],
"constraints": ["0 < inner_radius_mm < outer_radius_mm"]
},
"circles": {
"summary": "Multiple circular contours; circles nested inside another circle are interpreted as holes.",
"required": ["items"],
"constraints": ["items contains at least one circle with radius_mm > 0"]
}
}
}
+4 -50
View File
@@ -1,9 +1,9 @@
"""Core CDSL sketch resolver.
The runtime accepts only direct geometric descriptions: circles, straight-edge
polygons, closed analytic line/arc/circle contours, concentric annuli, and
multi-circle sets. 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 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
@@ -276,58 +276,12 @@ def _gen_analytic_contours(profile: _Ctx, meta: _Ctx) -> tuple[list[_Ctx], list[
return entities, []
def _gen_annulus(profile: _Ctx, meta: _Ctx) -> tuple[list[_Ctx], list[_Ctx]]:
"""annulus: 同心圆环,由内外两个实体圆组成。
与 legacy 链路(legacy_profiles._gen_annulus)同构:只产出圆实体、
不产轮廓边,建面交给 adapter 的 _faces_from_circles(内圆被外圆包含
→ 作为孔洞打掉,得到环面)。
"""
center = profile.get("center") or [0.0, 0.0]
inner_radius = float(profile.get("inner_radius_mm") or 0.0)
outer_radius = float(profile.get("outer_radius_mm") or 0.0)
if inner_radius <= 0 or outer_radius <= 0:
raise ValueError("annulus: radii must be > 0")
if inner_radius >= outer_radius:
raise ValueError("annulus: inner_radius must be < outer_radius")
cx, cy = float(center[0]), float(center[1])
return [_circle([cx, cy], inner_radius), _circle([cx, cy], outer_radius)], []
def _gen_circles(profile: _Ctx, meta: _Ctx) -> tuple[list[_Ctx], list[_Ctx]]:
"""circles: 多圆轮廓,每个圆一个实体圆(互不相交时为独立面)。
与 legacy 链路(legacy_profiles._gen_circles)同构:只产出圆实体、
不产轮廓边,建面交给 adapter 的 _faces_from_circles(按圆间包含关系
识别孔洞,被包含的圆跳过、直接包含的圆作为孔洞)。
"""
items = profile.get("items") or []
if not items:
raise ValueError("circles: items must be non-empty")
entities: list[_Ctx] = []
for item in items:
center = item.get("center") or [0.0, 0.0]
radius = float(item.get("radius_mm") or 0.0)
if radius <= 0:
raise ValueError("circles: radius_mm must be > 0")
entities.append(_circle([float(center[0]), float(center[1])], radius))
return entities, []
CORE_SHAPE_GENERATORS: dict[str, Any] = {
"circle": _gen_circle,
"polygon": _gen_polygon,
"analytic_contours": _gen_analytic_contours,
"annulus": _gen_annulus,
"circles": _gen_circles,
}
CORE_SHAPE_GENERATORS: dict[str, Any] = {"circle": _gen_circle, "polygon": _gen_polygon, "analytic_contours": _gen_analytic_contours}
SHAPE_GENERATORS = CORE_SHAPE_GENERATORS
SHAPE_CAPABILITIES: dict[str, _Ctx] = {
"circle": {"detectable": True, "arity": "circle", "description": "single circular contour"},
"polygon": {"detectable": True, "arity": "polygon", "description": "closed straight-edge contour"},
"analytic_contours": {"detectable": True, "arity": "analytic", "description": "closed line, arc, and circle contours"},
"annulus": {"detectable": True, "arity": "annulus", "description": "concentric inner and outer circular contours"},
"circles": {"detectable": True, "arity": "circles", "description": "multiple circular contours with hole nesting"},
}
@@ -1,86 +0,0 @@
from __future__ import annotations
import math
import sys
import tempfile
import unittest
from copy import deepcopy
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "backend"))
sys.path.insert(0, str(ROOT / "backend" / "engine"))
from cdsl_engine.sketch_solver import list_registered_shapes # noqa: E402
def _workplane() -> dict:
return {"origin_mm": [0, 0, 0], "x_dir": [1, 0, 0], "normal": [0, 0, 1]}
def _document(profile: dict) -> dict:
return {
"schema": "cad.cdsl.llm.v1", "schema_version": "1.1.0", "kind": "part", "part_id": "profile-chain",
"meta": {"unit": "mm"},
"geometry": {"sketches": [{
"id": "base", "workplane": _workplane(), "profile": profile,
}]},
"features": [{
"id": "base_add", "atomic_id": "extrude_add_blind", "depends_on": [],
"params": {"distance_mm": 10}, "sketch_id": "base",
}],
}
class EngineProfileContractTests(unittest.TestCase):
"""#10 Profile 链:annulus / circles 进入 CDSL-only 运行时与公开 schema。"""
def test_annulus_and_circles_are_registered_runtime_profiles(self) -> None:
registered = list_registered_shapes()
self.assertIn("annulus", registered)
self.assertIn("circles", registered)
def test_annulus_profile_rebuilds_as_ring_extrusion(self) -> None:
from cdsl_engine.runtime import rebuild_cdsl
cdsl = _document({
"type": "annulus", "center": [0, 0], "inner_radius_mm": 2, "outer_radius_mm": 5,
})
with tempfile.TemporaryDirectory() as directory:
result = rebuild_cdsl(cdsl, Path(directory) / "ring.step")
# 环面面积 π(5²-2²)=21π,拉伸 10 → 210π ≈ 659.734
self.assertAlmostEqual(result["volume_mm3"], 210 * math.pi, places=4)
self.assertEqual(result["solid_count"], 1)
def test_circles_profile_rebuilds_as_independent_solids(self) -> None:
from cdsl_engine.runtime import rebuild_cdsl
cdsl = _document({
"type": "circles",
"items": [
{"center": [-4, 0], "radius_mm": 2},
{"center": [4, 0], "radius_mm": 2},
],
})
with tempfile.TemporaryDirectory() as directory:
result = rebuild_cdsl(cdsl, Path(directory) / "two.step")
# 两个独立圆柱:2 × π×2²×10 = 80π ≈ 251.327
self.assertAlmostEqual(result["volume_mm3"], 2 * math.pi * 4 * 10, places=4)
self.assertEqual(result["solid_count"], 2)
def test_annulus_validation_rejects_inverted_radii(self) -> None:
from cdsl_engine.runtime import rebuild_cdsl
cdsl = _document({
"type": "annulus", "center": [0, 0], "inner_radius_mm": 5, "outer_radius_mm": 2,
})
with tempfile.TemporaryDirectory() as directory:
# 能力检查阶段以 profile_resolution_failed blocker 拒绝该文档
# (reason 为 "annulus: inner_radius must be < outer_radius")。
with self.assertRaises(ValueError):
rebuild_cdsl(cdsl, Path(directory) / "bad.step")
if __name__ == "__main__":
unittest.main()