use line intersection to improve precision
This commit is contained in:
parent
cf30027976
commit
9fd50e75fa
|
|
@ -70,18 +70,29 @@ impl BevelGearShape {
|
|||
let angle = 2.0 * PI / self.points.len() as f32;
|
||||
for (k, pt) in self.points.iter_mut().enumerate() {
|
||||
let dir = Vec2::from_angle(k as f32 * angle);
|
||||
for line in cutting_line.iter().zip(&cutting_line[1..]) {
|
||||
if line.0.dot(dir) <= 0. || line.1.dot(dir) <= 0. {
|
||||
continue;
|
||||
}
|
||||
if line.0.dot(dir.perp()) < 0. || line.1.dot(dir.perp()) > 0. {
|
||||
continue;
|
||||
}
|
||||
*pt = pt.min(f32::min(line.0.length(), line.1.length()));
|
||||
for (&a, &b) in cutting_line.iter().zip(&cutting_line[1..]) {
|
||||
if let Some(intersect) = intersect_ray_segment(dir, (a, b))
|
||||
&& intersect > 0.
|
||||
{
|
||||
*pt = pt.min(intersect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the intersection point of a line (from the origin along `dir`) and a line segment (from `a` to `b`).
|
||||
/// Returns the distance from the origin, in multiples of `dir`.
|
||||
fn intersect_ray_segment(dir: Vec2, (a, b): (Vec2, Vec2)) -> Option<f32> {
|
||||
const EPS: f32 = 1e-4;
|
||||
let den = dir.perp_dot(b - a);
|
||||
if den.abs() < EPS {
|
||||
// parallel or almost parallel
|
||||
return None;
|
||||
}
|
||||
let u = a.perp_dot(dir) / den; // intersection = a + u * (b - a)
|
||||
(0.0..1.0).contains(&u).then(|| a.perp_dot(b - a) / den)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum BevelGearCap {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user