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}