feat: extrude Arc and Circle thickness along WCS normal
Arc: tessellates bottom + top arcs (32 segs each) with 2 endpoint walls. Circle: tessellates bottom + top circles (64 segs each) with 4 quadrant walls. Both use TruckObject::Lines with NaN-separated segments. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ce17e8abdf
commit
c51eeb4ad0
2 changed files with 105 additions and 22 deletions
|
|
@ -45,20 +45,61 @@ fn to_truck(arc: &Arc) -> TruckEntity {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let cv = Vec3::new(cwx as f32, cwy as f32, cwz as f32);
|
||||||
|
let tangent = TangentGeom::Circle {
|
||||||
|
center: [cwx as f32, cwy as f32, cwz as f32],
|
||||||
|
radius: r as f32,
|
||||||
|
};
|
||||||
|
|
||||||
|
if arc.thickness.abs() > 1e-10 {
|
||||||
|
let t = arc.thickness;
|
||||||
|
let (nx, ny, nz) = normal;
|
||||||
|
let n = 32usize;
|
||||||
|
let (start_a, end_a) = if arc.normal.z < 0.0 {
|
||||||
|
let cw_span = if sa >= ea { sa - ea } else { sa - ea + TAU };
|
||||||
|
(sa, sa - cw_span)
|
||||||
|
} else {
|
||||||
|
let ccw_end = if ea >= sa { ea } else { ea + TAU };
|
||||||
|
(sa, ccw_end)
|
||||||
|
};
|
||||||
|
let mut pts: Vec<[f32; 3]> = Vec::with_capacity((n + 1) * 2 + 8);
|
||||||
|
for i in 0..=n {
|
||||||
|
let a = start_a + (end_a - start_a) * (i as f64 / n as f64);
|
||||||
|
let p = arc_pt(a);
|
||||||
|
pts.push([p.x as f32, p.y as f32, p.z as f32]);
|
||||||
|
}
|
||||||
|
pts.push([f32::NAN; 3]);
|
||||||
|
for i in 0..=n {
|
||||||
|
let a = start_a + (end_a - start_a) * (i as f64 / n as f64);
|
||||||
|
let p = arc_pt(a);
|
||||||
|
pts.push([(p.x + t * nx) as f32, (p.y + t * ny) as f32, (p.z + t * nz) as f32]);
|
||||||
|
}
|
||||||
|
pts.push([f32::NAN; 3]);
|
||||||
|
let ps = arc_pt(sa);
|
||||||
|
pts.push([ps.x as f32, ps.y as f32, ps.z as f32]);
|
||||||
|
pts.push([(ps.x + t * nx) as f32, (ps.y + t * ny) as f32, (ps.z + t * nz) as f32]);
|
||||||
|
pts.push([f32::NAN; 3]);
|
||||||
|
let pe = arc_pt(ea);
|
||||||
|
pts.push([pe.x as f32, pe.y as f32, pe.z as f32]);
|
||||||
|
pts.push([(pe.x + t * nx) as f32, (pe.y + t * ny) as f32, (pe.z + t * nz) as f32]);
|
||||||
|
return TruckEntity {
|
||||||
|
object: TruckObject::Lines(pts),
|
||||||
|
snap_pts: vec![(cv, SnapHint::Center)],
|
||||||
|
tangent_geoms: vec![tangent],
|
||||||
|
key_vertices: vec![],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let p_start = arc_pt(sa);
|
let p_start = arc_pt(sa);
|
||||||
let p_end = arc_pt(ea);
|
let p_end = arc_pt(ea);
|
||||||
let p_mid = arc_pt(mid_a);
|
let p_mid = arc_pt(mid_a);
|
||||||
let v_start = builder::vertex(p_start);
|
let v_start = builder::vertex(p_start);
|
||||||
let v_end = builder::vertex(p_end);
|
let v_end = builder::vertex(p_end);
|
||||||
let edge = builder::circle_arc(&v_start, &v_end, p_mid);
|
let edge = builder::circle_arc(&v_start, &v_end, p_mid);
|
||||||
let cv = Vec3::new(cwx as f32, cwy as f32, cwz as f32);
|
|
||||||
TruckEntity {
|
TruckEntity {
|
||||||
object: TruckObject::Curve(edge),
|
object: TruckObject::Curve(edge),
|
||||||
snap_pts: vec![(cv, SnapHint::Center)],
|
snap_pts: vec![(cv, SnapHint::Center)],
|
||||||
tangent_geoms: vec![TangentGeom::Circle {
|
tangent_geoms: vec![tangent],
|
||||||
center: [cwx as f32, cwy as f32, cwz as f32],
|
|
||||||
radius: r as f32,
|
|
||||||
}],
|
|
||||||
key_vertices: vec![],
|
key_vertices: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,6 @@ fn to_truck(circle: &Circle) -> TruckEntity {
|
||||||
let p_top = pt(ay, (0.0, 0.0, 0.0), r);
|
let p_top = pt(ay, (0.0, 0.0, 0.0), r);
|
||||||
let p_bot = pt((ay.0 * -1.0, ay.1 * -1.0, ay.2 * -1.0), (0.0, 0.0, 0.0), r);
|
let p_bot = pt((ay.0 * -1.0, ay.1 * -1.0, ay.2 * -1.0), (0.0, 0.0, 0.0), r);
|
||||||
|
|
||||||
let right = builder::vertex(p_right);
|
|
||||||
let left = builder::vertex(p_left);
|
|
||||||
let upper = builder::circle_arc(&right, &left, p_top);
|
|
||||||
let lower = builder::circle_arc(&left, &right, p_bot);
|
|
||||||
let wire: Wire = [upper, lower].into_iter().collect();
|
|
||||||
|
|
||||||
let cv = Vec3::new(cwx as f32, cwy as f32, cwz as f32);
|
let cv = Vec3::new(cwx as f32, cwy as f32, cwz as f32);
|
||||||
let rf = r as f32;
|
let rf = r as f32;
|
||||||
let q = |d: (f64, f64, f64)| Vec3::new(
|
let q = |d: (f64, f64, f64)| Vec3::new(
|
||||||
|
|
@ -48,19 +42,67 @@ fn to_truck(circle: &Circle) -> TruckEntity {
|
||||||
(cwy + r * d.1) as f32,
|
(cwy + r * d.1) as f32,
|
||||||
(cwz + r * d.2) as f32,
|
(cwz + r * d.2) as f32,
|
||||||
);
|
);
|
||||||
|
let snap_pts = vec![
|
||||||
|
(cv, SnapHint::Center),
|
||||||
|
(q(ax), SnapHint::Quadrant),
|
||||||
|
(q(ay), SnapHint::Quadrant),
|
||||||
|
(q((-ax.0, -ax.1, -ax.2)), SnapHint::Quadrant),
|
||||||
|
(q((-ay.0, -ay.1, -ay.2)), SnapHint::Quadrant),
|
||||||
|
];
|
||||||
|
let tangent = TangentGeom::Circle {
|
||||||
|
center: [cwx as f32, cwy as f32, cwz as f32],
|
||||||
|
radius: rf,
|
||||||
|
};
|
||||||
|
|
||||||
|
if circle.thickness.abs() > 1e-10 {
|
||||||
|
let t = circle.thickness;
|
||||||
|
let (nx, ny, nz) = normal;
|
||||||
|
let n = 64usize;
|
||||||
|
let tau = std::f64::consts::TAU;
|
||||||
|
let circ_pt = |a: f64| -> (f64, f64, f64) {
|
||||||
|
let (c, s) = (a.cos(), a.sin());
|
||||||
|
(
|
||||||
|
cwx + r * (c * ax.0 + s * ay.0),
|
||||||
|
cwy + r * (c * ax.1 + s * ay.1),
|
||||||
|
cwz + r * (c * ax.2 + s * ay.2),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let mut pts: Vec<[f32; 3]> = Vec::with_capacity((n + 1) * 2 + 4 * 3);
|
||||||
|
for i in 0..=n {
|
||||||
|
let (x, y, z) = circ_pt(i as f64 * tau / n as f64);
|
||||||
|
pts.push([x as f32, y as f32, z as f32]);
|
||||||
|
}
|
||||||
|
pts.push([f32::NAN; 3]);
|
||||||
|
for i in 0..=n {
|
||||||
|
let (x, y, z) = circ_pt(i as f64 * tau / n as f64);
|
||||||
|
pts.push([(x + t * nx) as f32, (y + t * ny) as f32, (z + t * nz) as f32]);
|
||||||
|
}
|
||||||
|
pts.push([f32::NAN; 3]);
|
||||||
|
for i in 0..4usize {
|
||||||
|
let (x, y, z) = circ_pt(i as f64 * std::f64::consts::FRAC_PI_2);
|
||||||
|
pts.push([x as f32, y as f32, z as f32]);
|
||||||
|
pts.push([(x + t * nx) as f32, (y + t * ny) as f32, (z + t * nz) as f32]);
|
||||||
|
if i < 3 {
|
||||||
|
pts.push([f32::NAN; 3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TruckEntity {
|
||||||
|
object: TruckObject::Lines(pts),
|
||||||
|
snap_pts,
|
||||||
|
tangent_geoms: vec![tangent],
|
||||||
|
key_vertices: vec![],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let right = builder::vertex(p_right);
|
||||||
|
let left = builder::vertex(p_left);
|
||||||
|
let upper = builder::circle_arc(&right, &left, p_top);
|
||||||
|
let lower = builder::circle_arc(&left, &right, p_bot);
|
||||||
|
let wire: Wire = [upper, lower].into_iter().collect();
|
||||||
TruckEntity {
|
TruckEntity {
|
||||||
object: TruckObject::Contour(wire),
|
object: TruckObject::Contour(wire),
|
||||||
snap_pts: vec![
|
snap_pts,
|
||||||
(cv, SnapHint::Center),
|
tangent_geoms: vec![tangent],
|
||||||
(q(ax), SnapHint::Quadrant),
|
|
||||||
(q(ay), SnapHint::Quadrant),
|
|
||||||
(q((-ax.0, -ax.1, -ax.2)), SnapHint::Quadrant),
|
|
||||||
(q((-ay.0, -ay.1, -ay.2)), SnapHint::Quadrant),
|
|
||||||
],
|
|
||||||
tangent_geoms: vec![TangentGeom::Circle {
|
|
||||||
center: [cwx as f32, cwy as f32, cwz as f32],
|
|
||||||
radius: rf,
|
|
||||||
}],
|
|
||||||
key_vertices: vec![],
|
key_vertices: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue