mirror of
https://github.com/hannobraun/Fornjot
synced 2025-01-12 03:06:59 +00:00
Merge pull request #2271 from hannobraun/geometry
Store `SurfacePath` of `HalfEdge` in geometry layer
This commit is contained in:
commit
e3c061ac98
@ -3,14 +3,15 @@ use std::collections::BTreeMap;
|
|||||||
use fj_math::Vector;
|
use fj_math::Vector;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{Objects, Surface},
|
objects::{HalfEdge, Objects, Surface},
|
||||||
storage::{Handle, HandleWrapper},
|
storage::{Handle, HandleWrapper},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{GlobalPath, SurfaceGeometry};
|
use super::{GlobalPath, HalfEdgeGeometry, SurfaceGeometry};
|
||||||
|
|
||||||
/// Geometric data that is associated with topological objects
|
/// Geometric data that is associated with topological objects
|
||||||
pub struct Geometry {
|
pub struct Geometry {
|
||||||
|
half_edge: BTreeMap<Handle<HalfEdge>, HalfEdgeGeometry>,
|
||||||
surface: BTreeMap<HandleWrapper<Surface>, SurfaceGeometry>,
|
surface: BTreeMap<HandleWrapper<Surface>, SurfaceGeometry>,
|
||||||
|
|
||||||
xy_plane: Handle<Surface>,
|
xy_plane: Handle<Surface>,
|
||||||
@ -22,6 +23,7 @@ impl Geometry {
|
|||||||
/// Create a new instance of `Geometry`
|
/// Create a new instance of `Geometry`
|
||||||
pub fn new(objects: &Objects) -> Self {
|
pub fn new(objects: &Objects) -> Self {
|
||||||
let mut self_ = Self {
|
let mut self_ = Self {
|
||||||
|
half_edge: BTreeMap::new(),
|
||||||
surface: BTreeMap::new(),
|
surface: BTreeMap::new(),
|
||||||
|
|
||||||
xy_plane: objects.surfaces.xy_plane(),
|
xy_plane: objects.surfaces.xy_plane(),
|
||||||
@ -54,6 +56,14 @@ impl Geometry {
|
|||||||
self_
|
self_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn define_half_edge_inner(
|
||||||
|
&mut self,
|
||||||
|
half_edge: Handle<HalfEdge>,
|
||||||
|
geometry: HalfEdgeGeometry,
|
||||||
|
) {
|
||||||
|
self.half_edge.insert(half_edge, geometry);
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn define_surface_inner(
|
pub(crate) fn define_surface_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
surface: Handle<Surface>,
|
surface: Handle<Surface>,
|
||||||
@ -62,6 +72,21 @@ impl Geometry {
|
|||||||
self.surface.insert(surface.into(), geometry);
|
self.surface.insert(surface.into(), geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Access the geometry of the provided half-edge
|
||||||
|
///
|
||||||
|
/// ## Panics
|
||||||
|
///
|
||||||
|
/// Panics, if the geometry of the half-edge is not defined.
|
||||||
|
pub fn of_half_edge(
|
||||||
|
&self,
|
||||||
|
half_edge: &Handle<HalfEdge>,
|
||||||
|
) -> HalfEdgeGeometry {
|
||||||
|
self.half_edge
|
||||||
|
.get(half_edge)
|
||||||
|
.copied()
|
||||||
|
.expect("Expected geometry of half-edge to be defined")
|
||||||
|
}
|
||||||
|
|
||||||
/// # Access the geometry of the provided surface
|
/// # Access the geometry of the provided surface
|
||||||
///
|
///
|
||||||
/// ## Panics
|
/// ## Panics
|
||||||
|
32
crates/fj-core/src/geometry/half_edge.rs
Normal file
32
crates/fj-core/src/geometry/half_edge.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use super::SurfacePath;
|
||||||
|
|
||||||
|
/// The geometry of a half-edge
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct HalfEdgeGeometry {
|
||||||
|
/// # The path of the half-edge
|
||||||
|
///
|
||||||
|
/// ## Implementation Note
|
||||||
|
///
|
||||||
|
/// Currently, all curve-related geometry is defined locally, in terms of
|
||||||
|
/// the surface that the curve is on (or purely in 2D, if there is no
|
||||||
|
/// surface associated with this geometry). However, curves exist globally,
|
||||||
|
/// independently of surfaces. Half-edges in multiple surfaces can refer to
|
||||||
|
/// the same curve, and in fact, that is the whole reason for their
|
||||||
|
/// existence as a topological object.
|
||||||
|
///
|
||||||
|
/// This contradiction, globally defined curves but locally defined curve
|
||||||
|
/// geometry, is the reason that this curve geometry is defined right here,
|
||||||
|
/// associated with a locally existing half-edge. (And, I might add,
|
||||||
|
/// redundantly so, as multiple half-edges within the same surface context
|
||||||
|
/// can refer to the same curve.)
|
||||||
|
///
|
||||||
|
/// Instead, it should be possible to define curve geometry *either* locally
|
||||||
|
/// or globally. Then that respective definition can be associated with the
|
||||||
|
/// curve (and possibly, in addition, a surface). How exactly that is going
|
||||||
|
/// to work is up in the air.
|
||||||
|
///
|
||||||
|
/// The point of all this exposition is to clarify that this field doesn't
|
||||||
|
/// really belong here. It exists here for practical reasons that are,
|
||||||
|
/// hopefully, temporary.
|
||||||
|
pub path: SurfacePath,
|
||||||
|
}
|
@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
mod boundary;
|
mod boundary;
|
||||||
mod geometry;
|
mod geometry;
|
||||||
|
mod half_edge;
|
||||||
mod path;
|
mod path;
|
||||||
mod surface;
|
mod surface;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
boundary::{CurveBoundary, CurveBoundaryElement},
|
boundary::{CurveBoundary, CurveBoundaryElement},
|
||||||
geometry::Geometry,
|
geometry::Geometry,
|
||||||
|
half_edge::HalfEdgeGeometry,
|
||||||
path::{GlobalPath, SurfacePath},
|
path::{GlobalPath, SurfacePath},
|
||||||
surface::SurfaceGeometry,
|
surface::SurfaceGeometry,
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,30 @@
|
|||||||
//! Layer infrastructure for [`Geometry`]
|
//! Layer infrastructure for [`Geometry`]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
geometry::{Geometry, SurfaceGeometry},
|
geometry::{Geometry, HalfEdgeGeometry, SurfaceGeometry},
|
||||||
objects::Surface,
|
objects::{HalfEdge, Surface},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Command, Event, Layer};
|
use super::{Command, Event, Layer};
|
||||||
|
|
||||||
impl Layer<Geometry> {
|
impl Layer<Geometry> {
|
||||||
|
/// Define the geometry of the provided half-edge
|
||||||
|
pub fn define_half_edge(
|
||||||
|
&mut self,
|
||||||
|
half_edge: Handle<HalfEdge>,
|
||||||
|
geometry: HalfEdgeGeometry,
|
||||||
|
) {
|
||||||
|
let mut events = Vec::new();
|
||||||
|
self.process(
|
||||||
|
DefineHalfEdge {
|
||||||
|
half_edge,
|
||||||
|
geometry,
|
||||||
|
},
|
||||||
|
&mut events,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Define the geometry of the provided surface
|
/// Define the geometry of the provided surface
|
||||||
pub fn define_surface(
|
pub fn define_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -20,6 +36,31 @@ impl Layer<Geometry> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Define the geometry of a half-edge
|
||||||
|
pub struct DefineHalfEdge {
|
||||||
|
half_edge: Handle<HalfEdge>,
|
||||||
|
geometry: HalfEdgeGeometry,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command<Geometry> for DefineHalfEdge {
|
||||||
|
type Result = ();
|
||||||
|
type Event = Self;
|
||||||
|
|
||||||
|
fn decide(
|
||||||
|
self,
|
||||||
|
_: &Geometry,
|
||||||
|
events: &mut Vec<Self::Event>,
|
||||||
|
) -> Self::Result {
|
||||||
|
events.push(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Event<Geometry> for DefineHalfEdge {
|
||||||
|
fn evolve(&self, state: &mut Geometry) {
|
||||||
|
state.define_half_edge_inner(self.half_edge.clone(), self.geometry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Define the geometry of a surface
|
/// Define the geometry of a surface
|
||||||
pub struct DefineSurface {
|
pub struct DefineSurface {
|
||||||
surface: Handle<Surface>,
|
surface: Handle<Surface>,
|
||||||
|
@ -2,7 +2,7 @@ use fj_interop::ext::ArrayExt;
|
|||||||
use fj_math::{Arc, Point, Scalar};
|
use fj_math::{Arc, Point, Scalar};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
geometry::{CurveBoundary, SurfacePath},
|
geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath},
|
||||||
objects::{Curve, HalfEdge, Vertex},
|
objects::{Curve, HalfEdge, Vertex},
|
||||||
operations::insert::Insert,
|
operations::insert::Insert,
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
@ -33,13 +33,22 @@ pub trait BuildHalfEdge {
|
|||||||
start_vertex: Handle<Vertex>,
|
start_vertex: Handle<Vertex>,
|
||||||
core: &mut Core,
|
core: &mut Core,
|
||||||
) -> Handle<HalfEdge> {
|
) -> Handle<HalfEdge> {
|
||||||
HalfEdge::new(
|
let half_edge = HalfEdge::new(
|
||||||
sibling.path(),
|
sibling.path(),
|
||||||
sibling.boundary().reverse(),
|
sibling.boundary().reverse(),
|
||||||
sibling.curve().clone(),
|
sibling.curve().clone(),
|
||||||
start_vertex,
|
start_vertex,
|
||||||
)
|
)
|
||||||
.insert(core)
|
.insert(core);
|
||||||
|
|
||||||
|
core.layers.geometry.define_half_edge(
|
||||||
|
half_edge.clone(),
|
||||||
|
HalfEdgeGeometry {
|
||||||
|
path: sibling.path(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
half_edge
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an arc
|
/// Create an arc
|
||||||
@ -65,7 +74,12 @@ pub trait BuildHalfEdge {
|
|||||||
let boundary =
|
let boundary =
|
||||||
[arc.start_angle, arc.end_angle].map(|coord| Point::from([coord]));
|
[arc.start_angle, arc.end_angle].map(|coord| Point::from([coord]));
|
||||||
|
|
||||||
HalfEdge::unjoined(path, boundary, core).insert(core)
|
let half_edge = HalfEdge::unjoined(path, boundary, core).insert(core);
|
||||||
|
core.layers
|
||||||
|
.geometry
|
||||||
|
.define_half_edge(half_edge.clone(), HalfEdgeGeometry { path });
|
||||||
|
|
||||||
|
half_edge
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a circle
|
/// Create a circle
|
||||||
@ -78,7 +92,12 @@ pub trait BuildHalfEdge {
|
|||||||
let boundary =
|
let boundary =
|
||||||
[Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord]));
|
[Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord]));
|
||||||
|
|
||||||
HalfEdge::unjoined(path, boundary, core).insert(core)
|
let half_edge = HalfEdge::unjoined(path, boundary, core).insert(core);
|
||||||
|
core.layers
|
||||||
|
.geometry
|
||||||
|
.define_half_edge(half_edge.clone(), HalfEdgeGeometry { path });
|
||||||
|
|
||||||
|
half_edge
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a line segment
|
/// Create a line segment
|
||||||
@ -93,7 +112,12 @@ pub trait BuildHalfEdge {
|
|||||||
boundary.zip_ext(points_surface),
|
boundary.zip_ext(points_surface),
|
||||||
);
|
);
|
||||||
|
|
||||||
HalfEdge::unjoined(path, boundary, core).insert(core)
|
let half_edge = HalfEdge::unjoined(path, boundary, core).insert(core);
|
||||||
|
core.layers
|
||||||
|
.geometry
|
||||||
|
.define_half_edge(half_edge.clone(), HalfEdgeGeometry { path });
|
||||||
|
|
||||||
|
half_edge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use fj_math::Point;
|
use fj_math::Point;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
geometry::{CurveBoundary, SurfacePath},
|
geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath},
|
||||||
objects::HalfEdge,
|
objects::HalfEdge,
|
||||||
operations::insert::Insert,
|
operations::insert::Insert,
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
@ -35,13 +35,19 @@ impl UpdateHalfEdgeGeometry for Handle<HalfEdge> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let path = update(self.path());
|
let path = update(self.path());
|
||||||
|
|
||||||
HalfEdge::new(
|
let half_edge = HalfEdge::new(
|
||||||
path,
|
path,
|
||||||
self.boundary(),
|
self.boundary(),
|
||||||
self.curve().clone(),
|
self.curve().clone(),
|
||||||
self.start_vertex().clone(),
|
self.start_vertex().clone(),
|
||||||
)
|
)
|
||||||
.insert(core)
|
.insert(core);
|
||||||
|
|
||||||
|
core.layers
|
||||||
|
.geometry
|
||||||
|
.define_half_edge(half_edge.clone(), HalfEdgeGeometry { path });
|
||||||
|
|
||||||
|
half_edge
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_boundary(
|
fn update_boundary(
|
||||||
|
@ -4,10 +4,11 @@ use fj_math::Point;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
geometry::{CurveBoundary, SurfacePath},
|
geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath},
|
||||||
objects::{Cycle, HalfEdge},
|
objects::{Cycle, HalfEdge},
|
||||||
operations::{
|
operations::{
|
||||||
build::BuildHalfEdge,
|
build::BuildHalfEdge,
|
||||||
|
insert::Insert,
|
||||||
update::{UpdateCycle, UpdateHalfEdge},
|
update::{UpdateCycle, UpdateHalfEdge},
|
||||||
},
|
},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
@ -88,12 +89,20 @@ impl JoinCycle for Cycle {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.circular_tuple_windows()
|
.circular_tuple_windows()
|
||||||
.map(|((prev_half_edge, _, _), (half_edge, path, boundary))| {
|
.map(|((prev_half_edge, _, _), (half_edge, path, boundary))| {
|
||||||
HalfEdge::unjoined(path, boundary, core)
|
let half_edge = HalfEdge::unjoined(path, boundary, core)
|
||||||
.update_curve(|_, _| half_edge.curve().clone(), core)
|
.update_curve(|_, _| half_edge.curve().clone(), core)
|
||||||
.update_start_vertex(
|
.update_start_vertex(
|
||||||
|_, _| prev_half_edge.start_vertex().clone(),
|
|_, _| prev_half_edge.start_vertex().clone(),
|
||||||
core,
|
core,
|
||||||
)
|
)
|
||||||
|
.insert(core);
|
||||||
|
|
||||||
|
core.layers.geometry.define_half_edge(
|
||||||
|
half_edge.clone(),
|
||||||
|
HalfEdgeGeometry { path },
|
||||||
|
);
|
||||||
|
|
||||||
|
half_edge
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
self.add_half_edges(half_edges, core)
|
self.add_half_edges(half_edges, core)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
geometry::HalfEdgeGeometry,
|
||||||
objects::{Cycle, HalfEdge},
|
objects::{Cycle, HalfEdge},
|
||||||
operations::{derive::DeriveFrom, insert::Insert},
|
operations::{derive::DeriveFrom, insert::Insert},
|
||||||
Core,
|
Core,
|
||||||
@ -12,14 +13,23 @@ impl Reverse for Cycle {
|
|||||||
.half_edges()
|
.half_edges()
|
||||||
.pairs()
|
.pairs()
|
||||||
.map(|(current, next)| {
|
.map(|(current, next)| {
|
||||||
HalfEdge::new(
|
let half_edge = HalfEdge::new(
|
||||||
current.path(),
|
current.path(),
|
||||||
current.boundary().reverse(),
|
current.boundary().reverse(),
|
||||||
current.curve().clone(),
|
current.curve().clone(),
|
||||||
next.start_vertex().clone(),
|
next.start_vertex().clone(),
|
||||||
)
|
)
|
||||||
.insert(core)
|
.insert(core)
|
||||||
.derive_from(current, core)
|
.derive_from(current, core);
|
||||||
|
|
||||||
|
core.layers.geometry.define_half_edge(
|
||||||
|
half_edge.clone(),
|
||||||
|
HalfEdgeGeometry {
|
||||||
|
path: current.path(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
half_edge
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
geometry::HalfEdgeGeometry,
|
||||||
objects::HalfEdge,
|
objects::HalfEdge,
|
||||||
operations::{derive::DeriveFrom, insert::Insert},
|
operations::{derive::DeriveFrom, insert::Insert},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
@ -12,13 +13,19 @@ impl ReverseCurveCoordinateSystems for Handle<HalfEdge> {
|
|||||||
let path = self.path().reverse();
|
let path = self.path().reverse();
|
||||||
let boundary = self.boundary().reverse();
|
let boundary = self.boundary().reverse();
|
||||||
|
|
||||||
HalfEdge::new(
|
let half_edge = HalfEdge::new(
|
||||||
path,
|
path,
|
||||||
boundary,
|
boundary,
|
||||||
self.curve().clone(),
|
self.curve().clone(),
|
||||||
self.start_vertex().clone(),
|
self.start_vertex().clone(),
|
||||||
)
|
)
|
||||||
.insert(core)
|
.insert(core)
|
||||||
.derive_from(self, core)
|
.derive_from(self, core);
|
||||||
|
|
||||||
|
core.layers
|
||||||
|
.geometry
|
||||||
|
.define_half_edge(half_edge.clone(), HalfEdgeGeometry { path });
|
||||||
|
|
||||||
|
half_edge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use fj_math::Point;
|
use fj_math::Point;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
geometry::HalfEdgeGeometry,
|
||||||
objects::{HalfEdge, Vertex},
|
objects::{HalfEdge, Vertex},
|
||||||
operations::insert::Insert,
|
operations::insert::Insert,
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
@ -57,6 +58,15 @@ impl SplitHalfEdge for HalfEdge {
|
|||||||
)
|
)
|
||||||
.insert(core);
|
.insert(core);
|
||||||
|
|
||||||
|
core.layers.geometry.define_half_edge(
|
||||||
|
a.clone(),
|
||||||
|
HalfEdgeGeometry { path: self.path() },
|
||||||
|
);
|
||||||
|
core.layers.geometry.define_half_edge(
|
||||||
|
b.clone(),
|
||||||
|
HalfEdgeGeometry { path: self.path() },
|
||||||
|
);
|
||||||
|
|
||||||
[a, b]
|
[a, b]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use fj_math::Transform;
|
use fj_math::Transform;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::HalfEdge, operations::insert::Insert, storage::Handle, Core,
|
geometry::HalfEdgeGeometry, objects::HalfEdge, operations::insert::Insert,
|
||||||
|
storage::Handle, Core,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{TransformCache, TransformObject};
|
use super::{TransformCache, TransformObject};
|
||||||
@ -26,6 +27,13 @@ impl TransformObject for Handle<HalfEdge> {
|
|||||||
.clone()
|
.clone()
|
||||||
.transform_with_cache(transform, core, cache);
|
.transform_with_cache(transform, core, cache);
|
||||||
|
|
||||||
HalfEdge::new(path, boundary, curve, start_vertex).insert(core)
|
let half_edge =
|
||||||
|
HalfEdge::new(path, boundary, curve, start_vertex).insert(core);
|
||||||
|
|
||||||
|
core.layers
|
||||||
|
.geometry
|
||||||
|
.define_half_edge(half_edge.clone(), HalfEdgeGeometry { path });
|
||||||
|
|
||||||
|
half_edge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user