egml_core/operations/
surface.rs1use crate::model::geometry::DirectPosition;
2use crate::operations::geometry::Geometry;
3use crate::util::plane::Plane;
4use nalgebra::Vector3;
5
6pub trait Surface: Geometry {
7 fn outer_boundary_points(&self) -> Vec<&DirectPosition>;
8
9 fn outer_boundary_lower_corner(&self) -> DirectPosition {
10 let x_min = self
11 .outer_boundary_points()
12 .iter()
13 .min_by(|a, b| a.x().partial_cmp(&b.x()).unwrap())
14 .unwrap()
15 .x();
16 let y_min = self
17 .outer_boundary_points()
18 .iter()
19 .min_by(|a, b| a.y().partial_cmp(&b.y()).unwrap())
20 .unwrap()
21 .y();
22 let z_min = self
23 .outer_boundary_points()
24 .iter()
25 .min_by(|a, b| a.z().partial_cmp(&b.z()).unwrap())
26 .unwrap()
27 .z();
28
29 DirectPosition::new(x_min, y_min, z_min).unwrap()
30 }
31
32 fn normal(&self) -> Vector3<f64> {
35 let mut enclosed_boundary_points = self.outer_boundary_points();
36 enclosed_boundary_points.extend(self.outer_boundary_points().first());
37
38 let mut normal = Vector3::new(0.0, 0.0, 0.0);
39 for current_point_pair in enclosed_boundary_points.windows(2) {
40 let current_first_point: Vector3<f64> = current_point_pair[0].into();
41 let current_second_point: Vector3<f64> = current_point_pair[1].into();
42
43 normal += (current_first_point - current_second_point)
44 .cross(&(current_first_point + current_second_point));
45 }
46
47 normal.normalize()
48 }
49
50 fn plane_equation(&self) -> Plane {
51 Plane::new(self.outer_boundary_lower_corner(), self.normal()).unwrap()
52 }
53}