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,
|
||||
'beta': 0.3,
|
||||
'R_edge': 15.0,
|
||||
's_min': 12.0,
|
||||
's_max': 35.0,
|
||||
's_min': 45.0,
|
||||
's_max': 55.0,
|
||||
't_min': 2.5,
|
||||
't_0': 3.0,
|
||||
'gamma': 1.0,
|
||||
|
||||
@@ -84,7 +84,7 @@ def build_pslg(geometry, params):
|
||||
# r_boss = r_hole + d_keep * hole_diameter / 2
|
||||
hole_radius = diameter / 2.0
|
||||
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:
|
||||
# Fallback for non-circular holes
|
||||
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)
|
||||
|
||||
# Initial triangulation with global max area
|
||||
s_max = params['s_max']
|
||||
global_max_area = (np.sqrt(3) / 4.0) * s_max**2
|
||||
|
||||
# Triangle options: p=PSLG, q30=min angle 30°, a=area constraint, D=conforming Delaunay
|
||||
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']
|
||||
# Use s_min as the uniform target spacing for initial/non-adaptive pass.
|
||||
# Density-adaptive refinement only kicks in when stress results are
|
||||
# available (future iterations). For now, uniform triangles everywhere.
|
||||
s_target = params['s_min']
|
||||
use_adaptive = params.get('adaptive_density', False)
|
||||
|
||||
areas = compute_triangle_areas(verts, tris)
|
||||
centroids = compute_centroids(verts, tris)
|
||||
# Target equilateral triangle area for the chosen spacing
|
||||
target_area = (np.sqrt(3) / 4.0) * s_target**2
|
||||
|
||||
# Compute target area for each triangle based on density at centroid
|
||||
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
|
||||
])
|
||||
# Triangle options: p=PSLG, q30=min angle 30°, a=area constraint, D=conforming
|
||||
result = tr.triangulate(pslg, f'pq30Da{target_area:.1f}')
|
||||
|
||||
# Check if all triangles satisfy constraints (20% tolerance)
|
||||
if np.all(areas <= target_areas * 1.2):
|
||||
break
|
||||
if use_adaptive:
|
||||
# Iterative density-adaptive refinement (for stress-informed passes)
|
||||
for iteration in range(max_refinement_passes):
|
||||
verts = result['vertices']
|
||||
tris = result['triangles']
|
||||
|
||||
# Set per-triangle max area and refine
|
||||
result['triangle_max_area'] = target_areas
|
||||
result = tr.triangulate(result, 'rpq30D')
|
||||
areas = compute_triangle_areas(verts, tris)
|
||||
centroids = compute_centroids(verts, tris)
|
||||
|
||||
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)
|
||||
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