Skip to content

Commit

Permalink
Merge pull request #417 from hannobraun/get_handle
Browse files Browse the repository at this point in the history
Add `Shape::get_handle`, `Shape::get_handle_or_insert`
  • Loading branch information
hannobraun authored Apr 1, 2022
2 parents 55a36cb + c780a71 commit 6f83081
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 3 deletions.
108 changes: 107 additions & 1 deletion fj-kernel/src/shape/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -68,6 +68,45 @@ 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<T>(&self, object: &T) -> Option<Handle<T>>
where
T: Object,
{
self.stores
.get::<T>()
.iter()
.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<T>(&mut self, object: T) -> ValidationResult<T>
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 {
Expand All @@ -93,3 +132,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(())
}
}
5 changes: 4 additions & 1 deletion fj-kernel/src/shape/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down
2 changes: 1 addition & 1 deletion fj-kernel/src/shape/stores.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub struct Stores {
}

impl Stores {
pub fn get<T>(&mut self) -> Store<T>
pub fn get<T>(&self) -> Store<T>
where
T: Object,
{
Expand Down

0 comments on commit 6f83081

Please sign in to comment.