Merge pull request #2265 from hannobraun/geometry

Prepare for moving `HalfEdge`'s `SurfacePath` to geometry layer
This commit is contained in:
Hanno Braun 2024-03-14 14:56:58 +01:00 committed by GitHub
commit 64784f5f23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 80 additions and 68 deletions

View File

@ -59,7 +59,7 @@ impl Geometry {
surface: Handle<Surface>, surface: Handle<Surface>,
geometry: SurfaceGeometry, geometry: SurfaceGeometry,
) { ) {
self.surface.insert(surface.clone().into(), geometry); self.surface.insert(surface.into(), geometry);
} }
/// # Access the geometry of the provided surface /// # Access the geometry of the provided surface

View File

@ -3,7 +3,7 @@ use itertools::Itertools;
use crate::{ use crate::{
objects::{Cycle, HalfEdge}, objects::{Cycle, HalfEdge},
operations::{build::BuildHalfEdge, insert::Insert, update::UpdateCycle}, operations::{build::BuildHalfEdge, update::UpdateCycle},
Core, Core,
}; };
@ -40,7 +40,7 @@ pub trait BuildCycle {
.map(Into::into) .map(Into::into)
.circular_tuple_windows() .circular_tuple_windows()
.map(|(start, end)| { .map(|(start, end)| {
HalfEdge::line_segment([start, end], None, core).insert(core) HalfEdge::line_segment([start, end], None, core)
}); });
Cycle::new(edges) Cycle::new(edges)

View File

@ -29,15 +29,17 @@ pub trait BuildHalfEdge {
/// Create a half-edge from its sibling /// Create a half-edge from its sibling
fn from_sibling( fn from_sibling(
sibling: &HalfEdge, sibling: &Handle<HalfEdge>,
start_vertex: Handle<Vertex>, start_vertex: Handle<Vertex>,
) -> HalfEdge { core: &mut Core,
) -> Handle<HalfEdge> {
HalfEdge::new( HalfEdge::new(
sibling.path(), sibling.path(),
sibling.boundary().reverse(), sibling.boundary().reverse(),
sibling.curve().clone(), sibling.curve().clone(),
start_vertex, start_vertex,
) )
.insert(core)
} }
/// Create an arc /// Create an arc
@ -50,7 +52,7 @@ pub trait BuildHalfEdge {
end: impl Into<Point<2>>, end: impl Into<Point<2>>,
angle_rad: impl Into<Scalar>, angle_rad: impl Into<Scalar>,
core: &mut Core, core: &mut Core,
) -> HalfEdge { ) -> Handle<HalfEdge> {
let angle_rad = angle_rad.into(); let angle_rad = angle_rad.into();
if angle_rad <= -Scalar::TAU || angle_rad >= Scalar::TAU { if angle_rad <= -Scalar::TAU || angle_rad >= Scalar::TAU {
panic!("arc angle must be in the range (-2pi, 2pi) radians"); panic!("arc angle must be in the range (-2pi, 2pi) radians");
@ -63,7 +65,7 @@ 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) HalfEdge::unjoined(path, boundary, core).insert(core)
} }
/// Create a circle /// Create a circle
@ -71,12 +73,12 @@ pub trait BuildHalfEdge {
center: impl Into<Point<2>>, center: impl Into<Point<2>>,
radius: impl Into<Scalar>, radius: impl Into<Scalar>,
core: &mut Core, core: &mut Core,
) -> HalfEdge { ) -> Handle<HalfEdge> {
let path = SurfacePath::circle_from_center_and_radius(center, radius); let path = SurfacePath::circle_from_center_and_radius(center, radius);
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) HalfEdge::unjoined(path, boundary, core).insert(core)
} }
/// Create a line segment /// Create a line segment
@ -84,14 +86,14 @@ pub trait BuildHalfEdge {
points_surface: [impl Into<Point<2>>; 2], points_surface: [impl Into<Point<2>>; 2],
boundary: Option<[Point<1>; 2]>, boundary: Option<[Point<1>; 2]>,
core: &mut Core, core: &mut Core,
) -> HalfEdge { ) -> Handle<HalfEdge> {
let boundary = let boundary =
boundary.unwrap_or_else(|| [[0.], [1.]].map(Point::from)); boundary.unwrap_or_else(|| [[0.], [1.]].map(Point::from));
let path = SurfacePath::line_from_points_with_coords( let path = SurfacePath::line_from_points_with_coords(
boundary.zip_ext(points_surface), boundary.zip_ext(points_surface),
); );
HalfEdge::unjoined(path, boundary, core) HalfEdge::unjoined(path, boundary, core).insert(core)
} }
} }

View File

