Merge pull request #2274 from hannobraun/geometry

Update half-edge geometry in geometry layer in more places
This commit is contained in:
Hanno Braun 2024-03-20 14:19:14 +01:00 committed by GitHub
commit ae743214d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 156 additions and 41 deletions

View File

@ -8,6 +8,7 @@ use crate::{
objects::{Curve, Face, HalfEdge, Shell, Surface, Vertex}, objects::{Curve, Face, HalfEdge, Shell, Surface, Vertex},
operations::{ operations::{
build::{BuildFace, BuildHalfEdge, BuildSurface, Polygon}, build::{BuildFace, BuildHalfEdge, BuildSurface, Polygon},
geometry::UpdateHalfEdgeGeometry,
insert::{Insert, IsInserted, IsInsertedNo, IsInsertedYes}, insert::{Insert, IsInserted, IsInsertedNo, IsInsertedYes},
join::JoinCycle, join::JoinCycle,
reverse::ReverseCurveCoordinateSystems, reverse::ReverseCurveCoordinateSystems,
@ -91,13 +92,22 @@ pub trait BuildShell {
.zip_ext([[a, b], [b, c], [c, a]]) .zip_ext([[a, b], [b, c], [c, a]])
.zip_ext(curves_and_boundaries) .zip_ext(curves_and_boundaries)
.map(|((vertex, positions), (curve, boundary))| { .map(|((vertex, positions), (curve, boundary))| {
HalfEdge::line_segment( let half_edge = HalfEdge::line_segment(
positions, positions,
Some(boundary.reverse().inner), Some(boundary.reverse().inner),
core, core,
) );
half_edge
.update_start_vertex(|_, _| vertex, core) .update_start_vertex(|_, _| vertex, core)
.update_curve(|_, _| curve, core) .update_curve(|_, _| curve, core)
.insert(core)
.set_path(
core.layers
.geometry
.of_half_edge(&half_edge)
.path,
&mut core.layers.geometry,
)
}) })
}; };

View File

@ -1,7 +1,8 @@
use fj_math::Point; use fj_math::Point;
use crate::{ use crate::{
geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath}, geometry::{CurveBoundary, Geometry, HalfEdgeGeometry, SurfacePath},
layers::Layer,
objects::HalfEdge, objects::HalfEdge,
operations::insert::Insert, operations::insert::Insert,
storage::Handle, storage::Handle,
@ -10,7 +11,14 @@ use crate::{
/// Update the geometry of a [`HalfEdge`] /// Update the geometry of a [`HalfEdge`]
pub trait UpdateHalfEdgeGeometry { pub trait UpdateHalfEdgeGeometry {
/// Update the path of the edge /// Set the path of the half-edge
fn set_path(
self,
path: SurfacePath,
geometry: &mut Layer<Geometry>,
) -> Self;
/// Update the path of the half-edge
#[must_use] #[must_use]
fn update_path( fn update_path(
&self, &self,
@ -18,7 +26,7 @@ pub trait UpdateHalfEdgeGeometry {
core: &mut Core, core: &mut Core,
) -> Self; ) -> Self;
/// Update the boundary of the edge /// Update the boundary of the half-edge
#[must_use] #[must_use]
fn update_boundary( fn update_boundary(
&self, &self,
@ -28,6 +36,15 @@ pub trait UpdateHalfEdgeGeometry {
} }
impl UpdateHalfEdgeGeometry for Handle<HalfEdge> { impl UpdateHalfEdgeGeometry for Handle<HalfEdge> {
fn set_path(
self,
path: SurfacePath,
geometry: &mut Layer<Geometry>,
) -> Self {
geometry.define_half_edge(self.clone(), HalfEdgeGeometry { path });
self
}
fn update_path( fn update_path(
&self, &self,
update: impl FnOnce(SurfacePath) -> SurfacePath, update: impl FnOnce(SurfacePath) -> SurfacePath,

View File

@ -8,6 +8,7 @@ use crate::{
objects::{Cycle, HalfEdge}, objects::{Cycle, HalfEdge},
operations::{ operations::{
build::BuildHalfEdge, build::BuildHalfEdge,
geometry::UpdateHalfEdgeGeometry,
insert::Insert, insert::Insert,
update::{UpdateCycle, UpdateHalfEdge}, update::{UpdateCycle, UpdateHalfEdge},
}, },
@ -129,8 +130,8 @@ impl JoinCycle for Cycle {
cycle cycle
.update_half_edge( .update_half_edge(
self.half_edges().nth_circular(index), self.half_edges().nth_circular(index),
|edge, core| { |half_edge, core| {
[edge [half_edge
.update_curve( .update_curve(
|_, _| edge_other.curve().clone(), |_, _| edge_other.curve().clone(),
core, core,
@ -144,16 +145,33 @@ impl JoinCycle for Cycle {
.clone() .clone()
}, },
core, core,
)
.insert(core)
.set_path(
core.layers
.geometry
.of_half_edge(half_edge)
.path,
&mut core.layers.geometry,
)] )]
}, },
core, core,
) )
.update_half_edge( .update_half_edge(
self.half_edges().nth_circular(index + 1), self.half_edges().nth_circular(index + 1),
|edge, core| { |half_edge, core| {
[edge.update_start_vertex( [half_edge
.update_start_vertex(
|_, _| edge_other.start_vertex().clone(), |_, _| edge_other.start_vertex().clone(),
core, core,
)
.insert(core)
.set_path(
core.layers
.geometry
.of_half_edge(half_edge)
.path,
&mut core.layers.geometry,
)] )]
}, },
core, core,

View File

@ -3,8 +3,8 @@ use fj_math::Point;
use crate::{ use crate::{
objects::{HalfEdge, Shell}, objects::{HalfEdge, Shell},
operations::{ operations::{
derive::DeriveFrom, insert::Insert, replace::ReplaceHalfEdge, derive::DeriveFrom, geometry::UpdateHalfEdgeGeometry, insert::Insert,
split::SplitHalfEdge, update::UpdateHalfEdge, replace::ReplaceHalfEdge, split::SplitHalfEdge, update::UpdateHalfEdge,
}, },
queries::SiblingOfHalfEdge, queries::SiblingOfHalfEdge,
storage::Handle, storage::Handle,
@ -55,10 +55,21 @@ impl SplitEdge for Shell {
) )
.insert(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).set_path(
core.layers.geometry.of_half_edge(&sibling).path,
&mut core.layers.geometry,
)
}) })
}; };
let [half_edge_a, half_edge_b] =
[half_edge_a, half_edge_b].map(|half_edge_part| {
half_edge_part.set_path(
core.layers.geometry.of_half_edge(half_edge).path,
&mut core.layers.geometry,
)
});
let shell = self let shell = self
.replace_half_edge( .replace_half_edge(
half_edge, half_edge,

View File

@ -7,6 +7,7 @@ use crate::{
operations::{ operations::{
build::{BuildCycle, BuildHalfEdge}, build::{BuildCycle, BuildHalfEdge},
derive::DeriveFrom, derive::DeriveFrom,
geometry::UpdateHalfEdgeGeometry,
insert::Insert, insert::Insert,
split::SplitEdge, split::SplitEdge,
update::{ update::{
@ -101,13 +102,20 @@ impl SplitFace for Shell {
.expect("Updated shell must contain updated face"); .expect("Updated shell must contain updated face");
// Build the edge that's going to divide the new faces. // Build the edge that's going to divide the new faces.
let dividing_half_edge_a_to_d = HalfEdge::line_segment( let dividing_half_edge_a_to_d = {
let half_edge = HalfEdge::line_segment(
[b.start_position(), d.start_position()], [b.start_position(), d.start_position()],
None, None,
core, core,
) );
half_edge
.update_start_vertex(|_, _| b.start_vertex().clone(), core) .update_start_vertex(|_, _| b.start_vertex().clone(), core)
.insert(core); .insert(core)
.set_path(
core.layers.geometry.of_half_edge(&half_edge).path,
&mut core.layers.geometry,
)
};
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(),

View File

@ -6,6 +6,7 @@ use crate::{
objects::{Cycle, Face, HalfEdge, Region, Vertex}, objects::{Cycle, Face, HalfEdge, Region, Vertex},
operations::{ operations::{
build::{BuildCycle, BuildHalfEdge}, build::{BuildCycle, BuildHalfEdge},
geometry::UpdateHalfEdgeGeometry,
insert::Insert, insert::Insert,
presentation::SetColor, presentation::SetColor,
update::{UpdateCycle, UpdateHalfEdge}, update::{UpdateCycle, UpdateHalfEdge},
@ -113,26 +114,30 @@ impl SweepHalfEdge for HalfEdge {
.zip_ext(vertices) .zip_ext(vertices)
.zip_ext(curves) .zip_ext(curves)
.map(|((((boundary, start), end), start_vertex), curve)| { .map(|((((boundary, start), end), start_vertex), curve)| {
let edge = { let half_edge = {
let edge = HalfEdge::line_segment( let line_segment = HalfEdge::line_segment(
[start, end], [start, end],
Some(boundary), Some(boundary),
core, core,
) );
let half_edge = line_segment
.update_start_vertex(|_, _| start_vertex, core); .update_start_vertex(|_, _| start_vertex, core);
let edge = if let Some(curve) = curve { let half_edge = if let Some(curve) = curve {
edge.update_curve(|_, _| curve, core) half_edge.update_curve(|_, _| curve, core)
} else { } else {
edge half_edge
}; };
edge.insert(core) half_edge.insert(core).set_path(
core.layers.geometry.of_half_edge(&line_segment).path,
&mut core.layers.geometry,
)
}; };
exterior = exterior.add_half_edges([edge.clone()], core); exterior = exterior.add_half_edges([half_edge.clone()], core);
edge half_edge
}); });
let exterior = exterior.insert(core); let exterior = exterior.insert(core);

View File

@ -404,6 +404,7 @@ mod tests {
operations::{ operations::{
build::BuildShell, build::BuildShell,
geometry::UpdateHalfEdgeGeometry, geometry::UpdateHalfEdgeGeometry,
insert::Insert,
update::{ update::{
UpdateCycle, UpdateFace, UpdateHalfEdge, UpdateRegion, UpdateCycle, UpdateFace, UpdateHalfEdge, UpdateRegion,
UpdateShell, UpdateShell,
@ -430,8 +431,36 @@ 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, core| { |half_edge, core| {
[edge // This is going to be weird:
//
// - That first call to `update_path` is
// going to reverse a path and insert
// a new object with the reversed
// path.
// - The next call to `update_boundary`
// relies on that, because it inserts
// an object too, and that would cause
// a validation failure without the
// first call.
// - But the new object created from
// those two operations doesn't
// actually have its geometry set in
// the geometry layer, because that
// happens in `update_path`, for an
// earlier version of the object.
// - So we need a last `set_path`, which
// sets the path again.
//
// This is very weird, but good new is,
// it's just an artifact of the
// transition from a unified object
// graph to separate topology and
// geometry layers. This should clear up
// again, once the separation is
// finished, and all APIs can adapt to
// the new reality.
[half_edge
.update_path( .update_path(
|path| path.reverse(), |path| path.reverse(),
core, core,
@ -439,6 +468,14 @@ mod tests {
.update_boundary( .update_boundary(
|boundary| boundary.reverse(), |boundary| boundary.reverse(),
core, core,
)
.set_path(
core.layers
.geometry
.of_half_edge(half_edge)
.path
.reverse(),
&mut core.layers.geometry,
)] )]
}, },
core, core,
@ -508,10 +545,19 @@ 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, core| { |half_edge, core| {
[edge.update_curve( [half_edge
.update_curve(
|_, _| Curve::new(), |_, _| Curve::new(),
core, core,
)
.insert(core)
.set_path(
core.layers
.geometry
.of_half_edge(half_edge)
.path,
&mut core.layers.geometry,
)] )]
}, },
core, core,