Separate building and inserting objects

This provides more flexibility, making it possible to use the partial
object and builder infrastructure, without automatically opting into
validation. This can be useful, especially in unit tests.
This commit is contained in:
Hanno Braun 2022-11-09 22:22:42 +01:00
parent 7758f81748
commit 3f2aa6e6f2
30 changed files with 220 additions and 139 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,11 +124,13 @@ mod tests {
let intersection = FaceFaceIntersection::compute([&a, &b], &objects)?;
let expected_curves = surfaces.try_map_ext(|surface| {
Curve::partial()
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)
.build(&objects)?
.insert(&objects)?)
})?;
let expected_intervals =
CurveFaceIntersection::from_intervals([[[-1.], [1.]]]);

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

@ -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,
@ -378,7 +379,8 @@ mod tests {
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());
@ -406,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());
@ -431,7 +434,8 @@ mod tests {
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());
@ -501,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());
@ -547,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());
@ -613,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

@ -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::{
use crate::objects::{
Curve, Cycle, Face, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge,
Objects, SurfaceVertex, Vertex,
},
storage::Handle,
};
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
valid.vertices().clone().try_map_ext(
|vertex| -> anyhow::Result<_, ValidationError> {
Ok(vertex
.to_partial()
.with_position(Some([0.]))
.infer_surface_form()
.build(&objects)
})?,
.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)?
}
};