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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use fj_interop::{ext::ArrayExt, mesh::Color};
use fj_math::{Point, Scalar, Vector};
use crate::{
builder::HalfEdgeBuilder,
objects::{Cycle, Face, HalfEdge, Objects, Surface, Vertex},
operations::Insert,
services::Service,
storage::Handle,
};
use super::{Sweep, SweepCache};
impl Sweep for (&HalfEdge, &Handle<Vertex>, &Surface, Option<Color>) {
type Swept = (Handle<Face>, Handle<HalfEdge>);
fn sweep_with_cache(
self,
path: impl Into<Vector<3>>,
cache: &mut SweepCache,
objects: &mut Service<Objects>,
) -> Self::Swept {
let (edge, next_vertex, surface, color) = self;
let path = path.into();
let (vertices, global_edges) = {
let [a, b] = [edge.start_vertex(), next_vertex].map(Clone::clone);
let (edge_up, [_, c]) =
b.clone().sweep_with_cache(path, cache, objects);
let (edge_down, [_, d]) =
a.clone().sweep_with_cache(path, cache, objects);
(
[a, b, c, d],
[
Some(edge.global_form().clone()),
Some(edge_up),
None,
Some(edge_down),
],
)
};
let surface_points = {
let [a, b] = edge.boundary();
[
[a.t, Scalar::ZERO],
[b.t, Scalar::ZERO],
[b.t, Scalar::ONE],
[a.t, Scalar::ONE],
]
.map(Point::from)
};
let surface_points_next = {
let mut points = surface_points;
points.rotate_left(1);
points
};
let boundaries = {
let [a, b] = edge.boundary();
let [c, d] = [0., 1.].map(|coord| Point::from([coord]));
[[a, b], [c, d], [b, a], [d, c]]
};
let mut exterior = Some(Cycle::new([]));
let [_edge_bottom, _edge_up, edge_top, _edge_down] = boundaries
.zip_ext(surface_points)
.zip_ext(surface_points_next)
.zip_ext(vertices)
.zip_ext(global_edges)
.map(|((((boundary, start), end), start_vertex), global_edge)| {
let half_edge = {
let builder = HalfEdgeBuilder::line_segment(
[start, end],
Some(boundary),
)
.with_start_vertex(start_vertex);
let builder = if let Some(global_edge) = global_edge {
builder.with_global_form(global_edge)
} else {
builder
};
builder.build(objects).insert(objects)
};
let updated = {
let exterior = exterior.take().unwrap();
let half_edges = exterior
.half_edges()
.cloned()
.chain([half_edge.clone()]);
Cycle::new(half_edges)
};
exterior = Some(updated);
half_edge
});
let face = Face::new(
(edge.curve(), surface).sweep_with_cache(path, cache, objects),
exterior.unwrap().insert(objects),
Vec::new(),
color,
);
let face = face.insert(objects);
(face, edge_top)
}
}