Skip to content

Commit

Permalink
Make solve_curve_for_t_along_axis the only variant of this function
Browse files Browse the repository at this point in the history
  • Loading branch information
Logicalshift committed Feb 27, 2023
1 parent 4ddf0cf commit 1b0f293
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/bezier/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub trait BezierCurve: Geo+Clone+Sized {
///
#[inline]
fn t_for_point(&self, point: &Self::Point) -> Option<f64> {
solve_curve_for_t(self, point)
solve_curve_for_t_along_axis(self, point, CLOSE_ENOUGH)
}

///
Expand Down
15 changes: 15 additions & 0 deletions src/bezier/nearest_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ use crate::geo::*;

use smallvec::*;

///
/// Finds the 't' value of the closest point on a curve to the supplied point
///
/// Note that in interactive applications the true 'closest' point may not be the most useful for the user trying to indicate
/// a point on the curve. This is because on the inside of convex regions of the curve, a moving point far enough away will
/// jump between the end points of the convex region. Consider using ray-casting instead via `curve_intersects_ray()` instead
/// to find points that the user might be indicating instead.
///
pub fn nearest_point_on_curve<C>(curve: &C, point: &C::Point) -> f64
where
C: BezierCurve + BezierCurve2D
{
nearest_point_on_curve_newton_raphson(curve, point)
}

///
/// Optimises an estimate of a nearest point on a bezier curve using the newton-raphson method
///
Expand Down
24 changes: 6 additions & 18 deletions src/bezier/solve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,28 +41,16 @@ pub fn solve_basis_for_t(w1: f64, w2: f64, w3: f64, w4: f64, p: f64) -> SmallVec
roots
}

///
/// Given a point that is close to or on the specified bezier curve, solves the 't' value that can
/// be used to retrieve it. This is intended to take points that are known (or thought) to be on the
/// curve and find the corresponding 't' value.
///
pub fn solve_curve_for_t<C: BezierCurve>(curve: &C, point: &C::Point) -> Option<f64> {
solve_curve_for_t_along_axis(curve, point, CLOSE_ENOUGH)
}

///
/// Searches along the x or y axis for a point within `accuracy` units of the curve, returning the `t` value of that point
///
/// This can be used to find points on the curve that are close to points that are not but does not find the closest point and
/// it's possible to construct a curve such that a nearby point is not nearby along either the x or the y axis. Therefore, this
/// is best used with accuracy values that are small compared to the length of the curve and with points far away from
/// inflection points or cusps.
///
/// This is often 'good enough' to find a point close to where a user has clicked along a curve, for example, but as it
/// effectively ray-casts along the x and y axes to do so is not suitable as a general-purpose way of finding the closest point
/// on a curve to another point.
/// This is best used for points that are known to either be on the curve or which are very close to it. There are a couple of
/// other options for finding points on a curve: `nearest_point_on_curve()` will return the true closest point on a curve rather
/// than just the closest point along a particular axis, and the ray casting function `curve_intersects_ray()` can be used to
/// search for the first point encountered along any direction instead of just searching the x or y axes.
///
/// Note that `curve_intersects_ray()` can be used to find points on a curve along any direction rather than solely along the axis.
/// For interactive use, `curve_intersects_ray()` might be more useful than eitehr this function or the `nearest_point_on_curve()`
/// function as the 'true' nearest point may move in an odd manner as the point it's closest to changes.
///
pub fn solve_curve_for_t_along_axis<C: BezierCurve>(curve: &C, point: &C::Point, accuracy: f64) -> Option<f64> {
let p1 = curve.start_point();
Expand Down
4 changes: 2 additions & 2 deletions tests/bezier/curve_intersection_clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ fn find_intersection_on_line_end_to_end_3() {
#[test]
fn solve_for_end_1() {
let curve1 = line::line_to_bezier::<_, bezier::Curve<_>>(&(Coord2(1.0, 5.0), Coord2(3.0, 3.0)));
let end_pos = bezier::solve_curve_for_t(&curve1, &Coord2(3.0, 3.0));
let end_pos = bezier::solve_curve_for_t_along_axis(&curve1, &Coord2(3.0, 3.0), 0.01);

assert!(end_pos.is_some());
assert!((end_pos.unwrap() - 1.0).abs() < 0.01);
Expand All @@ -150,7 +150,7 @@ fn solve_for_end_1() {
#[test]
fn solve_for_end_2() {
let curve1 = line::line_to_bezier::<_, bezier::Curve<_>>(&(Coord2(5.0, 1.0), Coord2(3.0, 3.0)));
let end_pos = bezier::solve_curve_for_t(&curve1, &Coord2(3.0, 3.0));
let end_pos = bezier::solve_curve_for_t_along_axis(&curve1, &Coord2(3.0, 3.0), 0.01);

assert!(end_pos.is_some());
assert!((end_pos.unwrap() - 1.0).abs() < 0.01);
Expand Down

0 comments on commit 1b0f293

Please sign in to comment.