brep_kernel/construction/
sweep_ellipsoid.rs1use crate::{sweep_solid, transform_brep, AffineTransform, BrepSolid, KernelRefusal, KernelStage, OrRefuse, OutlinePiece, ScrewStep, SolidMotion, SolidTool, Vec3};
12use std::f64::consts::FRAC_PI_2;
13
14pub fn sweep_ellipsoid_along_line(center: Vec3, x_direction: Vec3, y_hint: Vec3, semi_axes: [f64; 3], slide: Vec3) -> Result<BrepSolid, KernelRefusal> {
19 let input = |what: &'static str, message: &str| KernelRefusal::input(KernelStage::Collect, what, format!("sweepEllipsoid: {message}"));
20 if semi_axes.iter().any(|axis| !(axis.is_finite() && *axis > 0.0)) {
21 return Err(input("ellipsoid_axes", "the three semi-axes must be positive"));
22 }
23 let x = x_direction.normalized().map_err(|_| input("ellipsoid_frame", "the first direction must be non-zero"))?;
24 let y = y_hint.sub(x.scale(y_hint.dot(x))).normalized().map_err(|_| input("ellipsoid_frame", "the second direction must not be parallel to the first"))?;
25 let z = x.cross(y);
26 let [a, b, c] = semi_axes;
27 let seen = Vec3::new(slide.dot(x) / a, slide.dot(y) / b, slide.dot(z) / c);
29 let along = seen.normalized().map_err(|_| input("slide", "the slide has no length"))?;
30 let across = if along.x.abs() < 0.9 { Vec3::new(1.0, 0.0, 0.0) } else { Vec3::new(0.0, 1.0, 0.0) };
31 let radial = across.sub(along.scale(across.dot(along))).normalized().or_refuse(KernelStage::Collect, "sweepEllipsoid.frame")?;
32 let origin = Vec3::new(0.0, 0.0, 0.0);
33 let ball = SolidTool::Revolved {
35 axis_origin: origin,
36 axis_direction: along,
37 radial,
38 meridian: vec![
39 OutlinePiece::Arc { centre: [0.0, 0.0], radius: 1.0, start: -FRAC_PI_2, end: FRAC_PI_2 },
40 OutlinePiece::Line { from: [0.0, 1.0], to: [0.0, -1.0] },
41 ],
42 };
43 let motion = SolidMotion { steps: vec![ScrewStep { axis_origin: origin, axis_direction: along, turn: 0.0, advance: seen.length() }], from: 0.0, to: 1.0 };
44 let swept = sweep_solid(&ball, &motion)?;
45 let (ex, ey, ez) = (x.scale(a), y.scale(b), z.scale(c));
46 let map = AffineTransform { elements: [ex.x, ey.x, ez.x, center.x, ex.y, ey.y, ez.y, center.y, ex.z, ey.z, ez.z, center.z, 0.0, 0.0, 0.0, 1.0] };
47 transform_brep(&swept, map, false).or_refuse(KernelStage::Collect, "sweepEllipsoid.stretch")
48}
49