fj_core/objects/kinds/region.rs
1//! A single, continues 2d region
2
3use crate::{
4 objects::{Cycle, ObjectSet},
5 storage::Handle,
6};
7
8/// A single, continuous 2d region, may contain holes
9///
10/// Interior cycles must have the opposite winding of the exterior cycle,
11/// meaning on the front side of the region, they must appear clockwise. This
12/// means that all [`HalfEdge`]s that bound a `Region` have the interior of the
13/// region on their left side (on the region's front side).
14///
15/// [`HalfEdge`]: crate::objects::HalfEdge
16#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
17pub struct Region {
18 exterior: Handle<Cycle>,
19 interiors: ObjectSet<Cycle>,
20}
21
22impl Region {
23 /// Construct an instance of `Region`
24 pub fn new(
25 exterior: Handle<Cycle>,
26 interiors: impl IntoIterator<Item = Handle<Cycle>>,
27 ) -> Self {
28 Self {
29 exterior,
30 interiors: interiors.into_iter().collect(),
31 }
32 }
33
34 /// Access the cycle that bounds the region on the outside
35 pub fn exterior(&self) -> &Handle<Cycle> {
36 &self.exterior
37 }
38
39 /// Access the cycles that bound the region on the inside
40 ///
41 /// Each of these cycles defines a hole in the region .
42 pub fn interiors(&self) -> &ObjectSet<Cycle> {
43 &self.interiors
44 }
45
46 /// Access all cycles of the region (both exterior and interior)
47 pub fn all_cycles(&self) -> impl Iterator<Item = &Handle<Cycle>> {
48 // It would be nice to return `&ObjectSet` here, but I don't see a way
49 // for doing that here *and* in `interiors`.
50 [self.exterior()].into_iter().chain(self.interiors())
51 }
52}