Don't give up so quickly when performing Newton-Raphson
This commit is contained in:
parent
5393f63738
commit
410d2aa6cd
|
@ -83,17 +83,17 @@ pub fn solve_line_y_for_x(x: f32, a: &Point2D<f32>, b: &Point2D<f32>) -> f32 {
|
||||||
a.lerp(*b, (x - a.x) / (b.x - a.x)).y
|
a.lerp(*b, (x - a.x) / (b.x - a.x)).y
|
||||||
}
|
}
|
||||||
|
|
||||||
fn newton_raphson<F, DFDX>(f: F, dfdx: DFDX, mut x_guess: f32) -> Option<f32>
|
fn newton_raphson<F, DFDX>(f: F, dfdx: DFDX, mut x_guess: f32) -> f32
|
||||||
where F: Fn(f32) -> f32, DFDX: Fn(f32) -> f32 {
|
where F: Fn(f32) -> f32, DFDX: Fn(f32) -> f32 {
|
||||||
for _ in 0..NEWTON_RAPHSON_ITERATIONS {
|
for _ in 0..NEWTON_RAPHSON_ITERATIONS {
|
||||||
let y = f(x_guess);
|
let y = f(x_guess);
|
||||||
if y.approx_eq(&0.0) {
|
if y.approx_eq(&0.0) {
|
||||||
return Some(x_guess)
|
break
|
||||||
}
|
}
|
||||||
let yy = dfdx(x_guess);
|
let yy = dfdx(x_guess);
|
||||||
x_guess -= y / yy
|
x_guess -= y / yy
|
||||||
}
|
}
|
||||||
None
|
x_guess
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn solve_cubic_bezier_t_for_x(x: f32,
|
pub fn solve_cubic_bezier_t_for_x(x: f32,
|
||||||
|
@ -101,7 +101,7 @@ pub fn solve_cubic_bezier_t_for_x(x: f32,
|
||||||
p1: &Point2D<f32>,
|
p1: &Point2D<f32>,
|
||||||
p2: &Point2D<f32>,
|
p2: &Point2D<f32>,
|
||||||
p3: &Point2D<f32>)
|
p3: &Point2D<f32>)
|
||||||
-> Option<f32> {
|
-> f32 {
|
||||||
newton_raphson(|t| sample_cubic_bezier(t, p0, p1, p2, p3).x - x,
|
newton_raphson(|t| sample_cubic_bezier(t, p0, p1, p2, p3).x - x,
|
||||||
|t| sample_cubic_bezier_deriv(t, p0, p1, p2, p3).x,
|
|t| sample_cubic_bezier_deriv(t, p0, p1, p2, p3).x,
|
||||||
0.5)
|
0.5)
|
||||||
|
@ -112,6 +112,6 @@ pub fn solve_cubic_bezier_y_for_x(x: f32,
|
||||||
p1: &Point2D<f32>,
|
p1: &Point2D<f32>,
|
||||||
p2: &Point2D<f32>,
|
p2: &Point2D<f32>,
|
||||||
p3: &Point2D<f32>)
|
p3: &Point2D<f32>)
|
||||||
-> Option<f32> {
|
-> f32 {
|
||||||
solve_cubic_bezier_t_for_x(x, p0, p1, p2, p3).map(|t| sample_cubic_bezier(t, p0, p1, p2, p3).y)
|
sample_cubic_bezier(solve_cubic_bezier_t_for_x(x, p0, p1, p2, p3), p0, p1, p2, p3).y
|
||||||
}
|
}
|
||||||
|
|
|
@ -369,13 +369,12 @@ impl<'a> Partitioner<'a> {
|
||||||
(x - prev_endpoint.position.x) / x_vector
|
(x - prev_endpoint.position.x) / x_vector
|
||||||
}
|
}
|
||||||
Some(control_points_index) => {
|
Some(control_points_index) => {
|
||||||
// FIXME(pcwalton): Is `unwrap_or(0.0)` sensible?
|
|
||||||
let control_points = &self.control_points[control_points_index as usize];
|
let control_points = &self.control_points[control_points_index as usize];
|
||||||
geometry::solve_cubic_bezier_t_for_x(x,
|
geometry::solve_cubic_bezier_t_for_x(x,
|
||||||
&prev_endpoint.position,
|
&prev_endpoint.position,
|
||||||
&control_points.point1,
|
&control_points.point1,
|
||||||
&control_points.point2,
|
&control_points.point2,
|
||||||
&next_endpoint.position).unwrap_or(0.0)
|
&next_endpoint.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -414,12 +413,11 @@ impl<'a> Partitioner<'a> {
|
||||||
let control_points_index = self.control_points_index(next_endpoint_index)
|
let control_points_index = self.control_points_index(next_endpoint_index)
|
||||||
.expect("Edge not a cubic bezier!");
|
.expect("Edge not a cubic bezier!");
|
||||||
let control_points = &self.control_points[control_points_index as usize];
|
let control_points = &self.control_points[control_points_index as usize];
|
||||||
// FIXME(pcwalton): Is `.unwrap_or(0.0)` sensible?
|
|
||||||
geometry::solve_cubic_bezier_y_for_x(x,
|
geometry::solve_cubic_bezier_y_for_x(x,
|
||||||
&prev_endpoint.position,
|
&prev_endpoint.position,
|
||||||
&control_points.point1,
|
&control_points.point1,
|
||||||
&control_points.point2,
|
&control_points.point2,
|
||||||
&next_endpoint.position).unwrap_or(0.0)
|
&next_endpoint.position)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn control_points_index(&self, next_endpoint_index: u32) -> Option<u32> {
|
fn control_points_index(&self, next_endpoint_index: u32) -> Option<u32> {
|
||||||
|
|
Loading…
Reference in New Issue