axiolid_curve/
torus_section.rs1use axiolid_core::{Frame3, Point3, Scalar, Vec3};
24
25use crate::quadric_section::{Branch, Trig2};
26
27#[derive(Debug, Clone, Copy, PartialEq)]
31pub struct AngleGraph2 {
32 pub a: Trig2,
34 pub b: Trig2,
36 pub c: Trig2,
38 pub branch: Branch,
40}
41
42impl AngleGraph2 {
43 #[must_use]
45 pub fn angle(&self, t: Scalar) -> Option<Scalar> {
46 let (a, b, c) = (self.a.value(t), self.b.value(t), self.c.value(t));
47 let rr = a * a + b * b;
48 if rr == 0.0 {
49 return None;
50 }
51 let e = rr - c * c;
52 let size =
55 |t: &Trig2| t.constant.abs() + t.cos.abs() + t.sin.abs() + t.cos2.abs() + t.sin2.abs();
56 let scale = size(&self.a).powi(2) + size(&self.b).powi(2) + size(&self.c).powi(2);
57 if e < -1e-12 * scale {
58 return None;
59 }
60 let root = e.max(0.0).sqrt();
61 let s = self.branch.sign();
62 let u = (b * c + s * a * root).atan2(a * c - s * b * root);
63 u.is_finite().then_some(u)
64 }
65
66 #[must_use]
69 pub fn slope(&self, t: Scalar) -> Option<Scalar> {
70 let u = self.angle(t)?;
71 let (s, c) = u.sin_cos();
72 let f_t = self.a.derivative(t) * c + self.b.derivative(t) * s - self.c.derivative(t);
73 let f_u = -self.a.value(t) * s + self.b.value(t) * c;
74 let slope = -f_t / f_u;
75 slope.is_finite().then_some(slope)
76 }
77
78 #[must_use]
80 pub fn bend(&self, t: Scalar) -> Option<Scalar> {
81 let u = self.angle(t)?;
82 let p = self.slope(t)?;
83 let (s, c) = u.sin_cos();
84 let (a, b) = (self.a.value(t), self.b.value(t));
85 let (da, db) = (self.a.derivative(t), self.b.derivative(t));
86 let f_u = -a * s + b * c;
87 let f_tt = self.a.second(t) * c + self.b.second(t) * s - self.c.second(t);
88 let f_tu = -da * s + db * c;
89 let f_uu = -a * c - b * s;
90 let bend = -(f_tt + 2.0 * f_tu * p + f_uu * p * p) / f_u;
91 bend.is_finite().then_some(bend)
92 }
93
94 #[must_use]
96 pub fn is_finite(&self) -> bool {
97 self.a.is_finite() && self.b.is_finite() && self.c.is_finite()
98 }
99}
100
101#[derive(Debug, Clone, Copy, PartialEq)]
104pub struct TorusCarrier {
105 pub frame: Frame3,
107 pub major_radius: Scalar,
109 pub minor_radius: Scalar,
111}
112
113impl TorusCarrier {
114 #[must_use]
116 pub fn point(&self, u: Scalar, v: Scalar) -> Point3 {
117 let (su, cu) = u.sin_cos();
118 let (sv, cv) = v.sin_cos();
119 let ring = self.major_radius + self.minor_radius * cv;
120 self.frame.origin
121 + self.frame.x * (ring * cu)
122 + self.frame.y * (ring * su)
123 + self.frame.z * (self.minor_radius * sv)
124 }
125
126 #[must_use]
128 pub fn partials(&self, u: Scalar, v: Scalar) -> (Vec3, Vec3) {
129 let (su, cu) = u.sin_cos();
130 let (sv, cv) = v.sin_cos();
131 let ring = self.major_radius + self.minor_radius * cv;
132 let r = self.minor_radius;
133 (
134 self.frame.x * (-ring * su) + self.frame.y * (ring * cu),
135 self.frame.x * (-r * sv * cu) + self.frame.y * (-r * sv * su) + self.frame.z * (r * cv),
136 )
137 }
138}
139
140#[derive(Debug, Clone, Copy, PartialEq)]
143pub struct TorusSection3 {
144 pub torus: TorusCarrier,
146 pub graph: AngleGraph2,
148}
149
150impl TorusSection3 {
151 #[must_use]
153 pub fn point(&self, t: Scalar) -> Option<Point3> {
154 Some(self.torus.point(self.graph.angle(t)?, t))
155 }
156
157 #[must_use]
159 pub fn tangent(&self, t: Scalar) -> Option<Vec3> {
160 let u = self.graph.angle(t)?;
161 let (pu, pv) = self.torus.partials(u, t);
162 Some(pu * self.graph.slope(t)? + pv)
163 }
164
165 #[must_use]
167 pub fn bend(&self, t: Scalar) -> Option<Vec3> {
168 let u = self.graph.angle(t)?;
169 let p = self.graph.slope(t)?;
170 let q = self.graph.bend(t)?;
171 let (su, cu) = u.sin_cos();
172 let (sv, cv) = t.sin_cos();
173 let (x, y, z) = (self.torus.frame.x, self.torus.frame.y, self.torus.frame.z);
174 let r = self.torus.minor_radius;
175 let ring = self.torus.major_radius + r * cv;
176 let p_u = x * (-ring * su) + y * (ring * cu);
177 let p_uu = x * (-ring * cu) + y * (-ring * su);
178 let p_uv = x * (r * sv * su) + y * (-r * sv * cu);
179 let p_vv = x * (-r * cv * cu) + y * (-r * cv * su) + z * (-r * sv);
180 Some(p_uu * (p * p) + p_uv * (2.0 * p) + p_vv + p_u * q)
181 }
182}