@ -10,7 +10,6 @@ use crate::{
use super::{ use super::{
build::{BuildCycle, BuildHalfEdge, BuildRegion}, build::{BuildCycle, BuildHalfEdge, BuildRegion},
insert::Insert,
join::JoinCycle, join::JoinCycle,
sweep::{SweepCache, SweepRegion}, sweep::{SweepCache, SweepRegion},
update::{UpdateCycle, UpdateFace, UpdateRegion, UpdateShell}, update::{UpdateCycle, UpdateFace, UpdateRegion, UpdateShell},
@ -44,8 +43,7 @@ impl AddHole for Shell {
path: impl Into<Vector<3>>, path: impl Into<Vector<3>>,
core: &mut Core, core: &mut Core,
) -> Self { ) -> Self {
let entry = let entry = HalfEdge::circle(location.position, radius, core);
HalfEdge::circle(location.position, radius, core).insert(core);
let hole = Region::empty(core) let hole = Region::empty(core)
.update_exterior( .update_exterior(
|_, core| Cycle::empty().add_half_edges([entry.clone()], core), |_, core| Cycle::empty().add_half_edges([entry.clone()], core),
@ -94,8 +92,7 @@ impl AddHole for Shell {
) -> Self { ) -> Self {
let radius = radius.into(); let radius = radius.into();
let entry = HalfEdge::circle(entry_location.position, radius, core) let entry = HalfEdge::circle(entry_location.position, radius, core);
.insert(core);
let path = { let path = {
let point = |location: &HoleLocation| { let point = |location: &HoleLocation| {

View File

@ -87,8 +87,8 @@ impl JoinCycle for Cycle {
let half_edges = edges let half_edges = edges
.into_iter() .into_iter()
.circular_tuple_windows() .circular_tuple_windows()
.map(|((prev_half_edge, _, _), (half_edge, curve, boundary))| { .map(|((prev_half_edge, _, _), (half_edge, path, boundary))| {
HalfEdge::unjoined(curve, boundary, core) 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(),

View File

@ -31,11 +31,10 @@ impl Reverse for Cycle {
impl ReverseCurveCoordinateSystems for Cycle { impl ReverseCurveCoordinateSystems for Cycle {
fn reverse_curve_coordinate_systems(&self, core: &mut Core) -> Self { fn reverse_curve_coordinate_systems(&self, core: &mut Core) -> Self {
let edges = self.half_edges().iter().map(|edge| { let edges = self
edge.reverse_curve_coordinate_systems(core) .half_edges()
.insert(core) .iter()
.derive_from(edge, core) .map(|edge| edge.reverse_curve_coordinate_systems(core));
});
Cycle::new(edges) Cycle::new(edges)
} }

View File

@ -1,9 +1,14 @@
use crate::{objects::HalfEdge, Core}; use crate::{
objects::HalfEdge,
operations::{derive::DeriveFrom, insert::Insert},
storage::Handle,
Core,
};
use super::ReverseCurveCoordinateSystems; use super::ReverseCurveCoordinateSystems;
impl ReverseCurveCoordinateSystems for HalfEdge { impl ReverseCurveCoordinateSystems for Handle<HalfEdge> {
fn reverse_curve_coordinate_systems(&self, _: &mut Core) -> Self { fn reverse_curve_coordinate_systems(&self, core: &mut Core) -> Self {
let path = self.path().reverse(); let path = self.path().reverse();
let boundary = self.boundary().reverse(); let boundary = self.boundary().reverse();
@ -13,5 +18,7 @@ impl ReverseCurveCoordinateSystems for HalfEdge {
self.curve().clone(), self.curve().clone(),
self.start_vertex().clone(), self.start_vertex().clone(),
) )
.insert(core)
.derive_from(self, core)
} }
} }

View File

@ -48,10 +48,12 @@ impl SplitEdge for Shell {
let siblings = { let siblings = {
let [sibling_a, sibling_b] = sibling.split_half_edge(point, core); let [sibling_a, sibling_b] = sibling.split_half_edge(point, core);
let sibling_b = sibling_b.update_start_vertex( let sibling_b = sibling_b
|_, _| half_edge_b.start_vertex().clone(), .update_start_vertex(
core, |_, _| half_edge_b.start_vertex().clone(),
); core,
)
.insert(core);
[sibling_a, sibling_b].map(|half_edge| { [sibling_a, sibling_b].map(|half_edge| {
half_edge.insert(core).derive_from(&sibling, core) half_edge.insert(core).derive_from(&sibling, core)
}) })

View File

@ -106,10 +106,12 @@ impl SplitFace for Shell {
None, None,
core, core,
) )
.update_start_vertex(|_, _| b.start_vertex().clone(), core); .update_start_vertex(|_, _| b.start_vertex().clone(), core)
.insert(core);
let dividing_half_edge_c_to_b = HalfEdge::from_sibling( let dividing_half_edge_c_to_b = HalfEdge::from_sibling(
&dividing_half_edge_a_to_d, &dividing_half_edge_a_to_d,
d.start_vertex().clone(), d.start_vertex().clone(),
core,
); );
let mut half_edges_of_face_starting_at_b = let mut half_edges_of_face_starting_at_b =

View File

@ -3,6 +3,7 @@ use fj_math::Point;
use crate::{ use crate::{
objects::{HalfEdge, Vertex}, objects::{HalfEdge, Vertex},
operations::insert::Insert, operations::insert::Insert,
storage::Handle,
Core, Core,
}; };
@ -28,7 +29,7 @@ pub trait SplitHalfEdge {
&self, &self,
point: impl Into<Point<1>>, point: impl Into<Point<1>>,
core: &mut Core, core: &mut Core,
) -> [HalfEdge; 2]; ) -> [Handle<HalfEdge>; 2];
} }
impl SplitHalfEdge for HalfEdge { impl SplitHalfEdge for HalfEdge {
@ -36,7 +37,7 @@ impl SplitHalfEdge for HalfEdge {
&self, &self,
point: impl Into<Point<1>>, point: impl Into<Point<1>>,
core: &mut Core, core: &mut Core,
) -> [HalfEdge; 2] { ) -> [Handle<HalfEdge>; 2] {
let point = point.into(); let point = point.into();
let [start, end] = self.boundary().inner; let [start, end] = self.boundary().inner;
@ -46,13 +47,15 @@ impl SplitHalfEdge for HalfEdge {
[start, point], [start, point],
self.curve().clone(), self.curve().clone(),
self.start_vertex().clone(), self.start_vertex().clone(),
); )
.insert(core);
let b = HalfEdge::new( let b = HalfEdge::new(
self.path(), self.path(),
[point, end], [point, end],
self.curve().clone(), self.curve().clone(),
Vertex::new().insert(core), Vertex::new().insert(core),
); )
.insert(core);
[a, b] [a, b]
} }

View File

@ -1,10 +1,12 @@
use fj_math::Transform; use fj_math::Transform;
use crate::{objects::HalfEdge, Core}; use crate::{
objects::HalfEdge, operations::insert::Insert, storage::Handle, Core,
};
use super::{TransformCache, TransformObject}; use super::{TransformCache, TransformObject};
impl TransformObject for HalfEdge { impl TransformObject for Handle<HalfEdge> {
fn transform_with_cache( fn transform_with_cache(
&self, &self,
transform: &Transform, transform: &Transform,
@ -24,6 +26,6 @@ impl TransformObject for HalfEdge {
.clone() .clone()
.transform_with_cache(transform, core, cache); .transform_with_cache(transform, core, cache);
Self::new(path, boundary, curve, start_vertex) HalfEdge::new(path, boundary, curve, start_vertex).insert(core)
} }
} }

View File

@ -9,13 +9,14 @@ use crate::{
}; };
/// Update a [`HalfEdge`] /// Update a [`HalfEdge`]
pub trait UpdateHalfEdge { pub trait UpdateHalfEdge: Sized {
/// Update the path of the edge /// Update the path of the edge
#[must_use] #[must_use]
fn update_path( fn update_path(
&self, &self,
update: impl FnOnce(SurfacePath) -> SurfacePath, update: impl FnOnce(SurfacePath) -> SurfacePath,
) -> Self; core: &mut Core,
) -> Handle<Self>;
/// Update the boundary of the edge /// Update the boundary of the edge
#[must_use] #[must_use]
@ -49,13 +50,17 @@ impl UpdateHalfEdge for HalfEdge {
fn update_path( fn update_path(
&self, &self,
update: impl FnOnce(SurfacePath) -> SurfacePath, update: impl FnOnce(SurfacePath) -> SurfacePath,
) -> Self { core: &mut Core,
) -> Handle<Self> {
let path = update(self.path());
HalfEdge::new( HalfEdge::new(
update(self.path()), path,
self.boundary(), self.boundary(),
self.curve().clone(), self.curve().clone(),
self.start_vertex().clone(), self.start_vertex().clone(),
) )
.insert(core)
} }
fn update_boundary( fn update_boundary(

View File

@ -429,9 +429,12 @@ mod tests {
|cycle, core| { |cycle, core| {
cycle.update_half_edge( cycle.update_half_edge(
cycle.half_edges().nth_circular(0), cycle.half_edges().nth_circular(0),
|edge, _| { |edge, core| {
[edge [edge
.update_path(|path| path.reverse()) .update_path(
|path| path.reverse(),
core,
)
.update_boundary(|boundary| { .update_boundary(|boundary| {
boundary.reverse() boundary.reverse()
})] })]

View File

@ -186,8 +186,7 @@ mod tests {
fn should_find_clockwise_exterior_cycle() -> anyhow::Result<()> { fn should_find_clockwise_exterior_cycle() -> anyhow::Result<()> {
let mut core = Core::new(); let mut core = Core::new();
let valid_outer_circle = let valid_outer_circle = HalfEdge::circle([0., 0.], 1., &mut core);
HalfEdge::circle([0., 0.], 1., &mut core).insert(&mut core);
let valid_exterior = let valid_exterior =
Cycle::new(vec![valid_outer_circle.clone()]).insert(&mut core); Cycle::new(vec![valid_outer_circle.clone()]).insert(&mut core);
let valid_sketch = let valid_sketch =
@ -199,8 +198,8 @@ mod tests {
let invalid_outer_circle = HalfEdge::from_sibling( let invalid_outer_circle = HalfEdge::from_sibling(
&valid_outer_circle, &valid_outer_circle,
Vertex::new().insert(&mut core), Vertex::new().insert(&mut core),
) &mut core,
.insert(&mut core); );
let invalid_exterior = let invalid_exterior =
Cycle::new(vec![invalid_outer_circle.clone()]).insert(&mut core); Cycle::new(vec![invalid_outer_circle.clone()]).insert(&mut core);
let invalid_sketch = let invalid_sketch =
@ -222,15 +221,13 @@ mod tests {
fn should_find_counterclockwise_interior_cycle() -> anyhow::Result<()> { fn should_find_counterclockwise_interior_cycle() -> anyhow::Result<()> {
let mut core = Core::new(); let mut core = Core::new();
let outer_circle = let outer_circle = HalfEdge::circle([0., 0.], 2., &mut core);
HalfEdge::circle([0., 0.], 2., &mut core).insert(&mut core); let inner_circle = HalfEdge::circle([0., 0.], 1., &mut core);
let inner_circle =
HalfEdge::circle([0., 0.], 1., &mut core).insert(&mut core);
let cw_inner_circle = HalfEdge::from_sibling( let cw_inner_circle = HalfEdge::from_sibling(
&inner_circle, &inner_circle,
Vertex::new().insert(&mut core), Vertex::new().insert(&mut core),
) &mut core,
.insert(&mut core); );
let exterior = Cycle::new(vec![outer_circle.clone()]).insert(&mut core); let exterior = Cycle::new(vec![outer_circle.clone()]).insert(&mut core);
let valid_interior = let valid_interior =

View File

@ -202,10 +202,8 @@ mod tests {
&mut core, &mut core,
), ),
Region::new( Region::new(
Cycle::new(vec![ Cycle::new(vec![HalfEdge::circle([0., 0.], 1., &mut core)])
HalfEdge::circle([0., 0.], 1., &mut core).insert(&mut core) .insert(&mut core),
])
.insert(&mut core),
vec![], vec![],
) )
.insert(&mut core), .insert(&mut core),
@ -249,10 +247,8 @@ mod tests {
let mut core = Core::new(); let mut core = Core::new();
let shared_region = Region::new( let shared_region = Region::new(
Cycle::new(vec![ Cycle::new(vec![HalfEdge::circle([0., 0.], 1., &mut core)])
HalfEdge::circle([0., 0.], 1., &mut core).insert(&mut core) .insert(&mut core),
])
.insert(&mut core),
vec![], vec![],
) )
.insert(&mut core); .insert(&mut core);
@ -302,10 +298,8 @@ mod tests {
let mut core = Core::new(); let mut core = Core::new();
let shared_cycle = let shared_cycle =
Cycle::new(vec![ Cycle::new(vec![HalfEdge::circle([0., 0.], 1., &mut core)])
HalfEdge::circle([0., 0.], 1., &mut core).insert(&mut core) .insert(&mut core);
])
.insert(&mut core);
let invalid_solid = Solid::new(vec![Shell::new(vec![ let invalid_solid = Solid::new(vec![Shell::new(vec![
Face::new( Face::new(
@ -351,8 +345,7 @@ mod tests {
fn should_find_half_edge_multiple_references() -> anyhow::Result<()> { fn should_find_half_edge_multiple_references() -> anyhow::Result<()> {
let mut core = Core::new(); let mut core = Core::new();
let shared_edge = let shared_edge = HalfEdge::circle([0., 0.], 1., &mut core);
HalfEdge::circle([0., 0.], 1., &mut core).insert(&mut core);
let invalid_solid = Solid::new(vec![Shell::new(vec![Face::new( let invalid_solid = Solid::new(vec![Shell::new(vec![Face::new(
Surface::surface_from_uv( Surface::surface_from_uv(