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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
use fj_math::Point; use fj_math::Point;
use crate::{ use crate::{
insert::Insert,
objects::{Face, FaceSet, Objects, Sketch, Surface}, objects::{Face, FaceSet, Objects, Sketch, Surface},
partial::HasPartial, partial::HasPartial,
storage::Handle, storage::Handle,
@ -51,6 +52,8 @@ impl<'a> SketchBuilder<'a> {
.with_surface(surface.clone()) .with_surface(surface.clone())
.with_exterior_polygon_from_points(points) .with_exterior_polygon_from_points(points)
.build(self.objects) .build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()]); .unwrap()]);
self 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 { mod tests {
use crate::{ use crate::{
builder::{CurveBuilder, CycleBuilder, FaceBuilder, HalfEdgeBuilder}, builder::{CurveBuilder, CycleBuilder, FaceBuilder, HalfEdgeBuilder},
insert::Insert,
objects::{ objects::{
Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Objects, Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Objects,
Shell, Sketch, Solid, SurfaceVertex, Vertex, Shell, Sketch, Solid, SurfaceVertex, Vertex,
@ -371,14 +372,15 @@ mod tests {
use super::ObjectIters as _; use super::ObjectIters as _;
#[test] #[test]
fn curve() { fn curve() -> anyhow::Result<()> {
let objects = Objects::new(); let objects = Objects::new();
let surface = objects.surfaces.xy_plane(); let surface = objects.surfaces.xy_plane();
let object = Curve::partial() let object = Curve::partial()
.with_surface(Some(surface)) .with_surface(Some(surface))
.update_as_u_axis() .update_as_u_axis()
.build(&objects); .build(&objects)?
.insert(&objects)?;
assert_eq!(1, object.curve_iter().count()); assert_eq!(1, object.curve_iter().count());
assert_eq!(0, object.cycle_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.solid_iter().count());
assert_eq!(0, object.surface_iter().count()); assert_eq!(0, object.surface_iter().count());
assert_eq!(0, object.vertex_iter().count()); assert_eq!(0, object.vertex_iter().count());
Ok(())
} }
#[test] #[test]
fn cycle() { fn cycle() -> anyhow::Result<()> {
let objects = Objects::new(); let objects = Objects::new();
let surface = objects.surfaces.xy_plane(); let surface = objects.surfaces.xy_plane();
@ -404,7 +408,8 @@ mod tests {
[[0., 0.], [1., 0.], [0., 1.]], [[0., 0.], [1., 0.], [0., 1.]],
) )
.close_with_line_segment() .close_with_line_segment()
.build(&objects); .build(&objects)?
.insert(&objects);
assert_eq!(3, object.curve_iter().count()); assert_eq!(3, object.curve_iter().count());
assert_eq!(1, object.cycle_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.solid_iter().count());
assert_eq!(0, object.surface_iter().count()); assert_eq!(0, object.surface_iter().count());
assert_eq!(6, object.vertex_iter().count()); assert_eq!(6, object.vertex_iter().count());
Ok(())
} }
#[test] #[test]
fn face() { fn face() -> anyhow::Result<()> {
let objects = Objects::new(); let objects = Objects::new();
let surface = objects.surfaces.xy_plane(); let surface = objects.surfaces.xy_plane();
let object = Face::partial() let object = Face::partial()
.with_surface(surface) .with_surface(surface)
.with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) .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!(3, object.curve_iter().count());
assert_eq!(1, object.cycle_iter().count()); assert_eq!(1, object.cycle_iter().count());
@ -440,13 +448,15 @@ mod tests {
assert_eq!(0, object.solid_iter().count()); assert_eq!(0, object.solid_iter().count());
assert_eq!(1, object.surface_iter().count()); assert_eq!(1, object.surface_iter().count());
assert_eq!(6, object.vertex_iter().count()); assert_eq!(6, object.vertex_iter().count());
Ok(())
} }
#[test] #[test]
fn global_curve() { fn global_curve() -> anyhow::Result<()> {
let objects = Objects::new(); 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.curve_iter().count());
assert_eq!(0, object.cycle_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.solid_iter().count());
assert_eq!(0, object.surface_iter().count()); assert_eq!(0, object.surface_iter().count());
assert_eq!(0, object.vertex_iter().count()); assert_eq!(0, object.vertex_iter().count());
Ok(())
} }
#[test] #[test]
fn global_vertex() { fn global_vertex() -> anyhow::Result<()> {
let objects = Objects::new(); let objects = Objects::new();
let object = objects let object = objects
.global_vertices .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.curve_iter().count());
assert_eq!(0, object.cycle_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.solid_iter().count());
assert_eq!(0, object.surface_iter().count()); assert_eq!(0, object.surface_iter().count());
assert_eq!(0, object.vertex_iter().count()); assert_eq!(0, object.vertex_iter().count());
Ok(())
} }
#[test] #[test]
fn half_edge() { fn half_edge() -> anyhow::Result<()> {
let objects = Objects::new(); let objects = Objects::new();
let object = HalfEdge::partial() let object = HalfEdge::partial()
@ -491,7 +505,8 @@ mod tests {
objects.surfaces.xy_plane(), objects.surfaces.xy_plane(),
[[0., 0.], [1., 0.]], [[0., 0.], [1., 0.]],
) )
.build(&objects); .build(&objects)?
.insert(&objects)?;
assert_eq!(1, object.curve_iter().count()); assert_eq!(1, object.curve_iter().count());
assert_eq!(0, object.cycle_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.solid_iter().count());
assert_eq!(0, object.surface_iter().count()); assert_eq!(0, object.surface_iter().count());
assert_eq!(2, object.vertex_iter().count()); assert_eq!(2, object.vertex_iter().count());
Ok(())
} }
#[test] #[test]
@ -535,7 +552,8 @@ mod tests {
let face = Face::partial() let face = Face::partial()
.with_surface(surface) .with_surface(surface)
.with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) .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(); let object = Sketch::builder(&objects).with_faces([face]).build();
assert_eq!(3, object.curve_iter().count()); assert_eq!(3, object.curve_iter().count());
@ -601,7 +619,8 @@ mod tests {
let curve = Curve::partial() let curve = Curve::partial()
.with_surface(Some(surface.clone())) .with_surface(Some(surface.clone()))
.update_as_u_axis() .update_as_u_axis()
.build(&objects)?; .build(&objects)?
.insert(&objects)?;
let global_vertex = objects let global_vertex = objects
.global_vertices .global_vertices
.insert(GlobalVertex::from_position([0., 0., 0.]))?; .insert(GlobalVertex::from_position([0., 0., 0.]))?;

View File

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

View File

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

View File

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

View File

@ -86,7 +86,7 @@ impl PartialCycle {
pub fn build( pub fn build(
mut self, mut self,
objects: &Objects, objects: &Objects,
) -> Result<Handle<Cycle>, ValidationError> { ) -> Result<Cycle, ValidationError> {
// Check that the cycle is closed. This will lead to a panic further // 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 // down anyway, but that panic would be super-confusing. This one should
// be a bit more explicit on what is wrong. // be a bit more explicit on what is wrong.
@ -142,7 +142,7 @@ impl PartialCycle {
half_edges.push(half_edge); 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 /// Build a full [`HalfEdge`] from the partial half-edge
pub fn build( pub fn build(self, objects: &Objects) -> Result<HalfEdge, ValidationError> {
self,
objects: &Objects,
) -> Result<Handle<HalfEdge>, ValidationError> {
let curve = self.curve.into_full(objects)?; let curve = self.curve.into_full(objects)?;
let vertices = self.vertices.try_map_ext(|vertex| { let vertices = self.vertices.try_map_ext(|vertex| {
vertex vertex
@ -120,9 +117,7 @@ impl PartialHalfEdge {
}) })
.into_full(objects)?; .into_full(objects)?;
Ok(objects Ok(HalfEdge::new(vertices, global_form))
.half_edges
.insert(HalfEdge::new(vertices, global_form))?)
} }
} }
@ -202,16 +197,14 @@ impl PartialGlobalEdge {
pub fn build( pub fn build(
self, self,
objects: &Objects, objects: &Objects,
) -> Result<Handle<GlobalEdge>, ValidationError> { ) -> Result<GlobalEdge, ValidationError> {
let curve = self.curve.into_full(objects)?; let curve = self.curve.into_full(objects)?;
let vertices = self let vertices = self
.vertices .vertices
.expect("Can't build `GlobalEdge` without vertices") .expect("Can't build `GlobalEdge` without vertices")
.try_map_ext(|global_vertex| global_vertex.into_full(objects))?; .try_map_ext(|global_vertex| global_vertex.into_full(objects))?;
Ok(objects Ok(GlobalEdge::new(curve, vertices))
.global_edges
.insert(GlobalEdge::new(curve, vertices))?)
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -180,6 +180,7 @@ impl SurfaceVertexValidationError {
mod tests { mod tests {
use crate::{ use crate::{
builder::{CurveBuilder, SurfaceVertexBuilder}, builder::{CurveBuilder, SurfaceVertexBuilder},
insert::Insert,
objects::{Curve, GlobalVertex, Objects, SurfaceVertex, Vertex}, objects::{Curve, GlobalVertex, Objects, SurfaceVertex, Vertex},
partial::HasPartial, partial::HasPartial,
validate::Validate, validate::Validate,
@ -204,7 +205,8 @@ mod tests {
.surface_form() .surface_form()
.to_partial() .to_partial()
.with_surface(Some(objects.surfaces.xz_plane())) .with_surface(Some(objects.surfaces.xz_plane()))
.build(&objects)?, .build(&objects)?
.insert(&objects)?,
); );
assert!(valid.validate().is_ok()); assert!(valid.validate().is_ok());
@ -233,7 +235,8 @@ mod tests {
.to_partial() .to_partial()
.with_position(Some([1., 0.])) .with_position(Some([1., 0.]))
.infer_global_form() .infer_global_form()
.build(&objects)?, .build(&objects)?
.insert(&objects)?,
); );
assert!(valid.validate().is_ok()); 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_interop::{debug::DebugInfo, ext::ArrayExt, mesh::Color};
use fj_kernel::{ use fj_kernel::{
algorithms::reverse::Reverse, algorithms::reverse::Reverse,
insert::Insert,
iter::ObjectIters, iter::ObjectIters,
objects::{Face, Objects, Sketch}, objects::{Face, Objects, Sketch},
partial::HasPartial, partial::HasPartial,
@ -83,7 +84,8 @@ impl Shape for fj::Difference2d {
.with_exterior(exterior) .with_exterior(exterior)
.with_interiors(interiors) .with_interiors(interiors)
.with_color(Color(self.color())) .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_interop::{debug::DebugInfo, mesh::Color};
use fj_kernel::{ use fj_kernel::{
builder::{FaceBuilder, HalfEdgeBuilder}, builder::{FaceBuilder, HalfEdgeBuilder},
insert::Insert,
objects::{Cycle, Face, HalfEdge, Objects, Sketch}, objects::{Cycle, Face, HalfEdge, Objects, Sketch},
partial::HasPartial, partial::HasPartial,
validate::ValidationError, validate::ValidationError,
@ -29,13 +30,15 @@ impl Shape for fj::Sketch {
let half_edge = HalfEdge::partial() let half_edge = HalfEdge::partial()
.with_surface(surface) .with_surface(surface)
.update_as_circle_from_radius(circle.radius(), objects)? .update_as_circle_from_radius(circle.radius(), objects)?
.build(objects)?; .build(objects)?
.insert(objects)?;
let cycle = objects.cycles.insert(Cycle::new([half_edge]))?; let cycle = objects.cycles.insert(Cycle::new([half_edge]))?;
Face::partial() Face::partial()
.with_exterior(cycle) .with_exterior(cycle)
.with_color(Color(self.color())) .with_color(Color(self.color()))
.build(objects)? .build(objects)?
.insert(objects)?
} }
fj::Chain::PolyChain(poly_chain) => { fj::Chain::PolyChain(poly_chain) => {
let points = let points =
@ -46,6 +49,7 @@ impl Shape for fj::Sketch {
.with_exterior_polygon_from_points(points) .with_exterior_polygon_from_points(points)
.with_color(Color(self.color())) .with_color(Color(self.color()))
.build(objects)? .build(objects)?
.insert(objects)?
} }
}; };