cvmath/
plane.rs

1use super::*;
2
3/// Plane shape.
4#[derive(Copy, Clone, Debug, Eq, PartialEq)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6#[repr(C)]
7pub struct Plane<T> {
8	/// The normal of the plane.
9	pub normal: Vec3<T>,
10	/// The distance from the origin.
11	pub distance: T,
12}
13
14/// Plane constructor.
15#[allow(non_snake_case)]
16#[inline]
17pub fn Plane<T>(normal: Vec3<T>, distance: T) -> Plane<T> {
18	Plane { normal, distance }
19}
20
21#[cfg(feature = "dataview")]
22unsafe impl<T: dataview::Pod> dataview::Pod for Plane<T> {}
23
24impl<T> Plane<T> {
25	/// Constructs a new plane.
26	#[inline]
27	pub const fn new(normal: Vec3<T>, distance: T) -> Plane<T> {
28		Plane { normal, distance }
29	}
30
31	/// Constructs a new plane from a normal and a point.
32	#[inline]
33	pub fn from_point(normal: Vec3<T>, pt: Point3<T>) -> Plane<T> where T: Float {
34		let distance = -normal.dot(pt);
35		Plane { normal, distance }
36	}
37
38	/// Constructs a new plane from three points.
39	///
40	/// If the points are collinear, the plane normal is zero.
41	#[inline]
42	pub fn from_points(pt1: Point3<T>, pt2: Point3<T>, pt3: Point3<T>) -> Plane<T> where T: Float {
43		let normal = (pt2 - pt1).cross(pt3 - pt1).normalize();
44		let distance = -normal.dot(pt1);
45		Plane { normal, distance }
46	}
47}
48
49impl<T: Float> Plane<T> {
50	/// Returns the projection of a point onto the plane.
51	///
52	/// ```
53	/// use cvmath::{Plane, Point3, Vec3};
54	///
55	/// let plane = Plane(Vec3(0.0, 0.0, 1.0), 0.0);
56	/// let pt = Point3(20.0, 10.0, 4.0);
57	/// assert_eq!(plane.project_point(pt), Point3(20.0, 10.0, 0.0));
58	/// ```
59	#[inline]
60	pub fn project_point(&self, pt: Point3<T>) -> Point3<T> {
61		pt - self.normal * self.distance_to_point(pt)
62	}
63
64	/// Returns the distance from the plane to a point.
65	///
66	/// ```
67	/// use cvmath::{Plane, Point3, Vec3};
68	///
69	/// let plane = Plane(Vec3(0.0, 0.0, 1.0), 0.0);
70	/// let pt = Point3(20.0, 10.0, 4.0);
71	/// assert_eq!(plane.distance_to_point(pt), 4.0);
72	/// ```
73	#[inline]
74	pub fn distance_to_point(&self, pt: Point3<T>) -> T {
75		self.normal.dot(pt) + self.distance
76	}
77}
78
79//----------------------------------------------------------------
80
81impl<T: Float> TraceRay<T> for Plane<T> {
82	fn inside(&self, ray: &Ray<T>) -> bool {
83		self.normal.dot(ray.origin) + self.distance <= T::ZERO
84	}
85
86	fn trace(&self, ray: &Ray<T>, hits: &mut [TraceHit<T>]) -> usize {
87		let denom = self.normal.dot(ray.direction);
88		if denom.abs() < T::EPSILON {
89			return 0;
90		}
91
92		let distance = -self.normal.dot(ray.origin) / denom;
93		if distance < T::ZERO {
94			return 0;
95		}
96
97		if let Some(hit) = hits.get_mut(0) {
98			*hit = TraceHit { distance, normal: self.normal };
99		}
100
101		return 1;
102	}
103}