Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove end_vertex fields of HalfEdge/PartialHalfEdge #1638

Merged
merged 11 commits into from
Mar 1, 2023
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/algorithms/approx/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ mod tests {
half_edge.update_as_circle_from_radius(1.);
half_edge.infer_vertex_positions_if_necessary(
&surface.geometry(),
half_edge.end_vertex.clone(),
half_edge.start_vertex.clone(),
);

half_edge
Expand Down
1 change: 0 additions & 1 deletion crates/fj-kernel/src/algorithms/reverse/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ impl Reverse for Handle<Cycle> {
current.curve(),
boundary,
next.start_vertex().clone(),
current.start_vertex().clone(),
current.global_form().clone(),
)
.insert(objects)
Expand Down
6 changes: 1 addition & 5 deletions crates/fj-kernel/src/algorithms/transform/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,12 @@ impl TransformObject for HalfEdge {
.start_vertex()
.clone()
.transform_with_cache(transform, objects, cache);
let end_vertex = self
.end_vertex()
.clone()
.transform_with_cache(transform, objects, cache);
let global_form = self
.global_form()
.clone()
.transform_with_cache(transform, objects, cache);

Self::new(curve, boundary, start_vertex, end_vertex, global_form)
Self::new(curve, boundary, start_vertex, global_form)
}
}

