fj_kernel/operations/join/
cycle.rs1use std::ops::RangeInclusive;
2
3use fj_math::Point;
4use itertools::Itertools;
5
6use crate::{
7 geometry::curve::Curve,
8 objects::{Cycle, HalfEdge},
9 operations::{BuildHalfEdge, Insert, UpdateCycle, UpdateHalfEdge},
10 services::Services,
11 storage::Handle,
12};
13
14pub trait JoinCycle {
16 fn add_joined_edges<Es>(&self, edges: Es, services: &mut Services) -> Self
18 where
19 Es: IntoIterator<Item = (Handle<HalfEdge>, Curve, [Point<1>; 2])>,
20 Es::IntoIter: Clone + ExactSizeIterator;
21
22 fn join_to(
52 &self,
53 other: &Cycle,
54 range: RangeInclusive<usize>,
55 other_range: RangeInclusive<usize>,
56 services: &mut Services,
57 ) -> Self;
58}
59
60impl JoinCycle for Cycle {
61 fn add_joined_edges<Es>(&self, edges: Es, services: &mut Services) -> Self
62 where
63 Es: IntoIterator<Item = (Handle<HalfEdge>, Curve, [Point<1>; 2])>,
64 Es::IntoIter: Clone + ExactSizeIterator,
65 {
66 self.add_half_edges(edges.into_iter().circular_tuple_windows().map(
67 |((prev, _, _), (half_edge, curve, boundary))| {
68 HalfEdge::unjoined(curve, boundary, services)
69 .replace_start_vertex(prev.start_vertex().clone())
70 .replace_global_form(half_edge.global_form().clone())
71 .insert(services)
72 },
73 ))
74 }
75
76 fn join_to(
77 &self,
78 other: &Cycle,
79 range: RangeInclusive<usize>,
80 range_other: RangeInclusive<usize>,
81 services: &mut Services,
82 ) -> Self {
83 assert_eq!(
84 range.end() - range.start(),
85 range_other.end() - range_other.start()
86 );
87
88 let mut cycle = self.clone();
89
90 for (index, index_other) in range.zip(range_other) {
91 let index = index % self.len();
92 let index_other = index_other % self.len();
93
94 let half_edge = self
95 .nth_half_edge(index)
96 .expect("Index must be valid, due to use of `%` above");
97 let half_edge_other = other
98 .nth_half_edge(index_other)
99 .expect("Index must be valid, due to use of `%` above");
100
101 let vertex_a = other
102 .half_edge_after(half_edge_other)
103 .expect("Expected other cycle to contain edge")
104 .start_vertex()
105 .clone();
106 let vertex_b = half_edge_other.start_vertex().clone();
107
108 let next_edge = cycle
109 .half_edge_after(half_edge)
110 .expect("Expected this cycle to contain edge");
111
112 let this_joined = half_edge
113 .replace_start_vertex(vertex_a)
114 .replace_global_form(half_edge_other.global_form().clone())
115 .insert(services);
116 let next_joined =
117 next_edge.replace_start_vertex(vertex_b).insert(services);
118
119 cycle = cycle
120 .replace_half_edge(half_edge, this_joined)
121 .replace_half_edge(next_edge, next_joined)
122 }
123
124 cycle
125 }
126}