fj_kernel/algorithms/sweep/
edge.rs1use 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 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 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 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 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 let face = face.insert(services);
117 (face, edge_top)
118 }
119}