Bezier-rs: Add curvature and rotate functions to subpath (#1081)

* Add rotate and curvature

* Fix comments

* Fix case where curve is linear

* Address comments

* Fixed breakages caused by UI updates

* Scootch rotation point to center in frame

* Code review

* Visualize t value point when segment is linear

---------

Co-authored-by: Rob Nadal <robnadal44@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Linda Zheng
2023-03-27 19:35:57 -04:00
committed by Keavon Chambers
parent 3f8adbafba
commit d0ac86b713
8 changed files with 116 additions and 31 deletions

View File

@@ -283,7 +283,7 @@ impl Bezier {
let line_directional_vector = other.end - other.start;
let angle = line_directional_vector.angle_between(DVec2::new(1., 0.));
let rotation_matrix = DMat2::from_angle(angle);
let rotated_bezier = self.apply_transformation(&|point| rotation_matrix.mul_vec2(point));
let rotated_bezier = self.apply_transformation(|point| rotation_matrix.mul_vec2(point));
let rotated_line = [rotation_matrix.mul_vec2(other.start), rotation_matrix.mul_vec2(other.end)];
// Translate the bezier such that the line becomes aligned on top of the x-axis

View File

@@ -107,7 +107,7 @@ impl<ManipulatorGroupId: crate::Identifier> Subpath<ManipulatorGroupId> {
/// Return the min and max corners that represent the bounding box of the subpath, after a given affine transform.
pub fn bounding_box_with_transform(&self, transform: glam::DAffine2) -> Option<[DVec2; 2]> {
self.iter()
.map(|bezier| bezier.apply_transformation(&|v| transform.transform_point2(v)).bounding_box())
.map(|bezier| bezier.apply_transformation(|v| transform.transform_point2(v)).bounding_box())
.reduce(|bbox1, bbox2| [bbox1[0].min(bbox2[0]), bbox1[1].max(bbox2[1])])
}
@@ -222,6 +222,14 @@ impl<ManipulatorGroupId: crate::Identifier> Subpath<ManipulatorGroupId> {
[ManipulatorGroup::new_anchor(left + translation), ManipulatorGroup::new_anchor(right + translation)]
}
/// Returns the curvature, a scalar value for the derivative at the point `t` along the subpath.
/// Curvature is 1 over the radius of a circle with an equivalent derivative.
/// <iframe frameBorder="0" width="100%" height="400px" src="https://graphite.rs/bezier-rs-demos#subpath/curvature/solo" title="Curvature Demo"></iframe>
pub fn curvature(&self, t: SubpathTValue) -> f64 {
let (segment_index, t) = self.t_value_to_parametric(t);
self.get_segment(segment_index).unwrap().curvature(TValue::Parametric(t))
}
}
#[cfg(test)]

View File

@@ -333,6 +333,29 @@ impl<ManipulatorGroupId: crate::Identifier> Subpath<ManipulatorGroupId> {
Some((clipped_subpath1, clipped_subpath2.unwrap()))
}
/// Returns a subpath that results from rotating this subpath around the origin by the given angle (in radians).
/// <iframe frameBorder="0" width="100%" height="375px" src="https://graphite.rs/bezier-rs-demos#subpath/rotate/solo" title="Rotate Demo"></iframe>
pub fn rotate(&self, angle: f64) -> Subpath<ManipulatorGroupId> {
let mut rotated_subpath = self.clone();
let affine_transform: DAffine2 = DAffine2::from_angle(angle);
rotated_subpath.apply_transform(affine_transform);
rotated_subpath
}
/// Returns a subpath that results from rotating this subpath around the provided point by the given angle (in radians).
pub fn rotate_about_point(&self, angle: f64, pivot: DVec2) -> Subpath<ManipulatorGroupId> {
// Translate before and after the rotation to account for the pivot
let translate: DAffine2 = DAffine2::from_translation(pivot);
let rotate: DAffine2 = DAffine2::from_angle(angle);
let translate_inverse = translate.inverse();
let mut rotated_subpath = self.clone();
rotated_subpath.apply_transform(translate * rotate * translate_inverse);
rotated_subpath
}
/// Reduces the segments of the subpath into simple subcurves, then scales each subcurve a set `distance` away.
/// The intersections of segments of the subpath are joined using the method specified by the `join` argument.
/// <iframe frameBorder="0" width="100%" height="400px" src="https://graphite.rs/bezier-rs-demos#subpath/offset/solo" title="Offset Demo"></iframe>