///|
pub fn compile_calibration_chamfer_block(
ctx : StepContext,
node : SceneNode,
block : CalibrationChamferBlock,
reverse~ : Bool = false,
parent~ : Transform? = None,
) -> Array[@step.Ref] {
let xform = node_transform(node, parent)
let l = block.length_mm
let w = block.width_mm
let h = block.height_mm
let fillet_radius_mm = block.fillet_radius_mm
let fillet_segments = block.fillet_segments
let chamfer_size_mm = block.chamfer_size_mm
// Build a stack of inset rectangles (offset) along Z.
let rings : Array[(Double, Double)] = []
rings.push((0.0, 0.0))
if fillet_radius_mm > 0.0 {
let r = fillet_radius_mm
let start_z = h - r
rings.push((start_z, 0.0))
let segs = if fillet_segments <= 0 { 8 } else { fillet_segments }
for i in 1..<=segs {
let phi = Double::from_int(i) * (@math.PI / 2.0) / Double::from_int(segs)
let offset = r - r * @math.cos(phi)
let z = h - r + r * @math.sin(phi)
rings.push((z, offset))
}
} else if chamfer_size_mm > 0.0 {
let c = chamfer_size_mm
rings.push((h - c, 0.0))
rings.push((h, c))
} else {
rings.push((h, 0.0))
}
// Points (mm)
let pts_raw = rings
.iter()
.flat_map(fn(ring) {
let (rz, ro) = ring
let px0 = ro
let px1 = l - ro
let py0 = ro
let py1 = w - ro
[(px0, py0, rz), (px1, py0, rz), (px1, py1, rz), (px0, py1, rz)].iter()
})
.collect()
// Transform all points: Rotate then Translate (parent applied last)
let pts = pts_raw.map(fn(pt) { xform.apply(pt) })
// Cartesian points
let cp_refs = pts.map(fn(pt) {
let (px, py, pz) = pt
ctx.cartesian_point(px, py, pz)
})
// Vertex points
let vp_refs = cp_refs.map(fn(cp_ref) { ctx.vertex_point(cp_ref) })
let edges : Array[EdgeInfo] = []
let seen : Map[String, Bool] = Map([])
let add_edge = fn(a : Int32, b : Int32) -> Unit {
let key = if a < b { "\{a}:\{b}" } else { "\{b}:\{a}" }
if seen.get(key).unwrap_or(false) {
return
}
seen.set(key, true)
let start = if a < b { a } else { b }
let end = if a < b { b } else { a }
let dir_raw = v_norm(v_sub(pts[end], pts[start]))
let dir_ref = ctx.direction(dir_raw.0, dir_raw.1, dir_raw.2)
let vec_ref = ctx.vector(dir_ref, 1.0)
let line_ref = ctx.line(cp_refs[start], vec_ref)
let ec_ref = ctx.edge_curve(vp_refs[start], vp_refs[end], line_ref, true)
edges.push(EdgeInfo::{ start, end, edge: ec_ref, })
}
// Per-ring perimeter edges
for ri in 0..