feat(cadfs): expand selector provenance coverage
This commit is contained in:
@@ -17,6 +17,60 @@ if TYPE_CHECKING: # pragma: no cover - import for type checkers only
|
||||
from ..session import ExecutionSession
|
||||
|
||||
|
||||
def _single_member_dressup_members(
|
||||
node: FeaturePlanNode,
|
||||
session: "ExecutionSession",
|
||||
body: Any,
|
||||
selected_edges: list[Any],
|
||||
) -> dict[str, Any] | None:
|
||||
"""Preserve unchanged body members after one exact-member dress-up.
|
||||
|
||||
The adapter only reports Compound history when every selected edge maps to
|
||||
one source solid. Keep the same proof at the body-graph layer: all other
|
||||
members must appear unchanged in the result and exactly one result solid
|
||||
must remain for the changed member. Otherwise aggregate replay remains
|
||||
valid, but no member-lifecycle transfer is asserted.
|
||||
"""
|
||||
if not selected_edges or len(session.body_members) < 2:
|
||||
return None
|
||||
source_members: dict[str, Any] = {}
|
||||
for member_id, member in session.body_members.items():
|
||||
solids = session.adapter.body_solids(member)
|
||||
if len(solids) != 1:
|
||||
return None
|
||||
source_members[member_id] = solids[0]
|
||||
selected_members = {
|
||||
member_id
|
||||
for edge in selected_edges
|
||||
for member_id, member in source_members.items()
|
||||
if any(edge.is_same(candidate) for candidate in member.edges())
|
||||
}
|
||||
if len(selected_members) != 1:
|
||||
return None
|
||||
changed_member_id = next(iter(selected_members))
|
||||
result_solids = session.adapter.body_solids(body)
|
||||
unchanged: dict[str, Any] = {}
|
||||
matched_result_indexes: set[int] = set()
|
||||
for member_id, member in source_members.items():
|
||||
if member_id == changed_member_id:
|
||||
continue
|
||||
matches = [
|
||||
index for index, result in enumerate(result_solids)
|
||||
if session.topology._same_topology_value(member, result)
|
||||
]
|
||||
if len(matches) != 1 or matches[0] in matched_result_indexes:
|
||||
return None
|
||||
matched_result_indexes.add(matches[0])
|
||||
unchanged[member_id] = result_solids[matches[0]]
|
||||
changed = [
|
||||
result for index, result in enumerate(result_solids)
|
||||
if index not in matched_result_indexes
|
||||
]
|
||||
if len(changed) != 1:
|
||||
return None
|
||||
return {**unchanged, node.feature_id: changed[0]}
|
||||
|
||||
|
||||
def _execute_fillet(node: FeaturePlanNode, session: "ExecutionSession") -> FeatureResult:
|
||||
# 圆角特征(fillet)执行入口:对选中边按半径做圆角,平滑尖角与棱边。
|
||||
|
||||
@@ -28,11 +82,15 @@ def _execute_fillet(node: FeaturePlanNode, session: "ExecutionSession") -> Featu
|
||||
if radius <= 0:
|
||||
raise ValueError("fillet radius_mm must be > 0")
|
||||
# 3. 解析目标边(支持 tangent_propagation 相切传播),并执行圆角。
|
||||
edges = _selector_edges(node, session, tangent_propagation=bool(node.params.get("tangent_propagation")))
|
||||
body, topology_delta = session.adapter.fillet_with_topology_delta(
|
||||
session.body, radius, _selector_edges(node, session, tangent_propagation=bool(node.params.get("tangent_propagation"))),
|
||||
session.body, radius, edges,
|
||||
)
|
||||
# 4. 登记新主体并返回结果。
|
||||
session.register_body(node.feature_id, body, replay_node=node, topology_delta=topology_delta)
|
||||
session.register_body(
|
||||
node.feature_id, body, replay_node=node, topology_delta=topology_delta,
|
||||
body_members=_single_member_dressup_members(node, session, body, edges),
|
||||
)
|
||||
return session.result(node)
|
||||
|
||||
|
||||
@@ -86,7 +144,10 @@ def _execute_chamfer(node: FeaturePlanNode, session: "ExecutionSession") -> Feat
|
||||
detail={"distance_mm": distance, "surface_count": len(session.surface_members)},
|
||||
))
|
||||
# 5. 登记新主体并返回结果。
|
||||
session.register_body(node.feature_id, body, replay_node=node, topology_delta=topology_delta)
|
||||
session.register_body(
|
||||
node.feature_id, body, replay_node=node, topology_delta=topology_delta,
|
||||
body_members=_single_member_dressup_members(node, session, body, edges),
|
||||
)
|
||||
return session.result(node, diagnostics=diagnostics)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user