Merge pull request #1334 from hannobraun/insert

Separate building objects from inserting them into stores
This commit is contained in:
Hanno Braun 2022-11-09 22:37:36 +01:00 committed by GitHub
commit 84d5c599e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 294 additions and 147 deletions

View File

@ -198,6 +198,7 @@ mod tests {
use crate::{
algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint},
builder::CurveBuilder,
insert::Insert,
objects::{Curve, Objects, Surface},
partial::HasPartial,
path::GlobalPath,
@ -215,7 +216,8 @@ mod tests {
let curve = Curve::partial()
.with_surface(Some(surface))
.update_as_line_from_points([[1., 1.], [2., 1.]])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let range = RangeOnPath::from([[0.], [1.]]);
let approx = (&curve, range).approx(1.);
@ -236,7 +238,8 @@ mod tests {
let curve = Curve::partial()
.with_surface(Some(surface))
.update_as_line_from_points([[1., 1.], [1., 2.]])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let range = RangeOnPath::from([[0.], [1.]]);
let approx = (&curve, range).approx(1.);
@ -255,7 +258,8 @@ mod tests {
let curve = Curve::partial()
.with_surface(Some(surface.clone()))
.update_as_line_from_points([[0., 1.], [1., 1.]])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let range = RangeOnPath::from([[0.], [TAU]]);
let tolerance = 1.;
@ -287,7 +291,8 @@ mod tests {
let curve = Curve::partial()
.with_surface(Some(surface))
.update_as_circle_from_radius(1.)
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let range = RangeOnPath::from([[0.], [TAU]]);
let tolerance = 1.;

View File

@ -68,8 +68,10 @@ mod tests {
use crate::{
algorithms::intersect::CurveFaceIntersection,
builder::{CurveBuilder, FaceBuilder},
insert::Insert,
objects::{Curve, Face, Objects},
partial::HasPartial,
validate::ValidationError,
};
use super::FaceFaceIntersection;
@ -122,12 +124,14 @@ mod tests {
let intersection = FaceFaceIntersection::compute([&a, &b], &objects)?;
let expected_curves = surfaces.try_map_ext(|surface| {
Curve::partial()
.with_surface(Some(surface))
.update_as_line_from_points([[0., 0.], [1., 0.]])
.build(&objects)
})?;
let expected_curves =
surfaces.try_map_ext(|surface| -> Result<_, ValidationError> {
Ok(Curve::partial()
.with_surface(Some(surface))
.update_as_line_from_points([[0., 0.], [1., 0.]])
.build(&objects)?
.insert(&objects)?)
})?;
let expected_intervals =
CurveFaceIntersection::from_intervals([[[-1.], [1.]]]);
assert_eq!(

View File

@ -137,6 +137,7 @@ mod tests {
use crate::{
algorithms::intersect::{face_point::FacePointIntersection, Intersect},
builder::FaceBuilder,
insert::Insert,
iter::ObjectIters,
objects::{Face, Objects},
partial::HasPartial,
@ -150,7 +151,8 @@ mod tests {
let face = Face::partial()
.with_surface(surface)
.with_exterior_polygon_from_points([[0., 0.], [1., 1.], [0., 2.]])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let point = Point::from([2., 1.]);
let intersection = (&face, &point).intersect();
@ -167,7 +169,8 @@ mod tests {
let face = Face::partial()
.with_surface(surface)
.with_exterior_polygon_from_points([[0., 0.], [2., 1.], [0., 2.]])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let point = Point::from([1., 1.]);
let intersection = (&face, &point).intersect();
@ -187,7 +190,8 @@ mod tests {
let face = Face::partial()
.with_surface(surface)
.with_exterior_polygon_from_points([[4., 2.], [0., 4.], [0., 0.]])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let point = Point::from([1., 2.]);
let intersection = (&face, &point).intersect();
@ -212,7 +216,8 @@ mod tests {
[3., 0.],
[3., 4.],
])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let point = Point::from([1., 1.]);
let intersection = (&face, &point).intersect();
@ -238,7 +243,8 @@ mod tests {
[3., 1.],
[0., 2.],
])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let point = Point::from([1., 1.]);
let intersection = (&face, &point).intersect();
@ -265,7 +271,8 @@ mod tests {
[4., 0.],
[4., 5.],
])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let point = Point::from([1., 1.]);
let intersection = (&face, &point).intersect();
@ -285,7 +292,8 @@ mod tests {
let face = Face::partial()
.with_surface(surface)
.with_exterior_polygon_from_points([[0., 0.], [2., 0.], [0., 1.]])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let point = Point::from([1., 0.]);
let intersection = (&face, &point).intersect();
@ -314,7 +322,8 @@ mod tests {
let face = Face::partial()
.with_surface(surface)
.with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let point = Point::from([1., 0.]);
let intersection = (&face, &point).intersect();

View File

@ -153,6 +153,7 @@ mod tests {
transform::TransformObject,
},
builder::FaceBuilder,
insert::Insert,
iter::ObjectIters,
objects::{Face, Objects},
partial::HasPartial,
@ -174,6 +175,7 @@ mod tests {
[-1., 1.],
])
.build(&objects)?
.insert(&objects)?
.translate([-1., 0., 0.], &objects)?;
assert_eq!((&ray, &face).intersect(), None);
@ -196,6 +198,7 @@ mod tests {
[-1., 1.],
])
.build(&objects)?
.insert(&objects)?
.translate([1., 0., 0.], &objects)?;
assert_eq!(
@ -221,6 +224,7 @@ mod tests {
[-1., 1.],
])
.build(&objects)?
.insert(&objects)?
.translate([0., 0., 2.], &objects)?;
assert_eq!((&ray, &face).intersect(), None);
@ -243,6 +247,7 @@ mod tests {
[-1., 1.],
])
.build(&objects)?
.insert(&objects)?
.translate([1., 1., 0.], &objects)?;
let edge = face
@ -276,6 +281,7 @@ mod tests {
[-1., 1.],
])
.build(&objects)?
.insert(&objects)?
.translate([1., 1., 1.], &objects)?;
let vertex = face
@ -306,7 +312,8 @@ mod tests {
[1., 1.],
[-1., 1.],
])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
assert_eq!(
(&ray, &face).intersect(),
@ -332,6 +339,7 @@ mod tests {
[-1., 1.],
])
.build(&objects)?
.insert(&objects)?
.translate([0., 0., 1.], &objects)?;
assert_eq!((&ray, &face).intersect(), None);

View File

@ -93,6 +93,7 @@ mod tests {
use crate::{
algorithms::transform::TransformObject,
builder::CurveBuilder,
insert::Insert,
objects::{Curve, Objects},
partial::HasPartial,
};
@ -124,11 +125,13 @@ mod tests {
let expected_xy = Curve::partial()
.with_surface(Some(xy.clone()))
.update_as_u_axis()
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let expected_xz = Curve::partial()
.with_surface(Some(xz.clone()))
.update_as_u_axis()
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
assert_eq!(
SurfaceSurfaceIntersection::compute([xy, xz], &objects)?,

View File

@ -1,4 +1,5 @@
use crate::{
insert::Insert,
objects::{Face, Objects},
partial::HasPartial,
storage::Handle,
@ -15,10 +16,11 @@ impl Reverse for Handle<Face> {
.map(|cycle| cycle.clone().reverse(objects))
.collect::<Result<Vec<_>, _>>()?;
Face::partial()
Ok(Face::partial()
.with_exterior(exterior)
.with_interiors(interiors)
.with_color(self.color())
.build(objects)
.build(objects)?
.insert(objects)?)
}
}

View File

@ -3,6 +3,7 @@ use fj_math::{Line, Scalar, Vector};
use crate::{
algorithms::{reverse::Reverse, transform::TransformObject},
insert::Insert,
objects::{
Curve, Cycle, Face, GlobalEdge, HalfEdge, Objects, SurfaceVertex,
Vertex,
@ -176,10 +177,11 @@ impl Sweep for (Handle<HalfEdge>, Color) {
objects.cycles.insert(Cycle::new(edges))?
};
Face::partial()
Ok(Face::partial()
.with_exterior(cycle)
.with_color(color)
.build(objects)
.build(objects)?
.insert(objects)?)
}
}
@ -191,6 +193,7 @@ mod tests {
use crate::{
algorithms::{reverse::Reverse, sweep::Sweep},
builder::HalfEdgeBuilder,
insert::Insert,
objects::{Cycle, Face, HalfEdge, Objects, SurfaceVertex, Vertex},
partial::HasPartial,
};
@ -204,7 +207,8 @@ mod tests {
objects.surfaces.xy_plane(),
[[0., 0.], [1., 0.]],
)
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let face =
(half_edge, Color::default()).sweep([0., 0., 1.], &objects)?;
@ -218,7 +222,8 @@ mod tests {
surface.clone(),
[[0., 0.], [1., 0.]],
)
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let side_up = HalfEdge::partial()
.with_surface(surface.clone())
.with_back_vertex(Vertex::partial().with_surface_form(
@ -228,7 +233,8 @@ mod tests {
SurfaceVertex::partial().with_position(Some([1., 1.])),
))
.update_as_line_segment()
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let top = HalfEdge::partial()
.with_surface(surface.clone())
.with_back_vertex(Vertex::partial().with_surface_form(
@ -239,6 +245,7 @@ mod tests {
))
.update_as_line_segment()
.build(&objects)?
.insert(&objects)?
.reverse(&objects)?;
let side_down =
HalfEdge::partial()
@ -251,13 +258,17 @@ mod tests {
))
.update_as_line_segment()
.build(&objects)?
.insert(&objects)?
.reverse(&objects)?;
let cycle = objects
.cycles
.insert(Cycle::new([bottom, side_up, top, side_down]))?;
Face::partial().with_exterior(cycle).build(&objects)?
Face::partial()
.with_exterior(cycle)
.build(&objects)?
.insert(&objects)?
};
assert_eq!(face, expected_face);

View File

@ -85,6 +85,7 @@ mod tests {
use crate::{
algorithms::{reverse::Reverse, transform::TransformObject},
builder::{FaceBuilder, HalfEdgeBuilder},
insert::Insert,
objects::{Face, HalfEdge, Objects, Sketch},
partial::HasPartial,
};
@ -111,11 +112,13 @@ mod tests {
.with_surface(surface.clone())
.with_exterior_polygon_from_points(TRIANGLE)
.build(&objects)?
.insert(&objects)?
.reverse(&objects)?;
let top = Face::partial()
.with_surface(surface.translate(UP, &objects)?)
.with_exterior_polygon_from_points(TRIANGLE)
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
assert!(solid.find_face(&bottom).is_some());
assert!(solid.find_face(&top).is_some());
@ -129,7 +132,8 @@ mod tests {
objects.surfaces.xy_plane(),
[a, b],
)
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
(half_edge, Color::default()).sweep(UP, &objects)
})
.collect::<Result<Vec<_>, _>>()?;
@ -155,11 +159,13 @@ mod tests {
.with_surface(surface.clone().translate(DOWN, &objects)?)
.with_exterior_polygon_from_points(TRIANGLE)
.build(&objects)?
.insert(&objects)?
.reverse(&objects)?;
let top = Face::partial()
.with_surface(surface)
.with_exterior_polygon_from_points(TRIANGLE)
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
assert!(solid.find_face(&bottom).is_some());
assert!(solid.find_face(&top).is_some());
@ -174,6 +180,7 @@ mod tests {
[a, b],
)
.build(&objects)?
.insert(&objects)?
.reverse(&objects)?;
(half_edge, Color::default()).sweep(DOWN, &objects)
})

View File

@ -169,6 +169,7 @@ mod tests {
use crate::{
algorithms::sweep::Sweep,
builder::{CurveBuilder, HalfEdgeBuilder},
insert::Insert,
objects::{Curve, HalfEdge, Objects, Vertex},
partial::HasPartial,
};
@ -181,18 +182,21 @@ mod tests {
let curve = Curve::partial()
.with_surface(Some(surface.clone()))
.update_as_u_axis()
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let vertex = Vertex::partial()
.with_position(Some([0.]))
.with_curve(curve)
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let half_edge =
(vertex, surface.clone()).sweep([0., 0., 1.], &objects)?;
let expected_half_edge = HalfEdge::partial()
.update_as_line_segment_from_points(surface, [[0., 0.], [0., 1.]])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
assert_eq!(half_edge, expected_half_edge);
Ok(())
}

View File

@ -1,6 +1,7 @@
use fj_math::Transform;
use crate::{
insert::Insert,
objects::{Face, FaceSet, Objects},
partial::{HasPartial, PartialFace},
validate::ValidationError,
@ -26,11 +27,12 @@ impl TransformObject for PartialFace {
let interiors = self
.interiors()
.map(|cycle| -> Result<_, ValidationError> {
cycle
Ok(cycle
.into_partial()
.transform(transform, objects)?
.with_surface(surface.clone())
.build(objects)
.build(objects)?
.insert(objects)?)
})
.collect::<Result<Vec<_>, _>>()?;

View File

@ -13,10 +13,11 @@ mod vertex;
use fj_math::{Transform, Vector};
use crate::{
insert::Insert,
objects::Objects,
partial::{HasPartial, MaybePartial, Partial},
storage::Handle,
validate::ValidationError,
validate::{Validate, ValidationError},
};
/// Transform an object
@ -61,17 +62,20 @@ pub trait TransformObject: Sized {
impl<T> TransformObject for Handle<T>
where
T: HasPartial,
T: HasPartial + Insert,
T::Partial: TransformObject,
ValidationError: From<<T as Validate>::Error>,
{
fn transform(
self,
transform: &Transform,
objects: &Objects,
) -> Result<Self, ValidationError> {
self.to_partial()
Ok(self
.to_partial()
.transform(transform, objects)?
.build(objects)
.build(objects)?
.insert(objects)?)
}
}

View File

@ -85,6 +85,7 @@ mod tests {
use crate::{
algorithms::approx::{Approx, Tolerance},
builder::FaceBuilder,
insert::Insert,
objects::{Face, Objects},
partial::HasPartial,
storage::Handle,
@ -105,7 +106,8 @@ mod tests {
let face = Face::partial()
.with_surface(surface)
.with_exterior_polygon_from_points([a, b, c, d])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let a = Point::from(a).to_xyz();
let b = Point::from(b).to_xyz();
@ -141,7 +143,8 @@ mod tests {
.with_surface(surface.clone())
.with_exterior_polygon_from_points([a, b, c, d])
.with_interior_polygon_from_points([e, f, g, h])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let triangles = triangulate(face)?;
@ -201,7 +204,8 @@ mod tests {
let face = Face::partial()
.with_surface(surface.clone())
.with_exterior_polygon_from_points([a, b, c, d, e])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let triangles = triangulate(face)?;

View File

@ -2,6 +2,7 @@ use fj_interop::ext::ArrayExt;
use fj_math::{Point, Scalar};
use crate::{
insert::Insert,
objects::{
Curve, GlobalVertex, Objects, Surface, SurfaceVertex, Vertex,
VerticesInNormalizedOrder,
@ -89,7 +90,8 @@ impl HalfEdgeBuilder for PartialHalfEdge {
.with_position(Some(path.point_from_path_coords(a_curve)))
.with_surface(curve.surface())
.with_global_form(Some(global_vertex))
.build(objects)?;
.build(objects)?
.insert(objects)?;
let [back, front] = [a_curve, b_curve].map(|point_curve| {
Vertex::partial()

View File

@ -6,6 +6,7 @@ use fj_math::Scalar;
use crate::{
algorithms::transform::TransformObject,
builder::{FaceBuilder, HalfEdgeBuilder},
insert::Insert,
objects::{
Curve, Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface,
SurfaceVertex, Vertex,
@ -64,6 +65,8 @@ impl<'a> ShellBuilder<'a> {
])
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()
};
let (sides, top_edges) = {
@ -97,6 +100,8 @@ impl<'a> ShellBuilder<'a> {
)
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()
})
.collect::<Vec<_>>();
@ -120,6 +125,8 @@ impl<'a> ShellBuilder<'a> {
.update_as_line_segment()
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()
})
.collect::<Vec<_>>();
@ -157,6 +164,8 @@ impl<'a> ShellBuilder<'a> {
.update_as_line_segment()
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()
})
.collect::<Vec<_>>()
};
@ -180,6 +189,8 @@ impl<'a> ShellBuilder<'a> {
.update_as_line_segment()
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()
})
.collect::<Vec<_>>();
@ -192,12 +203,16 @@ impl<'a> ShellBuilder<'a> {
let cycle = Cycle::partial()
.with_half_edges([bottom, side_up, top, side_down])
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap();
Face::partial()
.with_exterior(cycle)
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()
});
(sides, tops)
@ -232,6 +247,8 @@ impl<'a> ShellBuilder<'a> {
))
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()
});
[a.clone(), b, c, d, a]
@ -259,6 +276,8 @@ impl<'a> ShellBuilder<'a> {
.with_global_form(edge.global_form().clone())
.update_as_line_segment()
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap(),
);
}
@ -269,6 +288,8 @@ impl<'a> ShellBuilder<'a> {
)
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()
};
self.faces.extend([bottom]);

View File

@ -1,6 +1,7 @@
use fj_math::Point;
use crate::{
insert::Insert,
objects::{Face, FaceSet, Objects, Sketch, Surface},
partial::HasPartial,
storage::Handle,
@ -51,6 +52,8 @@ impl<'a> SketchBuilder<'a> {
.with_surface(surface.clone())
.with_exterior_polygon_from_points(points)
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()]);
self
}

View File

@ -0,0 +1,53 @@
//! Convenience trait to insert objects into their respective stores
//!
//! See [`Insert`].
use crate::{
objects::{
Curve, Cycle, Face, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge,
Objects, Shell, Sketch, Solid, Surface, SurfaceVertex, Vertex,
},
storage::Handle,
validate::Validate,
};
/// Convenience trait to insert objects into their respective stores
pub trait Insert: Sized + Validate {
// TASK: Make error more specific.
/// Insert the object into its respective store
fn insert(
self,
objects: &Objects,
) -> Result<Handle<Self>, <Self as Validate>::Error>;
}
macro_rules! impl_insert {
($($ty:ty, $store:ident;)*) => {
$(
impl Insert for $ty {
fn insert(
self,
objects: &Objects,
) -> Result<Handle<Self>, <Self as Validate>::Error> {
objects.$store.insert(self)
}
}
)*
};
}
impl_insert!(
Curve, curves;
Cycle, cycles;
Face, faces;
GlobalCurve, global_curves;
GlobalEdge, global_edges;
GlobalVertex, global_vertices;
HalfEdge, half_edges;
Shell, shells;
Sketch, sketches;
Solid, solids;
SurfaceVertex, surface_vertices;
Surface, surfaces;
Vertex, vertices;
);

View File

@ -361,6 +361,7 @@ impl<T> Iterator for Iter<T> {
mod tests {
use crate::{
builder::{CurveBuilder, CycleBuilder, FaceBuilder, HalfEdgeBuilder},
insert::Insert,
objects::{
Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Objects,
Shell, Sketch, Solid, SurfaceVertex, Vertex,
@ -371,14 +372,15 @@ mod tests {
use super::ObjectIters as _;
#[test]
fn curve() {
fn curve() -> anyhow::Result<()> {
let objects = Objects::new();
let surface = objects.surfaces.xy_plane();
let object = Curve::partial()
.with_surface(Some(surface))
.update_as_u_axis()
.build(&objects);
.build(&objects)?
.insert(&objects)?;
assert_eq!(1, object.curve_iter().count());
assert_eq!(0, object.cycle_iter().count());
@ -391,10 +393,12 @@ mod tests {
assert_eq!(0, object.solid_iter().count());
assert_eq!(0, object.surface_iter().count());
assert_eq!(0, object.vertex_iter().count());
Ok(())
}
#[test]
fn cycle() {
fn cycle() -> anyhow::Result<()> {
let objects = Objects::new();
let surface = objects.surfaces.xy_plane();
@ -404,7 +408,8 @@ mod tests {
[[0., 0.], [1., 0.], [0., 1.]],
)
.close_with_line_segment()
.build(&objects);
.build(&objects)?
.insert(&objects);
assert_eq!(3, object.curve_iter().count());
assert_eq!(1, object.cycle_iter().count());
@ -417,17 +422,20 @@ mod tests {
assert_eq!(0, object.solid_iter().count());
assert_eq!(0, object.surface_iter().count());
assert_eq!(6, object.vertex_iter().count());
Ok(())
}
#[test]
fn face() {
fn face() -> anyhow::Result<()> {
let objects = Objects::new();
let surface = objects.surfaces.xy_plane();
let object = Face::partial()
.with_surface(surface)
.with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]])
.build(&objects);
.build(&objects)?
.insert(&objects)?;
assert_eq!(3, object.curve_iter().count());
assert_eq!(1, object.cycle_iter().count());
@ -440,13 +448,15 @@ mod tests {
assert_eq!(0, object.solid_iter().count());
assert_eq!(1, object.surface_iter().count());
assert_eq!(6, object.vertex_iter().count());
Ok(())
}
#[test]
fn global_curve() {
fn global_curve() -> anyhow::Result<()> {
let objects = Objects::new();
let object = objects.global_curves.insert(GlobalCurve);
let object = objects.global_curves.insert(GlobalCurve)?;
assert_eq!(0, object.curve_iter().count());
assert_eq!(0, object.cycle_iter().count());
@ -459,15 +469,17 @@ mod tests {
assert_eq!(0, object.solid_iter().count());
assert_eq!(0, object.surface_iter().count());
assert_eq!(0, object.vertex_iter().count());
Ok(())
}
#[test]
fn global_vertex() {
fn global_vertex() -> anyhow::Result<()> {
let objects = Objects::new();
let object = objects
.global_vertices
.insert(GlobalVertex::from_position([0., 0., 0.]));
.insert(GlobalVertex::from_position([0., 0., 0.]))?;
assert_eq!(0, object.curve_iter().count());
assert_eq!(0, object.cycle_iter().count());
@ -480,10 +492,12 @@ mod tests {
assert_eq!(0, object.solid_iter().count());
assert_eq!(0, object.surface_iter().count());
assert_eq!(0, object.vertex_iter().count());
Ok(())
}
#[test]
fn half_edge() {
fn half_edge() -> anyhow::Result<()> {
let objects = Objects::new();
let object = HalfEdge::partial()
@ -491,7 +505,8 @@ mod tests {
objects.surfaces.xy_plane(),
[[0., 0.], [1., 0.]],
)
.build(&objects);
.build(&objects)?
.insert(&objects)?;
assert_eq!(1, object.curve_iter().count());
assert_eq!(0, object.cycle_iter().count());
@ -504,6 +519,8 @@ mod tests {
assert_eq!(0, object.solid_iter().count());
assert_eq!(0, object.surface_iter().count());
assert_eq!(2, object.vertex_iter().count());
Ok(())
}
#[test]
@ -535,7 +552,8 @@ mod tests {
let face = Face::partial()
.with_surface(surface)
.with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]])
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let object = Sketch::builder(&objects).with_faces([face]).build();
assert_eq!(3, object.curve_iter().count());
@ -601,7 +619,8 @@ mod tests {
let curve = Curve::partial()
.with_surface(Some(surface.clone()))
.update_as_u_axis()
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
let global_vertex = objects
.global_vertices
.insert(GlobalVertex::from_position([0., 0., 0.]))?;

View File

@ -89,6 +89,7 @@
pub mod algorithms;
pub mod builder;
pub mod insert;
pub mod iter;
pub mod objects;
pub mod partial;

View File

@ -1,13 +1,14 @@
use fj_math::Point;
use crate::{
insert::Insert,
objects::{
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
Surface, SurfaceVertex, Vertex,
},
path::SurfacePath,
storage::Handle,
validate::ValidationError,
validate::{Validate, ValidationError},
};
use super::{HasPartial, Partial};
@ -91,9 +92,15 @@ impl<T: HasPartial> MaybePartial<T> {
pub fn into_full(
self,
objects: &Objects,
) -> Result<Handle<T>, ValidationError> {
) -> Result<Handle<T>, ValidationError>
where
T: Insert,
ValidationError: From<<T as Validate>::Error>,
{
match self {
Self::Partial(partial) => partial.build(objects),
Self::Partial(partial) => {
Ok(partial.build(objects)?.insert(objects)?)
}
Self::Full(full) => Ok(full),
}
}

View File

@ -80,10 +80,7 @@ impl PartialCurve {
}
/// Build a full [`Curve`] from the partial curve
pub fn build(
self,
objects: &Objects,
) -> Result<Handle<Curve>, ValidationError> {
pub fn build(self, objects: &Objects) -> Result<Curve, ValidationError> {
let path = self.path.expect("Can't build `Curve` without path");
let surface =
self.surface.expect("Can't build `Curve` without surface");
@ -94,9 +91,7 @@ impl PartialCurve {
}
.into_full(objects)?;
Ok(objects
.curves
.insert(Curve::new(surface, path, global_form))?)
Ok(Curve::new(surface, path, global_form))
}
}
@ -128,12 +123,8 @@ impl PartialGlobalCurve {
}
/// Build a full [`GlobalCurve`] from the partial global curve
pub fn build(
self,
objects: &Objects,
) -> Result<Handle<GlobalCurve>, ValidationError> {
let global_curve = objects.global_curves.insert(GlobalCurve)?;
Ok(global_curve)
pub fn build(self, _: &Objects) -> Result<GlobalCurve, ValidationError> {
Ok(GlobalCurve)
}
}

View File

@ -86,7 +86,7 @@ impl PartialCycle {
pub fn build(
mut self,
objects: &Objects,
) -> Result<Handle<Cycle>, ValidationError> {
) -> Result<Cycle, ValidationError> {
// Check that the cycle is closed. This will lead to a panic further
// down anyway, but that panic would be super-confusing. This one should
// be a bit more explicit on what is wrong.
@ -142,7 +142,7 @@ impl PartialCycle {
half_edges.push(half_edge);
}
Ok(objects.cycles.insert(Cycle::new(half_edges))?)
Ok(Cycle::new(half_edges))
}
}

View File

@ -102,10 +102,7 @@ impl PartialHalfEdge {
}
/// Build a full [`HalfEdge`] from the partial half-edge
pub fn build(
self,
objects: &Objects,
) -> Result<Handle<HalfEdge>, ValidationError> {
pub fn build(self, objects: &Objects) -> Result<HalfEdge, ValidationError> {
let curve = self.curve.into_full(objects)?;
let vertices = self.vertices.try_map_ext(|vertex| {
vertex
@ -120,9 +117,7 @@ impl PartialHalfEdge {
})
.into_full(objects)?;
Ok(objects
.half_edges
.insert(HalfEdge::new(vertices, global_form))?)
Ok(HalfEdge::new(vertices, global_form))
}
}
@ -202,16 +197,14 @@ impl PartialGlobalEdge {
pub fn build(
self,
objects: &Objects,
) -> Result<Handle<GlobalEdge>, ValidationError> {
) -> Result<GlobalEdge, ValidationError> {
let curve = self.curve.into_full(objects)?;
let vertices = self
.vertices
.expect("Can't build `GlobalEdge` without vertices")
.try_map_ext(|global_vertex| global_vertex.into_full(objects))?;
Ok(objects
.global_edges
.insert(GlobalEdge::new(curve, vertices))?)
Ok(GlobalEdge::new(curve, vertices))
}
}

View File

@ -84,10 +84,7 @@ impl PartialFace {
}
/// Construct a polygon from a list of points
pub fn build(
self,
objects: &Objects,
) -> Result<Handle<Face>, ValidationError> {
pub fn build(self, objects: &Objects) -> Result<Face, ValidationError> {
let exterior = self.exterior.into_full(objects)?;
let interiors = self
.interiors
@ -96,9 +93,7 @@ impl PartialFace {
.collect::<Result<Vec<_>, _>>()?;
let color = self.color.unwrap_or_default();
Ok(objects
.faces
.insert(Face::new(exterior, interiors, color))?)
Ok(Face::new(exterior, interiors, color))
}
}

View File

@ -4,12 +4,9 @@ pub mod edge;
pub mod face;
pub mod vertex;
use crate::{
objects::{
Curve, Cycle, Face, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge,
Objects, SurfaceVertex, Vertex,
},
storage::Handle,
use crate::objects::{
Curve, Cycle, Face, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge,
Objects, SurfaceVertex, Vertex,
};
use super::{
@ -34,7 +31,7 @@ macro_rules! impl_traits {
fn build(self, objects: &Objects)
-> Result<
Handle<Self::Full>,
Self::Full,
crate::validate::ValidationError
>
{

View File

@ -76,10 +76,7 @@ impl PartialVertex {
/// Panics, if position has not been provided.
///
/// Panics, if curve has not been provided.
pub fn build(
self,
objects: &Objects,
) -> Result<Handle<Vertex>, ValidationError> {
pub fn build(self, objects: &Objects) -> Result<Vertex, ValidationError> {
let position = self
.position
.expect("Cant' build `Vertex` without position");
@ -98,11 +95,7 @@ impl PartialVertex {
})
.into_full(objects)?;
Ok(objects.vertices.insert(Vertex::new(
position,
curve,
surface_form,
))?)
Ok(Vertex::new(position, curve, surface_form))
}
}
@ -185,7 +178,7 @@ impl PartialSurfaceVertex {
pub fn build(
self,
objects: &Objects,
) -> Result<Handle<SurfaceVertex>, ValidationError> {
) -> Result<SurfaceVertex, ValidationError> {
let position = self
.position
.expect("Can't build `SurfaceVertex` without position");
@ -200,11 +193,7 @@ impl PartialSurfaceVertex {
})
.into_full(objects)?;
Ok(objects.surface_vertices.insert(SurfaceVertex::new(
position,
surface,
global_form,
))?)
Ok(SurfaceVertex::new(position, surface, global_form))
}
}
@ -251,17 +240,12 @@ impl PartialGlobalVertex {
}
/// Build a full [`GlobalVertex`] from the partial global vertex
pub fn build(
self,
objects: &Objects,
) -> Result<Handle<GlobalVertex>, ValidationError> {
pub fn build(self, _: &Objects) -> Result<GlobalVertex, ValidationError> {
let position = self
.position
.expect("Can't build a `GlobalVertex` without a position");
Ok(objects
.global_vertices
.insert(GlobalVertex::from_position(position))?)
Ok(GlobalVertex::from_position(position))
}
}

View File

@ -1,4 +1,4 @@
use crate::{objects::Objects, storage::Handle, validate::ValidationError};
use crate::{objects::Objects, validate::ValidationError};
/// Implemented for objects that a partial object type exists for
///
@ -80,8 +80,5 @@ pub trait Partial: Default + for<'a> From<&'a Self::Full> {
/// Calling `build` on a partial object that can't infer its missing parts
/// is considered a programmer error, hence why this method doesn't return a
/// [`Result`].
fn build(
self,
objects: &Objects,
) -> Result<Handle<Self::Full>, ValidationError>;
fn build(self, objects: &Objects) -> Result<Self::Full, ValidationError>;
}

View File

@ -67,9 +67,10 @@ impl CycleValidationError {
mod tests {
use crate::{
builder::{CycleBuilder, HalfEdgeBuilder, VertexBuilder},
insert::Insert,
objects::{Cycle, Objects},
partial::HasPartial,
validate::Validate,
validate::{Validate, ValidationError},
};
#[test]
@ -102,7 +103,9 @@ mod tests {
let half_edges = half_edges
.into_iter()
.map(|half_edge| half_edge.build(&objects))
.map(|half_edge| -> anyhow::Result<_, ValidationError> {
Ok(half_edge.build(&objects)?.insert(&objects)?)
})
.collect::<Result<Vec<_>, _>>()?;
Cycle::new(half_edges)

View File

@ -202,9 +202,10 @@ mod tests {
use crate::{
builder::{HalfEdgeBuilder, VertexBuilder},
insert::Insert,
objects::{GlobalCurve, HalfEdge, Objects},
partial::HasPartial,
validate::Validate,
validate::{Validate, ValidationError},
};
#[test]
@ -223,7 +224,8 @@ mod tests {
.to_partial()
// Arranging for an equal but not identical curve here.
.with_curve(valid.curve().to_partial())
.build(&objects)?;
.build(&objects)?
.insert(&objects)?;
HalfEdge::new(vertices, valid.global_form().clone())
};
@ -250,7 +252,8 @@ mod tests {
.global_form()
.to_partial()
.with_curve(Some(objects.global_curves.insert(GlobalCurve)?))
.build(&objects)?,
.build(&objects)?
.insert(&objects)?,
);
assert!(valid.validate().is_ok());
@ -282,7 +285,8 @@ mod tests {
// Creating equal but not identical vertices here.
.map(|vertex| vertex.to_partial()),
))
.build(&objects)?,
.build(&objects)?
.insert(&objects)?,
);
assert!(valid.validate().is_ok());
@ -302,13 +306,16 @@ mod tests {
)
.build(&objects)?;
let invalid = HalfEdge::new(
valid.vertices().clone().try_map_ext(|vertex| {
vertex
.to_partial()
.with_position(Some([0.]))
.infer_surface_form()
.build(&objects)
})?,
valid.vertices().clone().try_map_ext(
|vertex| -> anyhow::Result<_, ValidationError> {
Ok(vertex
.to_partial()
.with_position(Some([0.]))
.infer_surface_form()
.build(&objects)?
.insert(&objects)?)
},
)?,
valid.global_form().clone(),
);

View File

@ -106,6 +106,7 @@ mod tests {
use crate::{
algorithms::reverse::Reverse,
builder::{CycleBuilder, FaceBuilder},
insert::Insert,
objects::{Cycle, Face, Objects},
partial::HasPartial,
validate::Validate,
@ -127,7 +128,8 @@ mod tests {
[[1., 1.], [1., 2.], [2., 1.]],
)
.close_with_line_segment()
.build(&objects)?];
.build(&objects)?
.insert(&objects)?];
Face::new(valid.exterior().clone(), interiors, valid.color())
};

View File

@ -180,6 +180,7 @@ impl SurfaceVertexValidationError {
mod tests {
use crate::{
builder::{CurveBuilder, SurfaceVertexBuilder},
insert::Insert,
objects::{Curve, GlobalVertex, Objects, SurfaceVertex, Vertex},
partial::HasPartial,
validate::Validate,
@ -204,7 +205,8 @@ mod tests {
.surface_form()
.to_partial()
.with_surface(Some(objects.surfaces.xz_plane()))
.build(&objects)?,
.build(&objects)?
.insert(&objects)?,
);
assert!(valid.validate().is_ok());
@ -233,7 +235,8 @@ mod tests {
.to_partial()
.with_position(Some([1., 0.]))
.infer_global_form()
.build(&objects)?,
.build(&objects)?
.insert(&objects)?,
);
assert!(valid.validate().is_ok());

View File

@ -3,6 +3,7 @@ use std::ops::Deref;
use fj_interop::{debug::DebugInfo, ext::ArrayExt, mesh::Color};
use fj_kernel::{
algorithms::reverse::Reverse,
insert::Insert,
iter::ObjectIters,
objects::{Face, Objects, Sketch},
partial::HasPartial,
@ -83,7 +84,8 @@ impl Shape for fj::Difference2d {
.with_exterior(exterior)
.with_interiors(interiors)
.with_color(Color(self.color()))
.build(objects)?,
.build(objects)?
.insert(objects)?,
);
}

View File

@ -3,6 +3,7 @@ use std::ops::Deref;
use fj_interop::{debug::DebugInfo, mesh::Color};
use fj_kernel::{
builder::{FaceBuilder, HalfEdgeBuilder},
insert::Insert,
objects::{Cycle, Face, HalfEdge, Objects, Sketch},
partial::HasPartial,
validate::ValidationError,
@ -29,13 +30,15 @@ impl Shape for fj::Sketch {
let half_edge = HalfEdge::partial()
.with_surface(surface)
.update_as_circle_from_radius(circle.radius(), objects)?
.build(objects)?;
.build(objects)?
.insert(objects)?;
let cycle = objects.cycles.insert(Cycle::new([half_edge]))?;
Face::partial()
.with_exterior(cycle)
.with_color(Color(self.color()))
.build(objects)?
.insert(objects)?
}
fj::Chain::PolyChain(poly_chain) => {
let points =
@ -46,6 +49,7 @@ impl Shape for fj::Sketch {
.with_exterior_polygon_from_points(points)
.with_color(Color(self.color()))
.build(objects)?
.insert(objects)?
}
};