fj_core/operations/replace/
half_edge.rs

1use std::ops::Deref;
2
3use crate::{
4    objects::{Cycle, Face, HalfEdge, IsObject, Region, Shell, Sketch, Solid},
5    operations::{derive::DeriveFrom, insert::Insert},
6    storage::Handle,
7    Core,
8};
9
10use super::ReplaceOutput;
11
12/// Replace a [`HalfEdge`] in the referenced object graph
13///
14/// See [module documentation] for more information.
15///
16/// [module documentation]: super
17pub trait ReplaceHalfEdge: IsObject + Sized {
18    /// Replace the half-edge
19    #[must_use]
20    fn replace_half_edge<const N: usize>(
21        &self,
22        original: &Handle<HalfEdge>,
23        replacements: [Handle<HalfEdge>; N],
24        core: &mut Core,
25    ) -> ReplaceOutput<Self, Self::BareObject>;
26}
27
28impl ReplaceHalfEdge for Cycle {
29    fn replace_half_edge<const N: usize>(
30        &self,
31        original: &Handle<HalfEdge>,
32        replacements: [Handle<HalfEdge>; N],
33        _: &mut Core,
34    ) -> ReplaceOutput<Self, Self::BareObject> {
35        if let Some(half_edges) =
36            self.half_edges().replace(original, replacements)
37        {
38            ReplaceOutput::Updated(Cycle::new(half_edges))
39        } else {
40            ReplaceOutput::Original(self.clone())
41        }
42    }
43}
44
45impl ReplaceHalfEdge for Region {
46    fn replace_half_edge<const N: usize>(
47        &self,
48        original: &Handle<HalfEdge>,
49        replacements: [Handle<HalfEdge>; N],
50        core: &mut Core,
51    ) -> ReplaceOutput<Self, Self::BareObject> {
52        let mut replacement_happened = false;
53
54        let exterior = self.exterior().replace_half_edge(
55            original,
56            replacements.clone(),
57            core,
58        );
59        replacement_happened |= exterior.was_updated();
60
61        let mut interiors = Vec::new();
62        for original_cycle in self.interiors() {
63            let cycle = original_cycle.replace_half_edge(
64                original,
65                replacements.clone(),
66                core,
67            );
68            replacement_happened |= cycle.was_updated();
69            interiors.push(
70                cycle
71                    .map_updated(|updated| {
72                        updated.insert(core).derive_from(original_cycle, core)
73                    })
74                    .into_inner(),
75            );
76        }
77
78        if replacement_happened {
79            ReplaceOutput::Updated(Region::new(
80                exterior
81                    .map_updated(|updated| {
82                        updated.insert(core).derive_from(self.exterior(), core)
83                    })
84                    .into_inner(),
85                interiors,
86            ))
87        } else {
88            ReplaceOutput::Original(self.clone())
89        }
90    }
91}
92
93impl ReplaceHalfEdge for Sketch {
94    fn replace_half_edge<const N: usize>(
95        &self,
96        original: &Handle<HalfEdge>,
97        replacements: [Handle<HalfEdge>; N],
98        core: &mut Core,
99    ) -> ReplaceOutput<Self, Self::BareObject> {
100        let mut replacement_happened = false;
101
102        let mut regions = Vec::new();
103        for original_region in self.regions() {
104            let region = original_region.replace_half_edge(
105                original,
106                replacements.clone(),
107                core,
108            );
109            replacement_happened |= region.was_updated();
110            regions.push(
111                region
112                    .map_updated(|updated| {
113                        updated.insert(core).derive_from(original_region, core)
114                    })
115                    .into_inner(),
116            );
117        }
118
119        if replacement_happened {
120            ReplaceOutput::Updated(Sketch::new(regions))
121        } else {
122            ReplaceOutput::Original(self.clone())
123        }
124    }
125}
126
127impl ReplaceHalfEdge for Face {
128    fn replace_half_edge<const N: usize>(
129        &self,
130        original: &Handle<HalfEdge>,
131        replacements: [Handle<HalfEdge>; N],
132        core: &mut Core,
133    ) -> ReplaceOutput<Self, Self::BareObject> {
134        let region =
135            self.region()
136                .replace_half_edge(original, replacements, core);
137
138        if region.was_updated() {
139            ReplaceOutput::Updated(Face::new(
140                self.surface().clone(),
141                region
142                    .map_updated(|updated| {
143                        updated.insert(core).derive_from(self.region(), core)
144                    })
145                    .into_inner(),
146            ))
147        } else {
148            ReplaceOutput::Original(self.clone())
149        }
150    }
151}
152
153impl ReplaceHalfEdge for Shell {
154    fn replace_half_edge<const N: usize>(
155        &self,
156        original: &Handle<HalfEdge>,
157        replacements: [Handle<HalfEdge>; N],
158        core: &mut Core,
159    ) -> ReplaceOutput<Self, Self::BareObject> {
160        let mut replacement_happened = false;
161
162        let mut faces = Vec::new();
163        for original_face in self.faces() {
164            let face = original_face.replace_half_edge(
165                original,
166                replacements.clone(),
167                core,
168            );
169            replacement_happened |= face.was_updated();
170            faces.push(
171                face.map_updated(|updated| {
172                    updated.insert(core).derive_from(original_face, core)
173                })
174                .into_inner(),
175            );
176        }
177
178        if replacement_happened {
179            ReplaceOutput::Updated(Shell::new(faces))
180        } else {
181            ReplaceOutput::Original(self.clone())
182        }
183    }
184}
185
186impl ReplaceHalfEdge for Solid {
187    fn replace_half_edge<const N: usize>(
188        &self,
189        original: &Handle<HalfEdge>,
190        replacements: [Handle<HalfEdge>; N],
191        core: &mut Core,
192    ) -> ReplaceOutput<Self, Self::BareObject> {
193        let mut replacement_happened = false;
194
195        let mut shells = Vec::new();
196        for original_shell in self.shells() {
197            let shell = original_shell.replace_half_edge(
198                original,
199                replacements.clone(),
200                core,
201            );
202            replacement_happened |= shell.was_updated();
203            shells.push(
204                shell
205                    .map_updated(|updated| {
206                        updated.insert(core).derive_from(original_shell, core)
207                    })
208                    .into_inner(),
209            );
210        }
211
212        if replacement_happened {
213            ReplaceOutput::Updated(Solid::new(shells))
214        } else {
215            ReplaceOutput::Original(self.clone())
216        }
217    }
218}
219
220impl ReplaceHalfEdge for Handle<Cycle> {
221    fn replace_half_edge<const N: usize>(
222        &self,
223        original: &Handle<HalfEdge>,
224        replacements: [Handle<HalfEdge>; N],
225        core: &mut Core,
226    ) -> ReplaceOutput<Self, Self::BareObject> {
227        self.deref()
228            .replace_half_edge(original, replacements, core)
229            .map_original(|_| self.clone())
230    }
231}
232
233impl ReplaceHalfEdge for Handle<Region> {
234    fn replace_half_edge<const N: usize>(
235        &self,
236        original: &Handle<HalfEdge>,
237        replacements: [Handle<HalfEdge>; N],
238        core: &mut Core,
239    ) -> ReplaceOutput<Self, Self::BareObject> {
240        self.deref()
241            .replace_half_edge(original, replacements, core)
242            .map_original(|_| self.clone())
243    }
244}
245
246impl ReplaceHalfEdge for Handle<Sketch> {
247    fn replace_half_edge<const N: usize>(
248        &self,
249        original: &Handle<HalfEdge>,
250        replacements: [Handle<HalfEdge>; N],
251        core: &mut Core,
252    ) -> ReplaceOutput<Self, Self::BareObject> {
253        self.deref()
254            .replace_half_edge(original, replacements, core)
255            .map_original(|_| self.clone())
256    }
257}
258
259impl ReplaceHalfEdge for Handle<Face> {
260    fn replace_half_edge<const N: usize>(
261        &self,
262        original: &Handle<HalfEdge>,
263        replacements: [Handle<HalfEdge>; N],
264        core: &mut Core,
265    ) -> ReplaceOutput<Self, Self::BareObject> {
266        self.deref()
267            .replace_half_edge(original, replacements, core)
268            .map_original(|_| self.clone())
269    }
270}
271
272impl ReplaceHalfEdge for Handle<Shell> {
273    fn replace_half_edge<const N: usize>(
274        &self,
275        original: &Handle<HalfEdge>,
276        replacements: [Handle<HalfEdge>; N],
277        core: &mut Core,
278    ) -> ReplaceOutput<Self, Self::BareObject> {
279        self.deref()
280            .replace_half_edge(original, replacements, core)
281            .map_original(|_| self.clone())
282    }
283}
284
285impl ReplaceHalfEdge for Handle<Solid> {
286    fn replace_half_edge<const N: usize>(
287        &self,
288        original: &Handle<HalfEdge>,
289        replacements: [Handle<HalfEdge>; N],
290        core: &mut Core,
291    ) -> ReplaceOutput<Self, Self::BareObject> {
292        self.deref()
293            .replace_half_edge(original, replacements, core)
294            .map_original(|_| self.clone())
295    }
296}