diff --git a/crates/fj-kernel/src/operations/build/face.rs b/crates/fj-kernel/src/operations/build/face.rs index 7d3cb6dda..127777444 100644 --- a/crates/fj-kernel/src/operations/build/face.rs +++ b/crates/fj-kernel/src/operations/build/face.rs @@ -2,8 +2,8 @@ use fj_interop::ext::ArrayExt; use fj_math::Point; use crate::{ - objects::{Cycle, Face, GlobalEdge, HalfEdge, Objects, Surface}, - operations::{Insert, UpdateHalfEdge}, + objects::{Cycle, Face, HalfEdge, Objects, Surface, Vertex}, + operations::Insert, services::Service, storage::Handle, }; @@ -15,39 +15,35 @@ pub trait BuildFace { /// Build a triangle fn triangle( points: [impl Into>; 3], - edges: [Option>; 3], objects: &mut Service, ) -> Triangle { let [a, b, c] = points.map(Into::into); let surface = Surface::plane_from_points([a, b, c]).insert(objects); - let (exterior, edges) = { - let half_edges = [[a, b], [b, c], [c, a]].zip_ext(edges).map( - |(points, global_form)| { - let mut half_edge = - HalfEdge::line_segment_from_global_points( - points, &surface, None, objects, - ); + let (exterior, edges, vertices) = { + let half_edges = [[a, b], [b, c], [c, a]].map(|points| { + let half_edge = HalfEdge::line_segment_from_global_points( + points, &surface, None, objects, + ); - if let Some(global_form) = global_form { - half_edge = half_edge.replace_global_form(global_form); - } - - half_edge.insert(objects) - }, - ); + half_edge.insert(objects) + }); + let vertices = half_edges + .each_ref_ext() + .map(|half_edge| half_edge.start_vertex().clone()); let cycle = Cycle::new(half_edges.clone()).insert(objects); - let global_edges = - half_edges.map(|half_edge| half_edge.global_form().clone()); - - (cycle, global_edges) + (cycle, half_edges, vertices) }; let face = Face::new(surface, exterior, [], None); - Triangle { face, edges } + Triangle { + face, + edges, + vertices, + } } } @@ -61,5 +57,8 @@ pub struct Triangle { pub face: Face, /// The edges of the triangle - pub edges: [Handle; 3], + pub edges: [Handle; 3], + + /// The vertices of the triangle + pub vertices: [Handle; 3], } diff --git a/crates/fj-kernel/src/operations/build/shell.rs b/crates/fj-kernel/src/operations/build/shell.rs index d5e4dbe0e..a8f0f3376 100644 --- a/crates/fj-kernel/src/operations/build/shell.rs +++ b/crates/fj-kernel/src/operations/build/shell.rs @@ -2,7 +2,7 @@ use fj_math::Point; use crate::{ objects::{Face, Objects, Shell}, - operations::Insert, + operations::{Insert, UpdateCycle, UpdateFace, UpdateHalfEdge}, services::Service, storage::Handle, }; @@ -35,33 +35,91 @@ pub trait BuildShell { ) -> Tetrahedron { let [a, b, c, d] = points.map(Into::into); - let Triangle { + let [Triangle { face: face_abc, edges: [ab, bc, ca], - } = Face::triangle([a, b, c], [None, None, None], objects); - let Triangle { + vertices: [a, b, c], + }, Triangle { face: face_bad, - edges: [_, ad, db], - } = Face::triangle([b, a, d], [Some(ab), None, None], objects); - let Triangle { + edges: [ba, ad, db], + vertices: [_, _, d], + }, Triangle { face: face_dac, - edges: [_, _, cd], - } = Face::triangle([d, a, c], [Some(ad), Some(ca), None], objects); - let Triangle { face: face_cbd, .. } = - Face::triangle([c, b, d], [Some(bc), Some(db), Some(cd)], objects); + edges: [da, ac, cd], + .. + }, Triangle { + face: face_cbd, + edges: [cb, bd, dc], + .. + }] = [ + Face::triangle([a, b, c], objects), + Face::triangle([b, a, d], objects), + Face::triangle([d, a, c], objects), + Face::triangle([c, b, d], objects), + ]; + + let face_bad = face_bad.update_exterior(|cycle| { + let ba_joined = ba + .replace_start_vertex(b.clone()) + .replace_global_form(ab.global_form().clone()) + .insert(objects); + let ad_joined = ad.replace_start_vertex(a.clone()).insert(objects); + + cycle + .replace_half_edge(&ba, ba_joined) + .replace_half_edge(&ad, ad_joined) + .insert(objects) + }); + let face_dac = face_dac.update_exterior(|cycle| { + let da_joined = da + .replace_start_vertex(d.clone()) + .replace_global_form(ad.global_form().clone()) + .insert(objects); + let ac_joined = ac + .replace_start_vertex(a) + .replace_global_form(ca.global_form().clone()) + .insert(objects); + let cd_joined = cd.replace_start_vertex(c.clone()).insert(objects); + + cycle + .replace_half_edge(&da, da_joined) + .replace_half_edge(&ac, ac_joined) + .replace_half_edge(&cd, cd_joined) + .insert(objects) + }); + let face_cbd = face_cbd.update_exterior(|cycle| { + let cb_joined = cb + .replace_start_vertex(c) + .replace_global_form(bc.global_form().clone()) + .insert(objects); + let bd_joined = bd + .replace_start_vertex(b) + .replace_global_form(db.global_form().clone()) + .insert(objects); + let dc_joined = dc + .replace_start_vertex(d) + .replace_global_form(cd.global_form().clone()) + .insert(objects); + + cycle + .replace_half_edge(&cb, cb_joined) + .replace_half_edge(&bd, bd_joined) + .replace_half_edge(&dc, dc_joined) + .insert(objects) + }); let faces = [face_abc, face_bad, face_dac, face_cbd] .map(|face| face.insert(objects)); let shell = Shell::new(faces.clone()); - let [face_abc, face_abd, face_cad, face_bcd] = faces; + let [face_abc, face_bad, face_dac, face_cbd] = faces; Tetrahedron { shell, face_abc, - face_abd, - face_cad, - face_bcd, + face_bad, + face_dac, + face_cbd, } } } @@ -82,12 +140,12 @@ pub struct Tetrahedron { /// The face formed by the points `a`, `b`, and `c`. pub face_abc: Handle, - /// The face formed by the points `a`, `b`, and `d`. - pub face_abd: Handle, + /// The face formed by the points `b`, `a`, and `d`. + pub face_bad: Handle, - /// The face formed by the points `c`, `a`, and `d`. - pub face_cad: Handle, + /// The face formed by the points `d`, `a`, and `c`. + pub face_dac: Handle, - /// The face formed by the points `b`, `c`, and `d`. - pub face_bcd: Handle, + /// The face formed by the points `c`, `b`, and `d`. + pub face_cbd: Handle, }