index/objects/geometry/
triangle.rs1use wasm_bindgen::prelude::*;
2
3use crate::{objects::vector_object::VectorObjectBuilder, utils::point2d::Point2D};
4
5#[wasm_bindgen]
7#[derive(Clone, Debug, PartialEq)]
8pub struct Triangle {
9 a: Point2D,
11 b: Point2D,
13 c: Point2D,
15}
16
17#[wasm_bindgen]
18impl Triangle {
19 #[wasm_bindgen(constructor, return_description = "A triangle with the given vertices.")]
21 pub fn new(
22 #[wasm_bindgen(param_description = "The first vertex of the triangle as Point2D.")]
23 a: Point2D,
24 #[wasm_bindgen(param_description = "The second vertex of the triangle as Point2D.")]
25 b: Point2D,
26 #[wasm_bindgen(param_description = "The third vertex of the triangle as Point2D.")]
27 c: Point2D,
28 ) -> Triangle {
29 Triangle { a, b, c }
30 }
31
32 #[wasm_bindgen(getter, return_description = "The area of the triangle.")]
34 pub fn area(&self) -> f32 {
35 0.5 * ((self.b.x - self.a.x) * (self.c.y - self.a.y) - (self.c.x - self.a.x) * (self.b.y - self.a.y)).abs()
36 }
37
38 #[wasm_bindgen(getter, return_description = "The perimeter of the triangle.")]
40 pub fn perimeter(&self) -> f32 {
41 self.a.distance(&self.b) + self.b.distance(&self.c) + self.c.distance(&self.a)
42 }
43
44 #[wasm_bindgen(return_description = "A VectorObjectBuilder with the triangle's points.")]
46 pub fn vector_object_builder(&self) -> VectorObjectBuilder {
47 VectorObjectBuilder::default().move_point(&self.a).line_to(&self.b).line_to(&self.c).close()
48 }
49
50 #[wasm_bindgen(getter, return_description = "The first vertex of the triangle.")]
52 pub fn a(&self) -> Point2D {
53 self.a
54 }
55
56 #[wasm_bindgen(getter, return_description = "The second vertex of the triangle.")]
58 pub fn b(&self) -> Point2D {
59 self.b
60 }
61
62 #[wasm_bindgen(getter, return_description = "The third vertex of the triangle.")]
64 pub fn c(&self) -> Point2D {
65 self.c
66 }
67}
68
69#[wasm_bindgen]
71#[derive(Clone, Debug, PartialEq)]
72pub struct EquilateralTriangle {
73 center: Point2D,
75 side_length: f32,
77 rotation: Option<f32>,
79}
80
81#[wasm_bindgen]
82impl EquilateralTriangle {
83 #[wasm_bindgen(constructor, return_description = "An equilateral triangle.")]
85 pub fn new(
86 #[wasm_bindgen(param_description = "The center Point2D of the equilateral triangle.")]
87 center: Point2D,
88 #[wasm_bindgen(param_description = "The side length of the equilateral triangle.")]
89 side_length: f32,
90 #[wasm_bindgen(param_description = "The rotation of the equilateral triangle, if any.")]
91 rotation: Option<f32>,
92 ) -> EquilateralTriangle {
93 EquilateralTriangle { center, side_length, rotation }
94 }
95
96 #[wasm_bindgen(getter, return_description = "A triangle with the equilateral triangle's vertices.")]
98 pub fn triangle(&self) -> Triangle {
99 let mut a = Point2D::new(self.center.x - self.side_length / 2.0, self.center.y - self.side_length / 2.0 / 3.0f32.sqrt());
100 let mut b = Point2D::new(self.center.x, self.center.y + 2.0 / 3.0f32.sqrt() * self.side_length / 2.0);
101 let mut c = Point2D::new(self.center.x + self.side_length / 2.0, self.center.y - self.side_length / 2.0 / 3.0f32.sqrt());
102 if let Some(rotation) = self.rotation {
103 a = a.rotate_around(self.center, rotation);
104 b = b.rotate_around(self.center, rotation);
105 c = c.rotate_around(self.center, rotation);
106 }
107 Triangle::new(a, b, c)
108 }
109
110 #[wasm_bindgen(getter, return_description = "A vector object builder with the equilateral triangle's points.")]
112 pub fn vector_object_builder(&self) -> VectorObjectBuilder {
113 self.triangle().vector_object_builder()
114 }
115
116 #[wasm_bindgen(getter, return_description = "The center point of the equilateral triangle.")]
118 pub fn center(&self) -> Point2D {
119 self.center
120 }
121
122 #[wasm_bindgen(getter, return_description = "The side length of the equilateral triangle.")]
124 pub fn side_length(&self) -> f32 {
125 self.side_length
126 }
127
128 #[wasm_bindgen(getter, return_description = "The area of the equilateral triangle.")]
130 pub fn area(&self) -> f32 {
131 0.25 * 3.0f32.sqrt() * self.side_length * self.side_length
132 }
133
134 #[wasm_bindgen(getter, return_description = "The perimeter of the equilateral triangle.")]
136 pub fn perimeter(&self) -> f32 {
137 3.0 * self.side_length
138 }
139
140 #[wasm_bindgen(getter, return_description = "The height of the equilateral triangle.")]
142 pub fn height(&self) -> f32 {
143 3.0f32.sqrt() / 2.0 * self.side_length
144 }
145}
146
147#[wasm_bindgen]
149#[derive(Clone, Debug, PartialEq)]
150pub struct RightTriangle {
151 center: Point2D,
153 base_length: f32,
155 height: f32,
157 rotation: Option<f32>,
159 flip: Option<bool>,
161}
162
163#[wasm_bindgen]
164impl RightTriangle {
165 #[wasm_bindgen(constructor, return_description = "A right triangle.")]
167 pub fn new(
168 #[wasm_bindgen(param_description = "The center Point2D of the right triangle.")]
169 center: Point2D,
170 #[wasm_bindgen(param_description = "The base length of the right triangle.")]
171 base_length: f32,
172 #[wasm_bindgen(param_description = "The height of the right triangle.")]
173 height: f32,
174 #[wasm_bindgen(param_description = "The rotation of the right triangle, if any.")]
175 rotation: Option<f32>,
176 #[wasm_bindgen(param_description = "The flip of the right triangle, by default false.")]
177 flip: Option<bool>,
178 ) -> RightTriangle {
179 RightTriangle { center, base_length, height, rotation, flip }
180 }
181
182 #[wasm_bindgen(getter, return_description = "A triangle.")]
184 pub fn triangle(&self) -> Triangle {
185 let mut a = Point2D::new(self.center.x - self.base_length / 2.0, self.center.y + self.height / 2.0);
186 let mut b = Point2D::new(self.center.x + self.base_length / 2.0, self.center.y + self.height / 2.0);
187 let mut c = if self.flip.unwrap_or(false) {
188 Point2D::new(self.center.x - self.base_length / 2.0, self.center.y - self.height / 2.0)
189 } else {
190 Point2D::new(self.center.x + self.base_length / 2.0, self.center.y - self.height / 2.0)
191 };
192 if let Some(rotation) = self.rotation {
193 a = a.rotate_around(self.center, rotation);
194 b = b.rotate_around(self.center, rotation);
195 c = c.rotate_around(self.center, rotation);
196 }
197 Triangle::new(a, b, c)
198 }
199
200 #[wasm_bindgen(getter, return_description = "A vector object builder with the right triangle's points.")]
202 pub fn vector_object_builder(&self) -> VectorObjectBuilder {
203 self.triangle().vector_object_builder()
204 }
205
206 #[wasm_bindgen(getter, return_description = "The center point of the right triangle.")]
208 pub fn center(&self) -> Point2D {
209 self.center
210 }
211
212 #[wasm_bindgen(getter, return_description = "The base length of the right triangle.")]
214 pub fn base_length(&self) -> f32 {
215 self.base_length
216 }
217
218 #[wasm_bindgen(getter, return_description = "The height of the right triangle.")]
220 pub fn height(&self) -> f32 {
221 self.height
222 }
223
224 #[wasm_bindgen(getter, return_description = "The area of the right triangle.")]
226 pub fn area(&self) -> f32 {
227 0.5 * self.base_length * self.height
228 }
229
230 #[wasm_bindgen(getter, return_description = "The perimeter of the right triangle.")]
232 pub fn perimeter(&self) -> f32 {
233 self.base_length + self.height + (self.base_length.powi(2) + self.height.powi(2)).sqrt()
234 }
235
236 #[wasm_bindgen(getter, return_description = "The hypotenuse of the right triangle.")]
238 pub fn hypotenuse(&self) -> f32 {
239 (self.base_length.powi(2) + self.height.powi(2)).sqrt()
240 }
241}