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
use fj_math::Point;
use itertools::Itertools;
use crate::{
geometry::surface::SurfaceGeometry,
objects::{HalfEdge, Objects},
partial::{Partial, PartialCycle},
services::Service,
};
use super::{HalfEdgeBuilder, ObjectArgument};
pub trait CycleBuilder {
fn add_half_edge(
&mut self,
objects: &mut Service<Objects>,
) -> Partial<HalfEdge>;
fn update_as_polygon_from_points<O, P>(
&mut self,
points: O,
objects: &mut Service<Objects>,
) -> O::SameSize<Partial<HalfEdge>>
where
O: ObjectArgument<P>,
P: Into<Point<2>>;
fn connect_to_closed_edges<O>(
&mut self,
edges: O,
surface: &SurfaceGeometry,
objects: &mut Service<Objects>,
) -> O::SameSize<Partial<HalfEdge>>
where
O: ObjectArgument<Partial<HalfEdge>>;
}
impl CycleBuilder for PartialCycle {
fn add_half_edge(
&mut self,
objects: &mut Service<Objects>,
) -> Partial<HalfEdge> {
let half_edge = Partial::new(objects);
self.half_edges.push(half_edge.clone());
half_edge
}
fn update_as_polygon_from_points<O, P>(
&mut self,
points: O,
objects: &mut Service<Objects>,
) -> O::SameSize<Partial<HalfEdge>>
where
O: ObjectArgument<P>,
P: Into<Point<2>>,
{
let mut start_positions = Vec::new();
let half_edges = points.map(|point| {
start_positions.push(point.into());
self.add_half_edge(objects)
});
for ((start, end), half_edge) in start_positions
.into_iter()
.circular_tuple_windows()
.zip(&mut self.half_edges)
{
half_edge.write().update_as_line_segment(start, end);
}
half_edges
}
fn connect_to_closed_edges<O>(
&mut self,
edges: O,
surface: &SurfaceGeometry,
objects: &mut Service<Objects>,
) -> O::SameSize<Partial<HalfEdge>>
where
O: ObjectArgument<Partial<HalfEdge>>,
{
edges.map_with_prev(|other, prev| {
let mut this = self.add_half_edge(objects);
this.write().update_from_other_edge(&other, &prev, surface);
this
})
}
}