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
78
use crate::base::{Shape, Intersection};
use crate::line3::Line3;
use list::List;
use std::fmt;
use vector3::Vector3;
/// A plane in 3D space.
#[derive(Clone, Copy)]
pub struct Plane {
pub a: Vector3, // Pivot point of plane
pub n: Vector3, // Normal of the Plane (already normalized)
pub d: f64, //"Independent" term precalculated for performance
}
impl Plane {
/// Creates a new `Plane`.
/// The plane is defined by a point in the plane, `a`, and the normal of the plane, `n`.
pub fn new(a: &Vector3, n: &Vector3) -> Plane {
if n.is_zero() {
panic!("The normal of the plane cannot be zero");
}
Self {
a: *a,
n: n.normalize(),
d: -n.dot(&a),
}
}
}
impl Shape for Plane {
/// Returns the normal (normalized) of the plane at a given point.
fn normal(&self, _point: &Vector3) -> Vector3 {
self.n
}
/// Returns the intersection of the plane with a line.
/// If the line is parallel to the plane, it returns an empty list.
/// If the line is in the plane, it returns an empty list as a convention (because really, all lambdas fulfill).
/// If the line intersects the plane, it returns a list with the lambda value.
/// The lambda value is used to calculate the point of intersection with the line.calc_point(lambda).
fn intersects(&self, line: &Line3) -> List<f64> {
let mut intersections: List<f64> = List::<f64>::new();
let denom: f64 = self.n.dot(&line.v);
if denom != 0. {
let num: f64 = -self.n.dot(&line.a) - self.d;
intersections.push(num / denom);
}
intersections
}
/// Returns the intersection of the plane with a line.
/// If the line is parallel to the plane, it returns Option None.
/// If the line is in the plane, it returns Option None as a convention (because really, all lambdas fulfill).
/// If the line intersects the plane, it returns the lambda value.
/// The lambda value is used to calculate the point of intersection with the line.calc_point(lambda).
fn closest_intersection(&self, line: &Line3) -> Option<Intersection> {
let denom: f64 = self.n.dot(&line.v);
if denom != 0. {
let num: f64 = -self.n.dot(&line.a) - self.d;
return Some(Intersection::new(num / denom, None));
}
return None;
}
}
impl fmt::Display for Plane {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"A ({}, {}, {}) --> N ({}, {}, {})",
self.a.x, self.a.y, self.a.z, self.n.x, self.n.y, self.n.z
)
}
}