feat: 增强一级关系识别与保持关系策略
This commit is contained in:
@@ -58,6 +58,7 @@ def _strategy_label(strategy: str) -> str:
|
||||
"auto": "自动选择",
|
||||
"local-edge-only-deform": "只改当前Edge",
|
||||
"move-edge-end-plane-by-push-pull": "移动端面/保持垂直",
|
||||
"keep-first-level-planar-relations": "保持一级平面关系",
|
||||
"resize-adjacent-cylinder-from-circular-edge-length": "相邻圆柱直径",
|
||||
"scale-owning-shape-from-edge": "缩放所属",
|
||||
}.get(strategy, strategy)
|
||||
@@ -133,6 +134,7 @@ def _verify_line_edge_intent_specs() -> None:
|
||||
_assert_edge_length_scope(length_spec, "auto", "自动", enabled=True)
|
||||
_assert_edge_length_scope(length_spec, "local-edge-only-deform", "只改当前Edge", enabled=True)
|
||||
_assert_edge_length_scope(length_spec, "move-edge-end-plane-by-push-pull", "移动端面", enabled=True)
|
||||
_assert_edge_length_scope(length_spec, "keep-first-level-planar-relations", "保持关系", enabled=True)
|
||||
_assert_edge_length_scope(
|
||||
length_spec,
|
||||
"resize-adjacent-cylinder-from-circular-edge-length",
|
||||
@@ -140,6 +142,12 @@ def _verify_line_edge_intent_specs() -> None:
|
||||
enabled=False,
|
||||
)
|
||||
_assert_edge_length_scope(length_spec, "scale-owning-shape-from-edge", "缩放所属", enabled=True)
|
||||
constrained_specs = _specs_for_edge(info, strategy="keep-first-level-planar-relations", anchor="keep-start")
|
||||
constrained_length_spec = _spec(constrained_specs, "length")
|
||||
_assert(
|
||||
str(constrained_length_spec.get("scope_default")) == "keep-first-level-planar-relations",
|
||||
"line Edge should honor the explicit keep-planar-relations modeling intent",
|
||||
)
|
||||
anchor_spec = _spec(specs, "edge_length_anchor_mode")
|
||||
_assert(str(anchor_spec.get("label")) == "长度基准", "line Edge should expose a length anchor row")
|
||||
print("line Edge modeling-intent specs ok")
|
||||
@@ -171,6 +179,7 @@ def _verify_circle_edge_intent_specs() -> None:
|
||||
)
|
||||
_assert_edge_length_scope(length_spec, "local-edge-only-deform", "只改当前Edge", enabled=False)
|
||||
_assert_edge_length_scope(length_spec, "move-edge-end-plane-by-push-pull", "移动端面", enabled=False)
|
||||
_assert_edge_length_scope(length_spec, "keep-first-level-planar-relations", "保持关系", enabled=False)
|
||||
_assert_edge_length_scope(
|
||||
length_spec,
|
||||
"resize-adjacent-cylinder-from-circular-edge-length",
|
||||
@@ -195,6 +204,7 @@ def _verify_edge_length_plan_intents() -> None:
|
||||
expectations = (
|
||||
("local-edge-only-deform", "keep-start", "local-edge-only-deform", "相邻面会自然变斜"),
|
||||
("move-edge-end-plane-by-push-pull", "keep-start", "move-edge-end-plane-by-push-pull", "正方体这类模型会更像变成长方体"),
|
||||
("keep-first-level-planar-relations", "keep-start", "move-edge-end-plane-by-push-pull", "保持一级平面关系"),
|
||||
("scale-owning-shape-from-edge", "center", "scale-owning-shape-from-edge", "其它尺寸会跟随变化"),
|
||||
)
|
||||
for strategy, anchor, expected_strategy, impact_fragment in expectations:
|
||||
@@ -206,6 +216,28 @@ def _verify_edge_length_plan_intents() -> None:
|
||||
)
|
||||
impact = str(plan.get("edge_length_impact_summary") or "")
|
||||
_assert(impact_fragment in impact, f"{strategy} impact summary should explain result: {impact}")
|
||||
if expected_strategy == "move-edge-end-plane-by-push-pull":
|
||||
_assert(
|
||||
plan.get("edge_length_planar_constraint_status") == "ready",
|
||||
f"end-face push/pull should expose ready planar constraints: {plan}",
|
||||
)
|
||||
_assert(
|
||||
"端面推拉平面约束" in str(plan.get("edge_length_planar_constraint_summary") or ""),
|
||||
f"end-face push/pull should explain its planar constraint guard: {plan}",
|
||||
)
|
||||
_assert(
|
||||
int(plan.get("edge_length_planar_constraint_perpendicular_count", 0) or 0) >= 1,
|
||||
f"end-face push/pull should detect perpendicular side-face relations: {plan}",
|
||||
)
|
||||
if strategy == "keep-first-level-planar-relations":
|
||||
_assert(
|
||||
plan.get("edge_length_planar_relation_constraint_requested") is True,
|
||||
f"explicit keep-planar-relations strategy should be preserved in the plan: {plan}",
|
||||
)
|
||||
_assert(
|
||||
str(plan.get("edge_length_strategy_label")) == "保持一级平面关系",
|
||||
f"explicit keep-planar-relations strategy should keep a user-facing label: {plan}",
|
||||
)
|
||||
blocked = model.general_edge_length_plan(
|
||||
edge_id,
|
||||
15.0,
|
||||
@@ -214,13 +246,71 @@ def _verify_edge_length_plan_intents() -> None:
|
||||
)
|
||||
_assert(str(blocked.get("status")) == "blocked", "moving an end plane while fixing center should be blocked")
|
||||
_assert("不能使用固定中心" in str(blocked.get("message") or ""), f"blocked message should explain center conflict: {blocked}")
|
||||
blocked_keep_relations = model.general_edge_length_plan(
|
||||
edge_id,
|
||||
15.0,
|
||||
anchor_mode="center",
|
||||
strategy_mode="keep-first-level-planar-relations",
|
||||
)
|
||||
_assert(
|
||||
str(blocked_keep_relations.get("status")) == "blocked",
|
||||
"keeping first-level planar relations while fixing center should be blocked",
|
||||
)
|
||||
_assert(
|
||||
"保持一级平面关系" in str(blocked_keep_relations.get("message") or ""),
|
||||
f"blocked keep-planar-relations plan should name the requested constraint: {blocked_keep_relations}",
|
||||
)
|
||||
print("Edge modeling-intent plans ok")
|
||||
|
||||
|
||||
def _verify_edge_coordinate_move_plan_semantics() -> None:
|
||||
model = StepModel.load(DEFAULT_CUBE)
|
||||
edge_id = _line_edge_ids_near_length(model, 10.0, 1e-5)[0]
|
||||
info = model.edge_info(edge_id)
|
||||
start = info.get("start_point")
|
||||
center = info.get("length_center")
|
||||
if not isinstance(start, (tuple, list)) or len(start) != 3:
|
||||
raise AssertionError(f"line Edge lacks a stable start point: {info}")
|
||||
if not isinstance(center, (tuple, list)) or len(center) != 3:
|
||||
raise AssertionError(f"line Edge lacks a stable center: {info}")
|
||||
|
||||
endpoint_plan = model.edge_endpoint_move_plan(
|
||||
edge_id,
|
||||
"start",
|
||||
(float(start[0]) - 1.0, float(start[1]), float(start[2])),
|
||||
)
|
||||
_assert(str(endpoint_plan.get("status")) != "blocked", f"endpoint move should be available: {endpoint_plan}")
|
||||
_assert(str(endpoint_plan.get("edge_endpoint_label")) == "起点", f"endpoint label should be Chinese: {endpoint_plan}")
|
||||
_assert(
|
||||
str(endpoint_plan.get("edit_strategy_label")) == "Edge端点局部移动",
|
||||
f"endpoint move should expose a user-facing strategy label: {endpoint_plan}",
|
||||
)
|
||||
_assert(
|
||||
"不是端面整体推拉" in str(endpoint_plan.get("edit_semantics") or ""),
|
||||
f"endpoint move should explain that it is local deformation: {endpoint_plan}",
|
||||
)
|
||||
|
||||
center_plan = model.edge_center_move_plan(
|
||||
edge_id,
|
||||
(float(center[0]), float(center[1]), float(center[2]) + 1.0),
|
||||
)
|
||||
_assert(str(center_plan.get("status")) != "blocked", f"center move should be available: {center_plan}")
|
||||
_assert(
|
||||
str(center_plan.get("edit_strategy_label")) == "Edge整体局部移动",
|
||||
f"center move should expose a user-facing strategy label: {center_plan}",
|
||||
)
|
||||
_assert(
|
||||
"不是移动整个端面" in str(center_plan.get("edit_semantics") or ""),
|
||||
f"center move should explain that it is local deformation: {center_plan}",
|
||||
)
|
||||
print("Edge coordinate move plan semantics ok")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
_verify_line_edge_intent_specs()
|
||||
_verify_circle_edge_intent_specs()
|
||||
_verify_edge_length_plan_intents()
|
||||
_verify_edge_coordinate_move_plan_semantics()
|
||||
print("Edge modeling-intent spec suite passed.")
|
||||
return 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user