mirror of
https://github.com/hannobraun/Fornjot
synced 2025-01-11 18:57:01 +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 crate::{
|
||||
objects::{Objects, Surface},
|
||||
objects::{HalfEdge, Objects, Surface},
|
||||
storage::{Handle, HandleWrapper},
|
||||
};
|
||||
|
||||
use super::{GlobalPath, SurfaceGeometry};
|
||||
use super::{GlobalPath, HalfEdgeGeometry, SurfaceGeometry};
|
||||
|
||||
/// Geometric data that is associated with topological objects
|
||||
pub struct Geometry {
|
||||
half_edge: BTreeMap<Handle<HalfEdge>, HalfEdgeGeometry>,
|
||||
surface: BTreeMap<HandleWrapper<Surface>, SurfaceGeometry>,
|
||||
|
||||
xy_plane: Handle<Surface>,
|
||||
@ -22,6 +23,7 @@ impl Geometry {
|
||||
/// Create a new instance of `Geometry`
|
||||
pub fn new(objects: &Objects) -> Self {
|
||||
let mut self_ = Self {
|
||||
half_edge: BTreeMap::new(),
|
||||
surface: BTreeMap::new(),
|
||||
|
||||
xy_plane: objects.surfaces.xy_plane(),
|
||||
@ -54,6 +56,14 @@ impl Geometry {
|
||||
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(
|
||||
&mut self,
|
||||
surface: Handle<Surface>,
|
||||
@ -62,6 +72,21 @@ impl 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
|
||||
///
|
||||
/// ## 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 geometry;
|
||||
mod half_edge;
|
||||
mod path;
|
||||
mod surface;
|
||||
|
||||
pub use self::{
|
||||
boundary::{CurveBoundary, CurveBoundaryElement},
|
||||
geometry::Geometry,
|
||||
half_edge::HalfEdgeGeometry,
|
||||
path::{GlobalPath, SurfacePath},
|
||||
surface::SurfaceGeometry,
|
||||
};
|
||||
|
@ -1,14 +1,30 @@
|
||||
//! Layer infrastructure for [`Geometry`]
|
||||
|
||||
use crate::{
|
||||
geometry::{Geometry, SurfaceGeometry},
|
||||
objects::Surface,
|
||||
geometry::{Geometry, HalfEdgeGeometry, SurfaceGeometry},
|
||||
objects::{HalfEdge, Surface},
|
||||
storage::Handle,
|
||||
};
|
||||
|
||||
use super::{Command, Event, Layer};
|
||||
|
||||
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
|
||||
pub fn define_surface(
|
||||
&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
|
||||
pub struct DefineSurface {
|
||||
surface: Handle<Surface>,
|
||||
|
@ -2,7 +2,7 @@ use fj_interop::ext::ArrayExt;
|
||||
use fj_math::{Arc, Point, Scalar};
|
||||
|
||||
use crate::{
|
||||
geometry::{CurveBoundary, SurfacePath},
|
||||
geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath},
|
||||
objects::{Curve, HalfEdge, Vertex},
|
||||
operations::insert::Insert,
|
||||
storage::Handle,
|
||||
@ -33,13 +33,22 @@ pub trait BuildHalfEdge {
|
||||
start_vertex: Handle<Vertex>,
|
||||
core: &mut Core,
|
||||
) -> Handle<HalfEdge> {
|
||||
HalfEdge::new(
|
||||
let half_edge = HalfEdge::new(
|
||||
sibling.path(),
|
||||
sibling.boundary().reverse(),
|
||||
sibling.curve().clone(),
|
||||
start_vertex,
|
||||
)
|
||||
.insert(core)
|
||||
.insert(core);
|
||||
|
||||
core.layers.geometry.define_half_edge(
|
||||
half_edge.clone(),
|
||||
HalfEdgeGeometry {
|
||||
path: sibling.path(),
|
||||
},
|
||||
);
|
||||
|
||||
half_edge
|
||||
}
|
||||
|
||||
/// Create an arc
|
||||
@ -65,7 +74,12 @@ pub trait BuildHalfEdge {
|
||||
let boundary =
|
||||
[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
|
||||
@ -78,7 +92,12 @@ pub trait BuildHalfEdge {
|
||||
let boundary =
|
||||
[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
|
||||
@ -93,7 +112,12 @@ pub trait BuildHalfEdge {
|
||||
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 crate::{
|
||||
geometry::{CurveBoundary, SurfacePath},
|
||||
geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath},
|
||||
objects::HalfEdge,
|
||||
operations::insert::Insert,
|
||||
storage::Handle,
|
||||
@ -35,13 +35,19 @@ impl UpdateHalfEdgeGeometry for Handle<HalfEdge> {
|
||||
) -> Self {
|
||||
let path = update(self.path());
|
||||
|
||||
HalfEdge::new(
|
||||
let half_edge = HalfEdge::new(
|
||||
path,
|
||||
self.boundary(),
|
||||
self.curve().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(
|
||||
|
@ -4,10 +4,11 @@ use fj_math::Point;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::{
|
||||
geometry::{CurveBoundary, SurfacePath},
|
||||
geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath},
|
||||
objects::{Cycle, HalfEdge},
|
||||
operations::{
|
||||
build::BuildHalfEdge,
|
||||
insert::Insert,
|
||||
update::{UpdateCycle, UpdateHalfEdge},
|
||||
},
|
||||
storage::Handle,
|
||||
@ -88,12 +89,20 @@ impl JoinCycle for Cycle {
|
||||
.into_iter()
|
||||
.circular_tuple_windows()
|
||||
.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_start_vertex(
|
||||
|_, _| prev_half_edge.start_vertex().clone(),
|
||||
core,
|
||||
)
|
||||
.insert(core);
|
||||
|
||||
core.layers.geometry.define_half_edge(
|
||||
half_edge.clone(),
|
||||
HalfEdgeGeometry { path },
|
||||
);
|
||||
|
||||
half_edge
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
self.add_half_edges(half_edges, core)
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{
|
||||
geometry::HalfEdgeGeometry,
|
||||
objects::{Cycle, HalfEdge},
|
||||
operations::{derive::DeriveFrom, insert::Insert},
|
||||
Core,
|
||||
@ -12,14 +13,23 @@ impl Reverse for Cycle {
|
||||
.half_edges()
|
||||
.pairs()
|
||||
.map(|(current, next)| {
|
||||
HalfEdge::new(
|
||||
let half_edge = HalfEdge::new(
|
||||
current.path(),
|
||||
current.boundary().reverse(),
|
||||
current.curve().clone(),
|
||||
next.start_vertex().clone(),
|
||||
)
|
||||
.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<_>>();
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{
|
||||
geometry::HalfEdgeGeometry,
|
||||
objects::HalfEdge,
|
||||
operations::{derive::DeriveFrom, insert::Insert},
|
||||
storage::Handle,
|
||||
@ -12,13 +13,19 @@ impl ReverseCurveCoordinateSystems for Handle<HalfEdge> {
|
||||
let path = self.path().reverse();
|
||||
let boundary = self.boundary().reverse();
|
||||
|
||||
HalfEdge::new(
|
||||
let half_edge = HalfEdge::new(
|
||||
path,
|
||||
boundary,
|
||||
self.curve().clone(),
|
||||
self.start_vertex().clone(),
|
||||
)
|
||||
.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 crate::{
|
||||
geometry::HalfEdgeGeometry,
|
||||
objects::{HalfEdge, Vertex},
|
||||
operations::insert::Insert,
|
||||
storage::Handle,
|
||||
@ -57,6 +58,15 @@ impl SplitHalfEdge for HalfEdge {
|
||||
)
|
||||
.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]
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
use fj_math::Transform;
|
||||
|
||||
use crate::{
|
||||
objects::HalfEdge, operations::insert::Insert, storage::Handle, Core,
|
||||
geometry::HalfEdgeGeometry, objects::HalfEdge, operations::insert::Insert,
|
||||
storage::Handle, Core,
|
||||
};
|
||||
|
||||
use super::{TransformCache, TransformObject};
|
||||
@ -26,6 +27,13 @@ impl TransformObject for Handle<HalfEdge> {
|
||||
.clone()
|
||||
.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