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
+39 -2
View File
@@ -1,4 +1,5 @@
use crate::consts::{MAX_ABSOLUTE_DIFFERENCE, MIN_SEPARATION_VALUE, STRICT_MAX_ABSOLUTE_DIFFERENCE};
use crate::ManipulatorGroup;
use glam::{BVec2, DMat2, DVec2};
use std::f64::consts::PI;
@@ -29,12 +30,23 @@ pub enum SubpathTValue {
}
#[derive(Copy, Clone)]
pub enum Joint {
Miter,
/// Enum to represent the join type between subpaths.
/// As defined in SVG: https://www.w3.org/TR/SVG2/painting.html#LineJoin.
pub enum Join {
Bevel,
Miter,
Round,
}
#[derive(Copy, Clone)]
/// Enum to represent the cap type at the ends of an outline
/// As defined in SVG: https://www.w3.org/TR/SVG2/painting.html#LineCaps.
pub enum Cap {
Butt,
Round,
Square,
}
/// Helper to perform the computation of a and c, where b is the provided point on the curve.
/// Given the correct power of `t` and `(1-t)`, the computation is the same for quadratic and cubic cases.
/// Relevant derivation and the definitions of a, b, and c can be found in [the projection identity section](https://pomax.github.io/bezierinfo/#abc) of Pomax's bezier curve primer.
@@ -266,6 +278,31 @@ pub fn scale_point_from_origin(point: DVec2, origin: DVec2, should_flip_directio
scale_point_from_direction_vector(point, (origin - point).normalize(), should_flip_direction, distance)
}
/// Computes the necessary details to form a circular join from `left` to `right`, along a circle around `center`.
/// By default, the angle is assumed to be 180 degrees.
pub fn compute_circular_subpath_details<ManipulatorGroupId: crate::Identifier>(
left: DVec2,
arc_point: DVec2,
right: DVec2,
center: DVec2,
angle: Option<f64>,
) -> (DVec2, ManipulatorGroup<ManipulatorGroupId>, DVec2) {
let center_to_arc_point = arc_point - center;
// Based on https://pomax.github.io/bezierinfo/#circles_cubic
let handle_offset_factor = if let Some(angle) = angle { 4. / 3. * (angle / 4.).tan() } else { 0.551784777779014 };
(
left - (left - center).perp() * handle_offset_factor,
ManipulatorGroup::new(
arc_point,
Some(arc_point + center_to_arc_point.perp() * handle_offset_factor),
Some(arc_point - center_to_arc_point.perp() * handle_offset_factor),
),
right + (right - center).perp() * handle_offset_factor,
)
}
#[cfg(test)]
mod tests {
use super::*;