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

Replace add_* method with Shape::insert #416

Merged
merged 15 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
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