1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
mod box_geometry;
mod cylinder_geometry;
mod geometry_shape_data;
mod mesh_geometry;
use nalgebra::Matrix3;
mod sphere_geometry;

pub use box_geometry::BoxGeometry;
pub use cylinder_geometry::CylinderGeometry;
pub use mesh_geometry::MeshGeometry;
pub use sphere_geometry::SphereGeometry;

pub use geometry_shape_data::GeometryShapeData;

// TODO: Maybe only exported for `wrapping` feature
pub use geometry_shape_data::GeometryShapeContainer;

use std::fmt::Debug;

use crate::transform::Mirror;

// use self::geometry_shape_data::GeometryShapeContainer;

pub trait BoxedMirror {
	fn boxed_mirrored(
		&self,
		mirror_matrix: &Matrix3<f32>,
	) -> Box<dyn GeometryInterface + Sync + Send>;
}

impl<Geometry> BoxedMirror for Geometry
where
	Geometry: GeometryInterface + Mirror + Sync + Send,
{
	fn boxed_mirrored(
		&self,
		mirror_matrix: &Matrix3<f32>,
	) -> Box<dyn GeometryInterface + Sync + Send> {
		self.mirrored(mirror_matrix).boxed_clone()
	}
}

/// An interface for working with `Geometry`s generically.
///
/// LONGTERM-TODO: DECIDE IF `Box<dyn dyn GeometryInterface + Sync + Send>` shoudl be replaced with [`GeometryShapeContainer`]
pub trait GeometryInterface: Debug + BoxedMirror {
	fn volume(&self) -> f32;
	fn surface_area(&self) -> f32;
	fn boxed_clone(&self) -> Box<dyn GeometryInterface + Sync + Send>;

	/// Get's the untransformed boundingbox size of the geometry from it's center. (X, Y, Z)
	fn bounding_box(&self) -> (f32, f32, f32);

	/// Gets a `GeometryShapeContainer` of the current Shape
	fn shape_container(&self) -> GeometryShapeContainer;
}

impl Mirror for Box<dyn GeometryInterface + Sync + Send> {
	fn mirrored(&self, mirror_matrix: &Matrix3<f32>) -> Self {
		self.boxed_mirrored(mirror_matrix)
	}
}

impl PartialEq for (dyn GeometryInterface + Sync + Send) {
	fn eq(&self, other: &Self) -> bool {
		// Should probably just get shape data
		self.volume() == other.volume()
			&& self.surface_area() == other.surface_area()
			&& self.bounding_box() == other.bounding_box()
	}
}

impl From<&(dyn GeometryInterface + Sync + Send)> for Box<dyn GeometryInterface + Sync + Send> {
	fn from(value: &(dyn GeometryInterface + Sync + Send)) -> Self {
		value.boxed_clone()
	}
}