Expand Down
20 changes: 8 additions & 12 deletions crates/fj-kernel/src/builder/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,17 @@ impl CycleBuilder for PartialCycle {
{
let shared_surface_vertex =
new_half_edge.read().start_vertex.clone();

let mut last_half_edge = last_half_edge.write();

last_half_edge.end_vertex = shared_surface_vertex.clone();
last_half_edge.infer_global_form(shared_surface_vertex);
last_half_edge
.write()
.infer_global_form(shared_surface_vertex);
}

{
let shared_surface_vertex =
first_half_edge.read().start_vertex.clone();

let mut new_half_edge = new_half_edge.write();

new_half_edge.end_vertex = shared_surface_vertex.clone();
new_half_edge.infer_global_form(shared_surface_vertex);
new_half_edge
.write()
.infer_global_form(shared_surface_vertex);
}

self.half_edges.push(new_half_edge.clone());
Expand Down Expand Up @@ -152,9 +148,9 @@ impl CycleBuilder for PartialCycle {
where
O: ObjectArgument<Partial<HalfEdge>>,
{
edges.map(|other| {
edges.map_with_prev(|other, prev| {
let mut this = self.add_half_edge();
this.write().update_from_other_edge(&other, surface);
this.write().update_from_other_edge(&other, &prev, surface);
this
})
}
Expand Down
19 changes: 9 additions & 10 deletions crates/fj-kernel/src/builder/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub trait HalfEdgeBuilder {
fn update_from_other_edge(
&mut self,
other: &Partial<HalfEdge>,
other_prev: &Partial<HalfEdge>,
surface: &SurfaceGeometry,
);
}
Expand All @@ -81,7 +82,6 @@ impl HalfEdgeBuilder for PartialHalfEdge {

self.start_vertex.write().position =
Some(path.point_from_path_coords(a_curve));
self.end_vertex = self.start_vertex.clone();

for (point_boundary, point_curve) in
self.boundary.each_mut_ext().zip_ext([a_curve, b_curve])
Expand Down Expand Up @@ -233,6 +233,7 @@ impl HalfEdgeBuilder for PartialHalfEdge {
fn update_from_other_edge(
&mut self,
other: &Partial<HalfEdge>,
other_prev: &Partial<HalfEdge>,
surface: &SurfaceGeometry,
) {
self.curve = other.read().curve.as_ref().and_then(|path| {
Expand Down Expand Up @@ -309,15 +310,13 @@ impl HalfEdgeBuilder for PartialHalfEdge {
}
});

let other = other.read();

for (this, other) in [&mut self.start_vertex, &mut self.end_vertex]
.iter_mut()
.zip([&other.end_vertex, &other.start_vertex])
{
this.write().global_form.write().position =
other.read().global_form.read().position;
}
self.start_vertex.write().global_form.write().position = other_prev
.read()
.start_vertex
.read()
.global_form
.read()
.position;
}
}

Expand Down
45 changes: 45 additions & 0 deletions crates/fj-kernel/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ pub trait ObjectArgument<T>: IntoIterator<Item = T> {
where
F: FnMut(T) -> R;

/// Create a return value by mapping the implementing type
///
/// Provides access to the (circular) next item.
fn map_with_prev<F, R>(self, f: F) -> Self::SameSize<R>
where
F: FnMut(T, T) -> R,
T: Clone;

/// Create a return value with one more element
fn map_plus_one<F, R>(self, item: R, f: F) -> Self::SizePlusOne<R>
where
Expand Down Expand Up @@ -80,6 +88,25 @@ impl<T> ObjectArgument<T> for Vec<T> {
ret
}

fn map_with_prev<F, R>(self, mut f: F) -> Self::SameSize<R>
where
F: FnMut(T, T) -> R,
T: Clone,
{
let mut prev = Vec::new();
for i in 0..self.len() {
prev.push(self[(i + self.len() - 1) % self.len()].clone());
}

let mut ret = Vec::new();
for (i, item) in self.into_iter().enumerate() {
let prev = prev[i].clone();
ret.push(f(item, prev));
}

ret
}

fn map_plus_one<F, R>(self, item: R, f: F) -> Self::SizePlusOne<R>
where
F: FnMut(T) -> R,
Expand Down Expand Up @@ -112,6 +139,24 @@ macro_rules! impl_object_argument_for_arrays {
self.map(f)
}

fn map_with_prev<F, R>(self, mut f: F) -> Self::SameSize<R>
where
F: FnMut(T, T) -> R,
T: Clone,
{
let prev: [_; $len] = array::from_fn(|i| {
self[(i + self.len() - 1) % self.len()].clone()
});

let mut i = 0;
self.map(|item| {
let prev = prev[i].clone();
i += 1;

f(item, prev)
})
}

fn map_plus_one<F, R>(self, item: R, mut f: F)
-> Self::SizePlusOne<R>
where
Expand Down
8 changes: 0 additions & 8 deletions crates/fj-kernel/src/objects/full/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ pub struct HalfEdge {
curve: Curve,
boundary: [Point<1>; 2],
start_vertex: Handle<SurfaceVertex>,
end_vertex: Handle<SurfaceVertex>,
global_form: Handle<GlobalEdge>,
}

Expand All @@ -57,14 +56,12 @@ impl HalfEdge {
curve: Curve,
boundary: [Point<1>; 2],
start_vertex: Handle<SurfaceVertex>,
end_vertex: Handle<SurfaceVertex>,
global_form: Handle<GlobalEdge>,
) -> Self {
Self {
curve,
boundary,
start_vertex,
end_vertex,
global_form,
}
}
Expand Down Expand Up @@ -94,11 +91,6 @@ impl HalfEdge {
&self.start_vertex
}

/// Access the vertex from where this half-edge ends
pub fn end_vertex(&self) -> &Handle<SurfaceVertex> {
&self.end_vertex
}

/// Access the global form of the half-edge
pub fn global_form(&self) -> &Handle<GlobalEdge> {
&self.global_form
Expand Down
11 changes: 1 addition & 10 deletions crates/fj-kernel/src/partial/objects/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ pub struct PartialHalfEdge {
/// The surface vertex where the half-edge starts
pub start_vertex: Partial<SurfaceVertex>,

/// The surface vertex where the half-edge ends
pub end_vertex: Partial<SurfaceVertex>,

/// The global form of the half-edge
pub global_form: Partial<GlobalEdge>,
}
Expand All @@ -46,10 +43,6 @@ impl PartialObject for PartialHalfEdge {
half_edge.start_vertex().clone(),
cache,
),
end_vertex: Partial::from_full(
half_edge.end_vertex().clone(),
cache,
),
global_form: Partial::from_full(
half_edge.global_form().clone(),
cache,
Expand All @@ -70,10 +63,9 @@ impl PartialObject for PartialHalfEdge {
point.expect("Can't build `HalfEdge` without boundary positions")
});
let start_vertex = self.start_vertex.build(objects);
let end_vertex = self.end_vertex.build(objects);
let global_form = self.global_form.build(objects);

HalfEdge::new(curve, boundary, start_vertex, end_vertex, global_form)
HalfEdge::new(curve, boundary, start_vertex, global_form)
}
}

Expand All @@ -99,7 +91,6 @@ impl Default for PartialHalfEdge {
curve,
boundary: [None; 2],
start_vertex,
end_vertex,
global_form,
}
}
Expand Down
67 changes: 0 additions & 67 deletions crates/fj-kernel/src/validate/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ impl Validate for Cycle {
config: &ValidationConfig,
errors: &mut Vec<ValidationError>,
) {
CycleValidationError::check_half_edge_connections(self, errors);
CycleValidationError::check_half_edge_boundaries(self, config, errors);
}
}
Expand Down Expand Up @@ -69,26 +68,6 @@ pub enum CycleValidationError {
}

impl CycleValidationError {
fn check_half_edge_connections(
cycle: &Cycle,
errors: &mut Vec<ValidationError>,
) {
for (a, b) in cycle.half_edges().circular_tuple_windows() {
let prev = a.end_vertex();
let next = b.start_vertex();

if prev.id() != next.id() {
errors.push(
Self::HalfEdgeConnection {
prev: prev.clone(),
next: next.clone(),
}
.into(),
);
}
}
}

fn check_half_edge_boundaries(
cycle: &Cycle,
config: &ValidationConfig,
Expand Down Expand Up @@ -138,52 +117,6 @@ mod tests {
validate::{CycleValidationError, Validate, ValidationError},
};

#[test]
fn cycle_half_edge_connections() -> anyhow::Result<()> {
let mut services = Services::new();

let valid = {
let surface = services.objects.surfaces.xy_plane();

let mut cycle = PartialCycle::default();
cycle.update_as_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]);
cycle.infer_vertex_positions_if_necessary(&surface.geometry());
cycle.build(&mut services.objects)
};
let invalid = {
let mut half_edges = valid
.half_edges()
.map(|half_edge| Partial::from(half_edge.clone()))
.collect::<Vec<_>>();

// Sever connection between the last and first half-edge in the
// cycle.
{
let first_half_edge = half_edges.first_mut().unwrap();
let first_vertex = &mut first_half_edge.write().start_vertex;
let surface_vertex =
Partial::from_partial(first_vertex.read().clone());
*first_vertex = surface_vertex;
}

let half_edges = half_edges
.into_iter()
.map(|half_edge| half_edge.build(&mut services.objects));

Cycle::new(half_edges)
};

valid.validate_and_return_first_error()?;
assert!(matches!(
invalid.validate_and_return_first_error(),
Err(ValidationError::Cycle(
CycleValidationError::HalfEdgeConnection { .. }
))
));

Ok(())
}

#[test]
fn vertex_position_mismatch() -> anyhow::Result<()> {
let mut services = Services::new();
Expand Down
2 changes: 0 additions & 2 deletions crates/fj-kernel/src/validate/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ mod tests {
valid.curve(),
valid.boundary(),
valid.start_vertex().clone(),
valid.end_vertex().clone(),
global_form,
)
};
Expand Down Expand Up @@ -216,7 +215,6 @@ mod tests {
valid.curve(),
boundary,
valid.start_vertex().clone(),
valid.end_vertex().clone(),
valid.global_form().clone(),
)
};
Expand Down
Loading