1use std::cmp::{Eq, Ordering};
26
27use crate::*;
28
29#[derive(Debug, PartialEq, PartialOrd, Clone, Hash, Default)]
32pub struct Circle {
34 pub center: Point2D,
35 pub radius: Positive,
36}
37
38impl Eq for Circle {}
39
40impl Ord for Circle {
41 fn cmp(&self, other: &Self) -> Ordering {
42 let origin = Point2D::default();
43 match sqr_dist_2d(&origin, &self.center).partial_cmp(&sqr_dist_2d(&origin, &other.center)) {
44 Some(x) => x,
45 None => self
46 .radius
47 .partial_cmp(&other.radius)
48 .unwrap_or(Ordering::Equal),
49 }
50 }
51}
52
53impl IsND for Circle {
54 fn n_dimensions() -> usize {
55 Point2D::n_dimensions()
56 }
57
58 fn position_nd(&self, dimension: usize) -> Result<f64> {
59 self.center.position_nd(dimension)
60 }
61}
62
63impl Is2D for Circle {
64 #[inline(always)]
65 fn x(&self) -> f64 {
66 self.center.x()
67 }
68
69 #[inline(always)]
70 fn y(&self) -> f64 {
71 self.center.y()
72 }
73}
74
75impl IsBuildableND for Circle {
76 #[inline(always)]
77 fn new_nd(coords: &[f64]) -> Result<Self> {
78 Ok(Circle {
79 center: Point2D::new_nd(coords)?,
80 radius: Positive::one(),
81 })
82 }
83
84 #[inline(always)]
85 fn from_nd<P>(&mut self, other: P) -> Result<()>
86 where
87 P: IsBuildableND,
88 {
89 self.center.from_nd(other)
90 }
91}
92
93impl IsBuildable2D for Circle {
94 #[inline(always)]
95 fn new(x: f64, y: f64) -> Self {
96 Circle {
97 center: Point2D { x, y },
98 radius: Positive::one(),
99 }
100 }
101
102 #[inline(always)]
103 fn from<P>(&mut self, other: &P)
104 where
105 P: Is2D,
106 {
107 self.center.from(other)
108 }
109}
110
111impl IsEditableND for Circle {
112 fn set_position(&mut self, dimension: usize, val: f64) -> Result<()> {
113 self.center.set_position(dimension, val)
114 }
115}
116
117impl IsEditable2D for Circle {
118 #[inline(always)]
119 fn set_x(&mut self, val: f64) {
120 self.center.set_x(val);
121 }
122
123 #[inline(always)]
124 fn set_y(&mut self, val: f64) {
125 self.center.set_y(val);
126 }
127}
128
129impl HasBoundingBox2D for Circle {
130 fn bounding_box(&self) -> BoundingBox2D {
131 let p_min = Point2D {
132 x: self.center.x() - self.radius.get(),
133 y: self.center.y() - self.radius.get(),
134 };
135 let p_max = Point2D {
136 x: self.center.x() + self.radius.get(),
137 y: self.center.y() + self.radius.get(),
138 };
139 BoundingBox2D::new(&p_min, &p_max).unwrap() }
141}
142
143impl HasBoundingBox2DMaybe for Circle {
144 fn bounding_box_maybe(&self) -> Result<BoundingBox2D> {
145 Ok(self.bounding_box())
146 }
147}
148
149impl IsScalable for Circle {
150 fn scale(&mut self, factor: Positive) {
151 self.radius *= factor;
152 }
153}