Bezier-rs: Add joins and caps to offsets and outlines (#1083)

* Intial work

* Improve miter and add round join

* Get arcs to go opposite direction

* Add cap and other refactors

* Rename joint to join, fix some bugs

* Fix single point issue

* Clean up

* Fix iframe sizes and update UI

* Address comments and handle single point outline

* Rename variables, fix branches in outline

* Address comments
This commit is contained in:
Hannah Li
2023-03-27 16:25:08 -04:00
committed by Keavon Chambers
parent 7e124c8035
commit c0576ab4e0
18 changed files with 684 additions and 173 deletions
+9 -4
View File
@@ -64,7 +64,12 @@ impl Bezier {
/// <iframe frameBorder="0" width="100%" height="400px" src="https://graphite.rs/bezier-rs-demos#bezier/tangent/solo" title="Tangent Demo"></iframe>
pub fn tangent(&self, t: TValue) -> DVec2 {
let t = self.t_value_to_parametric(t);
self.non_normalized_tangent(t).normalize()
let tangent = self.non_normalized_tangent(t);
if tangent.length() > 0. {
tangent.normalize()
} else {
tangent
}
}
/// Returns a normalized unit vector representing the direction of the normal at the point `t` along the curve.
@@ -88,7 +93,7 @@ impl Bezier {
let numerator = d.x * dd.y - d.y * dd.x;
let denominator = (d.x.powf(2.) + d.y.powf(2.)).powf(1.5);
if denominator == 0. {
if denominator.abs() < MAX_ABSOLUTE_DIFFERENCE {
0.
} else {
numerator / denominator
@@ -369,9 +374,9 @@ impl Bezier {
}
// Create iterators that combine a subcurve with the `t` value pair that it was trimmed with
let combined_iterator1 = self1.into_iter().zip(self1_t_values.windows(2).map(|t_pair| Range { start: t_pair[0], end: t_pair[1] }));
let combined_iterator1 = self1.into_iter().zip(self1_t_values.iter().map(|t_pair| Range { start: t_pair[0], end: t_pair[1] }));
// Second one needs to be a list because Iterator does not implement copy
let combined_list2: Vec<(Bezier, Range<f64>)> = self2.into_iter().zip(self2_t_values.windows(2).map(|t_pair| Range { start: t_pair[0], end: t_pair[1] })).collect();
let combined_list2: Vec<(Bezier, Range<f64>)> = self2.into_iter().zip(self2_t_values.iter().map(|t_pair| Range { start: t_pair[0], end: t_pair[1] })).collect();
// For each curve, look for intersections with every curve that is at least 2 indices away
combined_iterator1