dessin/shapes/
ellipse.rs

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}