From dea818e07d0177eab9c5e51244ec641691c0378d Mon Sep 17 00:00:00 2001 From: ganjihong Date: Wed, 26 Aug 2026 15:14:29 +0800 Subject: [PATCH] =?UTF-8?q?fix(engine):=20=E6=94=AF=E6=8C=81=E6=98=BE?= =?UTF-8?q?=E5=BC=8F=E5=9D=90=E6=A0=87=E9=80=89=E6=8B=A9=E5=99=A8=E7=9A=84?= =?UTF-8?q?=E9=98=B5=E5=88=97=E5=8F=98=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/engine/cdsl_engine/capabilities.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/backend/engine/cdsl_engine/capabilities.py b/backend/engine/cdsl_engine/capabilities.py index c73c217a..97df99ba 100644 --- a/backend/engine/cdsl_engine/capabilities.py +++ b/backend/engine/cdsl_engine/capabilities.py @@ -68,12 +68,19 @@ def _has_explicit_host_frame(params: dict[str, Any]) -> bool: def pattern_transform_blocker(source: FeaturePlanNode) -> str | None: """Return the selector dependency that cannot be transformed exactly. - An explicit host frame is coordinate data, not a topology guess. It can - be transformed with a patterned instance while preserving local hole - positions. All topology selectors and selector-dependent extents remain - blocked until their geometry transform contract is implemented. + Selectors fully captured by explicit coordinate data (a revolve axis with + origin/direction, or a host face with a complete world frame) are + transformed together with each patterned instance and are not blockers. + Any remaining topology selector and selector-dependent extent stays + blocked until its geometry transform contract is implemented. """ - if source.selectors: + for selector in source.selectors or (): + if selector.get("kind") == "axis" and _has_explicit_axis(source.params.get("axis")): + # The axis is coordinate data; _translated_node shifts its origin. + continue + if selector.get("kind") == "face" and _has_explicit_host_frame(source.params): + # The host face carries a complete world frame; positions stay local. + continue return "feature selector" host = source.params.get("host_face") if host is not None and not _has_explicit_host_frame(source.params):