|
3 | 3 |
|
4 | 4 | //! An ellipse arc.
|
5 | 5 |
|
6 |
| -use crate::{Affine, Ellipse, PathEl, Point, Rect, Shape, Vec2}; |
| 6 | +use crate::{Affine, Ellipse, ParamCurve, ParamCurveArclen, PathEl, Point, Rect, Shape, Vec2}; |
7 | 7 | use core::{
|
8 | 8 | f64::consts::{FRAC_PI_2, PI},
|
9 | 9 | iter,
|
10 |
| - ops::Mul, |
| 10 | + ops::{Mul, Range}, |
11 | 11 | };
|
12 | 12 |
|
13 | 13 | #[cfg(not(feature = "std"))]
|
@@ -171,6 +171,42 @@ fn rotate_pt(pt: Vec2, angle: f64) -> Vec2 {
|
171 | 171 | )
|
172 | 172 | }
|
173 | 173 |
|
| 174 | +impl ParamCurve for Arc { |
| 175 | + fn eval(&self, t: f64) -> Point { |
| 176 | + let angle = self.start_angle + (self.sweep_angle * t); |
| 177 | + sample_ellipse(self.radii, self.x_rotation, angle).to_point() |
| 178 | + } |
| 179 | + |
| 180 | + fn subsegment(&self, range: Range<f64>) -> Self { |
| 181 | + Self { |
| 182 | + center: self.center, |
| 183 | + radii: self.radii, |
| 184 | + start_angle: self.start_angle + (self.sweep_angle * range.start), |
| 185 | + sweep_angle: self.sweep_angle - (self.sweep_angle * (range.end - range.start)), |
| 186 | + x_rotation: self.x_rotation, |
| 187 | + } |
| 188 | + } |
| 189 | + |
| 190 | + fn start(&self) -> Point { |
| 191 | + sample_ellipse(self.radii, self.x_rotation, self.start_angle).to_point() |
| 192 | + } |
| 193 | + |
| 194 | + fn end(&self) -> Point { |
| 195 | + sample_ellipse( |
| 196 | + self.radii, |
| 197 | + self.x_rotation, |
| 198 | + self.start_angle + self.sweep_angle, |
| 199 | + ) |
| 200 | + .to_point() |
| 201 | + } |
| 202 | +} |
| 203 | + |
| 204 | +impl ParamCurveArclen for Arc { |
| 205 | + fn arclen(&self, accuracy: f64) -> f64 { |
| 206 | + self.path_segments(0.1).perimeter(accuracy) |
| 207 | + } |
| 208 | +} |
| 209 | + |
174 | 210 | impl Shape for Arc {
|
175 | 211 | type PathElementsIter<'iter> = iter::Chain<iter::Once<PathEl>, ArcAppendIter>;
|
176 | 212 |
|
|
0 commit comments