Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Shape::get_handle, Shape::get_handle_or_insert #417

Merged
merged 4 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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