Switch to Regions

This commit is contained in:
A-Walrus 2023-05-15 19:35:35 +03:00
parent 84307c126a
commit c2fbd8cb68
8 changed files with 109 additions and 45 deletions

View File

@ -12,9 +12,9 @@ impl Approx for &Sketch {
fn approx_with_cache(
self,
tolerance: impl Into<Tolerance>,
cache: &mut Self::Cache,
_tolerance: impl Into<Tolerance>,
_cache: &mut Self::Cache,
) -> Self::Approximation {
self.faces().approx_with_cache(tolerance, cache)
todo!()
}
}

View File

@ -1,7 +1,7 @@
use fj_math::Vector;
use crate::{
objects::{Sketch, Solid},
objects::{Sketch, Solid, Surface},
operations::Insert,
services::Services,
storage::Handle,
@ -9,7 +9,7 @@ use crate::{
use super::{Sweep, SweepCache};
impl Sweep for Handle<Sketch> {
impl Sweep for (Handle<Sketch>, Handle<Surface>) {
type Swept = Handle<Solid>;
fn sweep_with_cache(
@ -21,7 +21,7 @@ impl Sweep for Handle<Sketch> {
let path = path.into();
let mut shells = Vec::new();
for face in self.faces().clone() {
for face in self.0.faces(self.1, services).clone() {
let shell = face.sweep_with_cache(path, cache, services);
shells.push(shell);
}

View File

@ -4,7 +4,6 @@ mod cycle;
mod edge;
mod face;
mod shell;
mod sketch;
mod solid;
mod surface;
mod vertex;

View File

@ -1,21 +0,0 @@
use fj_math::Transform;
use crate::{objects::Sketch, services::Services};
use super::{TransformCache, TransformObject};
impl TransformObject for Sketch {
fn transform_with_cache(
self,
transform: &Transform,
services: &mut Services,
cache: &mut TransformCache,
) -> Self {
let faces =
self.faces().into_iter().cloned().map(|face| {
face.transform_with_cache(transform, services, cache)
});
Self::new(faces)
}
}

View File

@ -1,4 +1,5 @@
//! Types that are tied to objects, but aren't objects themselves
pub mod curve;
pub mod region;
pub mod surface;

View File

@ -0,0 +1,77 @@
//! A single, continues 2d region
use fj_interop::mesh::Color;
use crate::{
objects::{Cycle, Face, Surface},
operations::Insert,
services::Services,
storage::Handle,
};
/// A single, continues 2d region, may contain holes. Once applied to a
/// [`Surface`] becomes a [`Face`]
///
/// Interior cycles must have the opposite winding of the exterior cycle,
/// meaning on the front side of the region, they must appear clockwise. This
/// means that all [`HalfEdge`]s that bound a `Region` have the interior of the
/// region on their left side (on the region's front side).
///
/// [`HalfEdge`]: crate::objects::HalfEdge
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Region {
exterior: Handle<Cycle>,
interiors: Vec<Handle<Cycle>>,
color: Option<Color>,
}
impl Region {
/// Construct an instance of `Region`
pub fn new(
exterior: Handle<Cycle>,
interiors: Vec<Handle<Cycle>>,
color: Option<Color>,
) -> Self {
Self {
exterior,
interiors,
color,
}
}
/// Access the cycle that bounds the region on the outside
pub fn exterior(&self) -> &Handle<Cycle> {
&self.exterior
}
/// Access the cycles that bound the region on the inside
///
/// Each of these cycles defines a hole in the region .
pub fn interiors(&self) -> impl Iterator<Item = &Handle<Cycle>> + '_ {
self.interiors.iter()
}
/// Access all cycles of the region (both exterior and interior)
pub fn all_cycles(&self) -> impl Iterator<Item = &Handle<Cycle>> + '_ {
[self.exterior()].into_iter().chain(self.interiors())
}
/// Access the color of the region
pub fn color(&self) -> Option<Color> {
self.color
}
/// Convert the 2D region to a 3D face, by applying it to a surface.
pub fn face(
&self,
surface: Handle<Surface>,
services: &mut Services,
) -> Handle<Face> {
let face: Face = Face::new(
surface,
self.exterior().clone(),
self.interiors().cloned(),
self.color,
);
face.insert(services)
}
}

View File

@ -4,6 +4,7 @@ use fj_interop::mesh::Color;
use fj_math::Winding;
use crate::{
geometry::region::Region,
objects::{Cycle, Surface},
storage::Handle,
};
@ -35,9 +36,7 @@ use crate::{
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Face {
surface: Handle<Surface>,
exterior: Handle<Cycle>,
interiors: Vec<Handle<Cycle>>,
color: Option<Color>,
region: Region,
}
impl Face {
@ -52,9 +51,7 @@ impl Face {
Self {
surface,
exterior,
interiors,
color,
region: Region::new(exterior, interiors, color),
}
}
@ -65,24 +62,24 @@ impl Face {
/// Access the cycle that bounds the face on the outside
pub fn exterior(&self) -> &Handle<Cycle> {
&self.exterior
&self.region.exterior()
}
/// Access the cycles that bound the face on the inside
///
/// Each of these cycles defines a hole in the face.
pub fn interiors(&self) -> impl Iterator<Item = &Handle<Cycle>> + '_ {
self.interiors.iter()
self.region.interiors()
}
/// Access all cycles of the face (both exterior and interior)
pub fn all_cycles(&self) -> impl Iterator<Item = &Handle<Cycle>> + '_ {
[self.exterior()].into_iter().chain(self.interiors())
self.region.all_cycles()
}
/// Access the color of the face
pub fn color(&self) -> Option<Color> {
self.color
self.region.color()
}
/// Determine handed-ness of the face's front-side coordinate system

View File

@ -1,5 +1,9 @@
use std::collections::BTreeSet;
use crate::{
objects::{Face, FaceSet},
geometry::region::Region,
objects::{FaceSet, Surface},
services::Services,
storage::Handle,
};
@ -11,19 +15,26 @@ use crate::{
/// currently validated.
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Sketch {
faces: FaceSet,
regions: BTreeSet<Region>,
}
impl Sketch {
/// Construct an empty instance of `Sketch`
pub fn new(faces: impl IntoIterator<Item = Handle<Face>>) -> Self {
pub fn new(regions: impl IntoIterator<Item = Region>) -> Self {
Self {
faces: faces.into_iter().collect(),
regions: regions.into_iter().collect(),
}
}
/// Access the faces of the sketch
pub fn faces(&self) -> &FaceSet {
&self.faces
/// Apply the regions of the sketch to some [`Surface`]
pub fn faces(
&self,
surface: Handle<Surface>,
services: &mut Services,
) -> FaceSet {
self.regions
.iter()
.map(|r| r.face(surface.clone(), services))
.collect()
}
}