From 2c82d7fe81167a676a068d71aca53a4d695202bf Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Sat, 14 Sep 2024 23:43:34 +0700 Subject: [PATCH 1/2] Impl `ParamCurve`, `ParamCurveArclen` for `Arc` This uses an approximation of the arc length using beziers as the analytic solution is quite involved. --- CHANGELOG.md | 3 +++ src/arc.rs | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7810278f..33cdb28b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ You can find its changes [documented below](#0111-2024-09-12). This release has an [MSRV][] of 1.65. +### `Arc` now implements `ParamCurve` and `ParamCurveArclen`. ([#378] by [@waywardmonkeys]) + ## [0.11.1][] (2024-09-12) This release has an [MSRV][] of 1.65. @@ -75,6 +77,7 @@ Note: A changelog was not kept for or before this release [#370]: https://github.com/linebender/kurbo/pull/370 [#375]: https://github.com/linebender/kurbo/pull/375 [#376]: https://github.com/linebender/kurbo/pull/376 +[#378]: https://github.com/linebender/kurbo/pull/378 [Unreleased]: https://github.com/linebender/kurbo/compare/v0.11.1...HEAD [0.11.0]: https://github.com/linebender/kurbo/releases/tag/v0.11.0 diff --git a/src/arc.rs b/src/arc.rs index 9ac642be..ac18e874 100644 --- a/src/arc.rs +++ b/src/arc.rs @@ -3,11 +3,11 @@ //! An ellipse arc. -use crate::{Affine, Ellipse, PathEl, Point, Rect, Shape, Vec2}; +use crate::{Affine, Ellipse, ParamCurve, ParamCurveArclen, PathEl, Point, Rect, Shape, Vec2}; use core::{ f64::consts::{FRAC_PI_2, PI}, iter, - ops::Mul, + ops::{Mul, Range}, }; #[cfg(not(feature = "std"))] @@ -171,6 +171,42 @@ fn rotate_pt(pt: Vec2, angle: f64) -> Vec2 { ) } +impl ParamCurve for Arc { + fn eval(&self, t: f64) -> Point { + let angle = self.start_angle + (self.sweep_angle * t); + sample_ellipse(self.radii, self.x_rotation, angle).to_point() + } + + fn subsegment(&self, range: Range) -> Self { + Self { + center: self.center, + radii: self.radii, + start_angle: self.start_angle + (self.sweep_angle * range.start), + sweep_angle: self.sweep_angle - (self.sweep_angle * (1.0 - range.end)), + x_rotation: self.x_rotation, + } + } + + fn start(&self) -> Point { + sample_ellipse(self.radii, self.x_rotation, self.start_angle).to_point() + } + + fn end(&self) -> Point { + sample_ellipse( + self.radii, + self.x_rotation, + self.start_angle + self.sweep_angle, + ) + .to_point() + } +} + +impl ParamCurveArclen for Arc { + fn arclen(&self, accuracy: f64) -> f64 { + self.path_segments(0.1).perimeter(accuracy) + } +} + impl Shape for Arc { type PathElementsIter<'iter> = iter::Chain, ArcAppendIter>; From 060d6319b5b395454a000c3fdf25bf3cf71d5ed4 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Fri, 20 Sep 2024 23:25:43 +0700 Subject: [PATCH 2/2] Update CHANGELOG.md Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33cdb28b..be5b580c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,9 @@ You can find its changes [documented below](#0111-2024-09-12). This release has an [MSRV][] of 1.65. -### `Arc` now implements `ParamCurve` and `ParamCurveArclen`. ([#378] by [@waywardmonkeys]) +### Changes + +- `Arc` now implements `ParamCurve` and `ParamCurveArclen`. ([#378] by [@waywardmonkeys]) ## [0.11.1][] (2024-09-12)