index/objects/geometry/
rectangle.rs1use wasm_bindgen::prelude::*;
2
3use crate::{objects::vector_object::VectorObjectBuilder, utils::{bounding_box::BoundingBox, point2d::Point2D}};
4
5#[wasm_bindgen]
7pub struct Rectangle {
8 bbox: BoundingBox,
10 rotation: Option<f32>,
12}
13
14#[wasm_bindgen]
15impl Rectangle {
16 #[wasm_bindgen(constructor, return_description = "A new rectangle.")]
18 pub fn new(
19 #[wasm_bindgen(param_description = "The BoundingBox of the rectangle.")]
20 bbox: BoundingBox,
21 #[wasm_bindgen(param_description = "The rotation of the rectangle, if any.")]
22 rotation: Option<f32>
23 ) -> Rectangle {
24 Rectangle { bbox, rotation }
25 }
26 #[wasm_bindgen(getter, return_description = "A VectorObjectBuilder representing the rectangle.")]
28 pub fn vector_object_builder(&self) -> VectorObjectBuilder {
29 let mut builder = VectorObjectBuilder::default()
30 .move_point(&self.top_left())
31 .line_to(&self.top_right())
32 .line_to(&self.bottom_right())
33 .line_to(&self.bottom_left())
34 .close();
35 if let Some(rotation) = self.rotation {
36 builder = builder.rotate(rotation, Some(self.center()), None);
37 }
38 builder
39 }
40 #[wasm_bindgen(getter, return_description = "The position of the rectangle.")]
42 pub fn position(&self) -> Point2D {
43 Point2D::new(self.bbox.min_x(), self.bbox.min_y())
44 }
45 #[wasm_bindgen(getter, return_description = "The size of the rectangle.")]
47 pub fn bbox(&self) -> BoundingBox {
48 self.bbox.clone()
49 }
50 #[wasm_bindgen(getter, return_description = "The rotation of the rectangle.")]
52 pub fn rotation(&self) -> Option<f32> {
53 self.rotation
54 }
55 #[wasm_bindgen(getter, return_description = "The top left corner of the rectangle.")]
57 pub fn top_left(&self) -> Point2D {
58 self.position()
59 }
60 #[wasm_bindgen(getter, return_description = "The top right corner of the rectangle.")]
62 pub fn top_right(&self) -> Point2D {
63 self.position() + Point2D::new(self.bbox.width(), 0.0)
64 }
65 #[wasm_bindgen(getter, return_description = "The bottom left corner of the rectangle.")]
67 pub fn bottom_left(&self) -> Point2D {
68 self.position() + Point2D::new(0.0, self.bbox.height())
69 }
70 #[wasm_bindgen(getter, return_description = "The bottom right corner of the rectangle.")]
72 pub fn bottom_right(&self) -> Point2D {
73 self.position() + Point2D::new(self.bbox.width(), self.bbox.height())
74 }
75 #[wasm_bindgen(getter, return_description = "The top of the rectangle.")]
77 pub fn top(&self) -> Point2D {
78 self.position() + Point2D::new(self.bbox.width() / 2.0, 0.0)
79 }
80 #[wasm_bindgen(getter, return_description = "The bottom of the rectangle.")]
82 pub fn bottom(&self) -> Point2D {
83 self.position() + Point2D::new(self.bbox.width() / 2.0, self.bbox.height())
84 }
85 #[wasm_bindgen(getter, return_description = "The left of the rectangle.")]
87 pub fn left(&self) -> Point2D {
88 self.position() + Point2D::new(0.0, self.bbox.height() / 2.0)
89 }
90 #[wasm_bindgen(getter, return_description = "The right of the rectangle.")]
92 pub fn right(&self) -> Point2D {
93 self.position() + Point2D::new(self.bbox.width(), self.bbox.height() / 2.0)
94 }
95 #[wasm_bindgen(getter, return_description = "The area of the rectangle.")]
97 pub fn area(&self) -> f32 {
98 self.bbox.width() * self.bbox.height()
99 }
100 #[wasm_bindgen(getter, return_description = "The center of the rectangle.")]
102 pub fn center(&self) -> Point2D {
103 self.bbox.center()
104 }
105}
106
107#[wasm_bindgen]
109#[derive(Clone, Debug)]
110pub struct Square {
111 center: Point2D,
113 side_length: f32,
115 rotation: Option<f32>,
117}
118
119#[wasm_bindgen]
120impl Square {
121 #[wasm_bindgen(constructor, return_description = "A square.")]
123 pub fn new(
124 #[wasm_bindgen(param_description = "The center point of the square as a Point2D.")]
125 center: Point2D,
126 #[wasm_bindgen(param_description = "The side length of the square.")]
127 side_length: f32,
128 #[wasm_bindgen(param_description = "The rotation of the square, if any.")]
129 rotation: Option<f32>
130 ) -> Square {
131 Square { center, side_length, rotation }
132 }
133 #[wasm_bindgen(getter, return_description = "A Rectangle representing the square.")]
135 pub fn rectangle(&self) -> Result<Rectangle, JsError> {
136 if self.side_length <= 0.0 {
137 return Err(JsError::new("The side length must be positive."));
138 }
139 Ok(Rectangle::new(
140 BoundingBox::new(
141 self.center.x - self.side_length / 2.0,
142 self.center.y - self.side_length / 2.0,
143 self.side_length,
144 self.side_length,
145 ).unwrap(),
146 self.rotation,
147 ))
148 }
149 #[wasm_bindgen(getter, return_description = "A VectorObjectBuilder representing the square.")]
151 pub fn vector_object_builder(&self) -> Result<VectorObjectBuilder, JsError> {
152 let rectangle = self.rectangle()?;
153 Ok(rectangle.vector_object_builder())
154 }
155 #[wasm_bindgen(getter, return_description = "The center point of the square as a Point2D.")]
157 pub fn center(&self) -> Point2D {
158 self.center
159 }
160 #[wasm_bindgen(getter, return_description = "The side length of the square as a Point2D.")]
162 pub fn side_length(&self) -> f32 {
163 self.side_length
164 }
165 #[wasm_bindgen(getter, return_description = "The rotation of the square, if any.")]
167 pub fn rotation(&self) -> Option<f32> {
168 self.rotation
169 }
170 #[wasm_bindgen(getter, return_description = "The area of the square.")]
172 pub fn area(&self) -> f32 {
173 self.side_length * self.side_length
174 }
175 #[wasm_bindgen(getter, return_description = "The perimeter of the square.")]
177 pub fn perimeter(&self) -> f32 {
178 4.0 * self.side_length
179 }
180}