diff options
| author | Martin Haug <mhaug@live.de> | 2022-04-30 21:59:34 +0200 |
|---|---|---|
| committer | Martin Haug <mhaug@live.de> | 2022-05-01 11:50:34 +0200 |
| commit | 5f1499d380e223e7e1b2a8a96eb99e3ec95a56ac (patch) | |
| tree | 44945bc35618c9ce10380016200309e42c2b5ed4 /src/geom | |
| parent | f9e115daf54c29358f890b137f50a33a781af680 (diff) | |
Add round corners and change arguments
Diffstat (limited to 'src/geom')
| -rw-r--r-- | src/geom/angle.rs | 45 | ||||
| -rw-r--r-- | src/geom/sides.rs | 46 | ||||
| -rw-r--r-- | src/geom/transform.rs | 24 |
3 files changed, 115 insertions, 0 deletions
diff --git a/src/geom/angle.rs b/src/geom/angle.rs index 888442f7..65270ebd 100644 --- a/src/geom/angle.rs +++ b/src/geom/angle.rs @@ -64,6 +64,51 @@ impl Angle { pub fn cos(self) -> f64 { self.to_rad().cos() } + + /// Get the control points for a bezier curve that describes a circular arc + /// of this angle with the given radius. + pub fn bezier_arc( + self, + radius: Length, + rotate: bool, + mirror_x: bool, + mirror_y: bool, + ) -> [Point; 4] { + let end = Point::new(self.cos() * radius - radius, self.sin() * radius); + let center = Point::new(-radius, Length::zero()); + + let mut ts = if mirror_y { + Transform::mirror_y() + } else { + Transform::identity() + }; + + if mirror_x { + ts = ts.pre_concat(Transform::mirror_x()); + } + + if rotate { + ts = ts.pre_concat(Transform::rotate(Angle::deg(90.0))); + } + + let a = center * -1.0; + let b = end - center; + + let q1 = a.x.to_raw() * a.x.to_raw() + a.y.to_raw() * a.y.to_raw(); + let q2 = q1 + a.x.to_raw() * b.x.to_raw() + a.y.to_raw() * b.y.to_raw(); + let k2 = (4.0 / 3.0) * ((2.0 * q1 * q2).sqrt() - q2) + / (a.x.to_raw() * b.y.to_raw() - a.y.to_raw() * b.x.to_raw()); + + let control_1 = Point::new(center.x + a.x - k2 * a.y, center.y + a.y + k2 * a.x); + let control_2 = Point::new(center.x + b.x + k2 * b.y, center.y + b.y - k2 * b.x); + + [ + Point::zero(), + control_1.transform(ts), + control_2.transform(ts), + end.transform(ts), + ] + } } impl Numeric for Angle { diff --git a/src/geom/sides.rs b/src/geom/sides.rs index 3584a1ce..255c21ee 100644 --- a/src/geom/sides.rs +++ b/src/geom/sides.rs @@ -31,6 +31,32 @@ impl<T> Sides<T> { bottom: value, } } + + /// Maps the individual fields with `f`. + pub fn map<F, U>(self, mut f: F) -> Sides<U> + where + F: FnMut(T) -> U, + { + Sides { + left: f(self.left), + top: f(self.top), + right: f(self.right), + bottom: f(self.bottom), + } + } + + /// Returns an iterator over the sides. + pub fn iter(&self) -> impl Iterator<Item = &T> { + [&self.left, &self.top, &self.right, &self.bottom].into_iter() + } + + /// Returns whether all sides are equal. + pub fn is_uniform(&self) -> bool + where + T: PartialEq, + { + self.left == self.top && self.top == self.right && self.right == self.bottom + } } impl<T> Sides<T> @@ -100,4 +126,24 @@ impl Side { Self::Bottom => Self::Top, } } + + /// The next side, clockwise. + pub fn clockwise(self) -> Self { + match self { + Self::Left => Self::Top, + Self::Top => Self::Right, + Self::Right => Self::Bottom, + Self::Bottom => Self::Left, + } + } + + /// The next side, counter-clockwise. + pub fn counter_clockwise(self) -> Self { + match self { + Self::Left => Self::Bottom, + Self::Top => Self::Left, + Self::Right => Self::Top, + Self::Bottom => Self::Right, + } + } } diff --git a/src/geom/transform.rs b/src/geom/transform.rs index 28a1af80..de2a9781 100644 --- a/src/geom/transform.rs +++ b/src/geom/transform.rs @@ -24,6 +24,30 @@ impl Transform { } } + /// Transform by mirroring along the x-axis. + pub fn mirror_x() -> Self { + Self { + sx: Ratio::one(), + ky: Ratio::zero(), + kx: Ratio::zero(), + sy: -Ratio::one(), + tx: Length::zero(), + ty: Length::zero(), + } + } + + /// Transform by mirroring along the y-axis. + pub fn mirror_y() -> Self { + Self { + sx: -Ratio::one(), + ky: Ratio::zero(), + kx: Ratio::zero(), + sy: Ratio::one(), + tx: Length::zero(), + ty: Length::zero(), + } + } + /// A translate transform. pub const fn translate(tx: Length, ty: Length) -> Self { Self { tx, ty, ..Self::identity() } |
