1use super::{BoundingBox, Curve, ShapeBoundingBox, UnParticular};
2use crate::{
3 prelude::Circle,
4 shapes::{Shape, ShapeOp},
5};
6use nalgebra::{Point2, Scale2, Transform2, Vector2};
7
8#[derive(Debug, Clone, PartialEq)]
9pub struct EllipsePosition {
10 pub center: Point2<f32>,
11
12 pub semi_major_axis: f32,
13 pub semi_minor_axis: f32,
14
15 pub rotation: f32,
16}
17
18#[derive(Default, Debug, Clone, PartialEq)]
19pub struct Ellipse {
20 pub local_transform: Transform2<f32>,
21}
22
23impl Ellipse {
24 #[inline]
25 pub fn axis<S: Into<Scale2<f32>>>(&mut self, scale: S) -> &mut Self {
26 self.scale(scale);
27 self
28 }
29
30 #[inline]
31 pub fn with_axis<S: Into<Scale2<f32>>>(mut self, scale: S) -> Self {
32 self.axis(scale);
33 self
34 }
35
36 #[inline]
37 pub fn semi_major_axis(&mut self, value: f32) -> &mut Self {
38 self.scale(Scale2::new(2. * value, 1.));
39 self
40 }
41
42 #[inline]
43 pub fn with_semi_major_axis(mut self, value: f32) -> Self {
44 self.semi_major_axis(value);
45 self
46 }
47
48 #[inline]
49 pub fn semi_minor_axis(&mut self, value: f32) -> &mut Self {
50 self.scale(Scale2::new(1., 2. * value));
51 self
52 }
53
54 #[inline]
55 pub fn with_semi_minor_axis(mut self, value: f32) -> Self {
56 self.semi_minor_axis(value);
57 self
58 }
59
60 pub fn position(&self, parent_transform: &Transform2<f32>) -> EllipsePosition {
61 let transform = self.global_transform(parent_transform);
62
63 let center = transform * Point2::origin();
64
65 let semi_major_axis = transform * Vector2::new(0.5, 0.);
66 let semi_minor_axis = transform * Vector2::new(0., 0.5);
67
68 let rotation = semi_major_axis.y.atan2(semi_major_axis.x);
69
70 EllipsePosition {
71 center,
72 semi_major_axis: semi_major_axis.magnitude(),
73 semi_minor_axis: semi_minor_axis.magnitude(),
74 rotation,
75 }
76 }
77}
78
79impl From<Ellipse> for Curve {
80 #[inline]
81 fn from(e: Ellipse) -> Self {
82 Circle::from(e).into()
83 }
84}
85
86impl From<Ellipse> for Shape {
87 #[inline]
88 fn from(v: Ellipse) -> Self {
89 Shape::Ellipse(v)
90 }
91}
92
93impl ShapeOp for Ellipse {
94 #[inline]
95 fn transform(&mut self, transform_matrix: Transform2<f32>) -> &mut Self {
96 self.local_transform = transform_matrix * self.local_transform;
97 self
98 }
99
100 #[inline]
101 fn local_transform(&self) -> &Transform2<f32> {
102 &self.local_transform
103 }
104}
105
106impl ShapeBoundingBox for Ellipse {
107 fn local_bounding_box(&self) -> BoundingBox<UnParticular> {
108 BoundingBox::new(
109 self.local_transform() * Point2::new(-0.5, 0.5),
110 self.local_transform() * Point2::new(0.5, 0.5),
111 self.local_transform() * Point2::new(0.5, -0.5),
112 self.local_transform() * Point2::new(-0.5, -0.5),
113 )
114 }
115}