mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
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:
committed by
Keavon Chambers
parent
3f8adbafba
commit
d0ac86b713
@@ -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
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user