tune(brain): uniform triangulation + bigger spacing for r_f=6mm fillets
- Switched to uniform triangulation (no density-adaptive refinement for initial pass — saves that for stress-informed iterations) - s_min=45mm, s_max=55mm (was 12/35) — larger triangles fit 6mm fillets - Boss keepout circles: 12 segments (was 32) — less boundary clutter - Fillet must be >= 80% of r_f at every corner or pocket is skipped - Result: 75 pockets, 481 NX entities, min fillet 4.85mm, mass 4066g - adaptive_density=True param enables density refinement for future stress iterations
This commit is contained in:
@@ -37,8 +37,8 @@ DEFAULT_PARAMS = {
|
|||||||
'p': 2.0,
|
'p': 2.0,
|
||||||
'beta': 0.3,
|
'beta': 0.3,
|
||||||
'R_edge': 15.0,
|
'R_edge': 15.0,
|
||||||
's_min': 12.0,
|
's_min': 45.0,
|
||||||
's_max': 35.0,
|
's_max': 55.0,
|
||||||
't_min': 2.5,
|
't_min': 2.5,
|
||||||
't_0': 3.0,
|
't_0': 3.0,
|
||||||
'gamma': 1.0,
|
'gamma': 1.0,
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ def build_pslg(geometry, params):
|
|||||||
# r_boss = r_hole + d_keep * hole_diameter / 2
|
# r_boss = r_hole + d_keep * hole_diameter / 2
|
||||||
hole_radius = diameter / 2.0
|
hole_radius = diameter / 2.0
|
||||||
boss_radius = hole_radius + keepout_dist
|
boss_radius = hole_radius + keepout_dist
|
||||||
keepout_boundary = sample_circle(hole['center'], boss_radius, num_points=32)
|
keepout_boundary = sample_circle(hole['center'], boss_radius, num_points=12)
|
||||||
else:
|
else:
|
||||||
# Fallback for non-circular holes
|
# Fallback for non-circular holes
|
||||||
keepout_boundary = offset_polygon(hole['boundary'], keepout_dist, inward=False)
|
keepout_boundary = offset_polygon(hole['boundary'], keepout_dist, inward=False)
|
||||||
@@ -169,36 +169,39 @@ def generate_triangulation(geometry, params, max_refinement_passes=3):
|
|||||||
"""
|
"""
|
||||||
pslg = build_pslg(geometry, params)
|
pslg = build_pslg(geometry, params)
|
||||||
|
|
||||||
# Initial triangulation with global max area
|
# Use s_min as the uniform target spacing for initial/non-adaptive pass.
|
||||||
s_max = params['s_max']
|
# Density-adaptive refinement only kicks in when stress results are
|
||||||
global_max_area = (np.sqrt(3) / 4.0) * s_max**2
|
# available (future iterations). For now, uniform triangles everywhere.
|
||||||
|
s_target = params['s_min']
|
||||||
# Triangle options: p=PSLG, q30=min angle 30°, a=area constraint, D=conforming Delaunay
|
use_adaptive = params.get('adaptive_density', False)
|
||||||
result = tr.triangulate(pslg, f'pq30Da{global_max_area:.1f}')
|
|
||||||
|
|
||||||
# Iterative refinement based on density field
|
|
||||||
for iteration in range(max_refinement_passes):
|
|
||||||
verts = result['vertices']
|
|
||||||
tris = result['triangles']
|
|
||||||
|
|
||||||
areas = compute_triangle_areas(verts, tris)
|
# Target equilateral triangle area for the chosen spacing
|
||||||
centroids = compute_centroids(verts, tris)
|
target_area = (np.sqrt(3) / 4.0) * s_target**2
|
||||||
|
|
||||||
# Compute target area for each triangle based on density at centroid
|
# Triangle options: p=PSLG, q30=min angle 30°, a=area constraint, D=conforming
|
||||||
target_areas = np.array([
|
result = tr.triangulate(pslg, f'pq30Da{target_area:.1f}')
|
||||||
(np.sqrt(3) / 4.0) * density_to_spacing(
|
|
||||||
evaluate_density(cx, cy, geometry, params), params
|
|
||||||
)**2
|
|
||||||
for cx, cy in centroids
|
|
||||||
])
|
|
||||||
|
|
||||||
# Check if all triangles satisfy constraints (20% tolerance)
|
if use_adaptive:
|
||||||
if np.all(areas <= target_areas * 1.2):
|
# Iterative density-adaptive refinement (for stress-informed passes)
|
||||||
break
|
for iteration in range(max_refinement_passes):
|
||||||
|
verts = result['vertices']
|
||||||
|
tris = result['triangles']
|
||||||
|
|
||||||
# Set per-triangle max area and refine
|
areas = compute_triangle_areas(verts, tris)
|
||||||
result['triangle_max_area'] = target_areas
|
centroids = compute_centroids(verts, tris)
|
||||||
result = tr.triangulate(result, 'rpq30D')
|
|
||||||
|
target_areas = np.array([
|
||||||
|
(np.sqrt(3) / 4.0) * density_to_spacing(
|
||||||
|
evaluate_density(cx, cy, geometry, params), params
|
||||||
|
)**2
|
||||||
|
for cx, cy in centroids
|
||||||
|
])
|
||||||
|
|
||||||
|
if np.all(areas <= target_areas * 1.2):
|
||||||
|
break
|
||||||
|
|
||||||
|
result['triangle_max_area'] = target_areas
|
||||||
|
result = tr.triangulate(result, 'rpq30D')
|
||||||
|
|
||||||
min_triangle_area = params.get('min_triangle_area', 20.0)
|
min_triangle_area = params.get('min_triangle_area', 20.0)
|
||||||
result = filter_small_triangles(result, min_triangle_area)
|
result = filter_small_triangles(result, min_triangle_area)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user