mirror of
https://github.com/hannobraun/Fornjot
synced 2025-01-11 18:57:01 +00:00
Merge pull request #2274 from hannobraun/geometry
Update half-edge geometry in geometry layer in more places
This commit is contained in:
commit
ae743214d1
@ -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,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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(),
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user