Skip to content

Commit

Permalink
Merge pull request #1630 from hannobraun/edge
Browse files Browse the repository at this point in the history
Prepare for next step in `HalfEdge` simplification
  • Loading branch information
hannobraun authored Feb 27, 2023
2 parents 9056c49 + 213635a commit 32eb8b7
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 471 deletions.
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

0 comments on commit 32eb8b7

Please sign in to comment.