Merge pull request #1828 from A-Walrus/sketch_face_v2

Rework Sketches v2
This commit is contained in:
Hanno Braun 2023-05-16 10:32:21 +02:00 committed by GitHub
commit 2d15ac0555
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 109 additions and 45 deletions

View File

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

View File

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

View File

@ -4,7 +4,6 @@ mod cycle;
mod edge; mod edge;
mod face; mod face;
mod shell; mod shell;
mod sketch;
mod solid; mod solid;
mod surface; mod surface;
mod vertex; 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 //! Types that are tied to objects, but aren't objects themselves
pub mod curve; pub mod curve;
pub mod region;
pub mod surface; 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, continuous 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 fj_math::Winding;
use crate::{ use crate::{
geometry::region::Region,
objects::{Cycle, Surface}, objects::{Cycle, Surface},
storage::Handle, storage::Handle,
}; };
@ -35,9 +36,7 @@ use crate::{
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Face { pub struct Face {
surface: Handle<Surface>, surface: Handle<Surface>,
exterior: Handle<Cycle>, region: Region,
interiors: Vec<Handle<Cycle>>,
color: Option<Color>,
} }
impl Face { impl Face {
@ -52,9 +51,7 @@ impl Face {
Self { Self {
surface, surface,
exterior, region: Region::new(exterior, interiors, color),
interiors,
color,
} }
} }
@ -65,24 +62,24 @@ impl Face {
/// Access the cycle that bounds the face on the outside /// Access the cycle that bounds the face on the outside
pub fn exterior(&self) -> &Handle<Cycle> { pub fn exterior(&self) -> &Handle<Cycle> {
&self.exterior self.region.exterior()
} }
/// Access the cycles that bound the face on the inside /// Access the cycles that bound the face on the inside
/// ///
/// Each of these cycles defines a hole in the face. /// Each of these cycles defines a hole in the face.
pub fn interiors(&self) -> impl Iterator<Item = &Handle<Cycle>> + '_ { 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) /// Access all cycles of the face (both exterior and interior)
pub fn all_cycles(&self) -> impl Iterator<Item = &Handle<Cycle>> + '_ { 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 /// Access the color of the face
pub fn color(&self) -> Option<Color> { pub fn color(&self) -> Option<Color> {
self.color self.region.color()
} }
/// Determine handed-ness of the face's front-side coordinate system /// Determine handed-ness of the face's front-side coordinate system

View File

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