diff --git a/crates/fj-kernel/src/algorithms/approx/curve.rs b/crates/fj-kernel/src/algorithms/approx/curve.rs index 783729e23..2521ae043 100644 --- a/crates/fj-kernel/src/algorithms/approx/curve.rs +++ b/crates/fj-kernel/src/algorithms/approx/curve.rs @@ -15,7 +15,7 @@ impl Approx for Curve { tolerance: Tolerance, range: Self::Params, ) -> Self::Approximation { - self.global() + self.global_form() .approx(tolerance, range) .into_iter() .map(|(point_curve, point_global)| { diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index 15a90f065..332de02ec 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -15,8 +15,9 @@ impl Approx for Edge { ) -> Self::Approximation { // The range is only used for circles right now. let boundary = match self.vertices().get() { - Some(vertices) => vertices - .map(|vertex| (vertex.position(), vertex.global().position())), + Some(vertices) => vertices.map(|vertex| { + (vertex.position(), vertex.global_form().position()) + }), None => { let start_curve = Point::from([Scalar::ZERO]); let end_curve = Point::from([Scalar::TAU]); @@ -24,7 +25,7 @@ impl Approx for Edge { // We're dealing with a circle here. Start and end are identical // points, in global coordinates. let point_global = self - .global() + .global_form() .curve() .kind() .point_from_curve_coords(start_curve); diff --git a/crates/fj-kernel/src/algorithms/intersect/face_point.rs b/crates/fj-kernel/src/algorithms/intersect/face_point.rs index a613d4c3b..b9d28ceef 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_point.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_point.rs @@ -238,8 +238,8 @@ mod tests { .copied() .find(|edge| { let [a, b] = edge.vertices().get_or_panic(); - a.global().position() == Point::from([0., 0., 0.]) - && b.global().position() == Point::from([2., 0., 0.]) + a.global_form().position() == Point::from([0., 0., 0.]) + && b.global_form().position() == Point::from([2., 0., 0.]) }) .unwrap(); assert_eq!( @@ -261,7 +261,7 @@ mod tests { .vertex_iter() .copied() .find(|vertex| { - vertex.global().position() == Point::from([1., 0., 0.]) + vertex.global_form().position() == Point::from([1., 0., 0.]) }) .unwrap(); assert_eq!( diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs index e4349f56c..8ea88bf56 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs @@ -217,8 +217,8 @@ mod tests { .copied() .find(|edge| { let [a, b] = edge.vertices().get_or_panic(); - a.global().position() == Point::from([1., 0., 1.]) - && b.global().position() == Point::from([1., 0., -1.]) + a.global_form().position() == Point::from([1., 0., 1.]) + && b.global_form().position() == Point::from([1., 0., -1.]) }) .unwrap(); assert_eq!( @@ -240,7 +240,7 @@ mod tests { .vertex_iter() .copied() .find(|vertex| { - vertex.global().position() == Point::from([1., 0., 0.]) + vertex.global_form().position() == Point::from([1., 0., 0.]) }) .unwrap(); assert_eq!( diff --git a/crates/fj-kernel/src/algorithms/reverse/curve.rs b/crates/fj-kernel/src/algorithms/reverse/curve.rs index 6b49e0b2c..178de7f00 100644 --- a/crates/fj-kernel/src/algorithms/reverse/curve.rs +++ b/crates/fj-kernel/src/algorithms/reverse/curve.rs @@ -20,7 +20,7 @@ impl Reverse for Curve { Curve::new( *self.surface(), self.kind().reverse(), - self.global().reverse(), + self.global_form().reverse(), ) } } diff --git a/crates/fj-kernel/src/algorithms/reverse/face.rs b/crates/fj-kernel/src/algorithms/reverse/face.rs index 24a2d7462..436a436d9 100644 --- a/crates/fj-kernel/src/algorithms/reverse/face.rs +++ b/crates/fj-kernel/src/algorithms/reverse/face.rs @@ -1,6 +1,8 @@ use fj_math::{Circle, Line, Point, Vector}; -use crate::objects::{Curve, CurveKind, Cycle, Edge, Face, Vertex}; +use crate::objects::{ + Curve, CurveKind, Cycle, Edge, Face, SurfaceVertex, Vertex, +}; use super::Reverse; @@ -72,12 +74,32 @@ fn reverse_local_coordinates_in_cycle<'r>( Curve::new( edge.curve().surface().reverse(), local, - *edge.curve().global(), + *edge.curve().global_form(), ) }; let vertices = edge.vertices().map(|vertex| { - Vertex::new(vertex.position(), curve, *vertex.global()) + let surface_vertex = { + let vertex = vertex.surface_form(); + + let position = Point::from([ + vertex.position().u, + -vertex.position().v, + ]); + + SurfaceVertex::new( + position, + vertex.surface().reverse(), + *vertex.global_form(), + ) + }; + + Vertex::new( + vertex.position(), + curve, + surface_vertex, + *vertex.global_form(), + ) }); Edge::from_curve_and_vertices(curve, vertices) diff --git a/crates/fj-kernel/src/algorithms/sweep/curve.rs b/crates/fj-kernel/src/algorithms/sweep/curve.rs index 0dfdb63e7..19b8e9c0b 100644 --- a/crates/fj-kernel/src/algorithms/sweep/curve.rs +++ b/crates/fj-kernel/src/algorithms/sweep/curve.rs @@ -11,7 +11,7 @@ impl Sweep for Curve { tolerance: impl Into, color: fj_interop::mesh::Color, ) -> Self::Swept { - self.global().sweep(path, tolerance, color) + self.global_form().sweep(path, tolerance, color) } } diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index bb90ad64b..5224cedbf 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -8,8 +8,8 @@ use crate::{ transform::TransformObject, }, objects::{ - Curve, CurveKind, Cycle, Edge, Face, GlobalEdge, Surface, Vertex, - VerticesOfEdge, + Curve, CurveKind, Cycle, Edge, Face, GlobalEdge, Surface, + SurfaceVertex, Vertex, VerticesOfEdge, }, }; @@ -57,27 +57,51 @@ fn create_non_continuous_side_face( let bottom_edge = { let vertices = edge.vertices().get_or_panic(); + let points_curve_and_surface = vertices.map(|vertex| { + (vertex.position(), [vertex.position().t, Scalar::ZERO]) + }); + let curve = { // Please note that creating a line here is correct, even if the // global curve is a circle. Projected into the side surface, it is // going to be a line either way. - let points = vertices.map(|vertex| { - (vertex.position(), [vertex.position().t, Scalar::ZERO]) - }); - let kind = - CurveKind::Line(Line::from_points_with_line_coords(points)); + let kind = CurveKind::Line(Line::from_points_with_line_coords( + points_curve_and_surface, + )); - Curve::new(surface, kind, *edge.curve().global()) + Curve::new(surface, kind, *edge.curve().global_form()) }; let vertices = { - let vertices = vertices.map(|vertex| { - Vertex::new(vertex.position(), curve, *vertex.global()) - }); + let points_surface = points_curve_and_surface + .map(|(_, point_surface)| point_surface); + + // Can be cleaned up, once `zip` is stable: + // https://doc.rust-lang.org/std/primitive.array.html#method.zip + let [a_vertex, b_vertex] = vertices; + let [a_surface, b_surface] = points_surface; + let vertices_with_surface_points = + [(a_vertex, a_surface), (b_vertex, b_surface)]; + + let vertices = + vertices_with_surface_points.map(|(vertex, point_surface)| { + let surface_vertex = SurfaceVertex::new( + point_surface, + surface, + *vertex.global_form(), + ); + + Vertex::new( + vertex.position(), + curve, + surface_vertex, + *vertex.global_form(), + ) + }); VerticesOfEdge::from_vertices(vertices) }; - Edge::new(curve, vertices, *edge.global()) + Edge::new(curve, vertices, *edge.global_form()) }; let side_edges = bottom_edge @@ -90,40 +114,57 @@ fn create_non_continuous_side_face( let global_vertices = side_edges.map(|edge| { let [_, vertex] = edge.vertices().get_or_panic(); - *vertex.global() + *vertex.global_form() + }); + + let points_curve_and_surface = bottom_vertices.map(|vertex| { + (vertex.position(), [vertex.position().t, Scalar::ONE]) }); let curve = { - let global = bottom_edge.curve().global().translate(path.inner()); + let global = + bottom_edge.curve().global_form().translate(path.inner()); // Please note that creating a line here is correct, even if the // global curve is a circle. Projected into the side surface, it is // going to be a line either way. - let points = bottom_vertices.map(|vertex| { - (vertex.position(), [vertex.position().t, Scalar::ONE]) - }); - let kind = - CurveKind::Line(Line::from_points_with_line_coords(points)); + let kind = CurveKind::Line(Line::from_points_with_line_coords( + points_curve_and_surface, + )); Curve::new(surface, kind, global) }; let global = { GlobalEdge::new( - *curve.global(), + *curve.global_form(), VerticesOfEdge::from_vertices(global_vertices), ) }; let vertices = { + let surface_points = points_curve_and_surface + .map(|(_, point_surface)| point_surface); + // Can be cleaned up, once `zip` is stable: // https://doc.rust-lang.org/std/primitive.array.html#method.zip - let [a_bottom, b_bottom] = bottom_vertices; + let [a_vertex, b_vertex] = bottom_vertices; + let [a_surface, b_surface] = surface_points; let [a_global, b_global] = global_vertices; - let vertices = [(a_bottom, a_global), (b_bottom, b_global)]; - - vertices.map(|(bottom, global)| { - Vertex::new(bottom.position(), curve, global) + let vertices = [ + (a_vertex, a_surface, a_global), + (b_vertex, b_surface, b_global), + ]; + + vertices.map(|(vertex, point_surface, vertex_global)| { + let vertex_surface = + SurfaceVertex::new(point_surface, surface, vertex_global); + Vertex::new( + vertex.position(), + curve, + vertex_surface, + vertex_global, + ) }) }; @@ -145,7 +186,7 @@ fn create_non_continuous_side_face( let [_, prev_last] = edges[i].vertices().get_or_panic(); let [next_first, _] = edges[j].vertices().get_or_panic(); - if prev_last.global() != next_first.global() { + if prev_last.global_form() != next_first.global_form() { edges[j] = edges[j].reverse(); } diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index 236e4016d..d9c405824 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -5,7 +5,7 @@ use crate::{ algorithms::approx::Tolerance, objects::{ Curve, CurveKind, Edge, GlobalCurve, GlobalEdge, GlobalVertex, Surface, - SweptCurve, Vertex, VerticesOfEdge, + SurfaceVertex, SweptCurve, Vertex, VerticesOfEdge, }, }; @@ -61,14 +61,14 @@ impl Sweep for (Vertex, Surface) { path: surface_path, }) = surface; - assert_eq!(vertex.curve().global().kind(), &surface_curve); + assert_eq!(vertex.curve().global_form().kind(), &surface_curve); assert_eq!(path.inner(), surface_path); } // With that out of the way, let's start by creating the `GlobalEdge`, // as that is the most straight-forward part of this operations, and // we're going to need it soon anyway. - let edge_global = vertex.global().sweep(path, tolerance, color); + let edge_global = vertex.global_form().sweep(path, tolerance, color); // Next, let's compute the surface coordinates of the two vertices of // the output `Edge`, as we're going to need these for the rest of this @@ -84,29 +84,54 @@ impl Sweep for (Vertex, Surface) { // thereby defined its coordinate system. That makes the v-coordinates // straight-forward: The start of the edge is at zero, the end is at // one. - let u = vertex.position().t; - let v_a = Scalar::ZERO; - let v_b = Scalar::ONE; + let points_surface = [ + Point::from([vertex.position().t, Scalar::ZERO]), + Point::from([vertex.position().t, Scalar::ONE]), + ]; // Armed with those coordinates, creating the `Curve` of the output // `Edge` becomes straight-forward. let curve = { - let a = Point::from([u, v_a]); - let b = Point::from([u, v_b]); - - let line = Line::from_points([a, b]); + let line = Line::from_points(points_surface); Curve::new(surface, CurveKind::Line(line), *edge_global.curve()) }; // And now the vertices. Again, nothing wild here. let vertices = { - let [&a, &b] = edge_global.vertices().get_or_panic(); - - let a = Vertex::new([v_a], curve, a); - let b = Vertex::new([v_b], curve, b); - - VerticesOfEdge::from_vertices([a, b]) + let vertices_global = edge_global.vertices().get_or_panic(); + + // Can be cleaned up, once `zip` is stable: + // https://doc.rust-lang.org/std/primitive.array.html#method.zip + let [a_surface, b_surface] = points_surface; + let [a_global, b_global] = vertices_global; + let vertices_surface = + [(a_surface, a_global), (b_surface, b_global)].map( + |(point_surface, &vertex_global)| { + SurfaceVertex::new( + point_surface, + surface, + vertex_global, + ) + }, + ); + + // Can be cleaned up, once `zip` is stable: + // https://doc.rust-lang.org/std/primitive.array.html#method.zip + let [a_surface, b_surface] = vertices_surface; + let [a_global, b_global] = vertices_global; + let vertices = [(a_surface, a_global), (b_surface, b_global)]; + + let vertices = vertices.map(|(vertex_surface, &vertex_global)| { + Vertex::new( + [vertex_surface.position().v], + curve, + vertex_surface, + vertex_global, + ) + }); + + VerticesOfEdge::from_vertices(vertices) }; // And finally, creating the output `Edge` is just a matter of diff --git a/crates/fj-kernel/src/algorithms/transform.rs b/crates/fj-kernel/src/algorithms/transform.rs index 52f1828c6..e0274dd4c 100644 --- a/crates/fj-kernel/src/algorithms/transform.rs +++ b/crates/fj-kernel/src/algorithms/transform.rs @@ -4,7 +4,7 @@ use fj_math::{Transform, Vector}; use crate::objects::{ Curve, Cycle, Edge, Face, GlobalCurve, GlobalVertex, Shell, Sketch, Solid, - Surface, Vertex, + Surface, SurfaceVertex, Vertex, }; /// Transform an object @@ -37,7 +37,7 @@ pub trait TransformObject: Sized { impl TransformObject for Curve { fn transform(self, transform: &Transform) -> Self { let surface = self.surface().transform(transform); - let global = self.global().transform(transform); + let global = self.global_form().transform(transform); // Don't need to transform `self.kind`, as that's in local form. Curve::new(surface, *self.kind(), global) @@ -135,12 +135,23 @@ impl TransformObject for Surface { } } +impl TransformObject for SurfaceVertex { + fn transform(self, transform: &Transform) -> Self { + Self::new( + self.position(), + self.surface().transform(transform), + self.global_form().transform(transform), + ) + } +} + impl TransformObject for Vertex { fn transform(self, transform: &Transform) -> Self { Self::new( self.position(), self.curve().transform(transform), - self.global().transform(transform), + self.surface_form().transform(transform), + self.global_form().transform(transform), ) } } diff --git a/crates/fj-kernel/src/algorithms/validate/coherence.rs b/crates/fj-kernel/src/algorithms/validate/coherence.rs index d3f679b8f..bae4d679a 100644 --- a/crates/fj-kernel/src/algorithms/validate/coherence.rs +++ b/crates/fj-kernel/src/algorithms/validate/coherence.rs @@ -16,8 +16,10 @@ pub fn validate_curve( let point_surface = curve.kind().point_from_curve_coords(point_curve); let point_surface_as_global = curve.surface().point_from_surface_coords(point_surface); - let point_global = - curve.global().kind().point_from_curve_coords(point_curve); + let point_global = curve + .global_form() + .kind() + .point_from_curve_coords(point_curve); let distance = (point_surface_as_global - point_global).magnitude(); @@ -48,10 +50,10 @@ pub fn validate_vertex( let local = vertex.position(); let local_as_global = vertex .curve() - .global() + .global_form() .kind() .point_from_curve_coords(local); - let global = vertex.global().position(); + let global = vertex.global_form().position(); let distance = (local_as_global - global).magnitude(); if distance > max_distance { diff --git a/crates/fj-kernel/src/algorithms/validate/mod.rs b/crates/fj-kernel/src/algorithms/validate/mod.rs index e670d6cd0..a3e5ce129 100644 --- a/crates/fj-kernel/src/algorithms/validate/mod.rs +++ b/crates/fj-kernel/src/algorithms/validate/mod.rs @@ -161,8 +161,8 @@ mod tests { use crate::{ algorithms::validate::{Validate, ValidationConfig, ValidationError}, objects::{ - Curve, CurveKind, Edge, GlobalCurve, GlobalVertex, Surface, Vertex, - VerticesOfEdge, + Curve, CurveKind, Edge, GlobalCurve, GlobalVertex, Surface, + SurfaceVertex, Vertex, VerticesOfEdge, }, }; @@ -184,23 +184,43 @@ mod tests { #[test] fn coherence_edge() { - let a = Point::from([0., 0., 0.]); - let b = Point::from([1., 0., 0.]); + let surface = Surface::xy_plane(); + + let points_surface = [[0., 0.], [1., 0.]]; + let points_global = [[0., 0., 0.], [1., 0., 0.]]; let curve = { - let curve_local = CurveKind::line_from_points([[0., 0.], [1., 0.]]); - let curve_global = - GlobalCurve::from_kind(CurveKind::line_from_points([a, b])); - Curve::new(Surface::xy_plane(), curve_local, curve_global) + let curve_local = CurveKind::line_from_points(points_surface); + let curve_global = GlobalCurve::from_kind( + CurveKind::line_from_points(points_global), + ); + Curve::new(surface, curve_local, curve_global) }; - let a = GlobalVertex::from_position(a); - let b = GlobalVertex::from_position(b); + let [a_global, b_global] = + points_global.map(GlobalVertex::from_position); + + let [a_surface, b_surface] = { + // Can be cleaned up, once `zip` is stable: + // https://doc.rust-lang.org/std/primitive.array.html#method.zip + let [a_surface, b_surface] = points_surface; + [(a_surface, a_global), (b_surface, b_global)].map( + |(point_surface, vertex_global)| { + SurfaceVertex::new(point_surface, surface, vertex_global) + }, + ) + }; let deviation = Scalar::from_f64(0.25); - let a = Vertex::new(Point::from([Scalar::ZERO + deviation]), curve, a); - let b = Vertex::new(Point::from([Scalar::ONE]), curve, b); + let a = Vertex::new( + Point::from([Scalar::ZERO + deviation]), + curve, + a_surface, + a_global, + ); + let b = + Vertex::new(Point::from([Scalar::ONE]), curve, b_surface, b_global); let vertices = VerticesOfEdge::from_vertices([a, b]); let edge = Edge::from_curve_and_vertices(curve, vertices); diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 4b7cc934a..941ec97fc 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -1,8 +1,8 @@ use fj_math::{Circle, Line, Point, Scalar, Vector}; use crate::objects::{ - Curve, CurveKind, Edge, GlobalCurve, GlobalVertex, Surface, Vertex, - VerticesOfEdge, + Curve, CurveKind, Edge, GlobalCurve, GlobalVertex, Surface, SurfaceVertex, + Vertex, VerticesOfEdge, }; /// API for building an [`Edge`] @@ -50,6 +50,22 @@ impl EdgeBuilder { GlobalVertex::from_position(position) }); + let surface_vertices = { + // Can be cleaned up, once `zip` is stable: + // https://doc.rust-lang.org/std/primitive.array.html#method.zip + let [a_surface, b_surface] = points; + let [a_global, b_global] = global_vertices; + [(a_surface, a_global), (b_surface, b_global)].map( + |(point_surface, vertex_global)| { + SurfaceVertex::new( + point_surface, + self.surface, + vertex_global, + ) + }, + ) + }; + let curve = { let curve_local = CurveKind::Line(Line::from_points(points)); let curve_global = { @@ -63,10 +79,12 @@ impl EdgeBuilder { }; let vertices = { - let [a, b] = global_vertices; + let [a_global, b_global] = global_vertices; + let [a_surface, b_surface] = surface_vertices; + let vertices = [ - Vertex::new(Point::from([0.]), curve, a), - Vertex::new(Point::from([1.]), curve, b), + Vertex::new(Point::from([0.]), curve, a_surface, a_global), + Vertex::new(Point::from([1.]), curve, b_surface, b_global), ]; VerticesOfEdge::from_vertices(vertices) diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index 8b09fa7f6..e20b9fa3f 100644 --- a/crates/fj-kernel/src/iter.rs +++ b/crates/fj-kernel/src/iter.rs @@ -139,7 +139,7 @@ pub trait ObjectIters<'r> { impl<'r> ObjectIters<'r> for Curve { fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { - vec![self.global() as &dyn ObjectIters] + vec![self.global_form() as &dyn ObjectIters] } fn curve_iter(&'r self) -> Iter<&'r Curve> { @@ -281,7 +281,7 @@ impl<'r> ObjectIters<'r> for Vertex { fn referenced_objects(&'r self) -> Vec<&'r dyn ObjectIters> { vec![ self.curve() as &dyn ObjectIters, - self.global() as &dyn ObjectIters, + self.global_form() as &dyn ObjectIters, ] } @@ -350,7 +350,7 @@ impl Iterator for Iter { mod tests { use crate::objects::{ Curve, Cycle, Edge, Face, GlobalCurve, GlobalVertex, Shell, Sketch, - Solid, Surface, Vertex, + Solid, Surface, SurfaceVertex, Vertex, }; use super::ObjectIters as _; @@ -547,7 +547,9 @@ mod tests { let surface = Surface::xy_plane(); let curve = Curve::build(surface).u_axis(); let global_vertex = GlobalVertex::from_position([0., 0., 0.]); - let object = Vertex::new([0.], curve, global_vertex); + let surface_vertex = + SurfaceVertex::new([0., 0.], surface, global_vertex); + let object = Vertex::new([0.], curve, surface_vertex, global_vertex); assert_eq!(1, object.curve_iter().count()); assert_eq!(0, object.cycle_iter().count()); diff --git a/crates/fj-kernel/src/objects/curve.rs b/crates/fj-kernel/src/objects/curve.rs index 2a563c981..ab864f41d 100644 --- a/crates/fj-kernel/src/objects/curve.rs +++ b/crates/fj-kernel/src/objects/curve.rs @@ -42,7 +42,7 @@ impl Curve { } /// Access the global form of this curve - pub fn global(&self) -> &GlobalCurve { + pub fn global_form(&self) -> &GlobalCurve { &self.global } } diff --git a/crates/fj-kernel/src/objects/cycle.rs b/crates/fj-kernel/src/objects/cycle.rs index f69b27789..3589f8b7d 100644 --- a/crates/fj-kernel/src/objects/cycle.rs +++ b/crates/fj-kernel/src/objects/cycle.rs @@ -55,8 +55,8 @@ impl Cycle { let [next, _] = b.vertices().get_or_panic(); assert_eq!( - prev.global(), - next.global(), + prev.surface_form(), + next.surface_form(), "Edges in cycle do not connect" ); } @@ -68,8 +68,8 @@ impl Cycle { let [_, last] = last.vertices().get_or_panic(); assert_eq!( - first.global(), - last.global(), + first.surface_form(), + last.surface_form(), "Edges do not form a cycle" ); } diff --git a/crates/fj-kernel/src/objects/edge.rs b/crates/fj-kernel/src/objects/edge.rs index 44dce0755..0e92e8f26 100644 --- a/crates/fj-kernel/src/objects/edge.rs +++ b/crates/fj-kernel/src/objects/edge.rs @@ -34,7 +34,7 @@ impl Edge { vertices: VerticesOfEdge, global: GlobalEdge, ) -> Self { - assert_eq!(curve.global(), global.curve()); + assert_eq!(curve.global_form(), global.curve()); assert_eq!(&vertices.to_global(), global.vertices()); // Make sure that the edge vertices are not coincident on the curve. If @@ -67,7 +67,8 @@ impl Edge { curve: Curve, vertices: VerticesOfEdge, ) -> Self { - let global = GlobalEdge::new(*curve.global(), vertices.to_global()); + let global = + GlobalEdge::new(*curve.global_form(), vertices.to_global()); Self::new(curve, vertices, global) } @@ -90,7 +91,7 @@ impl Edge { } /// Access the global form of this edge - pub fn global(&self) -> &GlobalEdge { + pub fn global_form(&self) -> &GlobalEdge { &self.global } } @@ -105,7 +106,7 @@ impl fmt::Display for Edge { None => write!(f, "continuous edge")?, } - write!(f, " on {:?}", self.curve().global())?; + write!(f, " on {:?}", self.curve().global_form())?; Ok(()) } @@ -212,14 +213,24 @@ impl VerticesOfEdge { pub fn reverse(self) -> Self { Self(self.0.map(|[a, b]| { [ - Vertex::new(-b.position(), b.curve().reverse(), *b.global()), - Vertex::new(-a.position(), a.curve().reverse(), *a.global()), + Vertex::new( + -b.position(), + b.curve().reverse(), + *b.surface_form(), + *b.global_form(), + ), + Vertex::new( + -a.position(), + a.curve().reverse(), + *a.surface_form(), + *a.global_form(), + ), ] })) } /// Convert this instance into its global variant pub fn to_global(&self) -> VerticesOfEdge { - VerticesOfEdge(self.convert(|vertex| *vertex.global())) + VerticesOfEdge(self.convert(|vertex| *vertex.global_form())) } } diff --git a/crates/fj-kernel/src/objects/mod.rs b/crates/fj-kernel/src/objects/mod.rs index 121fb6a8a..b830b82c3 100644 --- a/crates/fj-kernel/src/objects/mod.rs +++ b/crates/fj-kernel/src/objects/mod.rs @@ -23,5 +23,5 @@ pub use self::{ sketch::Sketch, solid::Solid, surface::{Surface, SweptCurve}, - vertex::{GlobalVertex, Vertex}, + vertex::{GlobalVertex, SurfaceVertex, Vertex}, }; diff --git a/crates/fj-kernel/src/objects/vertex.rs b/crates/fj-kernel/src/objects/vertex.rs index ec2ca9850..ff0f3879e 100644 --- a/crates/fj-kernel/src/objects/vertex.rs +++ b/crates/fj-kernel/src/objects/vertex.rs @@ -1,12 +1,12 @@ use fj_math::Point; -use super::Curve; +use super::{Curve, Surface}; /// A vertex /// /// `Vertex` is defined in terms of a 1-dimensional position on a curve. If you -/// need the 3D position of a vertex, you can use [`Vertex::global`], to get -/// access of the global form of a vertex ([`GlobalVertex`]). +/// need the 3D position of a vertex, you can use [`Vertex::global_form`], to +/// get access of the global form of a vertex ([`GlobalVertex`]). /// /// # Implementation Note /// @@ -19,7 +19,8 @@ use super::Curve; pub struct Vertex { position: Point<1>, curve: Curve, - global: GlobalVertex, + surface_form: SurfaceVertex, + global_form: GlobalVertex, } impl Vertex { @@ -27,13 +28,15 @@ impl Vertex { pub fn new( position: impl Into>, curve: Curve, - global: GlobalVertex, + surface_form: SurfaceVertex, + global_form: GlobalVertex, ) -> Self { let position = position.into(); Self { position, curve, - global, + surface_form, + global_form, } } @@ -47,9 +50,53 @@ impl Vertex { &self.curve } + /// Access the surface form of this vertex + pub fn surface_form(&self) -> &SurfaceVertex { + &self.surface_form + } + + /// Access the global form of this vertex + pub fn global_form(&self) -> &GlobalVertex { + &self.global_form + } +} + +/// A vertex, defined in surface (2D) coordinates +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct SurfaceVertex { + position: Point<2>, + surface: Surface, + global_form: GlobalVertex, +} + +impl SurfaceVertex { + /// Construct a new instance of `SurfaceVertex` + pub fn new( + position: impl Into>, + surface: Surface, + global_form: GlobalVertex, + ) -> Self { + let position = position.into(); + Self { + position, + surface, + global_form, + } + } + + /// Access the position of the vertex on the surface + pub fn position(&self) -> Point<2> { + self.position + } + + /// Access the surface that the vertex is defined on + pub fn surface(&self) -> &Surface { + &self.surface + } + /// Access the global form of this vertex - pub fn global(&self) -> &GlobalVertex { - &self.global + pub fn global_form(&self) -> &GlobalVertex { + &self.global_form } }