|
| 1 | +use std::path::Path; |
| 2 | + |
1 | 3 | use super::poisson_disk::poisson_disk_sample; |
2 | | -use crate::vector::algorithms::offset_subpath::MAX_ABSOLUTE_DIFFERENCE; |
3 | 4 | use crate::vector::misc::{PointSpacingType, dvec2_to_point}; |
4 | 5 | use glam::DVec2; |
5 | | -use kurbo::{BezPath, CubicBez, DEFAULT_ACCURACY, Line, ParamCurve, ParamCurveDeriv, PathEl, PathSeg, Point, QuadBez, Rect, Shape}; |
| 6 | +use kurbo::{BezPath, DEFAULT_ACCURACY, Line, ParamCurve, ParamCurveDeriv, PathEl, PathSeg, Point, Rect, Shape}; |
6 | 7 |
|
7 | 8 | /// Splits the [`BezPath`] at `t` value which lie in the range of [0, 1]. |
8 | 9 | /// Returns [`None`] if the given [`BezPath`] has no segments or `t` is within f64::EPSILON of 0 or 1. |
@@ -175,6 +176,25 @@ pub fn t_value_to_parametric(bezpath: &BezPath, t: f64, euclidian: bool, segment |
175 | 176 | bezpath_t_value_to_parametric(bezpath, BezPathTValue::GlobalParametric(t), segments_length) |
176 | 177 | } |
177 | 178 |
|
| 179 | +pub enum TValue { |
| 180 | + Parametric(f64), |
| 181 | + Euclidean(f64), |
| 182 | +} |
| 183 | + |
| 184 | +pub fn trim_pathseg(segment: PathSeg, t1: TValue, t2: TValue) -> Option<PathSeg> { |
| 185 | + let t1 = eval_pathseg(segment, t1); |
| 186 | + let t2 = eval_pathseg(segment, t2); |
| 187 | + |
| 188 | + if t1 > t2 { None } else { Some(segment.subsegment(t1..t2)) } |
| 189 | +} |
| 190 | + |
| 191 | +pub fn eval_pathseg(segment: PathSeg, t_value: TValue) -> f64 { |
| 192 | + match t_value { |
| 193 | + TValue::Parametric(t) => t, |
| 194 | + TValue::Euclidean(t) => eval_pathseg_euclidean(segment, t, DEFAULT_ACCURACY), |
| 195 | + } |
| 196 | +} |
| 197 | + |
178 | 198 | /// Finds the t value of point on the given path segment i.e fractional distance along the segment's total length. |
179 | 199 | /// It uses a binary search to find the value `t` such that the ratio `length_up_to_t / total_length` approximates the input `distance`. |
180 | 200 | pub fn eval_pathseg_euclidean(path_segment: PathSeg, distance: f64, accuracy: f64) -> f64 { |
@@ -315,16 +335,3 @@ pub fn poisson_disk_points(bezpath_index: usize, bezpaths: &[(BezPath, Rect)], s |
315 | 335 |
|
316 | 336 | poisson_disk_sample(offset, width, height, separation_disk_diameter, point_in_shape_checker, line_intersect_shape_checker, rng) |
317 | 337 | } |
318 | | - |
319 | | -/// Returns true if the Bezier curve is equivalent to a line. |
320 | | -/// |
321 | | -/// **NOTE**: This is different from simply checking if the segment is [`PathSeg::Line`] or [`PathSeg::Quad`] or [`PathSeg::Cubic`]. Bezier curve can also be a line if the control points are colinear to the start and end points. Therefore if the handles exceed the start and end point, it will still be considered as a line. |
322 | | -pub fn is_linear(segment: &PathSeg) -> bool { |
323 | | - let is_colinear = |a: Point, b: Point, c: Point| -> bool { ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)).abs() < MAX_ABSOLUTE_DIFFERENCE }; |
324 | | - |
325 | | - match *segment { |
326 | | - PathSeg::Line(_) => true, |
327 | | - PathSeg::Quad(QuadBez { p0, p1, p2 }) => is_colinear(p0, p1, p2), |
328 | | - PathSeg::Cubic(CubicBez { p0, p1, p2, p3 }) => is_colinear(p0, p1, p3) && is_colinear(p0, p2, p3), |
329 | | - } |
330 | | -} |
|
0 commit comments