From 3ba26f05e8898d85402d1e4c0625a6e564d4e0d3 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Apr 2022 17:43:03 +0200 Subject: [PATCH 1/4] Add more bounds to `Object` This is required for a method I'm working on right now. --- fj-kernel/src/shape/object.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fj-kernel/src/shape/object.rs b/fj-kernel/src/shape/object.rs index 059ab3728..75b5fa724 100644 --- a/fj-kernel/src/shape/object.rs +++ b/fj-kernel/src/shape/object.rs @@ -8,7 +8,10 @@ use crate::{ use super::validate::Validate; /// Marker trait for geometric and topological objects -pub trait Object: 'static + Validate + private::Sealed {} +pub trait Object: + 'static + Clone + PartialEq + Validate + private::Sealed +{ +} impl private::Sealed for Point<3> {} impl private::Sealed for Curve {} From 80741904a41462df06fe49e8113ac2f9148a5050 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Apr 2022 17:43:48 +0200 Subject: [PATCH 2/4] Make `Stores::get` easier to call It doesn't need the `&mut self`, and requiring it in the first place has been an oversight. --- fj-kernel/src/shape/stores.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fj-kernel/src/shape/stores.rs b/fj-kernel/src/shape/stores.rs index a612d8d64..905289bea 100644 --- a/fj-kernel/src/shape/stores.rs +++ b/fj-kernel/src/shape/stores.rs @@ -28,7 +28,7 @@ pub struct Stores { } impl Stores { - pub fn get(&mut self) -> Store + pub fn get(&self) -> Store where T: Object, { From 13c1d366a79b5195f281b6ec7dd4d69cb244aaab Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Apr 2022 17:59:58 +0200 Subject: [PATCH 3/4] Add `Shape::get_handle` --- fj-kernel/src/shape/api.rs | 93 +++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/fj-kernel/src/shape/api.rs b/fj-kernel/src/shape/api.rs index 6b9461ca1..07b0175b7 100644 --- a/fj-kernel/src/shape/api.rs +++ b/fj-kernel/src/shape/api.rs @@ -6,7 +6,7 @@ use super::{ stores::{ Curves, Cycles, Edges, Faces, Points, Stores, Surfaces, Vertices, }, - Geometry, Object, Topology, ValidationResult, + Geometry, Handle, Object, Topology, ValidationResult, }; /// The boundary representation of a shape @@ -68,6 +68,30 @@ impl Shape { Ok(handle) } + /// Access the handle of an object + /// + /// Returns the handle that refers to the given object, if it is part of the + /// shape. Returns `None`, if it isn't. + /// + /// # Implementation note + /// + /// If `object` is present multiple times, the handle of the first that is + /// found is returned. This is weird. It would be better, if objects were + /// unique, but currently they are stored in `Vec`s. + /// + /// This probably isn't worth thinking too much about right now. At some + /// point, we need smarter and probably more performant object storage + /// anyway. + pub fn get_handle(&self, object: &T) -> Option> + where + T: Object, + { + self.stores + .get::() + .iter() + .find(|obj| &obj.get() == object) + } + /// Access the shape's geometry pub fn geometry(&mut self) -> Geometry { Geometry { @@ -93,3 +117,70 @@ impl Default for Shape { Self::new() } } + +#[cfg(test)] +mod tests { + use fj_math::Point; + + use crate::{ + geometry::{Curve, Surface}, + shape::Shape, + topology::{Cycle, Edge, Face, Vertex}, + }; + + #[test] + + fn get_handle() -> anyhow::Result<()> { + let mut shape = Shape::new(); + + let point = Point::from([1., 0., 0.]); + let curve = Curve::x_axis(); + let surface = Surface::x_y_plane(); + + assert!(shape.get_handle(&point).is_none()); + assert!(shape.get_handle(&curve).is_none()); + assert!(shape.get_handle(&surface).is_none()); + + let point = shape.insert(point)?; + let curve = shape.insert(curve)?; + let surface = shape.insert(surface)?; + + assert!(shape.get_handle(&point.get()).as_ref() == Some(&point)); + assert!(shape.get_handle(&curve.get()).as_ref() == Some(&curve)); + assert!(shape.get_handle(&surface.get()).as_ref() == Some(&surface)); + + let vertex = Vertex { point }; + let edge = Edge { + curve, + vertices: None, + }; + + assert!(shape.get_handle(&vertex).is_none()); + assert!(shape.get_handle(&edge).is_none()); + + let vertex = shape.insert(vertex)?; + let edge = shape.insert(edge)?; + + assert!(shape.get_handle(&vertex.get()).as_ref() == Some(&vertex)); + assert!(shape.get_handle(&edge.get()).as_ref() == Some(&edge)); + + let cycle = Cycle { edges: vec![edge] }; + assert!(shape.get_handle(&cycle).is_none()); + + let cycle = shape.insert(cycle)?; + assert!(shape.get_handle(&cycle.get()).as_ref() == Some(&cycle)); + + let face = Face::Face { + surface, + exteriors: Vec::new(), + interiors: Vec::new(), + color: [0, 0, 0, 0], + }; + assert!(shape.get_handle(&face).is_none()); + + let face = shape.insert(face)?; + assert!(shape.get_handle(&face.get()).as_ref() == Some(&face)); + + Ok(()) + } +} From c780a717ab12d98e89c784f376250e6eb52bcb5d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 1 Apr 2022 18:00:16 +0200 Subject: [PATCH 4/4] Add `Shape::get_handle_or_insert` --- fj-kernel/src/shape/api.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/fj-kernel/src/shape/api.rs b/fj-kernel/src/shape/api.rs index 07b0175b7..89d2edb9a 100644 --- a/fj-kernel/src/shape/api.rs +++ b/fj-kernel/src/shape/api.rs @@ -92,6 +92,21 @@ impl Shape { .find(|obj| &obj.get() == object) } + /// Get handle of an identical object, if it exists, or add the object + /// + /// In any case, returns a handle that refers to an object that is identical + /// to the provided object. + pub fn get_handle_or_insert(&mut self, object: T) -> ValidationResult + where + T: Object, + { + if let Some(handle) = self.get_handle(&object) { + return Ok(handle); + } + + self.insert(object) + } + /// Access the shape's geometry pub fn geometry(&mut self) -> Geometry { Geometry {