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
use std::ops::Deref;
use fj_interop::ext::ArrayExt;
use fj_math::{Scalar, Vector};
use itertools::Itertools;
use crate::{
algorithms::{reverse::Reverse, transform::TransformObject},
builder::{CycleBuilder, FaceBuilder},
geometry::curve::GlobalPath,
insert::Insert,
objects::{Face, Objects, Shell},
partial::{Partial, PartialFace, PartialObject, PartialShell},
services::Service,
storage::Handle,
};
use super::{Sweep, SweepCache};
impl Sweep for Handle<Face> {
type Swept = Handle<Shell>;
fn sweep_with_cache(
self,
path: impl Into<Vector<3>>,
cache: &mut SweepCache,
objects: &mut Service<Objects>,
) -> Self::Swept {
let path = path.into();
let mut faces = Vec::new();
let is_negative_sweep = {
let u = match self.surface().geometry().u {
GlobalPath::Circle(_) => todo!(
"Sweeping from faces defined in round surfaces is not \
supported"
),
GlobalPath::Line(line) => line.direction(),
};
let v = self.surface().geometry().v;
let normal = u.cross(&v);
normal.dot(&path) < Scalar::ZERO
};
let bottom_face = {
if is_negative_sweep {
self.clone()
} else {
self.clone().reverse(objects)
}
};
faces.push(bottom_face.clone());
let top_surface =
bottom_face.surface().clone().translate(path, objects);
let mut top_face = PartialFace::new(objects);
top_face.surface = Some(top_surface.clone());
top_face.color = Some(self.color());
for (i, cycle) in bottom_face.all_cycles().cloned().enumerate() {
let cycle = cycle.reverse(objects);
let mut top_cycle = if i == 0 {
top_face.exterior.clone()
} else {
top_face.add_interior(objects)
};
let mut original_edges = Vec::new();
let mut top_edges = Vec::new();
for (half_edge, next) in
cycle.half_edges().cloned().circular_tuple_windows()
{
let (face, top_edge) = (
half_edge.clone(),
next.start_vertex(),
self.surface().deref(),
self.color(),
)
.sweep_with_cache(path, cache, objects);
faces.push(face);
original_edges.push(half_edge);
top_edges.push(Partial::from(top_edge));
}
top_cycle.write().connect_to_closed_edges(
top_edges,
&top_surface.geometry(),
objects,
);
for (bottom, top) in original_edges
.into_iter()
.zip(top_cycle.write().half_edges.iter_mut())
{
top.write().curve = Some(bottom.curve().into());
let boundary = bottom.boundary();
for (top, bottom) in
top.write().boundary.each_mut_ext().zip_ext(boundary)
{
*top = Some(bottom);
}
}
}
let top_face = top_face.build(objects).insert(objects);
faces.push(top_face);
let faces = faces.into_iter().map(Partial::from).collect();
PartialShell { faces }.build(objects).insert(objects)
}
}