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

Prepare for next step in HalfEdge simplification #1630

Merged
merged 16 commits into from
Feb 27, 2023
Merged
4 changes: 2 additions & 2 deletions crates/fj-kernel/src/algorithms/approx/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,8 @@ mod tests {

half_edge.update_as_line_segment_from_points([[0., 1.], [1., 1.]]);

half_edge.vertices[0].0 = Some(range.boundary[0]);
half_edge.vertices[1].0 = Some(range.boundary[1]);
half_edge.boundary[0] = Some(range.boundary[0]);
half_edge.boundary[1] = Some(range.boundary[1]);

half_edge.infer_vertex_positions_if_necessary(&surface.geometry());

Expand Down
23 changes: 21 additions & 2 deletions crates/fj-kernel/src/algorithms/reverse/cycle.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use itertools::Itertools;

use crate::{
insert::Insert,
objects::{Cycle, Objects},
objects::{Cycle, HalfEdge, Objects},
services::Service,
storage::Handle,
};
Expand All @@ -12,7 +14,24 @@ impl Reverse for Handle<Cycle> {
let mut edges = self
.half_edges()
.cloned()
.map(|edge| edge.reverse(objects))
.circular_tuple_windows()
.map(|(current, next)| {
let boundary = {
let [a, b] = current.boundary();
[b, a]
};
let surface_vertices =
[next.start_vertex(), current.start_vertex()]
.map(Clone::clone);

HalfEdge::new(
current.curve(),
boundary,
surface_vertices,
current.global_form().clone(),
)
.insert(objects)
})
.collect::<Vec<_>>();

edges.reverse();
Expand Down
24 changes: 0 additions & 24 deletions crates/fj-kernel/src/algorithms/reverse/edge.rs

This file was deleted.

1 change: 0 additions & 1 deletion crates/fj-kernel/src/algorithms/reverse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use crate::{objects::Objects, services::Service};

mod cycle;
mod edge;
mod face;

/// Reverse the direction/orientation of an object
Expand Down
152 changes: 7 additions & 145 deletions crates/fj-kernel/src/algorithms/sweep/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use fj_math::{Point, Scalar, Vector};
use crate::{
builder::{CycleBuilder, HalfEdgeBuilder},
insert::Insert,
objects::{Face, HalfEdge, Objects, Surface},
objects::{Face, HalfEdge, Objects, Surface, SurfaceVertex},
partial::{Partial, PartialFace, PartialObject},
services::Service,
storage::Handle,
};

use super::{Sweep, SweepCache};

impl Sweep for (Handle<HalfEdge>, &Surface, Color) {
impl Sweep for (Handle<HalfEdge>, &Handle<SurfaceVertex>, &Surface, Color) {
type Swept = (Handle<Face>, Handle<HalfEdge>);

fn sweep_with_cache(
Expand All @@ -21,7 +21,7 @@ impl Sweep for (Handle<HalfEdge>, &Surface, Color) {
cache: &mut SweepCache,
objects: &mut Service<Objects>,
) -> Self::Swept {
let (edge, surface, color) = self;
let (edge, next_vertex, surface, color) = self;
let path = path.into();

// The result of sweeping an edge is a face. Let's create that.
Expand Down Expand Up @@ -51,8 +51,7 @@ impl Sweep for (Handle<HalfEdge>, &Surface, Color) {
//
// Let's start with the global vertices and edges.
let (global_vertices, global_edges) = {
let [a, b] = edge
.surface_vertices()
let [a, b] = [edge.start_vertex(), next_vertex]
.map(|surface_vertex| surface_vertex.global_form().clone());
let (edge_right, [_, c]) =
b.clone().sweep_with_cache(path, cache, objects);
Expand Down Expand Up @@ -98,16 +97,16 @@ impl Sweep for (Handle<HalfEdge>, &Surface, Color) {
.zip_ext(global_vertices)
.map(
|(((mut half_edge, boundary), surface_point), global_vertex)| {
for ((a, _), b) in
half_edge.vertices.each_mut_ext().zip_ext(boundary)
for (a, b) in
half_edge.boundary.each_mut_ext().zip_ext(boundary)
{
*a = Some(b);
}

// Writing to the start vertices is enough. Neighboring half-
// edges share surface vertices, so writing the start vertex of
// each half-edge writes to all vertices.
let mut vertex = half_edge.vertices[0].1.write();
let mut vertex = half_edge.surface_vertices[0].write();
vertex.position = Some(surface_point);
vertex.global_form = Partial::from(global_vertex);
},
Expand Down Expand Up @@ -143,140 +142,3 @@ impl Sweep for (Handle<HalfEdge>, &Surface, Color) {
(face, edge_top)
}
}

#[cfg(test)]
mod tests {
use std::ops::Deref;

use fj_interop::{ext::ArrayExt, mesh::Color};
use fj_math::Point;
use pretty_assertions::assert_eq;

use crate::{
algorithms::sweep::Sweep,
builder::HalfEdgeBuilder,
insert::Insert,
partial::{
Partial, PartialCycle, PartialFace, PartialHalfEdge, PartialObject,
},
services::Services,
};

#[test]
fn sweep() {
let mut services = Services::new();

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

let half_edge = {
let mut half_edge = PartialHalfEdge::default();
half_edge.update_as_line_segment_from_points([[0., 0.], [1., 0.]]);
half_edge.infer_vertex_positions_if_necessary(&surface.geometry());

half_edge
.build(&mut services.objects)
.insert(&mut services.objects)
};

let (face, _) = (half_edge, surface.deref(), Color::default())
.sweep([0., 0., 1.], &mut services.objects);

let expected_face = {
let surface = services.objects.surfaces.xz_plane();

let bottom = {
let mut half_edge = PartialHalfEdge::default();
half_edge
.update_as_line_segment_from_points([[0., 0.], [1., 0.]]);

half_edge
};
let side_up = {
let mut side_up = PartialHalfEdge::default();

{
let [back, front] = side_up
.vertices
.each_mut_ext()
.map(|(_, surface_vertex)| surface_vertex);

*back = bottom.vertices[1].1.clone();

let mut front = front.write();
front.position = Some([1., 1.].into());
}

side_up.infer_global_form();
side_up.update_as_line_segment();

side_up
};
let top = {
let mut top = PartialHalfEdge::default();

{
let [(back, back_surface), (front, front_surface)] =
top.vertices.each_mut_ext();

*back = Some(Point::from([1.]));
*back_surface = side_up.vertices[1].1.clone();

*front = Some(Point::from([0.]));
let mut front_surface = front_surface.write();
front_surface.position = Some([0., 1.].into());
}

top.infer_global_form();
top.update_as_line_segment();
top.infer_vertex_positions_if_necessary(&surface.geometry());

Partial::from(
top.build(&mut services.objects)
.insert(&mut services.objects),
)
.read()
.clone()
};
let side_down = {
let mut side_down = PartialHalfEdge::default();

let [(back, back_surface), (front, front_surface)] =
side_down.vertices.each_mut_ext();

*back = Some(Point::from([1.]));
*front = Some(Point::from([0.]));

*back_surface = top.vertices[1].1.clone();
*front_surface = bottom.vertices[0].1.clone();

side_down.infer_global_form();
side_down.update_as_line_segment();
side_down
.infer_vertex_positions_if_necessary(&surface.geometry());

Partial::from(
side_down
.build(&mut services.objects)
.insert(&mut services.objects),
)
.read()
.clone()
};

let mut cycle = PartialCycle::default();
cycle.half_edges.extend(
[bottom, side_up, top, side_down].map(Partial::from_partial),
);

let face = PartialFace {
surface: Partial::from(surface),
exterior: Partial::from_partial(cycle),
..Default::default()
};
face.build(&mut services.objects)
.insert(&mut services.objects)
};

assert_eq!(face, expected_face);
}
}
Loading