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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use fj_interop::ext::ArrayExt;
use fj_math::Point;
use crate::{
objects::{Surface, SurfaceVertex},
partial::{Partial, PartialCycle, PartialHalfEdge, PartialSurfaceVertex},
storage::Handle,
};
use super::HalfEdgeBuilder;
pub trait CycleBuilder {
fn with_poly_chain(
self,
vertices: impl IntoIterator<Item = PartialSurfaceVertex>,
) -> Self;
fn with_poly_chain_from_points(
self,
surface: Handle<Surface>,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Self;
fn close_with_line_segment(self) -> Self;
}
impl CycleBuilder for PartialCycle {
fn with_poly_chain(
mut self,
vertices: impl IntoIterator<Item = PartialSurfaceVertex>,
) -> Self {
let vertices = vertices.into_iter();
let mut previous: Option<Partial<SurfaceVertex>> =
self.half_edges.last().map(|half_edge| {
let [_, last] = &half_edge.read().vertices;
let last = last.read();
last.surface_form.clone()
});
let mut half_edges = Vec::new();
for vertex_next in vertices {
let vertex_next = Partial::from_partial(vertex_next);
if let Some(vertex_prev) = previous {
let surface = vertex_prev.read().surface.clone();
previous = Some(vertex_next.clone());
let surface_vertices = [vertex_prev, vertex_next];
let mut half_edge = PartialHalfEdge::default();
half_edge.curve().write().surface = surface;
{
let global_vertices =
&mut half_edge.global_form.write().vertices;
for ((vertex, surface_form), global_form) in half_edge
.vertices
.each_mut_ext()
.zip_ext(surface_vertices)
.zip_ext(global_vertices.each_mut_ext())
{
*global_form = surface_form.read().global_form.clone();
vertex.write().surface_form = surface_form;
}
}
half_edge.update_as_line_segment();
half_edges.push(Partial::from_partial(half_edge));
continue;
}
previous = Some(vertex_next);
}
self.half_edges.extend(half_edges);
self
}
fn with_poly_chain_from_points(
self,
surface: Handle<Surface>,
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Self {
self.with_poly_chain(points.into_iter().map(|position| {
PartialSurfaceVertex {
position: Some(position.into()),
surface: Partial::from_full_entry_point(surface.clone()),
..Default::default()
}
}))
}
fn close_with_line_segment(mut self) -> Self {
let first = self.half_edges.first();
let last = self.half_edges.last();
let vertices = [first, last].map(|option| {
option.map(|half_edge| {
half_edge
.read()
.vertices
.each_ref_ext()
.map(|vertex| vertex.read().surface_form.clone())
})
});
let [Some([first, _]), Some([_, last])] = vertices else {
return self;
};
let mut half_edge = PartialHalfEdge::default();
half_edge.curve().write().surface =
self.surface().expect("Need surface to close cycle");
{
let global_vertices = &mut half_edge.global_form.write().vertices;
for ((vertex, surface_form), global_form) in half_edge
.vertices
.each_mut_ext()
.zip_ext([last, first])
.zip_ext(global_vertices.each_mut_ext())
{
*global_form = surface_form.read().global_form.clone();
vertex.write().surface_form = surface_form;
}
}
half_edge.update_as_line_segment();
self.half_edges.push(Partial::from_partial(half_edge));
self
}
}