fj_core/operations/sweep/
half_edge.rs1use fj_interop::{ext::ArrayExt, Color};
2use fj_math::{Point, Scalar, Vector};
3
4use crate::{
5 geometry::SurfaceGeometry,
6 objects::{Cycle, Face, HalfEdge, Region, Vertex},
7 operations::{
8 build::{BuildCycle, BuildHalfEdge},
9 geometry::UpdateHalfEdgeGeometry,
10 insert::Insert,
11 presentation::SetColor,
12 update::{UpdateCycle, UpdateHalfEdge},
13 },
14 storage::Handle,
15 Core,
16};
17
18use super::{vertex::SweepVertex, SweepCache, SweepSurfacePath};
19
20pub trait SweepHalfEdge {
26 fn sweep_half_edge(
40 &self,
41 end_vertex: Handle<Vertex>,
42 surface: &SurfaceGeometry,
43 color: Option<Color>,
44 path: impl Into<Vector<3>>,
45 cache: &mut SweepCache,
46 core: &mut Core,
47 ) -> (Face, Handle<HalfEdge>);
48}
49
50impl SweepHalfEdge for Handle<HalfEdge> {
51 fn sweep_half_edge(
52 &self,
53 end_vertex: Handle<Vertex>,
54 surface: &SurfaceGeometry,
55 color: Option<Color>,
56 path: impl Into<Vector<3>>,
57 cache: &mut SweepCache,
58 core: &mut Core,
59 ) -> (Face, Handle<HalfEdge>) {
60 let path = path.into();
61
62 let surface = core
63 .layers
64 .geometry
65 .of_half_edge(self)
66 .path
67 .sweep_surface_path(surface, path, core);
68
69 let (vertices, curves) = {
72 let [a, b] = [self.start_vertex().clone(), end_vertex];
73 let (curve_up, c) = b.clone().sweep_vertex(cache, core);
74 let (curve_down, d) = a.clone().sweep_vertex(cache, core);
75
76 (
77 [a, b, c, d],
78 [
79 Some(self.curve().clone()),
80 Some(curve_up),
81 None,
82 Some(curve_down),
83 ],
84 )
85 };
86
87 let surface_points = {
89 let [a, b] = self.boundary().inner;
90
91 [
92 [a.t, Scalar::ZERO],
93 [b.t, Scalar::ZERO],
94 [b.t, Scalar::ONE],
95 [a.t, Scalar::ONE],
96 ]
97 .map(Point::from)
98 };
99 let surface_points_next = {
100 let mut points = surface_points;
101 points.rotate_left(1);
102 points
103 };
104
105 let boundaries = {
107 let [a, b] = self.boundary().inner;
108 let [c, d] = [0., 1.].map(|coord| Point::from([coord]));
109
110 [[a, b], [c, d], [b, a], [d, c]]
111 };
112
113 let mut exterior = Cycle::empty();
114
115 let [_edge_bottom, _edge_up, edge_top, _edge_down] = boundaries
117 .zip_ext(surface_points)
118 .zip_ext(surface_points_next)
119 .zip_ext(vertices)
120 .zip_ext(curves)
121 .map(|((((boundary, start), end), start_vertex), curve)| {
122 let half_edge = {
123 let line_segment = HalfEdge::line_segment(
124 [start, end],
125 Some(boundary),
126 core,
127 );
128 let half_edge = line_segment
129 .update_start_vertex(|_, _| start_vertex, core);
130
131 let half_edge = if let Some(curve) = curve {
132 half_edge.update_curve(|_, _| curve, core)
133 } else {
134 half_edge
135 };
136
137 half_edge.insert(core).set_path(
138 core.layers.geometry.of_half_edge(&line_segment).path,
139 &mut core.layers.geometry,
140 )
141 };
142
143 exterior = exterior.add_half_edges([half_edge.clone()], core);
144
145 half_edge
146 });
147
148 let exterior = exterior.insert(core);
149 let region = Region::new(exterior, []).insert(core);
150
151 if let Some(color) = color {
152 region.set_color(color, core);
153 }
154
155 let face = Face::new(surface, region);
156
157 (face, edge_top)
158 }
159}