fj_core/geometry/
surface.rs1use fj_math::{Line, Plane, Point, Transform, Vector};
4
5use super::GlobalPath;
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
9pub struct SurfaceGeometry {
10 pub u: GlobalPath,
12
13 pub v: Vector<3>,
15}
16
17impl SurfaceGeometry {
18 pub fn point_from_surface_coords(
20 &self,
21 point: impl Into<Point<2>>,
22 ) -> Point<3> {
23 let point = point.into();
24 self.u.point_from_path_coords([point.u])
25 + self.path_to_line().vector_from_line_coords([point.v])
26 }
27
28 pub fn vector_from_surface_coords(
30 &self,
31 vector: impl Into<Vector<2>>,
32 ) -> Vector<3> {
33 let vector = vector.into();
34 self.u.vector_from_path_coords([vector.u])
35 + self.path_to_line().vector_from_line_coords([vector.v])
36 }
37
38 fn path_to_line(&self) -> Line<3> {
39 Line::from_origin_and_direction(self.u.origin(), self.v)
40 }
41
42 pub fn project_global_point(&self, point: impl Into<Point<3>>) -> Point<2> {
44 let GlobalPath::Line(line) = self.u else {
45 todo!("Projecting point into non-plane surface is not supported")
46 };
47
48 let plane =
49 Plane::from_parametric(line.origin(), line.direction(), self.v);
50 plane.project_point(point)
51 }
52
53 #[must_use]
55 pub fn transform(self, transform: &Transform) -> Self {
56 let u = self.u.transform(transform);
57 let v = transform.transform_vector(&self.v);
58 Self { u, v }
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use fj_math::{Line, Point, Vector};
65 use pretty_assertions::assert_eq;
66
67 use crate::geometry::{GlobalPath, SurfaceGeometry};
68
69 #[test]
70 fn point_from_surface_coords() {
71 let surface = SurfaceGeometry {
72 u: GlobalPath::Line(Line::from_origin_and_direction(
73 Point::from([1., 1., 1.]),
74 Vector::from([0., 2., 0.]),
75 )),
76 v: Vector::from([0., 0., 2.]),
77 };
78
79 assert_eq!(
80 surface.point_from_surface_coords([2., 4.]),
81 Point::from([1., 5., 9.]),
82 );
83 }
84
85 #[test]
86 fn vector_from_surface_coords() {
87 let surface = SurfaceGeometry {
88 u: GlobalPath::Line(Line::from_origin_and_direction(
89 Point::from([1., 0., 0.]),
90 Vector::from([0., 2., 0.]),
91 )),
92 v: Vector::from([0., 0., 2.]),
93 };
94
95 assert_eq!(
96 surface.vector_from_surface_coords([2., 4.]),
97 Vector::from([0., 4., 8.]),
98 );
99 }
100}