diff --git a/crates/fj-kernel/src/objects/edge.rs b/crates/fj-kernel/src/objects/edge.rs index 50234a954..a472c577a 100644 --- a/crates/fj-kernel/src/objects/edge.rs +++ b/crates/fj-kernel/src/objects/edge.rs @@ -47,10 +47,10 @@ impl HalfEdge { the half-edge's global form" ); assert_eq!( - &normalize_vertex_order( + &VerticesInNormalizedOrder::new( [&a, &b].map(|vertex| vertex.global_form().clone()) ), - global_form.vertices_in_normalized_order(), + global_form.vertices(), "The global forms of a half-edge's vertices must match the \ vertices of the half-edge's global form" ); @@ -104,7 +104,7 @@ impl fmt::Display for HalfEdge { #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct GlobalEdge { curve: HandleWrapper, - vertices: [Handle; 2], + vertices: VerticesInNormalizedOrder, } impl GlobalEdge { @@ -118,7 +118,7 @@ impl GlobalEdge { vertices: [Handle; 2], ) -> Self { let curve = curve.into(); - let vertices = normalize_vertex_order(vertices); + let vertices = VerticesInNormalizedOrder::new(vertices); Self { curve, vertices } } @@ -137,18 +137,34 @@ impl GlobalEdge { /// and might not match the order of the vertices that were passed to /// [`GlobalEdge::new`]. You must not rely on the vertices being in any /// specific order. - pub fn vertices_in_normalized_order(&self) -> &[Handle; 2] { + pub fn vertices(&self) -> &VerticesInNormalizedOrder { &self.vertices } } -fn normalize_vertex_order( - [a, b]: [Handle; 2], -) -> [Handle; 2] { - if a < b { - [a, b] - } else { - [b, a] +/// The vertices of a [`GlobalEdge`] +/// +/// Since [`GlobalEdge`] is the single global representation of an edge in +/// global space, it must normalize the order of its vertices. Otherwise, it is +/// possible to construct two [`GlobalEdge`] instances that are meant to +/// represent the same edge, but aren't equal. +#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct VerticesInNormalizedOrder([Handle; 2]); + +impl VerticesInNormalizedOrder { + /// Construct a new instance of `VerticesInNormalizedOrder` + /// + /// The provided vertices can be in any order. + pub fn new([a, b]: [Handle; 2]) -> Self { + let vertices = if a < b { [a, b] } else { [b, a] }; + Self(vertices) + } + + /// Access the vertices + /// + /// The vertices in the returned array will be in normalized order. + pub fn access_in_normalized_order(&self) -> &[Handle; 2] { + &self.0 } } diff --git a/crates/fj-kernel/src/objects/mod.rs b/crates/fj-kernel/src/objects/mod.rs index 0a1ee6035..8f137b1ff 100644 --- a/crates/fj-kernel/src/objects/mod.rs +++ b/crates/fj-kernel/src/objects/mod.rs @@ -87,7 +87,7 @@ mod vertex; pub use self::{ curve::{Curve, GlobalCurve}, cycle::Cycle, - edge::{GlobalEdge, HalfEdge}, + edge::{GlobalEdge, HalfEdge, VerticesInNormalizedOrder}, face::{Face, Faces, Handedness}, shell::Shell, sketch::Sketch, diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 7430f4a0f..3036720fb 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -288,7 +288,9 @@ impl From<&GlobalEdge> for PartialGlobalEdge { fn from(global_edge: &GlobalEdge) -> Self { Self { curve: Some(global_edge.curve().clone().into()), - vertices: Some(global_edge.vertices_in_normalized_order().clone()), + vertices: Some( + global_edge.vertices().access_in_normalized_order().clone(), + ), } } }