Skip to content

Commit

Permalink
Merge pull request #416 from hannobraun/insert
Browse files Browse the repository at this point in the history
Replace `add_*` method with `Shape::insert`
  • Loading branch information
hannobraun authored Apr 1, 2022
2 parents c865c7a + 92df8ef commit 55a36cb
Show file tree
Hide file tree
Showing 19 changed files with 241 additions and 239 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions fj-kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ categories = ["mathematics"]

[dependencies]
anyhow = "1.0.56"
anymap = "1.0.0-beta.2"
approx = "0.5.1"
map-macro = "0.2.0"
nalgebra = "0.30.0"
Expand Down
4 changes: 2 additions & 2 deletions fj-kernel/src/algorithms/approximation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,11 @@ mod tests {
let da =
Edge::build(&mut shape).line_segment_from_vertices([v4, v1])?;

let abcd = shape.topology().add_cycle(Cycle {
let abcd = shape.insert(Cycle {
edges: vec![ab, bc, cd, da],
})?;

let surface = shape.geometry().add_surface(Surface::x_y_plane());
let surface = shape.insert(Surface::x_y_plane())?;
let face = Face::Face {
surface,
exteriors: vec![abcd],
Expand Down
93 changes: 36 additions & 57 deletions fj-kernel/src/algorithms/sweep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,15 @@ pub fn sweep_shape(

// Create the new vertices.
for vertex_source in source.topology().vertices() {
let point_bottom =
target.geometry().add_point(vertex_source.get().point());
let point_top = target.geometry().add_point(point_bottom.get() + path);
let point_bottom = target.insert(vertex_source.get().point()).unwrap();
let point_top = target.insert(point_bottom.get() + path).unwrap();

let vertex_bottom = target
.topology()
.add_vertex(Vertex {
.insert(Vertex {
point: point_bottom,
})
.unwrap();
let vertex_top = target
.topology()
.add_vertex(Vertex { point: point_top })
.unwrap();
let vertex_top = target.insert(Vertex { point: point_top }).unwrap();

source_to_bottom
.vertices
Expand All @@ -49,25 +44,22 @@ pub fn sweep_shape(

// Create the new edges.
for edge_source in source.topology().edges() {
let curve_bottom =
target.geometry().add_curve(edge_source.get().curve());
let curve_bottom = target.insert(edge_source.get().curve()).unwrap();
let curve_top = target
.geometry()
.add_curve(curve_bottom.get().transform(&translation));
.insert(curve_bottom.get().transform(&translation))
.unwrap();

let vertices_bottom = source_to_bottom.vertices_for_edge(&edge_source);
let vertices_top = source_to_top.vertices_for_edge(&edge_source);

let edge_bottom = target
.topology()
.add_edge(Edge {
.insert(Edge {
curve: curve_bottom,
vertices: vertices_bottom,
})
.unwrap();
let edge_top = target
.topology()
.add_edge(Edge {
.insert(Edge {
curve: curve_top,
vertices: vertices_top,
})
Expand All @@ -85,15 +77,11 @@ pub fn sweep_shape(
let edges_top = source_to_top.edges_for_cycle(&cycle_source);

let cycle_bottom = target
.topology()
.add_cycle(Cycle {
.insert(Cycle {
edges: edges_bottom,
})
.unwrap();
let cycle_top = target
.topology()
.add_cycle(Cycle { edges: edges_top })
.unwrap();
let cycle_top = target.insert(Cycle { edges: edges_top }).unwrap();

source_to_bottom
.cycles
Expand All @@ -103,11 +91,10 @@ pub fn sweep_shape(

// Create top faces.
for face_source in source.topology().faces().values() {
let surface_bottom =
target.geometry().add_surface(face_source.surface());
let surface_bottom = target.insert(face_source.surface()).unwrap();
let surface_top = target
.geometry()
.add_surface(surface_bottom.get().transform(&translation));
.insert(surface_bottom.get().transform(&translation))
.unwrap();

let exteriors_bottom =
source_to_bottom.exteriors_for_face(&face_source);
Expand All @@ -117,17 +104,15 @@ pub fn sweep_shape(
let interiors_top = source_to_top.interiors_for_face(&face_source);

target
.topology()
.add_face(Face::Face {
.insert(Face::Face {
surface: surface_bottom,
exteriors: exteriors_bottom,
interiors: interiors_bottom,
color,
})
.unwrap();
target
.topology()
.add_face(Face::Face {
.insert(Face::Face {
surface: surface_top,
exteriors: exteriors_top,
interiors: interiors_top,
Expand Down Expand Up @@ -178,10 +163,7 @@ pub fn sweep_shape(
s.set_color(color);
}

target
.topology()
.add_face(Face::Triangles(side_face))
.unwrap();
target.insert(Face::Triangles(side_face)).unwrap();
} else {
// If there's no continuous edge, we can create the non-
// continuous faces using boundary representation.
Expand All @@ -208,8 +190,8 @@ pub fn sweep_shape(
.entry(vertex_bottom.clone())
.or_insert_with(|| {
let curve = target
.geometry()
.add_curve(edge_source.get().curve());
.insert(edge_source.get().curve())
.unwrap();

let vertex_top = source_to_top
.vertices
Expand All @@ -218,8 +200,7 @@ pub fn sweep_shape(
.clone();

target
.topology()
.add_edge(Edge {
.insert(Edge {
curve,
vertices: Some([
vertex_bottom,
Expand All @@ -239,16 +220,15 @@ pub fn sweep_shape(
let top_edge =
source_to_top.edges.get(edge_source).unwrap().clone();

let surface = target.geometry().add_surface(
Surface::SweptCurve(SweptCurve {
let surface = target
.insert(Surface::SweptCurve(SweptCurve {
curve: bottom_edge.get().curve(),
path,
}),
);
}))
.unwrap();

let cycle = target
.topology()
.add_cycle(Cycle {
.insert(Cycle {
edges: vec![
bottom_edge,
top_edge,
Expand All @@ -259,8 +239,7 @@ pub fn sweep_shape(
.unwrap();

target
.topology()
.add_face(Face::Face {
.insert(Face::Face {
surface,
exteriors: vec![cycle],
interiors: Vec::new(),
Expand Down Expand Up @@ -401,13 +380,13 @@ mod tests {
fn new([a, b, c]: [impl Into<Point<3>>; 3]) -> anyhow::Result<Self> {
let mut shape = Shape::new();

let a = shape.geometry().add_point(a.into());
let b = shape.geometry().add_point(b.into());
let c = shape.geometry().add_point(c.into());
let a = shape.insert(a.into())?;
let b = shape.insert(b.into())?;
let c = shape.insert(c.into())?;

let a = shape.topology().add_vertex(Vertex { point: a })?;
let b = shape.topology().add_vertex(Vertex { point: b })?;
let c = shape.topology().add_vertex(Vertex { point: c })?;
let a = shape.insert(Vertex { point: a })?;
let b = shape.insert(Vertex { point: b })?;
let c = shape.insert(Vertex { point: c })?;

let ab = Edge::build(&mut shape)
.line_segment_from_vertices([a.clone(), b.clone()])?;
Expand All @@ -416,23 +395,23 @@ mod tests {
let ca = Edge::build(&mut shape)
.line_segment_from_vertices([c.clone(), a.clone()])?;

let cycles = shape.topology().add_cycle(Cycle {
let cycles = shape.insert(Cycle {
edges: vec![ab, bc, ca],
})?;

let surface = shape.geometry().add_surface(Surface::SweptCurve(
let surface = shape.insert(Surface::SweptCurve(
SweptCurve::plane_from_points(
[a, b, c].map(|vertex| vertex.get().point()),
),
));
))?;
let abc = Face::Face {
surface,
exteriors: vec![cycles],
interiors: Vec::new(),
color: [255, 0, 0, 255],
};

let face = shape.topology().add_face(abc)?;
let face = shape.insert(abc)?;

Ok(Self { shape, face })
}
Expand Down
16 changes: 14 additions & 2 deletions 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, Topology,
Geometry, Object, Topology, ValidationResult,
};

/// The boundary representation of a shape
Expand Down Expand Up @@ -55,6 +55,19 @@ impl Shape {
self
}

/// Insert an object into the shape
///
/// Validates the object, and returns an error if it is not valid. See the
/// documentation of each object for validation requirements.
pub fn insert<T>(&mut self, object: T) -> ValidationResult<T>
where
T: Object,
{
object.validate(self.min_distance, &self.stores)?;
let handle = self.stores.get::<T>().insert(object);
Ok(handle)
}

/// Access the shape's geometry
pub fn geometry(&mut self) -> Geometry {
Geometry {
Expand All @@ -69,7 +82,6 @@ impl Shape {
/// Access the shape's topology
pub fn topology(&mut self) -> Topology {
Topology {
min_distance: self.min_distance,
stores: self.stores.clone(),
_lifetime: PhantomData,
}
Expand Down
31 changes: 1 addition & 30 deletions fj-kernel/src/shape/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,10 @@ use crate::{

use super::{
stores::{Curves, Faces, Points, Surfaces},
Handle, Iter,
Iter,
};

/// API to access a shape's geometry
///
/// Other than topology, geometry doesn't need to be validated. Hence adding
/// geometry is infallible.
///
/// There are several reasons for this:
/// - Geometry doesn't refer to other objects, so structural validation doesn't
/// apply.
/// - There simply no reason that geometry needs to be unique. In addition, it's
/// probably quite hard to rule out generating duplicate geometry. Think about
/// line segment edges that are on identical lines, but are created
/// separately.
/// - Geometric validation doesn't apply either. It simply doesn't matter, if
/// curves or surfaces intersect, for example, as long as they don't do that
/// where an edge or face is defined.
pub struct Geometry<'r> {
pub(super) points: &'r mut Points,
pub(super) curves: &'r mut Curves,
Expand All @@ -41,21 +27,6 @@ pub struct Geometry<'r> {
}

impl Geometry<'_> {
/// Add a point to the shape
pub fn add_point(&mut self, point: Point<3>) -> Handle<Point<3>> {
self.points.insert(point)
}

/// Add a curve to the shape
pub fn add_curve(&mut self, curve: Curve) -> Handle<Curve> {
self.curves.insert(curve)
}

/// Add a surface to the shape
pub fn add_surface(&mut self, surface: Surface) -> Handle<Surface> {
self.surfaces.insert(surface)
}

/// Transform the geometry of the shape
///
/// Since the topological types refer to geometry, and don't contain any
Expand Down
2 changes: 2 additions & 0 deletions fj-kernel/src/shape/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
mod api;
mod geometry;
mod object;
mod stores;
mod topology;
mod validate;

pub use self::{
api::Shape,
geometry::Geometry,
object::Object,
stores::{Handle, Iter},
topology::Topology,
validate::{StructuralIssues, ValidationError, ValidationResult},
Expand Down
33 changes: 33 additions & 0 deletions fj-kernel/src/shape/object.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use fj_math::Point;

use crate::{
geometry::{Curve, Surface},
topology::{Cycle, Edge, Face, Vertex},
};

use super::validate::Validate;

/// Marker trait for geometric and topological objects
pub trait Object: 'static + Validate + private::Sealed {}

impl private::Sealed for Point<3> {}
impl private::Sealed for Curve {}
impl private::Sealed for Surface {}

impl private::Sealed for Vertex {}
impl private::Sealed for Edge {}
impl private::Sealed for Cycle {}
impl private::Sealed for Face {}

impl Object for Point<3> {}
impl Object for Curve {}
impl Object for Surface {}

impl Object for Vertex {}
impl Object for Edge {}
impl Object for Cycle {}
impl Object for Face {}

mod private {
pub trait Sealed {}
}
Loading

0 comments on commit 55a36cb

Please sign in to comment.