N1: COM hatch non-associative (AddHatch associativity=False) N2: ezdxf refuses DWG saves with clear error; server.py derives fmt from extension R19: dimension_aligned dist→distance; dimension_angular correct add_angular_dim_2l args (base/line1/line2/location) R9: polar array 360° no-duplicate (divisor=n when fill_angle%360<ε) R13: entity_offset side_x/side_y honored in ezdxf via cross-product (LINE) and distance-to-center (CIRCLE) R18: drawing_new bootstrap failure surfaces status="degraded" instead of swallowing silently Dead code: engineering/section.py, gear.generate_tooth_profile, CommandResult, _ACI_NAMES, set_layer_active, ensure_linetypes, ComBackend._batch_mode instance attr, engineering/__init__ build-seam comment Ruff: 38 auto-fixed + 5 manual → codebase is now ruff-clean; CI lint is now blocking 184 tests pass.
174 lines
5.3 KiB
Python
174 lines
5.3 KiB
Python
"""DIN 6885 keyway geometry — bore + keyway cutter for shafts and hubs."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from backends.base import AutoCADBackend
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
DIN6885_TABLE: list[tuple[float, float, float, float, float]] = [
|
|
# (bore_min, bore_max, key_width, key_height, depth_in_shaft_t1)
|
|
(6, 8, 2, 2, 1.2),
|
|
(8, 10, 3, 3, 1.8),
|
|
(10, 12, 4, 4, 2.5),
|
|
(12, 17, 5, 5, 3.0),
|
|
(17, 22, 6, 6, 3.5),
|
|
(22, 30, 8, 7, 4.0),
|
|
(30, 38, 10, 8, 5.0),
|
|
(38, 44, 12, 8, 5.0),
|
|
(44, 50, 14, 9, 5.5),
|
|
(50, 58, 16, 10, 6.0),
|
|
(58, 65, 18, 11, 7.0),
|
|
(65, 75, 20, 12, 7.5),
|
|
(75, 85, 22, 14, 9.0),
|
|
(85, 95, 25, 14, 9.0),
|
|
(95, 110, 28, 16, 10.0),
|
|
(110, 130, 32, 18, 11.0),
|
|
]
|
|
|
|
|
|
def keyway_dimensions(bore_diameter: float) -> dict:
|
|
"""Look up DIN 6885 key width/height/depth for a given bore diameter (mm)."""
|
|
if bore_diameter < DIN6885_TABLE[0][0]:
|
|
raise ValueError(
|
|
f"bore_diameter {bore_diameter} mm is below DIN 6885 minimum "
|
|
f"({DIN6885_TABLE[0][0]} mm)."
|
|
)
|
|
if bore_diameter > DIN6885_TABLE[-1][1]:
|
|
raise ValueError(
|
|
f"bore_diameter {bore_diameter} mm exceeds DIN 6885 maximum "
|
|
f"({DIN6885_TABLE[-1][1]} mm)."
|
|
)
|
|
for b_min, b_max, width, height, t1 in DIN6885_TABLE:
|
|
if b_min < bore_diameter <= b_max or (bore_diameter == b_min and b_min == DIN6885_TABLE[0][0]):
|
|
return {
|
|
"width": float(width),
|
|
"height": float(height),
|
|
"depth_shaft": float(t1),
|
|
"depth_hub": float(height) - float(t1),
|
|
}
|
|
raise ValueError(f"No DIN 6885 row matched bore_diameter={bore_diameter}.")
|
|
|
|
|
|
async def draw_keyed_bore(
|
|
backend: AutoCADBackend,
|
|
*,
|
|
center: tuple[float, float],
|
|
bore_diameter: float,
|
|
keyway_width: float | None = None,
|
|
keyway_depth: float | None = None,
|
|
layer: str = "GEOMETRY",
|
|
center_layer: str = "CENTER",
|
|
) -> dict:
|
|
"""Draw bore + upward-opening keyway notch + horizontal/vertical centerlines."""
|
|
cx, cy = float(center[0]), float(center[1])
|
|
r = float(bore_diameter) / 2.0
|
|
|
|
if keyway_width is None or keyway_depth is None:
|
|
dims = keyway_dimensions(bore_diameter)
|
|
if keyway_width is None:
|
|
keyway_width = dims["width"]
|
|
if keyway_depth is None:
|
|
keyway_depth = dims["depth_hub"]
|
|
|
|
bore = await backend.entity_create_circle(cx, cy, r, layer=layer)
|
|
|
|
half_w = float(keyway_width) / 2.0
|
|
depth = float(keyway_depth)
|
|
bore_top_y = cy + r
|
|
notch_top_y = bore_top_y + depth
|
|
left_x = cx - half_w
|
|
right_x = cx + half_w
|
|
|
|
points = [
|
|
[left_x, bore_top_y],
|
|
[left_x, notch_top_y],
|
|
[right_x, notch_top_y],
|
|
[right_x, bore_top_y],
|
|
]
|
|
keyway_poly = await backend.entity_create_polyline(points, closed=False, layer=layer)
|
|
|
|
overshoot = max(r * 0.2, 5.0)
|
|
horiz = await backend.entity_create_line(
|
|
cx - r - overshoot, cy, cx + r + overshoot, cy, layer=center_layer,
|
|
)
|
|
vert = await backend.entity_create_line(
|
|
cx, cy - r - overshoot, cx, cy + r + depth + overshoot, layer=center_layer,
|
|
)
|
|
|
|
return {
|
|
"bore": bore.handle,
|
|
"keyway_polyline": keyway_poly.handle,
|
|
"centerline_h": horiz.handle,
|
|
"centerline_v": vert.handle,
|
|
}
|
|
|
|
|
|
async def draw_keyway_section(
|
|
backend: AutoCADBackend,
|
|
*,
|
|
center: tuple[float, float],
|
|
bore_diameter: float,
|
|
face_width: float,
|
|
keyway_width: float | None = None,
|
|
keyway_depth: float | None = None,
|
|
layer: str = "GEOMETRY",
|
|
) -> dict:
|
|
"""Side cross-section: bore as two horizontal lines with rectangular keyway notch on top."""
|
|
cx, cy = float(center[0]), float(center[1])
|
|
r = float(bore_diameter) / 2.0
|
|
half_face = float(face_width) / 2.0
|
|
|
|
if keyway_width is None or keyway_depth is None:
|
|
dims = keyway_dimensions(bore_diameter)
|
|
if keyway_width is None:
|
|
keyway_width = dims["width"]
|
|
if keyway_depth is None:
|
|
keyway_depth = dims["depth_hub"]
|
|
|
|
half_kw = float(keyway_width) / 2.0
|
|
depth = float(keyway_depth)
|
|
top_y = cy + r
|
|
bot_y = cy - r
|
|
notch_top_y = top_y + depth
|
|
x_left = cx - half_face
|
|
x_right = cx + half_face
|
|
notch_left = cx - half_kw
|
|
notch_right = cx + half_kw
|
|
|
|
bore_top = await backend.entity_create_line(
|
|
x_left, top_y, x_right, top_y, layer=layer,
|
|
)
|
|
bore_bottom = await backend.entity_create_line(
|
|
x_left, bot_y, x_right, bot_y, layer=layer,
|
|
)
|
|
|
|
notch_bottom = await backend.entity_create_line(
|
|
notch_left, top_y, notch_right, top_y, layer=layer,
|
|
)
|
|
notch_left_wall = await backend.entity_create_line(
|
|
notch_left, top_y, notch_left, notch_top_y, layer=layer,
|
|
)
|
|
notch_top = await backend.entity_create_line(
|
|
notch_left, notch_top_y, notch_right, notch_top_y, layer=layer,
|
|
)
|
|
notch_right_wall = await backend.entity_create_line(
|
|
notch_right, notch_top_y, notch_right, top_y, layer=layer,
|
|
)
|
|
|
|
return {
|
|
"bore_top": bore_top.handle,
|
|
"bore_bottom": bore_bottom.handle,
|
|
"keyway": [
|
|
notch_bottom.handle,
|
|
notch_left_wall.handle,
|
|
notch_top.handle,
|
|
notch_right_wall.handle,
|
|
],
|
|
}
|