fj_kernel/algorithms/sweep/
edge.rs

1use fj_interop::{ext::ArrayExt, mesh::Color};
2use fj_math::{Point, Scalar, Vector};
3
4use crate::{
5    objects::{Cycle, Face, HalfEdge, Surface, Vertex},
6    operations::{BuildHalfEdge, Insert, UpdateCycle, UpdateHalfEdge},
7    services::Services,
8    storage::Handle,
9};
10
11use super::{Sweep, SweepCache};
12
13impl Sweep for (&HalfEdge, &Handle<Vertex>, &Surface, Option<Color>) {
14    type Swept = (Handle<Face>, Handle<HalfEdge>);
15
16    fn sweep_with_cache(
17        self,
18        path: impl Into<Vector<3>>,
19        cache: &mut SweepCache,
20        services: &mut Services,
21    ) -> Self::Swept {
22        let (edge, next_vertex, surface, color) = self;
23        let path = path.into();
24
25        // Next, we need to define the boundaries of the face. Let's start with
26        // the global vertices and edges.
27        let (vertices, global_edges) = {
28            let [a, b] = [edge.start_vertex(), next_vertex].map(Clone::clone);
29            let (edge_up, [_, c]) =
30                b.clone().sweep_with_cache(path, cache, services);
31            let (edge_down, [_, d]) =
32                a.clone().sweep_with_cache(path, cache, services);
33
34            (
35                [a, b, c, d],
36                [
37                    Some(edge.global_form().clone()),
38                    Some(edge_up),
39                    None,
40                    Some(edge_down),
41                ],
42            )
43        };
44
45        // Let's figure out the surface coordinates of the edge vertices.
46        let surface_points = {
47            let [a, b] = edge.boundary();
48
49            [
50                [a.t, Scalar::ZERO],
51                [b.t, Scalar::ZERO],
52                [b.t, Scalar::ONE],
53                [a.t, Scalar::ONE],
54            ]
55            .map(Point::from)
56        };
57        let surface_points_next = {
58            let mut points = surface_points;
59            points.rotate_left(1);
60            points
61        };
62
63        // Now, the boundaries of each edge.
64        let boundaries = {
65            let [a, b] = edge.boundary();
66            let [c, d] = [0., 1.].map(|coord| Point::from([coord]));
67
68            [[a, b], [c, d], [b, a], [d, c]]
69        };
70
71        let mut exterior = Some(Cycle::new([]));
72
73        // Armed with all of that, we're ready to create the edges.
74        let [_edge_bottom, _edge_up, edge_top, _edge_down] = boundaries
75            .zip_ext(surface_points)
76            .zip_ext(surface_points_next)
77            .zip_ext(vertices)
78            .zip_ext(global_edges)
79            .map(|((((boundary, start), end), start_vertex), global_edge)| {
80                let half_edge = {
81                    let half_edge = HalfEdge::line_segment(
82                        [start, end],
83                        Some(boundary),
84                        services,
85                    )
86                    .replace_start_vertex(start_vertex);
87
88                    let half_edge = if let Some(global_edge) = global_edge {
89                        half_edge.replace_global_form(global_edge)
90                    } else {
91                        half_edge
92                    };
93
94                    half_edge.insert(services)
95                };
96
97                exterior = Some(
98                    exterior
99                        .take()
100                        .unwrap()
101                        .add_half_edges([half_edge.clone()]),
102                );
103
104                half_edge
105            });
106
107        let face = Face::new(
108            (edge.curve(), surface).sweep_with_cache(path, cache, services),
109            exterior.unwrap().insert(services),
110            Vec::new(),
111            color,
112        );
113
114        // And we're done creating the face! All that's left to do is build our
115        // return values.
116        let face = face.insert(services);
117        (face, edge_top)
118    }
119}