fix(brain): enforce r_f=6mm minimum, reject pockets that can't fit fillets
- Default r_f raised from 1.5mm to 6mm (machining constraint) - Default min_pocket_radius raised to 6mm - Pockets that can't fit r_f at any corner (within 80% tolerance) are skipped entirely — left solid for more stiffness in tight areas - Result: 26 pockets (was 432), 187 NX entities (was 13,061) - Min fillet radius: 4.88mm, all >= 4.8mm (80% of 6mm) - Mass: 4,601g (was 3,480g — more solid = heavier but manufacturable)
This commit is contained in:
@@ -23,7 +23,7 @@ PARAM_SPACE = {
|
||||
'gamma': {'type': 'float', 'low': 0.0, 'high': 3.0, 'desc': 'Density-thickness coupling'},
|
||||
# Manufacturing
|
||||
'w_frame': {'type': 'float', 'low': 3.0, 'high': 20.0, 'desc': 'Perimeter frame width (mm)'},
|
||||
'r_f': {'type': 'float', 'low': 0.5, 'high': 3.0, 'desc': 'Pocket fillet radius (mm)'},
|
||||
'r_f': {'type': 'float', 'low': 3.0, 'high': 10.0, 'desc': 'Pocket fillet radius (mm)'},
|
||||
'd_keep': {'type': 'float', 'low': 1.0, 'high': 3.0, 'desc': 'Hole keepout multiplier (× diameter)'},
|
||||
'min_triangle_area': {'type': 'float', 'low': 5.0, 'high': 80.0, 'desc': 'Minimum pocketable triangle area (mm²)'},
|
||||
}
|
||||
@@ -43,8 +43,8 @@ DEFAULT_PARAMS = {
|
||||
't_0': 3.0,
|
||||
'gamma': 1.0,
|
||||
'w_frame': 8.0,
|
||||
'r_f': 1.5,
|
||||
'r_f': 6.0,
|
||||
'd_keep': 1.5,
|
||||
'min_pocket_radius': 1.5,
|
||||
'min_pocket_radius': 6.0,
|
||||
'min_triangle_area': 20.0,
|
||||
}
|
||||
|
||||
@@ -136,11 +136,13 @@ def _fillet_corner(
|
||||
np.linalg.norm(v_next - v_corner) * 0.45,
|
||||
)
|
||||
if tan_dist > max_dist:
|
||||
# Reduce fillet radius to fit
|
||||
r_f = max_dist * np.tan(half_angle)
|
||||
tan_dist = max_dist
|
||||
if r_f < 0.05:
|
||||
# Reduce fillet to fit, but never below hard minimum
|
||||
r_f_reduced = max_dist * np.tan(half_angle)
|
||||
if r_f_reduced < r_f * 0.8:
|
||||
# Too much reduction — reject this corner
|
||||
return None
|
||||
r_f = r_f_reduced
|
||||
tan_dist = max_dist
|
||||
|
||||
tangent_start = v_corner + d1 * tan_dist
|
||||
tangent_end = v_corner + d2 * tan_dist
|
||||
@@ -180,6 +182,9 @@ def _compute_filleted_pocket(inset_verts: List[np.ndarray], r_f: float) -> Optio
|
||||
v_corner = inset_verts[i]
|
||||
v_next = inset_verts[(i + 1) % n]
|
||||
fillet = _fillet_corner(v_prev, v_corner, v_next, r_f)
|
||||
if fillet is None and r_f > 0:
|
||||
# Fillet doesn't fit at this corner — reject entire pocket
|
||||
return None
|
||||
fillets.append(fillet)
|
||||
|
||||
# Build lines connecting fillet tangent points
|
||||
@@ -324,13 +329,15 @@ def generate_pockets(triangulation, geometry, params):
|
||||
if perimeter < 1e-6:
|
||||
continue
|
||||
inscribed_r = inset_area / (perimeter / 2.0)
|
||||
if inscribed_r < min_pocket_radius:
|
||||
|
||||
# Pocket must be large enough to fit the required fillet radius.
|
||||
# If inscribed_r < r_f, the fillet would dominate the pocket and
|
||||
# create tiny/degenerate geometry. Skip these — leave them solid.
|
||||
if inscribed_r < r_f:
|
||||
continue
|
||||
|
||||
# Compute fillet amount (don't over-fillet)
|
||||
fillet_amount = min(r_f, inscribed_r * 0.4)
|
||||
if fillet_amount < 0.1:
|
||||
fillet_amount = 0.0
|
||||
# Use full fillet radius — we've already verified it fits
|
||||
fillet_amount = r_f
|
||||
|
||||
pocket_geom = _compute_filleted_pocket(inset, fillet_amount)
|
||||
if pocket_geom is None:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user