feat: 增强一级关系识别与保持关系策略
This commit is contained in:
@@ -156,6 +156,10 @@ def _feature_dimension_keys(action_info: dict[str, object]) -> tuple[str, ...]:
|
||||
angular_span = _float_or_none(action_info.get("angular_span"))
|
||||
|
||||
if surface == "plane":
|
||||
if action_info.get("multistep_prismatic_status") == "blocked":
|
||||
return ()
|
||||
if action_info.get("existing_chamfer_status") == "candidate":
|
||||
return ("existing_chamfer_distance_estimate",)
|
||||
if action_info.get("prismatic_profile_status") == "candidate":
|
||||
keys = ["local_face_width", "local_face_height"]
|
||||
if action_info.get("prismatic_extrusion_status") == "candidate":
|
||||
@@ -195,6 +199,8 @@ def _feature_dimension_keys(action_info: dict[str, object]) -> tuple[str, ...]:
|
||||
if feature_guess == "boss/outer-round candidate":
|
||||
return ("boss_diameter", "boss_height")
|
||||
if feature_guess == "round/fillet candidate":
|
||||
if str(action_info.get("existing_fillet_status") or "") == "blocked":
|
||||
return ()
|
||||
return ("existing_fillet_radius_estimate", "existing_fillet_arc_length_estimate")
|
||||
return ("generic_cylinder_diameter", "cylinder_height")
|
||||
|
||||
@@ -1029,13 +1035,23 @@ class WindowStateMixin:
|
||||
is_generic_surface = has_face and surface in FREEFORM_FACE_SURFACES
|
||||
is_hole_or_groove = is_cylinder and feature_guess == "hole/groove candidate"
|
||||
is_boss = is_cylinder and feature_guess == "boss/outer-round candidate"
|
||||
is_existing_fillet = is_cylinder and feature_guess == "round/fillet candidate"
|
||||
is_existing_fillet = (
|
||||
is_cylinder
|
||||
and feature_guess == "round/fillet candidate"
|
||||
and str(action_info.get("existing_fillet_status") or "") != "blocked"
|
||||
)
|
||||
is_existing_chamfer = (
|
||||
is_plane
|
||||
and feature_guess == "chamfer candidate"
|
||||
and str(action_info.get("existing_chamfer_status") or "") == "candidate"
|
||||
)
|
||||
is_full_cylinder = _is_effectively_full_cylinder(action_info)
|
||||
is_slot_or_half_hole = (
|
||||
is_hole_or_groove
|
||||
and not is_full_cylinder
|
||||
and angular_span is not None
|
||||
and angular_span < math.tau * 0.92
|
||||
and str(action_info.get("slot_status") or "") == "candidate"
|
||||
and _float_or_none(action_info.get("slot_chord_width_estimate")) is not None
|
||||
)
|
||||
is_blind = action_info.get("cylinder_end_type") == "blind"
|
||||
@@ -1049,8 +1065,8 @@ class WindowStateMixin:
|
||||
)
|
||||
has_fillet_support = len(_int_values(action_info.get("feature_existing_fillet_support_face_ids"))) >= 2
|
||||
is_line_edge = has_edge and curve == "line"
|
||||
can_push = has_model and is_plane
|
||||
can_resize_shell = has_model and is_shell_candidate
|
||||
can_push = has_model and is_plane and not is_existing_chamfer
|
||||
can_resize_shell = has_model and is_shell_candidate and not is_existing_chamfer
|
||||
can_resize_hole = has_model and is_hole_or_groove
|
||||
can_resize_slot = has_model and is_slot_or_half_hole
|
||||
can_resize_boss = has_model and is_boss and is_full_cylinder
|
||||
@@ -1535,7 +1551,7 @@ class WindowStateMixin:
|
||||
"Face:面内长度/宽度、中心、偏移、壳体厚度。\n"
|
||||
"孔/槽:孔径、轴心、封堵、盲孔/盲槽深度、槽宽/槽深/弧长/总长。\n"
|
||||
"凸台:圆柱凸台直径/高度/轴心;矩形凸台/矩形槽口袋长宽、中心、高度/深度;多台阶矩形凸台顶层规则台阶。\n"
|
||||
"圆角/倒角:简单已有圆角半径/弧长,直线 Edge 新增圆角/倒角。\n"
|
||||
"圆角/倒角:简单已有圆角半径/弧长、简单等半径圆角链半径/弧长、已有等距倒角距离,直线 Edge 新增圆角/倒角。\n"
|
||||
"Edge/解析曲面:直线 Edge 长度/端点/中心、圆/椭圆 Edge、简单圆锥/球/环面。\n"
|
||||
"受限:复杂链式特征、二级/三级拓扑传播和原 CAD 历史恢复。"
|
||||
)
|
||||
@@ -2566,7 +2582,16 @@ class WindowStateMixin:
|
||||
is_generic_surface = has_face and surface in FREEFORM_FACE_SURFACES
|
||||
is_hole_or_groove = is_cylinder and feature_guess == "hole/groove candidate"
|
||||
is_boss = is_cylinder and feature_guess == "boss/outer-round candidate"
|
||||
is_existing_fillet = is_cylinder and feature_guess == "round/fillet candidate"
|
||||
is_existing_fillet = (
|
||||
is_cylinder
|
||||
and feature_guess == "round/fillet candidate"
|
||||
and str(action_info.get("existing_fillet_status") or "") != "blocked"
|
||||
)
|
||||
is_existing_chamfer = (
|
||||
is_plane
|
||||
and feature_guess == "chamfer candidate"
|
||||
and str(action_info.get("existing_chamfer_status") or "") == "candidate"
|
||||
)
|
||||
recognition_fields_present = any(
|
||||
key in action_info
|
||||
for key in (
|
||||
@@ -2605,6 +2630,7 @@ class WindowStateMixin:
|
||||
and not is_full_cylinder
|
||||
and angular_span is not None
|
||||
and angular_span < math.tau * 0.92
|
||||
and str(action_info.get("slot_status") or "") == "candidate"
|
||||
and _float_or_none(action_info.get("slot_chord_width_estimate")) is not None
|
||||
)
|
||||
is_blind = action_info.get("cylinder_end_type") == "blind"
|
||||
@@ -2613,7 +2639,7 @@ class WindowStateMixin:
|
||||
_int_values(action_info.get("feature_start_end_face_ids"))
|
||||
or _int_values(action_info.get("feature_end_end_face_ids"))
|
||||
)
|
||||
show_generic_face_edit_specs = bool(has_face and (is_plane or is_shell_candidate))
|
||||
show_generic_face_edit_specs = bool(has_face and (is_plane or is_shell_candidate) and not is_existing_chamfer)
|
||||
local_face_deform_ready = bool(action_info.get("local_face_deform_ready", True))
|
||||
local_face_deform_blocker = str(action_info.get("local_face_deform_blocker") or "").strip()
|
||||
has_fillet_support = len(_int_values(action_info.get("feature_existing_fillet_support_face_ids"))) >= 2
|
||||
@@ -2978,6 +3004,11 @@ class WindowStateMixin:
|
||||
"工程特征 / 倒圆角:移除已有圆角后按目标半径重新倒圆。",
|
||||
"STEP 没有原始倒圆角历史时,只能基于当前圆角面和支撑面推断;复杂 blend 会阻止或回滚。",
|
||||
)
|
||||
if is_existing_chamfer:
|
||||
return (
|
||||
"工程特征 / 倒角:移除已有倒角斜面后按目标距离重新倒角。",
|
||||
"STEP 没有原始倒角历史时,只能基于当前斜面、支撑面和恢复出的锐边推断;倒角链或不等距倒角先保持受限。",
|
||||
)
|
||||
if is_shell_candidate:
|
||||
return (
|
||||
"工程特征 / 抽壳:按壳体厚度或相对面距离调整薄壁区域。",
|
||||
@@ -3062,6 +3093,11 @@ class WindowStateMixin:
|
||||
"优先改圆角半径;复杂圆角链先不要用整体缩放替代。",
|
||||
"已有圆角需要先恢复支撑锐边再重新倒圆,支撑面不明确时失败回滚是正常保护。",
|
||||
)
|
||||
if is_existing_chamfer:
|
||||
return (
|
||||
"优先改倒角距离;复杂倒角链先保持只读或重新选 Edge 新增倒角。",
|
||||
"已有倒角需要先移除斜面、恢复原始锐边再重新倒角;如果支撑面或长边不明确,会在计划阶段阻止。",
|
||||
)
|
||||
if is_shell_candidate:
|
||||
return (
|
||||
"优先改壳体厚度;普通位置变化再用偏移。",
|
||||
@@ -3243,6 +3279,16 @@ class WindowStateMixin:
|
||||
"再寻找可重新倒圆的锐边。复杂 blend 或支撑面不稳定时会阻止或回滚。"
|
||||
),
|
||||
)
|
||||
elif is_existing_chamfer:
|
||||
add_readonly_spec(
|
||||
key="existing_chamfer_edit_semantics",
|
||||
label="建模意图",
|
||||
text="倒角:移除已有倒角斜面,再尝试按目标距离重新倒角。",
|
||||
tip=(
|
||||
"已有倒角修改不是恢复 CAD 历史参数;当前会先 defeature 当前倒角斜面,"
|
||||
"再寻找恢复出的原始锐边并按目标距离重新倒角。复杂倒角链、不等距倒角或支撑面不稳定时会阻止或回滚。"
|
||||
),
|
||||
)
|
||||
elif is_cone or is_sphere or is_torus:
|
||||
add_readonly_spec(
|
||||
key="analytic_surface_edit_semantics",
|
||||
@@ -3502,7 +3548,7 @@ class WindowStateMixin:
|
||||
used=("area_center", "bbox_center"),
|
||||
)
|
||||
|
||||
if is_plane:
|
||||
if is_plane and not is_existing_chamfer:
|
||||
plane_origin = _triple_or_none(action_info.get("plane_origin"))
|
||||
plane_direction = (
|
||||
_triple_or_none(action_info.get("push_pull_outward_direction"))
|
||||
@@ -4547,6 +4593,35 @@ class WindowStateMixin:
|
||||
used=("existing_fillet_arc_length_estimate", "existing_fillet_angular_span", "angular_span"),
|
||||
**positive_minimum(),
|
||||
)
|
||||
if is_existing_chamfer:
|
||||
current_distance = _float_or_none(action_info.get("existing_chamfer_distance_estimate"))
|
||||
chamfer_hint = relative_range_hint(current_distance, 0.35, 1.0)
|
||||
cross_length = _float_or_none(action_info.get("existing_chamfer_cross_edge_length_estimate"))
|
||||
if cross_length is not None and cross_length > 0:
|
||||
chamfer_hint = (
|
||||
f"{chamfer_hint} 当前倒角截面边长约 {_format_float(cross_length)};"
|
||||
"目标距离过大时恢复锐边再倒角更容易失败。"
|
||||
)
|
||||
add_spec(
|
||||
key="existing_chamfer_distance_estimate",
|
||||
label="倒角距离",
|
||||
current_raw=current_distance if current_distance is not None else "",
|
||||
target_text=numeric_text(current_distance),
|
||||
action="resize_existing_chamfer",
|
||||
target_attr="edge_chamfer_distance_input",
|
||||
enabled=bool(current_distance is not None and current_distance > 0),
|
||||
enabled_tip="输入已有倒角面的目标距离;程序会先确认支撑面,再尝试移除旧倒角后重新倒角。",
|
||||
disabled_tip="当前倒角候选缺少稳定距离估算,暂不放行修改。",
|
||||
value_type="positive",
|
||||
range_hint=chamfer_hint,
|
||||
used=(
|
||||
"existing_chamfer_distance_estimate",
|
||||
"existing_chamfer_cross_edge_length_estimate",
|
||||
"feature_existing_chamfer_support_face_ids",
|
||||
"feature_existing_chamfer_long_edge_ids",
|
||||
),
|
||||
**positive_minimum(),
|
||||
)
|
||||
def analytic_surface_enabled(value_present: bool, capability_supported: bool = True) -> bool:
|
||||
return bool(value_present and capability_supported and analytic_surface_recognition_ready)
|
||||
|
||||
@@ -4773,6 +4848,7 @@ class WindowStateMixin:
|
||||
"auto": "自动选择:按局部边形变、端面移动、相邻圆柱编辑、缩放所属对象的顺序寻找可用路径。",
|
||||
"local-edge-only-deform": "只改当前Edge:移动被选Edge端点,相邻面自然变斜,整体端面不一起平移。",
|
||||
"move-edge-end-plane-by-push-pull": "移动端面/保持垂直:端面和端面上的相关边一起移动,相邻平面尽量保持垂直,正方体会更像变成长方体。",
|
||||
"keep-first-level-planar-relations": "保持关系:保持一级平面平行/垂直关系;只在直接相邻平面和移动端面能验证时执行,不能验证就直接阻止。",
|
||||
"resize-adjacent-cylinder-from-circular-edge-length": "相邻圆柱直径:把圆Edge长度换算成圆柱直径,优先改孔/槽/凸台局部特征。",
|
||||
"scale-owning-shape-from-edge": "缩放所属对象:所属特征或 Solid 整体跟随变化,其它尺寸也会变。",
|
||||
}.get(strategy_mode, "自动选择:程序会在确认窗口显示实际采用的策略。")
|
||||
@@ -4836,6 +4912,19 @@ class WindowStateMixin:
|
||||
),
|
||||
"preselect_combos": edge_length_strategy_preselect("move-edge-end-plane-by-push-pull"),
|
||||
},
|
||||
"keep-first-level-planar-relations": {
|
||||
"label": "保持关系",
|
||||
"action": "resize_any_edge_length",
|
||||
"target_attr": "edge_target_length_input",
|
||||
"enabled": bool(is_line_edge and current_length is not None),
|
||||
"enabled_tip": "输入当前Edge的目标长度;程序会尝试移动端面,并要求一级平面平行/垂直关系可验证。",
|
||||
"disabled_tip": "只有直线Edge才能尝试保持一级平面关系;圆Edge请用相邻圆柱,复杂曲线暂未实现。",
|
||||
"range_hint": (
|
||||
f"{edge_strategy_effect_text('keep-first-level-planar-relations', current_anchor_mode)} "
|
||||
f"{relative_range_hint(current_length, 0.25, 0.5)}"
|
||||
),
|
||||
"preselect_combos": edge_length_strategy_preselect("keep-first-level-planar-relations"),
|
||||
},
|
||||
"resize-adjacent-cylinder-from-circular-edge-length": {
|
||||
"label": "相邻圆柱",
|
||||
"action": "resize_any_edge_length",
|
||||
|
||||
Reference in New Issue
Block a user