Repository: GraphiteEditor/Graphite
File: editor/src/messages/tool/common_functionality/snapping/layer_snapper.rs (Rust)

Code before:
	/// Calculates the point on the curve which lies closest to `point`.
	///
	/// ## Algorithm:
	/// 1. We first perform a coarse scan of the path segment to find the most promising starting point.
	/// 2. Afterwards we refine this point by performing a binary search to either side assuming that the segment contains at most one extremal point.
	/// 3. The smaller of the two resulting distances is returned.
	///
	/// ## Visualization:
	/// ```text
	///        Query Point (×)
	///             ×
	///            /|\
	///           / | \  distance checks
	///          /  |  \
	///         v   v   v
	///     ●---●---●---●---●  <- Curve with coarse scan points
	///     0  0.25 0.5 0.75 1  (parameter t values)
	///         ^       ^
	///         |   |   |
	///        min mid max
	///    Find closest scan point
	///
	///    Refine left region using binary search:
	///
	///            ●------●------●
	///           0.25  0.357   0.5
	///
	///    Result:           |     (=0.4)
	///    And the right region:
	///
	///            ●------●------●
	///           0.5   0.625   0.75
	///    Result: |               (=0.5)
	///
	///    The t value with minimal dist is thus 0.4
	///    Return: (dist_closest, point_on_curve)
	/// ```
	pub fn approx_nearest_point(&self, point: DVec2, lut_steps: usize) -> Option<(f64, kurbo::Point)> {
		let point = dvec2_to_point(point);

		let time_values = (0..lut_steps).map(|x| x as f64 / lut_steps as f64);
		let points = time_values.map(|t| (t, self.document_curve.eval(t)));
		let points_with_distances = points.map(|(t, p)| (t, p.distance_squared(point), p));
		let (t, _, _) = points_with_distances.min_by(|(_, a, _), (_, b, _)| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))?;

		let min_t = (t - (lut_steps as f64).recip()).max(0.);
		let max_t = (t + (lut_steps as f64).recip()).min(1.);
		let left = self.refine_nearest_point(point, min_t, t);
		let right = self.refine_nearest_point(point, t, max_t);

		if left.0 < right.0 { Some(left) } else { Some(right) }

Review comment (suggestion):
```suggestion
	///           0.25  0.375   0.5
```

Code after:
	/// Calculates the point on the curve which lies closest to `point`.
	///
	/// ## Algorithm:
	/// 1. We first perform a coarse scan of the path segment to find the most promising starting point.
	/// 2. Afterwards we refine this point by performing a binary search to either side assuming that the segment contains at most one extremal point.
	/// 3. The smaller of the two resulting distances is returned.
	///
	/// ## Visualization:
	/// ```text
	///        Query Point (×)
	///             ×
	///            /|\
	///           / | \  distance checks
	///          /  |  \
	///         v   v   v
	///     ●---●---●---●---●  <- Curve with coarse scan points
	///     0  0.25 0.5 0.75 1  (parameter t values)
	///         ^       ^
	///         |   |   |
	///        min mid max
	///    Find closest scan point
	///
	///    Refine left region using binary search:
	///
	///            ●------●------●
	///           0.25  0.375   0.5
	///
	///    Result:           |     (=0.4)
	///    And the right region:
	///
	///            ●------●------●
	///           0.5   0.625   0.75
	///    Result: |               (=0.5)
	///
	///    The t value with minimal dist is thus 0.4
	///    Return: (dist_closest, point_on_curve)
	/// ```
	pub fn approx_nearest_point(&self, point: DVec2, lut_steps: usize) -> Option<(f64, kurbo::Point)> {
		let point = dvec2_to_point(point);

		let time_values = (0..lut_steps).map(|x| x as f64 / lut_steps as f64);
		let points = time_values.map(|t| (t, self.document_curve.eval(t)));
		let points_with_distances = points.map(|(t, p)| (t, p.distance_squared(point), p));
		let (t, _, _) = points_with_distances.min_by(|(_, a, _), (_, b, _)| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))?;

		let min_t = (t - (lut_steps as f64).recip()).max(0.);
		let max_t = (t + (lut_steps as f64).recip()).min(1.);
		let left = self.refine_nearest_point(point, min_t, t);
		let right = self.refine_nearest_point(point, t, max_t);

		if left.0 < right.0 { Some(left) } else { Some(right) }