1use super::error::{GateError, Result};
2use super::traits::*;
3use super::types::GateNode;
4
5#[derive(Debug, Clone)]
6pub struct EllipseGateGeometry {
7 pub center: GateNode,
8 pub radius_x: f32,
9 pub radius_y: f32,
10 pub angle: f32, }
12
13impl GateCenter for EllipseGateGeometry {
14 fn calculate_center(&self, x_param: &str, y_param: &str) -> Result<(f32, f32)> {
15 let cx = self
16 .center
17 .get_coordinate(x_param)
18 .ok_or_else(|| GateError::missing_parameter(x_param, "ellipse center"))?;
19 let cy = self
20 .center
21 .get_coordinate(y_param)
22 .ok_or_else(|| GateError::missing_parameter(y_param, "ellipse center"))?;
23
24 Ok((cx, cy))
25 }
26}
27
28impl GateContainment for EllipseGateGeometry {
29 fn contains_point(&self, x: f32, y: f32, x_param: &str, y_param: &str) -> Result<bool> {
30 let cx = self
31 .center
32 .get_coordinate(x_param)
33 .ok_or_else(|| GateError::missing_parameter(x_param, "ellipse center"))?;
34 let cy = self
35 .center
36 .get_coordinate(y_param)
37 .ok_or_else(|| GateError::missing_parameter(y_param, "ellipse center"))?;
38
39 let cos_a = self.angle.cos();
41 let sin_a = self.angle.sin();
42 let dx = x - cx;
43 let dy = y - cy;
44 let rotated_x = dx * cos_a + dy * sin_a;
45 let rotated_y = -dx * sin_a + dy * cos_a;
46
47 let normalized = (rotated_x / self.radius_x).powi(2) + (rotated_y / self.radius_y).powi(2);
49 Ok(normalized <= 1.0)
50 }
51}
52
53impl GateBounds for EllipseGateGeometry {
54 fn bounding_box(&self, x_param: &str, y_param: &str) -> Result<(f32, f32, f32, f32)> {
55 let cx = self
56 .center
57 .get_coordinate(x_param)
58 .ok_or_else(|| GateError::missing_parameter(x_param, "ellipse center"))?;
59 let cy = self
60 .center
61 .get_coordinate(y_param)
62 .ok_or_else(|| GateError::missing_parameter(y_param, "ellipse center"))?;
63
64 let max_radius = self.radius_x.max(self.radius_y);
67
68 Ok((
69 cx - max_radius,
70 cy - max_radius,
71 cx + max_radius,
72 cy + max_radius,
73 ))
74 }
75}
76
77impl GateValidation for EllipseGateGeometry {
78 fn is_valid(&self, x_param: &str, y_param: &str) -> Result<bool> {
79 if self.center.get_coordinate(x_param).is_none()
81 || self.center.get_coordinate(y_param).is_none()
82 {
83 return Ok(false);
84 }
85
86 Ok(self.radius_x > 0.0 && self.radius_y > 0.0)
88 }
89}
90
91impl GateGeometryOps for EllipseGateGeometry {
92 fn gate_type_name(&self) -> &'static str {
93 "Ellipse"
94 }
95}