mirror of https://github.com/hannobraun/Fornjot
Merge pull request #1310 from hannobraun/partial
Continue cleanup of partial object API
This commit is contained in:
commit
edcd61ffaf
|
@ -92,8 +92,7 @@ mod tests {
|
||||||
.update_as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(surface))
|
.update_as_line_segment_from_points(surface, [[1., -1.], [1., 1.]])
|
||||||
.update_as_line_segment_from_points([[1., -1.], [1., 1.]])
|
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
|
|
||||||
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
|
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
|
||||||
|
@ -117,8 +116,10 @@ mod tests {
|
||||||
.update_as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(surface))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([[-1., -1.], [-1., 1.]])
|
surface,
|
||||||
|
[[-1., -1.], [-1., 1.]],
|
||||||
|
)
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
|
|
||||||
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
|
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
|
||||||
|
@ -142,8 +143,10 @@ mod tests {
|
||||||
.update_as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(surface))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([[-1., -1.], [1., -1.]])
|
surface,
|
||||||
|
[[-1., -1.], [1., -1.]],
|
||||||
|
)
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
|
|
||||||
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
|
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
|
||||||
|
@ -162,8 +165,7 @@ mod tests {
|
||||||
.update_as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(surface))
|
.update_as_line_segment_from_points(surface, [[-1., 0.], [1., 0.]])
|
||||||
.update_as_line_segment_from_points([[-1., 0.], [1., 0.]])
|
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
|
|
||||||
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
|
let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
|
||||||
|
|
|
@ -199,8 +199,10 @@ mod tests {
|
||||||
let objects = Objects::new();
|
let objects = Objects::new();
|
||||||
|
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(objects.surfaces.xy_plane()))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([[0., 0.], [1., 0.]])
|
objects.surfaces.xy_plane(),
|
||||||
|
[[0., 0.], [1., 0.]],
|
||||||
|
)
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
|
|
||||||
let face =
|
let face =
|
||||||
|
@ -210,8 +212,10 @@ mod tests {
|
||||||
let surface = objects.surfaces.xz_plane();
|
let surface = objects.surfaces.xz_plane();
|
||||||
|
|
||||||
let bottom = HalfEdge::partial()
|
let bottom = HalfEdge::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([[0., 0.], [1., 0.]])
|
surface.clone(),
|
||||||
|
[[0., 0.], [1., 0.]],
|
||||||
|
)
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let side_up = HalfEdge::partial()
|
let side_up = HalfEdge::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.with_surface(Some(surface.clone()))
|
||||||
|
|
|
@ -125,8 +125,10 @@ mod tests {
|
||||||
.array_windows_ext()
|
.array_windows_ext()
|
||||||
.map(|&[a, b]| {
|
.map(|&[a, b]| {
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(objects.surfaces.xy_plane()))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([a, b])
|
objects.surfaces.xy_plane(),
|
||||||
|
[a, b],
|
||||||
|
)
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
(half_edge, Color::default()).sweep(UP, &objects)
|
(half_edge, Color::default()).sweep(UP, &objects)
|
||||||
})
|
})
|
||||||
|
@ -167,8 +169,10 @@ mod tests {
|
||||||
.array_windows_ext()
|
.array_windows_ext()
|
||||||
.map(|&[a, b]| {
|
.map(|&[a, b]| {
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(objects.surfaces.xy_plane()))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([a, b])
|
objects.surfaces.xy_plane(),
|
||||||
|
[a, b],
|
||||||
|
)
|
||||||
.build(&objects)?
|
.build(&objects)?
|
||||||
.reverse(&objects)?;
|
.reverse(&objects)?;
|
||||||
(half_edge, Color::default()).sweep(DOWN, &objects)
|
(half_edge, Color::default()).sweep(DOWN, &objects)
|
||||||
|
|
|
@ -191,8 +191,7 @@ mod tests {
|
||||||
(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()
|
||||||
.with_surface(Some(surface))
|
.update_as_line_segment_from_points(surface, [[0., 0.], [0., 1.]])
|
||||||
.update_as_line_segment_from_points([[0., 0.], [0., 1.]])
|
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
assert_eq!(half_edge, expected_half_edge);
|
assert_eq!(half_edge, expected_half_edge);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -12,22 +12,11 @@ impl TransformObject for PartialCycle {
|
||||||
transform: &Transform,
|
transform: &Transform,
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
) -> Result<Self, ValidationError> {
|
) -> Result<Self, ValidationError> {
|
||||||
let surface = self
|
|
||||||
.surface()
|
|
||||||
.map(|surface| surface.transform(transform, objects))
|
|
||||||
.transpose()?;
|
|
||||||
let half_edges = self
|
let half_edges = self
|
||||||
.half_edges()
|
.half_edges()
|
||||||
.map(|edge| {
|
.map(|edge| edge.into_partial().transform(transform, objects))
|
||||||
Ok(edge
|
|
||||||
.into_partial()
|
|
||||||
.transform(transform, objects)?
|
|
||||||
.with_surface(surface.clone()))
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, ValidationError>>()?;
|
.collect::<Result<Vec<_>, ValidationError>>()?;
|
||||||
|
|
||||||
Ok(Self::default()
|
Ok(Self::default().with_half_edges(half_edges))
|
||||||
.with_surface(surface)
|
|
||||||
.with_half_edges(half_edges))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,10 @@ impl TransformObject for PartialHalfEdge {
|
||||||
transform: &Transform,
|
transform: &Transform,
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
) -> Result<Self, ValidationError> {
|
) -> Result<Self, ValidationError> {
|
||||||
let surface = self
|
|
||||||
.surface()
|
|
||||||
.map(|surface| surface.transform(transform, objects))
|
|
||||||
.transpose()?;
|
|
||||||
let curve: MaybePartial<_> = self
|
let curve: MaybePartial<_> = self
|
||||||
.curve()
|
.curve()
|
||||||
.into_partial()
|
.into_partial()
|
||||||
.transform(transform, objects)?
|
.transform(transform, objects)?
|
||||||
.with_surface(surface.clone())
|
|
||||||
.into();
|
.into();
|
||||||
let vertices = self.vertices().try_map_ext(
|
let vertices = self.vertices().try_map_ext(
|
||||||
|vertex| -> Result<_, ValidationError> {
|
|vertex| -> Result<_, ValidationError> {
|
||||||
|
@ -41,7 +36,6 @@ impl TransformObject for PartialHalfEdge {
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
Ok(Self::default()
|
Ok(Self::default()
|
||||||
.with_surface(surface)
|
|
||||||
.with_curve(Some(curve))
|
.with_curve(Some(curve))
|
||||||
.with_vertices(Some(vertices))
|
.with_vertices(Some(vertices))
|
||||||
.with_global_form(global_form))
|
.with_global_form(global_form))
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use fj_math::Point;
|
use fj_math::Point;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{Curve, HalfEdge, SurfaceVertex, Vertex},
|
objects::{Curve, HalfEdge, Surface, SurfaceVertex, Vertex},
|
||||||
partial::{HasPartial, MaybePartial, PartialCycle},
|
partial::{HasPartial, MaybePartial, PartialCycle},
|
||||||
|
storage::Handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{CurveBuilder, HalfEdgeBuilder};
|
use super::{CurveBuilder, HalfEdgeBuilder};
|
||||||
|
@ -18,6 +19,7 @@ pub trait CycleBuilder {
|
||||||
/// Update the partial cycle with a polygonal chain from the provided points
|
/// Update the partial cycle with a polygonal chain from the provided points
|
||||||
fn with_poly_chain_from_points(
|
fn with_poly_chain_from_points(
|
||||||
self,
|
self,
|
||||||
|
surface: Handle<Surface>,
|
||||||
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
||||||
) -> Self;
|
) -> Self;
|
||||||
|
|
||||||
|
@ -49,9 +51,8 @@ impl CycleBuilder for PartialCycle {
|
||||||
let mut half_edges = Vec::new();
|
let mut half_edges = Vec::new();
|
||||||
for vertex_next in iter {
|
for vertex_next in iter {
|
||||||
if let Some(vertex_prev) = previous {
|
if let Some(vertex_prev) = previous {
|
||||||
let surface = self
|
let surface = vertex_prev
|
||||||
.surface()
|
.surface()
|
||||||
.clone()
|
|
||||||
.expect("Need surface to extend cycle with poly-chain");
|
.expect("Need surface to extend cycle with poly-chain");
|
||||||
|
|
||||||
let position_prev = vertex_prev
|
let position_prev = vertex_prev
|
||||||
|
@ -61,12 +62,8 @@ impl CycleBuilder for PartialCycle {
|
||||||
.position()
|
.position()
|
||||||
.expect("Need surface position to extend cycle");
|
.expect("Need surface position to extend cycle");
|
||||||
|
|
||||||
let from = vertex_prev.update_partial(|partial| {
|
let from = vertex_prev;
|
||||||
partial.with_surface(Some(surface.clone()))
|
let to = vertex_next;
|
||||||
});
|
|
||||||
let to = vertex_next.update_partial(|partial| {
|
|
||||||
partial.with_surface(Some(surface.clone()))
|
|
||||||
});
|
|
||||||
|
|
||||||
previous = Some(to.clone());
|
previous = Some(to.clone());
|
||||||
|
|
||||||
|
@ -99,10 +96,13 @@ impl CycleBuilder for PartialCycle {
|
||||||
|
|
||||||
fn with_poly_chain_from_points(
|
fn with_poly_chain_from_points(
|
||||||
self,
|
self,
|
||||||
|
surface: Handle<Surface>,
|
||||||
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.with_poly_chain(points.into_iter().map(|position| {
|
self.with_poly_chain(points.into_iter().map(|position| {
|
||||||
SurfaceVertex::partial().with_position(Some(position))
|
SurfaceVertex::partial()
|
||||||
|
.with_surface(Some(surface.clone()))
|
||||||
|
.with_position(Some(position))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,8 +127,7 @@ impl CycleBuilder for PartialCycle {
|
||||||
|
|
||||||
self.with_half_edges(Some(
|
self.with_half_edges(Some(
|
||||||
HalfEdge::partial()
|
HalfEdge::partial()
|
||||||
.with_surface(Some(surface))
|
.update_as_line_segment_from_points(surface, vertices),
|
||||||
.update_as_line_segment_from_points(vertices),
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use fj_math::{Point, Scalar};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{
|
objects::{
|
||||||
Curve, GlobalVertex, Objects, SurfaceVertex, Vertex,
|
Curve, GlobalVertex, Objects, Surface, SurfaceVertex, Vertex,
|
||||||
VerticesInNormalizedOrder,
|
VerticesInNormalizedOrder,
|
||||||
},
|
},
|
||||||
partial::{HasPartial, PartialGlobalEdge, PartialHalfEdge},
|
partial::{HasPartial, PartialGlobalEdge, PartialHalfEdge},
|
||||||
|
@ -31,6 +31,7 @@ pub trait HalfEdgeBuilder: Sized {
|
||||||
/// Update partial half-edge as a line segment, from the given points
|
/// Update partial half-edge as a line segment, from the given points
|
||||||
fn update_as_line_segment_from_points(
|
fn update_as_line_segment_from_points(
|
||||||
self,
|
self,
|
||||||
|
surface: Handle<Surface>,
|
||||||
points: [impl Into<Point<2>>; 2],
|
points: [impl Into<Point<2>>; 2],
|
||||||
) -> Self;
|
) -> Self;
|
||||||
|
|
||||||
|
@ -44,9 +45,10 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
||||||
radius: impl Into<Scalar>,
|
radius: impl Into<Scalar>,
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
) -> Result<Self, ValidationError> {
|
) -> Result<Self, ValidationError> {
|
||||||
let curve = Curve::partial()
|
let curve = self
|
||||||
|
.curve()
|
||||||
|
.into_partial()
|
||||||
.with_global_form(Some(self.extract_global_curve()))
|
.with_global_form(Some(self.extract_global_curve()))
|
||||||
.with_surface(self.surface())
|
|
||||||
.update_as_circle_from_radius(radius);
|
.update_as_circle_from_radius(radius);
|
||||||
|
|
||||||
let path = curve.path().expect("Expected path that was just created");
|
let path = curve.path().expect("Expected path that was just created");
|
||||||
|
@ -55,7 +57,8 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
||||||
[Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord]));
|
[Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord]));
|
||||||
|
|
||||||
let global_vertex = self
|
let global_vertex = self
|
||||||
.extract_global_vertices()
|
.global_form()
|
||||||
|
.vertices()
|
||||||
.map(|[global_form, _]| global_form)
|
.map(|[global_form, _]| global_form)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
GlobalVertex::partial()
|
GlobalVertex::partial()
|
||||||
|
@ -65,7 +68,7 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
||||||
|
|
||||||
let surface_vertex = SurfaceVertex::partial()
|
let surface_vertex = SurfaceVertex::partial()
|
||||||
.with_position(Some(path.point_from_path_coords(a_curve)))
|
.with_position(Some(path.point_from_path_coords(a_curve)))
|
||||||
.with_surface(self.surface())
|
.with_surface(curve.surface())
|
||||||
.with_global_form(Some(global_vertex))
|
.with_global_form(Some(global_vertex))
|
||||||
.build(objects)?;
|
.build(objects)?;
|
||||||
|
|
||||||
|
@ -83,18 +86,20 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
||||||
|
|
||||||
fn update_as_line_segment_from_points(
|
fn update_as_line_segment_from_points(
|
||||||
self,
|
self,
|
||||||
|
surface: Handle<Surface>,
|
||||||
points: [impl Into<Point<2>>; 2],
|
points: [impl Into<Point<2>>; 2],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let surface = self.surface();
|
|
||||||
let vertices = points.map(|point| {
|
let vertices = points.map(|point| {
|
||||||
let surface_form = SurfaceVertex::partial()
|
let surface_form = SurfaceVertex::partial()
|
||||||
.with_surface(surface.clone())
|
.with_surface(Some(surface.clone()))
|
||||||
.with_position(Some(point));
|
.with_position(Some(point));
|
||||||
|
|
||||||
Vertex::partial().with_surface_form(Some(surface_form))
|
Vertex::partial().with_surface_form(Some(surface_form))
|
||||||
});
|
});
|
||||||
|
|
||||||
self.with_vertices(Some(vertices)).update_as_line_segment()
|
self.with_surface(Some(surface))
|
||||||
|
.with_vertices(Some(vertices))
|
||||||
|
.update_as_line_segment()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_as_line_segment(self) -> Self {
|
fn update_as_line_segment(self) -> Self {
|
||||||
|
@ -103,6 +108,7 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
||||||
[&from, &to].map(|vertex| vertex.surface_form());
|
[&from, &to].map(|vertex| vertex.surface_form());
|
||||||
|
|
||||||
let surface = self
|
let surface = self
|
||||||
|
.curve()
|
||||||
.surface()
|
.surface()
|
||||||
.or_else(|| from_surface.surface())
|
.or_else(|| from_surface.surface())
|
||||||
.or_else(|| to_surface.surface())
|
.or_else(|| to_surface.surface())
|
||||||
|
@ -147,7 +153,8 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
||||||
must_switch_order
|
must_switch_order
|
||||||
};
|
};
|
||||||
|
|
||||||
self.extract_global_vertices()
|
self.global_form()
|
||||||
|
.vertices()
|
||||||
.map(
|
.map(
|
||||||
|[a, b]| {
|
|[a, b]| {
|
||||||
if must_switch_order {
|
if must_switch_order {
|
||||||
|
|
|
@ -50,10 +50,14 @@ impl<'a> FaceBuilder<'a> {
|
||||||
mut self,
|
mut self,
|
||||||
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let surface = self
|
||||||
|
.surface
|
||||||
|
.as_ref()
|
||||||
|
.expect("Need surface to create polygon");
|
||||||
|
|
||||||
self.exterior = Some(
|
self.exterior = Some(
|
||||||
Cycle::partial()
|
Cycle::partial()
|
||||||
.with_surface(self.surface.clone())
|
.with_poly_chain_from_points(surface.clone(), points)
|
||||||
.with_poly_chain_from_points(points)
|
|
||||||
.close_with_line_segment()
|
.close_with_line_segment()
|
||||||
.build(self.objects)
|
.build(self.objects)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
@ -75,10 +79,14 @@ impl<'a> FaceBuilder<'a> {
|
||||||
mut self,
|
mut self,
|
||||||
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let surface = self
|
||||||
|
.surface
|
||||||
|
.as_ref()
|
||||||
|
.expect("Need surface to build polygon.");
|
||||||
|
|
||||||
self.interiors.push(
|
self.interiors.push(
|
||||||
Cycle::partial()
|
Cycle::partial()
|
||||||
.with_surface(self.surface.clone())
|
.with_poly_chain_from_points(surface.clone(), points)
|
||||||
.with_poly_chain_from_points(points)
|
|
||||||
.close_with_line_segment()
|
.close_with_line_segment()
|
||||||
.build(self.objects)
|
.build(self.objects)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
|
|
@ -89,12 +89,11 @@ impl<'a> ShellBuilder<'a> {
|
||||||
.zip(&surfaces)
|
.zip(&surfaces)
|
||||||
.map(|(half_edge, surface)| {
|
.map(|(half_edge, surface)| {
|
||||||
HalfEdge::partial()
|
HalfEdge::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
|
||||||
.with_global_form(Some(half_edge.global_form().clone()))
|
.with_global_form(Some(half_edge.global_form().clone()))
|
||||||
.update_as_line_segment_from_points([
|
.update_as_line_segment_from_points(
|
||||||
[Z, Z],
|
surface.clone(),
|
||||||
[edge_length, Z],
|
[[Z, Z], [edge_length, Z]],
|
||||||
])
|
)
|
||||||
.build(self.objects)
|
.build(self.objects)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
})
|
})
|
||||||
|
@ -188,10 +187,8 @@ impl<'a> ShellBuilder<'a> {
|
||||||
.zip(sides_up)
|
.zip(sides_up)
|
||||||
.zip(tops.clone())
|
.zip(tops.clone())
|
||||||
.zip(sides_down)
|
.zip(sides_down)
|
||||||
.zip(surfaces)
|
.map(|(((bottom, side_up), top), side_down)| {
|
||||||
.map(|((((bottom, side_up), top), side_down), surface)| {
|
|
||||||
let cycle = Cycle::partial()
|
let cycle = Cycle::partial()
|
||||||
.with_surface(Some(surface))
|
|
||||||
.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();
|
.unwrap();
|
||||||
|
|
|
@ -399,8 +399,10 @@ mod tests {
|
||||||
|
|
||||||
let surface = objects.surfaces.xy_plane();
|
let surface = objects.surfaces.xy_plane();
|
||||||
let object = Cycle::partial()
|
let object = Cycle::partial()
|
||||||
.with_surface(Some(surface))
|
.with_poly_chain_from_points(
|
||||||
.with_poly_chain_from_points([[0., 0.], [1., 0.], [0., 1.]])
|
surface,
|
||||||
|
[[0., 0.], [1., 0.], [0., 1.]],
|
||||||
|
)
|
||||||
.close_with_line_segment()
|
.close_with_line_segment()
|
||||||
.build(&objects);
|
.build(&objects);
|
||||||
|
|
||||||
|
@ -485,8 +487,10 @@ mod tests {
|
||||||
let objects = Objects::new();
|
let objects = Objects::new();
|
||||||
|
|
||||||
let object = HalfEdge::partial()
|
let object = HalfEdge::partial()
|
||||||
.with_surface(Some(objects.surfaces.xy_plane()))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([[0., 0.], [1., 0.]])
|
objects.surfaces.xy_plane(),
|
||||||
|
[[0., 0.], [1., 0.]],
|
||||||
|
)
|
||||||
.build(&objects);
|
.build(&objects);
|
||||||
|
|
||||||
assert_eq!(1, object.curve_iter().count());
|
assert_eq!(1, object.curve_iter().count());
|
||||||
|
|
|
@ -165,12 +165,10 @@ mod tests {
|
||||||
let b = [1., 0.];
|
let b = [1., 0.];
|
||||||
|
|
||||||
let a_to_b = HalfEdge::partial()
|
let a_to_b = HalfEdge::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.update_as_line_segment_from_points(surface.clone(), [a, b])
|
||||||
.update_as_line_segment_from_points([a, b])
|
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let b_to_a = HalfEdge::partial()
|
let b_to_a = HalfEdge::partial()
|
||||||
.with_surface(Some(surface))
|
.update_as_line_segment_from_points(surface, [b, a])
|
||||||
.update_as_line_segment_from_points([b, a])
|
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
|
|
||||||
assert_eq!(a_to_b.global_form(), b_to_a.global_form());
|
assert_eq!(a_to_b.global_form(), b_to_a.global_form());
|
||||||
|
|
|
@ -64,6 +64,20 @@ impl<T: HasPartial> MaybePartial<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Merge this `MaybePartial` with another of the same type
|
||||||
|
pub fn merge_with(self, other: Self) -> Self {
|
||||||
|
match (self, other) {
|
||||||
|
(Self::Full(_), Self::Full(_)) => {
|
||||||
|
panic!("Can't merge two full objects")
|
||||||
|
}
|
||||||
|
(Self::Full(full), Self::Partial(_))
|
||||||
|
| (Self::Partial(_), Self::Full(full)) => Self::Full(full),
|
||||||
|
(Self::Partial(a), Self::Partial(b)) => {
|
||||||
|
Self::Partial(a.merge_with(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return or build a full object
|
/// Return or build a full object
|
||||||
///
|
///
|
||||||
/// If this already is a full object, it is returned. If this is a partial
|
/// If this already is a full object, it is returned. If this is a partial
|
||||||
|
@ -160,6 +174,14 @@ impl MaybePartial<GlobalEdge> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MaybePartial<HalfEdge> {
|
impl MaybePartial<HalfEdge> {
|
||||||
|
/// Access the curve
|
||||||
|
pub fn curve(&self) -> MaybePartial<Curve> {
|
||||||
|
match self {
|
||||||
|
Self::Full(full) => full.curve().clone().into(),
|
||||||
|
Self::Partial(partial) => partial.curve(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Access the front vertex
|
/// Access the front vertex
|
||||||
pub fn front(&self) -> MaybePartial<Vertex> {
|
pub fn front(&self) -> MaybePartial<Vertex> {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
mod maybe_partial;
|
mod maybe_partial;
|
||||||
mod objects;
|
mod objects;
|
||||||
mod traits;
|
mod traits;
|
||||||
|
mod util;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
maybe_partial::MaybePartial,
|
maybe_partial::MaybePartial,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{Curve, GlobalCurve, Objects, Surface},
|
objects::{Curve, GlobalCurve, Objects, Surface},
|
||||||
partial::MaybePartial,
|
partial::{util::merge_options, MaybePartial},
|
||||||
path::SurfacePath,
|
path::SurfacePath,
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
|
@ -59,6 +59,26 @@ impl PartialCurve {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Merge this partial object with another
|
||||||
|
pub fn merge_with(self, other: Self) -> Self {
|
||||||
|
// This is harder than it should be, as `global_form` uses the redundant
|
||||||
|
// `Option<MaybePartial<_>>` representation. There's some code relying
|
||||||
|
// on that though, so we have to live with it for now.
|
||||||
|
let global_form = match (self.global_form, other.global_form) {
|
||||||
|
(Some(a), Some(b)) => Some(a.merge_with(b)),
|
||||||
|
(Some(global_form), None) | (None, Some(global_form)) => {
|
||||||
|
Some(global_form)
|
||||||
|
}
|
||||||
|
(None, None) => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
path: merge_options(self.path, other.path),
|
||||||
|
surface: merge_options(self.surface, other.surface),
|
||||||
|
global_form,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a full [`Curve`] from the partial curve
|
/// Build a full [`Curve`] from the partial curve
|
||||||
pub fn build(
|
pub fn build(
|
||||||
self,
|
self,
|
||||||
|
@ -102,6 +122,11 @@ impl From<&Curve> for PartialCurve {
|
||||||
pub struct PartialGlobalCurve;
|
pub struct PartialGlobalCurve;
|
||||||
|
|
||||||
impl PartialGlobalCurve {
|
impl PartialGlobalCurve {
|
||||||
|
/// Merge this partial object with another
|
||||||
|
pub fn merge_with(self, _: Self) -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
/// 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,
|
self,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{Cycle, HalfEdge, Objects, Surface},
|
objects::{Cycle, HalfEdge, Objects, Surface},
|
||||||
partial::MaybePartial,
|
partial::{util::merge_options, MaybePartial},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
@ -10,46 +10,80 @@ use crate::{
|
||||||
/// See [`crate::partial`] for more information.
|
/// See [`crate::partial`] for more information.
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct PartialCycle {
|
pub struct PartialCycle {
|
||||||
surface: Option<Handle<Surface>>,
|
|
||||||
half_edges: Vec<MaybePartial<HalfEdge>>,
|
half_edges: Vec<MaybePartial<HalfEdge>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialCycle {
|
impl PartialCycle {
|
||||||
/// Access the surface that the [`Cycle`] is defined in
|
|
||||||
pub fn surface(&self) -> Option<Handle<Surface>> {
|
|
||||||
self.surface.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Access the half-edges that make up the [`Cycle`]
|
/// Access the half-edges that make up the [`Cycle`]
|
||||||
pub fn half_edges(&self) -> impl Iterator<Item = MaybePartial<HalfEdge>> {
|
pub fn half_edges(&self) -> impl Iterator<Item = MaybePartial<HalfEdge>> {
|
||||||
self.half_edges.clone().into_iter()
|
self.half_edges.clone().into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the partial cycle with the given surface
|
/// Access the surface that the [`Cycle`]'s [`HalfEdge`]s are defined in
|
||||||
pub fn with_surface(mut self, surface: Option<Handle<Surface>>) -> Self {
|
pub fn surface(&self) -> Option<Handle<Surface>> {
|
||||||
if let Some(surface) = surface {
|
self.half_edges
|
||||||
self.surface = Some(surface);
|
.first()
|
||||||
}
|
.and_then(|half_edge| half_edge.curve().surface())
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the partial cycle with the given half-edges
|
/// Add the provided half-edges to the partial cycle
|
||||||
|
///
|
||||||
|
/// This will merge all the surfaces of the added half-edges. All added
|
||||||
|
/// half-edges will end up with the same merged surface.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics, if the surfaces can't be merged.
|
||||||
pub fn with_half_edges(
|
pub fn with_half_edges(
|
||||||
mut self,
|
mut self,
|
||||||
half_edges: impl IntoIterator<Item = impl Into<MaybePartial<HalfEdge>>>,
|
half_edges: impl IntoIterator<Item = impl Into<MaybePartial<HalfEdge>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.half_edges
|
let half_edges = half_edges.into_iter().map(Into::into);
|
||||||
.extend(half_edges.into_iter().map(Into::into));
|
|
||||||
|
let mut surface = self.surface();
|
||||||
|
for half_edge in half_edges {
|
||||||
|
surface = merge_options(surface, half_edge.curve().surface());
|
||||||
|
self.half_edges.push(half_edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.with_surface(surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the partial cycle with the provided surface
|
||||||
|
///
|
||||||
|
/// All [`HalfEdge`]s will be updated with this surface.
|
||||||
|
pub fn with_surface(mut self, surface: Option<Handle<Surface>>) -> Self {
|
||||||
|
if let Some(surface) = surface {
|
||||||
|
for half_edge in &mut self.half_edges {
|
||||||
|
*half_edge = half_edge.clone().update_partial(|half_edge| {
|
||||||
|
half_edge.with_surface(Some(surface.clone()))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Merge this partial object with another
|
||||||
|
pub fn merge_with(self, other: Self) -> Self {
|
||||||
|
let a_is_empty = self.half_edges.is_empty();
|
||||||
|
let b_is_empty = other.half_edges.is_empty();
|
||||||
|
let half_edges = match (a_is_empty, b_is_empty) {
|
||||||
|
(true, true) => {
|
||||||
|
panic!("Can't merge `PartialHalfEdge`, if both have half-edges")
|
||||||
|
}
|
||||||
|
(true, false) => self.half_edges,
|
||||||
|
(false, true) => other.half_edges,
|
||||||
|
(false, false) => self.half_edges, // doesn't matter which we use
|
||||||
|
};
|
||||||
|
|
||||||
|
Self { half_edges }
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a full [`Cycle`] from the partial cycle
|
/// Build a full [`Cycle`] from the partial cycle
|
||||||
pub fn build(
|
pub fn build(
|
||||||
mut self,
|
mut self,
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
) -> Result<Handle<Cycle>, ValidationError> {
|
) -> Result<Handle<Cycle>, ValidationError> {
|
||||||
let surface = self.surface.expect("Need surface to build `Cycle`");
|
|
||||||
let surface_for_edges = surface.clone();
|
|
||||||
let half_edges = {
|
let half_edges = {
|
||||||
let last_vertex = self
|
let last_vertex = self
|
||||||
.half_edges
|
.half_edges
|
||||||
|
@ -65,11 +99,7 @@ impl PartialCycle {
|
||||||
.map(|(half_edge, vertex, surface_vertex)|
|
.map(|(half_edge, vertex, surface_vertex)|
|
||||||
-> Result<_, ValidationError>
|
-> Result<_, ValidationError>
|
||||||
{
|
{
|
||||||
let surface_vertex = surface_vertex
|
let surface_vertex = surface_vertex.into_full(objects)?;
|
||||||
.update_partial(|surface_vertex| {
|
|
||||||
surface_vertex.with_surface(Some(surface.clone()))
|
|
||||||
})
|
|
||||||
.into_full(objects)?;
|
|
||||||
|
|
||||||
*half_edge =
|
*half_edge =
|
||||||
half_edge.clone().update_partial(|half_edge| {
|
half_edge.clone().update_partial(|half_edge| {
|
||||||
|
@ -98,9 +128,7 @@ impl PartialCycle {
|
||||||
partial.with_surface_form(previous_vertex)
|
partial.with_surface_form(previous_vertex)
|
||||||
});
|
});
|
||||||
|
|
||||||
half_edge
|
half_edge.with_back_vertex(Some(back))
|
||||||
.with_surface(Some(surface_for_edges.clone()))
|
|
||||||
.with_back_vertex(Some(back))
|
|
||||||
})
|
})
|
||||||
.into_full(objects)?;
|
.into_full(objects)?;
|
||||||
|
|
||||||
|
@ -121,7 +149,6 @@ impl PartialCycle {
|
||||||
impl From<&Cycle> for PartialCycle {
|
impl From<&Cycle> for PartialCycle {
|
||||||
fn from(cycle: &Cycle) -> Self {
|
fn from(cycle: &Cycle) -> Self {
|
||||||
Self {
|
Self {
|
||||||
surface: Some(cycle.surface().clone()),
|
|
||||||
half_edges: cycle.half_edges().cloned().map(Into::into).collect(),
|
half_edges: cycle.half_edges().cloned().map(Into::into).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
||||||
Surface, Vertex,
|
Surface, Vertex,
|
||||||
},
|
},
|
||||||
partial::MaybePartial,
|
partial::{util::merge_arrays, MaybePartial},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
@ -16,18 +16,12 @@ use crate::{
|
||||||
/// See [`crate::partial`] for more information.
|
/// See [`crate::partial`] for more information.
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct PartialHalfEdge {
|
pub struct PartialHalfEdge {
|
||||||
surface: Option<Handle<Surface>>,
|
|
||||||
curve: MaybePartial<Curve>,
|
curve: MaybePartial<Curve>,
|
||||||
vertices: [MaybePartial<Vertex>; 2],
|
vertices: [MaybePartial<Vertex>; 2],
|
||||||
global_form: MaybePartial<GlobalEdge>,
|
global_form: MaybePartial<GlobalEdge>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialHalfEdge {
|
impl PartialHalfEdge {
|
||||||
/// Access the surface that the [`HalfEdge`]'s [`Curve`] is defined in
|
|
||||||
pub fn surface(&self) -> Option<Handle<Surface>> {
|
|
||||||
self.surface.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Access the curve that the [`HalfEdge`] is defined in
|
/// Access the curve that the [`HalfEdge`] is defined in
|
||||||
pub fn curve(&self) -> MaybePartial<Curve> {
|
pub fn curve(&self) -> MaybePartial<Curve> {
|
||||||
self.curve.clone()
|
self.curve.clone()
|
||||||
|
@ -52,17 +46,24 @@ impl PartialHalfEdge {
|
||||||
.unwrap_or_else(|| self.global_form.curve())
|
.unwrap_or_else(|| self.global_form.curve())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the vertices of the global form, if available
|
|
||||||
pub fn extract_global_vertices(
|
|
||||||
&self,
|
|
||||||
) -> Option<[MaybePartial<GlobalVertex>; 2]> {
|
|
||||||
self.global_form.vertices()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update the partial half-edge with the given surface
|
/// Update the partial half-edge with the given surface
|
||||||
pub fn with_surface(mut self, surface: Option<Handle<Surface>>) -> Self {
|
pub fn with_surface(mut self, surface: Option<Handle<Surface>>) -> Self {
|
||||||
if let Some(surface) = surface {
|
if let Some(surface) = surface {
|
||||||
self.surface = Some(surface);
|
self.curve = self.curve.update_partial(|curve| {
|
||||||
|
curve.with_surface(Some(surface.clone()))
|
||||||
|
});
|
||||||
|
|
||||||
|
self.vertices = self.vertices.map(|vertex| {
|
||||||
|
vertex.update_partial(|vertex| {
|
||||||
|
let surface_form = vertex.surface_form().update_partial(
|
||||||
|
|surface_vertex| {
|
||||||
|
surface_vertex.with_surface(Some(surface.clone()))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
vertex.with_surface_form(Some(surface_form))
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -78,7 +79,7 @@ impl PartialHalfEdge {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the partial half-edge with the given from vertex
|
/// Update the partial half-edge with the given back vertex
|
||||||
pub fn with_back_vertex(
|
pub fn with_back_vertex(
|
||||||
mut self,
|
mut self,
|
||||||
vertex: Option<impl Into<MaybePartial<Vertex>>>,
|
vertex: Option<impl Into<MaybePartial<Vertex>>>,
|
||||||
|
@ -90,7 +91,7 @@ impl PartialHalfEdge {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the partial half-edge with the given from vertex
|
/// Update the partial half-edge with the given front vertex
|
||||||
pub fn with_front_vertex(
|
pub fn with_front_vertex(
|
||||||
mut self,
|
mut self,
|
||||||
vertex: Option<impl Into<MaybePartial<Vertex>>>,
|
vertex: Option<impl Into<MaybePartial<Vertex>>>,
|
||||||
|
@ -125,16 +126,21 @@ impl PartialHalfEdge {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Merge this partial object with another
|
||||||
|
pub fn merge_with(self, other: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
curve: self.curve.merge_with(other.curve),
|
||||||
|
vertices: merge_arrays(self.vertices, other.vertices),
|
||||||
|
global_form: self.global_form.merge_with(other.global_form),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 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,
|
self,
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
) -> Result<Handle<HalfEdge>, ValidationError> {
|
) -> Result<Handle<HalfEdge>, ValidationError> {
|
||||||
let surface = self.surface;
|
let curve = self.curve.into_full(objects)?;
|
||||||
let curve = self
|
|
||||||
.curve
|
|
||||||
.update_partial(|curve| curve.with_surface(surface))
|
|
||||||
.into_full(objects)?;
|
|
||||||
let vertices = self.vertices.try_map_ext(|vertex| {
|
let vertices = self.vertices.try_map_ext(|vertex| {
|
||||||
vertex
|
vertex
|
||||||
.update_partial(|vertex| vertex.with_curve(Some(curve.clone())))
|
.update_partial(|vertex| vertex.with_curve(Some(curve.clone())))
|
||||||
|
@ -160,7 +166,6 @@ impl From<&HalfEdge> for PartialHalfEdge {
|
||||||
half_edge.vertices().clone().map(Into::into);
|
half_edge.vertices().clone().map(Into::into);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
surface: Some(half_edge.curve().surface().clone()),
|
|
||||||
curve: half_edge.curve().clone().into(),
|
curve: half_edge.curve().clone().into(),
|
||||||
vertices: [back_vertex, front_vertex],
|
vertices: [back_vertex, front_vertex],
|
||||||
global_form: half_edge.global_form().clone().into(),
|
global_form: half_edge.global_form().clone().into(),
|
||||||
|
@ -210,6 +215,23 @@ impl PartialGlobalEdge {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Merge this partial object with another
|
||||||
|
pub fn merge_with(self, other: Self) -> Self {
|
||||||
|
// This is harder than it needs to be, because `vertices` uses the
|
||||||
|
// redundant combination of `Option` and `MaybePartial`. There's some
|
||||||
|
// code relying on that, however, so we have to live with it for now.
|
||||||
|
let vertices = match (self.vertices, other.vertices) {
|
||||||
|
(Some(a), Some(b)) => Some(merge_arrays(a, b)),
|
||||||
|
(Some(vertices), None) | (None, Some(vertices)) => Some(vertices),
|
||||||
|
(None, None) => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
curve: self.curve.merge_with(other.curve),
|
||||||
|
vertices,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a full [`GlobalEdge`] from the partial global edge
|
/// Build a full [`GlobalEdge`] from the partial global edge
|
||||||
pub fn build(
|
pub fn build(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -27,6 +27,10 @@ macro_rules! impl_traits {
|
||||||
impl Partial for $partial {
|
impl Partial for $partial {
|
||||||
type Full = $full;
|
type Full = $full;
|
||||||
|
|
||||||
|
fn merge_with(self, other: Self) -> Self {
|
||||||
|
self.merge_with(other)
|
||||||
|
}
|
||||||
|
|
||||||
fn build(self, objects: &Objects)
|
fn build(self, objects: &Objects)
|
||||||
-> Result<
|
-> Result<
|
||||||
Handle<Self::Full>,
|
Handle<Self::Full>,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use fj_math::Point;
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::GlobalVertexBuilder,
|
builder::GlobalVertexBuilder,
|
||||||
objects::{Curve, GlobalVertex, Objects, Surface, SurfaceVertex, Vertex},
|
objects::{Curve, GlobalVertex, Objects, Surface, SurfaceVertex, Vertex},
|
||||||
partial::MaybePartial,
|
partial::{util::merge_options, MaybePartial},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
@ -67,6 +67,15 @@ impl PartialVertex {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Merge this partial object with another
|
||||||
|
pub fn merge_with(self, other: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
position: merge_options(self.position, other.position),
|
||||||
|
curve: self.curve.merge_with(other.curve),
|
||||||
|
surface_form: self.surface_form.merge_with(other.surface_form),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a full [`Vertex`] from the partial vertex
|
/// Build a full [`Vertex`] from the partial vertex
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
|
@ -170,6 +179,15 @@ impl PartialSurfaceVertex {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Merge this partial object with another
|
||||||
|
pub fn merge_with(self, other: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
position: merge_options(self.position, other.position),
|
||||||
|
surface: merge_options(self.surface, other.surface),
|
||||||
|
global_form: self.global_form.merge_with(other.global_form),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a full [`SurfaceVertex`] from the partial surface vertex
|
/// Build a full [`SurfaceVertex`] from the partial surface vertex
|
||||||
pub fn build(
|
pub fn build(
|
||||||
self,
|
self,
|
||||||
|
@ -232,6 +250,13 @@ impl PartialGlobalVertex {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Merge this partial object with another
|
||||||
|
pub fn merge_with(self, other: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
position: merge_options(self.position, other.position),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 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,
|
self,
|
||||||
|
|
|
@ -68,6 +68,9 @@ pub trait Partial: Default + for<'a> From<&'a Self::Full> {
|
||||||
/// The type representing the full variant of this object
|
/// The type representing the full variant of this object
|
||||||
type Full;
|
type Full;
|
||||||
|
|
||||||
|
/// Merge another partial object of the same type into this one
|
||||||
|
fn merge_with(self, other: Self) -> Self;
|
||||||
|
|
||||||
/// Build a full object from this partial one
|
/// Build a full object from this partial one
|
||||||
///
|
///
|
||||||
/// Implementations of this method will typically try to infer any missing
|
/// Implementations of this method will typically try to infer any missing
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
use fj_interop::ext::ArrayExt;
|
||||||
|
|
||||||
|
use super::{HasPartial, MaybePartial};
|
||||||
|
|
||||||
|
pub fn merge_options<T>(a: Option<T>, b: Option<T>) -> Option<T>
|
||||||
|
where
|
||||||
|
T: Eq,
|
||||||
|
{
|
||||||
|
if a == b {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know that `a != b`, or we wouldn't have made it here.
|
||||||
|
if a.is_some() && b.is_some() {
|
||||||
|
panic!("Can't merge `Option`s if both are defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
a.xor(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn merge_arrays<T: HasPartial>(
|
||||||
|
a: [MaybePartial<T>; 2],
|
||||||
|
b: [MaybePartial<T>; 2],
|
||||||
|
) -> [MaybePartial<T>; 2] {
|
||||||
|
a.zip_ext(b).map(|(a, b)| a.merge_with(b))
|
||||||
|
}
|
|
@ -207,8 +207,10 @@ mod tests {
|
||||||
let objects = Objects::new();
|
let objects = Objects::new();
|
||||||
|
|
||||||
let valid = HalfEdge::partial()
|
let valid = HalfEdge::partial()
|
||||||
.with_surface(Some(objects.surfaces.xy_plane()))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([[0., 0.], [1., 0.]])
|
objects.surfaces.xy_plane(),
|
||||||
|
[[0., 0.], [1., 0.]],
|
||||||
|
)
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let invalid = {
|
let invalid = {
|
||||||
let mut vertices = valid.vertices().clone();
|
let mut vertices = valid.vertices().clone();
|
||||||
|
@ -232,8 +234,10 @@ mod tests {
|
||||||
let objects = Objects::new();
|
let objects = Objects::new();
|
||||||
|
|
||||||
let valid = HalfEdge::partial()
|
let valid = HalfEdge::partial()
|
||||||
.with_surface(Some(objects.surfaces.xy_plane()))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([[0., 0.], [1., 0.]])
|
objects.surfaces.xy_plane(),
|
||||||
|
[[0., 0.], [1., 0.]],
|
||||||
|
)
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let invalid = HalfEdge::new(
|
let invalid = HalfEdge::new(
|
||||||
valid.vertices().clone(),
|
valid.vertices().clone(),
|
||||||
|
@ -255,8 +259,10 @@ mod tests {
|
||||||
let objects = Objects::new();
|
let objects = Objects::new();
|
||||||
|
|
||||||
let valid = HalfEdge::partial()
|
let valid = HalfEdge::partial()
|
||||||
.with_surface(Some(objects.surfaces.xy_plane()))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([[0., 0.], [1., 0.]])
|
objects.surfaces.xy_plane(),
|
||||||
|
[[0., 0.], [1., 0.]],
|
||||||
|
)
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let invalid = HalfEdge::new(
|
let invalid = HalfEdge::new(
|
||||||
valid.vertices().clone(),
|
valid.vertices().clone(),
|
||||||
|
@ -285,8 +291,10 @@ mod tests {
|
||||||
let objects = Objects::new();
|
let objects = Objects::new();
|
||||||
|
|
||||||
let valid = HalfEdge::partial()
|
let valid = HalfEdge::partial()
|
||||||
.with_surface(Some(objects.surfaces.xy_plane()))
|
.update_as_line_segment_from_points(
|
||||||
.update_as_line_segment_from_points([[0., 0.], [1., 0.]])
|
objects.surfaces.xy_plane(),
|
||||||
|
[[0., 0.], [1., 0.]],
|
||||||
|
)
|
||||||
.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| {
|
||||||
|
|
Loading…
Reference in New Issue