提交关于N5功能,“involute_gear渐开线齿廓与齿条专用生成”的改动

This commit is contained in:
2026-09-08 13:47:24 +08:00
parent f48ba19dfa
commit 673ae62e70
14 changed files with 774 additions and 13 deletions
+51 -1
View File
@@ -12,7 +12,7 @@ from .build123d_adapter import Build123dGeometryAdapter
from .capabilities import CapabilityAnalyzer, pattern_transform_blocker, sketch_ids_required_by_contract
from .runtime_types import (
AxisSpec, BendSpec, CapabilityResult, FeaturePlanNode, FeatureResult, HoleSpec, PlaneSpec,
ThreadSpec, Vector3,
GearSpec, RackSpec, ThreadSpec, Vector3,
RuntimeDiagnostic, SelectorResolution, TopologyRecord, TopologyRegistry,
vector_add, vector_cross, vector_dot, vector_scale, vector_subtract, vector_unit,
)
@@ -29,6 +29,7 @@ ALL_ATOMIC_IDS = frozenset({
"pattern_circular",
"thread_add", "thread_cut",
"bend_add",
"gear_add", "rack_add",
})
@@ -92,6 +93,8 @@ class GeometryAdapter(Protocol):
def sphere(self, radius_mm: float, center_mm: Vector3) -> Any: ...
def thread_solid(self, spec: ThreadSpec) -> Any: ...
def bend_solid(self, spec: BendSpec) -> Any: ...
def gear_solid(self, spec: GearSpec) -> Any: ...
def rack_solid(self, spec: RackSpec) -> Any: ...
def hole_tool(self, spec: HoleSpec, starts: list[Vector3], inward: Vector3, through_depth_mm: float) -> Any: ...
def body_center(self, body: Any) -> Vector3: ...
def body_span(self, body: Any, direction: Vector3) -> float: ...
@@ -636,6 +639,51 @@ def _bend_executor(node: FeaturePlanNode, session: ExecutionSession, sketch: dic
return _execute_bend(node, session)
def _execute_gear(node: FeaturePlanNode, session: ExecutionSession) -> FeatureResult:
# 齿轮特征(gear_add)执行入口:按规格生成渐开线齿轮并入当前主体。
# 1. 解析并校验模数/齿数/齿宽/螺旋角与放置轴,非法输入抛出带具体原因的 ValueError。
spec = GearSpec.from_feature(node.params)
# 2. 由适配器门面生成沿 spec.axis 放置的齿轮实体(直齿/斜齿/人字齿)。
solid = session.adapter.gear_solid(spec)
# 3. 与当前主体做布尔并(fuse)后登记为新主体,并返回该特征的结果对象。
session.register_body(node.feature_id, session.adapter.fuse(session.body, solid), replay_node=node)
# 4. 小齿数根切风险:不阻断执行,附加 info 级诊断供完成报告如实披露。
diagnostics: list[RuntimeDiagnostic] = []
if spec.teeth_count < 17:
diagnostics.append(RuntimeDiagnostic(
code="undercut_risk",
message=(
f"Gear with {spec.teeth_count} teeth and a 20 degree pressure angle is undercut-prone; "
"standard involute geometry is generated without profile shift"
),
feature_id=node.feature_id,
))
return session.result(node, diagnostics=diagnostics)
def _gear_executor(node: FeaturePlanNode, session: ExecutionSession, sketch: dict[str, Any] | None) -> FeatureResult:
# 齿轮特征(gear_add)不需要草图平面,丢弃该参数后执行。
del sketch
return _execute_gear(node, session)
def _execute_rack(node: FeaturePlanNode, session: ExecutionSession) -> FeatureResult:
# 齿条特征(rack_add)执行入口:按规格生成直线齿条并入当前主体。
# 1. 解析并校验模数/齿数/厚度/压力角与放置轴,非法输入抛出带具体原因的 ValueError。
spec = RackSpec.from_feature(node.params)
# 2. 由适配器门面生成沿 spec.axis 放置的齿条实体(齿沿轴方向伸出)。
solid = session.adapter.rack_solid(spec)
# 3. 与当前主体做布尔并(fuse)后登记为新主体,并返回该特征的结果对象。
session.register_body(node.feature_id, session.adapter.fuse(session.body, solid), replay_node=node)
return session.result(node)
def _rack_executor(node: FeaturePlanNode, session: ExecutionSession, sketch: dict[str, Any] | None) -> FeatureResult:
# 齿条特征(rack_add)不需要草图平面,丢弃该参数后执行。
del sketch
return _execute_rack(node, session)
def _host_plane(resolution: SelectorResolution) -> PlaneSpec:
if resolution.record is None:
raise ValueError(resolution.diagnostic.message if resolution.diagnostic else "host face was not resolved")
@@ -1439,6 +1487,8 @@ EXECUTORS: dict[str, ExecutorFunction] = {
"thread_add": _thread_executor,
"thread_cut": _thread_executor,
"bend_add": _bend_executor,
"gear_add": _gear_executor,
"rack_add": _rack_executor,
"extrude_add_blind": _primary_executor,
"extrude_add_two_sided": _primary_executor,
"extrude_cut_blind": _primary_executor,