diff --git a/crates/fj-core/src/geometry/curve.rs b/crates/fj-core/src/geometry/curve.rs new file mode 100644 index 000000000..a85d43329 --- /dev/null +++ b/crates/fj-core/src/geometry/curve.rs @@ -0,0 +1,36 @@ +use crate::{storage::Handle, topology::Surface}; + +use super::SurfacePath; + +/// The geometric definition of a curve +#[derive(Clone)] +pub struct CurveGeom { + /// # The redundant local definitions of the curve geometry + /// + /// ## Implementation Note + /// + /// Having multiple redundant definitions is undesirable. However, we can't + /// just use one global definition in 3D, as we need the local 2D + /// definitions to approximate and triangulate curves, and we currently + /// don't have the tools to project a global definition into a local + /// context. + /// + /// Eventually, it should be possible to define the geometry of a curve + /// once, either locally or globally, and then convert that single + /// definition into (other) local contexts, as needed. There currently is no + /// issue to track that specifically, but there is the following issue, + /// which is a prerequisite for making the required tooling practical: + /// + /// + pub definitions: Vec, +} + +/// The geometric definition of a curve in 2D surface coordinates +#[derive(Clone)] +pub struct LocalCurveGeom { + /// The path that defines the curve on its surface + pub path: SurfacePath, + + /// The surface that the curve is defined on + pub surface: Handle, +} diff --git a/crates/fj-core/src/geometry/geometry.rs b/crates/fj-core/src/geometry/geometry.rs index 6a83194dd..6b76d3661 100644 --- a/crates/fj-core/src/geometry/geometry.rs +++ b/crates/fj-core/src/geometry/geometry.rs @@ -4,13 +4,14 @@ use fj_math::Vector; use crate::{ storage::Handle, - topology::{HalfEdge, Surface, Topology}, + topology::{Curve, HalfEdge, Surface, Topology}, }; -use super::{GlobalPath, HalfEdgeGeom, SurfaceGeom}; +use super::{CurveGeom, GlobalPath, HalfEdgeGeom, SurfaceGeom}; /// Geometric data that is associated with topological objects pub struct Geometry { + curve: BTreeMap, CurveGeom>, half_edge: BTreeMap, HalfEdgeGeom>, surface: BTreeMap, SurfaceGeom>, @@ -25,6 +26,7 @@ impl Geometry { /// Create a new instance of `Geometry` pub fn new(topology: &Topology) -> Self { let mut self_ = Self { + curve: BTreeMap::new(), half_edge: BTreeMap::new(), surface: BTreeMap::new(), @@ -60,6 +62,14 @@ impl Geometry { self_ } + pub(crate) fn define_curve_inner( + &mut self, + curve: Handle, + geometry: CurveGeom, + ) { + self.curve.insert(curve, geometry); + } + pub(crate) fn define_half_edge_inner( &mut self, half_edge: Handle, @@ -88,6 +98,17 @@ impl Geometry { self.surface.insert(surface, geometry); } + /// # Access the geometry of the provided curve + /// + /// ## Panics + /// + /// Panics, if the geometry of the curve is not defined. + pub fn of_curve(&self, curve: &Handle) -> &CurveGeom { + self.curve + .get(curve) + .expect("Expected geometry of half-edge to be defined") + } + /// # Access the geometry of the provided half-edge /// /// ## Panics diff --git a/crates/fj-core/src/geometry/mod.rs b/crates/fj-core/src/geometry/mod.rs index f4db527be..194e9167e 100644 --- a/crates/fj-core/src/geometry/mod.rs +++ b/crates/fj-core/src/geometry/mod.rs @@ -1,6 +1,7 @@ //! Types that are tied to objects, but aren't objects themselves mod boundary; +mod curve; mod geometry; mod half_edge; mod path; @@ -8,6 +9,7 @@ mod surface; pub use self::{ boundary::{CurveBoundary, CurveBoundaryElement}, + curve::{CurveGeom, LocalCurveGeom}, geometry::Geometry, half_edge::HalfEdgeGeom, path::{GlobalPath, SurfacePath}, diff --git a/crates/fj-core/src/layers/geometry.rs b/crates/fj-core/src/layers/geometry.rs index b23aa5cd2..b621acfff 100644 --- a/crates/fj-core/src/layers/geometry.rs +++ b/crates/fj-core/src/layers/geometry.rs @@ -1,14 +1,20 @@ //! Layer infrastructure for [`Geometry`] use crate::{ - geometry::{Geometry, HalfEdgeGeom, SurfaceGeom}, + geometry::{CurveGeom, Geometry, HalfEdgeGeom, SurfaceGeom}, storage::Handle, - topology::{HalfEdge, Surface}, + topology::{Curve, HalfEdge, Surface}, }; use super::{Command, Event, Layer}; impl Layer { + /// Define the geometry of the provided curve + pub fn define_curve(&mut self, curve: Handle, geometry: CurveGeom) { + let mut events = Vec::new(); + self.process(DefineCurve { curve, geometry }, &mut events); + } + /// Define the geometry of the provided half-edge pub fn define_half_edge( &mut self, @@ -41,6 +47,31 @@ impl Layer { } } +/// Define the geometry of a curve +pub struct DefineCurve { + curve: Handle, + geometry: CurveGeom, +} + +impl Command for DefineCurve { + type Result = (); + type Event = Self; + + fn decide( + self, + _: &Geometry, + events: &mut Vec, + ) -> Self::Result { + events.push(self); + } +} + +impl Event for DefineCurve { + fn evolve(&self, state: &mut Geometry) { + state.define_curve_inner(self.curve.clone(), self.geometry.clone()); + } +} + /// Define the geometry of a half-edge pub struct DefineHalfEdge { half_edge: Handle,