Merge pull request #1312 from hannobraun/partial

Continue cleanup of partial object API
This commit is contained in:
Hanno Braun 2022-11-05 22:19:09 +01:00 committed by GitHub
commit 19f802b57e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 166 additions and 206 deletions

View File

@ -208,7 +208,8 @@ mod tests {
let face = let face =
(half_edge, Color::default()).sweep([0., 0., 1.], &objects)?; (half_edge, Color::default()).sweep([0., 0., 1.], &objects)?;
let expected_face = { let expected_face =
{
let surface = objects.surfaces.xz_plane(); let surface = objects.surfaces.xz_plane();
let bottom = HalfEdge::partial() let bottom = HalfEdge::partial()
@ -218,38 +219,35 @@ mod tests {
) )
.build(&objects)?; .build(&objects)?;
let side_up = HalfEdge::partial() let side_up = HalfEdge::partial()
.with_surface(Some(surface.clone())) .with_surface(surface.clone())
.with_back_vertex(Some(Vertex::partial().with_surface_form( .with_back_vertex(Vertex::partial().with_surface_form(
Some(bottom.front().surface_form().clone()), bottom.front().surface_form().clone(),
))) ))
.with_front_vertex(Some(Vertex::partial().with_surface_form( .with_front_vertex(Vertex::partial().with_surface_form(
Some(
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)?;
let top = HalfEdge::partial() let top = HalfEdge::partial()
.with_surface(Some(surface.clone())) .with_surface(surface.clone())
.with_back_vertex(Some(Vertex::partial().with_surface_form( .with_back_vertex(Vertex::partial().with_surface_form(
Some(
SurfaceVertex::partial().with_position(Some([0., 1.])), SurfaceVertex::partial().with_position(Some([0., 1.])),
), ))
))) .with_front_vertex(Vertex::partial().with_surface_form(
.with_front_vertex(Some(Vertex::partial().with_surface_form( side_up.front().surface_form().clone(),
Some(side_up.front().surface_form().clone()), ))
)))
.update_as_line_segment() .update_as_line_segment()
.build(&objects)? .build(&objects)?
.reverse(&objects)?; .reverse(&objects)?;
let side_down = HalfEdge::partial() let side_down =
.with_surface(Some(surface)) HalfEdge::partial()
.with_back_vertex(Some(Vertex::partial().with_surface_form( .with_surface(surface)
Some(bottom.back().surface_form().clone()), .with_back_vertex(Vertex::partial().with_surface_form(
))) bottom.back().surface_form().clone(),
.with_front_vertex(Some(Vertex::partial().with_surface_form( ))
Some(top.front().surface_form().clone()), .with_front_vertex(Vertex::partial().with_surface_form(
))) top.front().surface_form().clone(),
))
.update_as_line_segment() .update_as_line_segment()
.build(&objects)? .build(&objects)?
.reverse(&objects)?; .reverse(&objects)?;

View File

@ -184,7 +184,7 @@ mod tests {
.build(&objects)?; .build(&objects)?;
let vertex = Vertex::partial() let vertex = Vertex::partial()
.with_position(Some([0.])) .with_position(Some([0.]))
.with_curve(Some(curve)) .with_curve(curve)
.build(&objects)?; .build(&objects)?;
let half_edge = let half_edge =

View File

@ -25,19 +25,18 @@ impl TransformObject for PartialHalfEdge {
Ok(vertex Ok(vertex
.into_partial() .into_partial()
.transform(transform, objects)? .transform(transform, objects)?
.with_curve(Some(curve.clone()))) .with_curve(curve.clone()))
}, },
)?; )?;
let global_form = self let global_form = self
.global_form() .global_form()
.into_partial() .into_partial()
.transform(transform, objects)? .transform(transform, objects)?
.with_curve(curve.global_form()) .with_curve(curve.global_form());
.into();
Ok(Self::default() Ok(Self::default()
.with_curve(Some(curve)) .with_curve(curve)
.with_vertices(Some(vertices)) .with_vertices(vertices)
.with_global_form(global_form)) .with_global_form(global_form))
} }
} }

View File

@ -18,14 +18,13 @@ impl TransformObject for PartialVertex {
let surface_form = self let surface_form = self
.surface_form() .surface_form()
.into_partial() .into_partial()
.transform(transform, objects)? .transform(transform, objects)?;
.into();
// Don't need to transform `self.position`, as that is in curve // Don't need to transform `self.position`, as that is in curve
// coordinates and thus transforming the curve takes care of it. // coordinates and thus transforming the curve takes care of it.
Ok(Self::default() Ok(Self::default()
.with_position(self.position()) .with_position(self.position())
.with_curve(Some(curve)) .with_curve(curve)
.with_surface_form(surface_form)) .with_surface_form(surface_form))
} }
} }

View File

@ -74,15 +74,15 @@ impl CycleBuilder for PartialCycle {
let [from, to] = let [from, to] =
[(0., from), (1., to)].map(|(position, surface_form)| { [(0., from), (1., to)].map(|(position, surface_form)| {
Vertex::partial() Vertex::partial()
.with_curve(Some(curve.clone())) .with_curve(curve.clone())
.with_position(Some([position])) .with_position(Some([position]))
.with_surface_form(Some(surface_form)) .with_surface_form(surface_form)
}); });
half_edges.push( half_edges.push(
HalfEdge::partial() HalfEdge::partial()
.with_curve(Some(curve)) .with_curve(curve)
.with_vertices(Some([from, to])), .with_vertices([from, to]),
); );
continue; continue;

View File

@ -75,13 +75,11 @@ impl HalfEdgeBuilder for PartialHalfEdge {
let [back, front] = [a_curve, b_curve].map(|point_curve| { let [back, front] = [a_curve, b_curve].map(|point_curve| {
Vertex::partial() Vertex::partial()
.with_position(Some(point_curve)) .with_position(Some(point_curve))
.with_curve(Some(curve.clone())) .with_curve(curve.clone())
.with_surface_form(Some(surface_vertex.clone())) .with_surface_form(surface_vertex.clone())
}); });
Ok(self Ok(self.with_curve(curve).with_vertices([back, front]))
.with_curve(Some(curve))
.with_vertices(Some([back, front])))
} }
fn update_as_line_segment_from_points( fn update_as_line_segment_from_points(
@ -94,11 +92,11 @@ impl HalfEdgeBuilder for PartialHalfEdge {
.with_surface(Some(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(surface_form)
}); });
self.with_surface(Some(surface)) self.with_surface(surface)
.with_vertices(Some(vertices)) .with_vertices(vertices)
.update_as_line_segment() .update_as_line_segment()
} }
@ -129,7 +127,7 @@ impl HalfEdgeBuilder for PartialHalfEdge {
vertex.update_partial(|vertex| { vertex.update_partial(|vertex| {
vertex vertex
.with_position(Some([position])) .with_position(Some([position]))
.with_curve(Some(curve.clone())) .with_curve(curve.clone())
}) })
}); });
@ -170,19 +168,18 @@ impl HalfEdgeBuilder for PartialHalfEdge {
vertices.zip_ext(global_forms).map(|(vertex, global_form)| { vertices.zip_ext(global_forms).map(|(vertex, global_form)| {
vertex.update_partial(|vertex| { vertex.update_partial(|vertex| {
vertex.clone().with_surface_form(Some( vertex.clone().with_surface_form(
vertex.surface_form().update_partial( vertex.surface_form().update_partial(
|surface_vertex| { |surface_vertex| {
surface_vertex.with_global_form(global_form) surface_vertex.with_global_form(global_form)
}, },
), ),
)) )
}) })
}) })
}; };
self.with_curve(Some(curve)) self.with_curve(curve).with_vertices([back, front])
.with_vertices(Some([back, front]))
} }
} }

View File

@ -89,7 +89,7 @@ impl<'a> ShellBuilder<'a> {
.zip(&surfaces) .zip(&surfaces)
.map(|(half_edge, surface)| { .map(|(half_edge, surface)| {
HalfEdge::partial() HalfEdge::partial()
.with_global_form(Some(half_edge.global_form().clone())) .with_global_form(half_edge.global_form().clone())
.update_as_line_segment_from_points( .update_as_line_segment_from_points(
surface.clone(), surface.clone(),
[[Z, Z], [edge_length, Z]], [[Z, Z], [edge_length, Z]],
@ -112,10 +112,10 @@ impl<'a> ShellBuilder<'a> {
.with_surface(Some(surface.clone())); .with_surface(Some(surface.clone()));
HalfEdge::partial() HalfEdge::partial()
.with_vertices(Some([ .with_vertices([
Vertex::partial().with_surface_form(Some(from)), Vertex::partial().with_surface_form(from),
Vertex::partial().with_surface_form(Some(to)), Vertex::partial().with_surface_form(to),
])) ])
.update_as_line_segment() .update_as_line_segment()
.build(self.objects) .build(self.objects)
.unwrap() .unwrap()
@ -148,11 +148,11 @@ impl<'a> ShellBuilder<'a> {
)); ));
HalfEdge::partial() HalfEdge::partial()
.with_curve(Some(curve)) .with_curve(curve)
.with_vertices(Some([ .with_vertices([
Vertex::partial().with_surface_form(Some(from)), Vertex::partial().with_surface_form(from),
Vertex::partial().with_surface_form(Some(to)), Vertex::partial().with_surface_form(to),
])) ])
.update_as_line_segment() .update_as_line_segment()
.build(self.objects) .build(self.objects)
.unwrap() .unwrap()
@ -171,11 +171,11 @@ impl<'a> ShellBuilder<'a> {
let from = from.surface_form().clone(); let from = from.surface_form().clone();
let to = to.surface_form().clone(); let to = to.surface_form().clone();
let from = Vertex::partial().with_surface_form(Some(from)); let from = Vertex::partial().with_surface_form(from);
let to = Vertex::partial().with_surface_form(Some(to)); let to = Vertex::partial().with_surface_form(to);
HalfEdge::partial() HalfEdge::partial()
.with_vertices(Some([from, to])) .with_vertices([from, to])
.update_as_line_segment() .update_as_line_segment()
.build(self.objects) .build(self.objects)
.unwrap() .unwrap()
@ -246,13 +246,13 @@ impl<'a> ShellBuilder<'a> {
.map(|(vertex, surface_form)| { .map(|(vertex, surface_form)| {
Vertex::partial() Vertex::partial()
.with_position(Some(vertex.position())) .with_position(Some(vertex.position()))
.with_surface_form(Some(surface_form)) .with_surface_form(surface_form)
}); });
edges.push( edges.push(
HalfEdge::partial() HalfEdge::partial()
.with_vertices(Some(vertices)) .with_vertices(vertices)
.with_global_form(Some(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(), .unwrap(),

View File

@ -16,7 +16,7 @@ pub trait VertexBuilder {
impl VertexBuilder for PartialVertex { impl VertexBuilder for PartialVertex {
fn infer_surface_form(self) -> Self { fn infer_surface_form(self) -> Self {
self.with_surface_form(Some(PartialSurfaceVertex::default())) self.with_surface_form(PartialSurfaceVertex::default())
} }
} }

View File

@ -65,8 +65,8 @@ impl<T: HasPartial> MaybePartial<T> {
} }
/// Merge this `MaybePartial` with another of the same type /// Merge this `MaybePartial` with another of the same type
pub fn merge_with(self, other: Self) -> Self { pub fn merge_with(self, other: impl Into<Self>) -> Self {
match (self, other) { match (self, other.into()) {
(Self::Full(_), Self::Full(_)) => { (Self::Full(_), Self::Full(_)) => {
panic!("Can't merge two full objects") panic!("Can't merge two full objects")
} }

View File

@ -1,6 +1,8 @@
use crate::{ use crate::{
objects::{Cycle, HalfEdge, Objects, Surface}, objects::{Cycle, HalfEdge, Objects, Surface},
partial::{util::merge_options, MaybePartial}, partial::{
util::merge_options, MaybePartial, PartialHalfEdge, PartialVertex,
},
storage::Handle, storage::Handle,
validate::ValidationError, validate::ValidationError,
}; };
@ -56,7 +58,7 @@ impl PartialCycle {
if let Some(surface) = surface { if let Some(surface) = surface {
for half_edge in &mut self.half_edges { for half_edge in &mut self.half_edges {
*half_edge = half_edge.clone().update_partial(|half_edge| { *half_edge = half_edge.clone().update_partial(|half_edge| {
half_edge.with_surface(Some(surface.clone())) half_edge.with_surface(surface.clone())
}); });
} }
} }
@ -84,63 +86,47 @@ impl PartialCycle {
mut self, mut self,
objects: &Objects, objects: &Objects,
) -> Result<Handle<Cycle>, ValidationError> { ) -> Result<Handle<Cycle>, ValidationError> {
let half_edges = { // To create a cycle, we need to make sure that all its half-edges
let last_vertex = self // connect to each other. Let's start with all the connections between
.half_edges // the first and the last half-edge.
.last_mut() let mut previous_vertex = None;
.map(|half_edge| { for half_edge in &mut self.half_edges {
let vertex = half_edge.front(); let back_vertex = previous_vertex.unwrap_or_default();
(half_edge, vertex) let front_vertex =
}) half_edge.front().surface_form().into_full(objects)?;
.map(|(half_edge, vertex)| {
let surface_vertex = vertex.surface_form();
(half_edge, vertex, surface_vertex)
})
.map(|(half_edge, vertex, surface_vertex)|
-> Result<_, ValidationError>
{
let surface_vertex = surface_vertex.into_full(objects)?;
*half_edge = *half_edge = half_edge.clone().merge_with(
half_edge.clone().update_partial(|half_edge| { PartialHalfEdge::default()
half_edge.with_front_vertex(Some( .with_back_vertex(
vertex.update_partial(|vertex| { PartialVertex::default().with_surface_form(back_vertex),
vertex.with_surface_form(Some( )
surface_vertex.clone(), .with_front_vertex(
)) PartialVertex::default()
}), .with_surface_form(front_vertex.clone()),
)) ),
}); );
Ok(surface_vertex) previous_vertex = Some(MaybePartial::from(front_vertex));
}) }
.transpose()?;
let (half_edges, _) = self.half_edges.into_iter().fold( // We're not quite done yet. We need to close the cycle, by connecting
Ok((Vec::new(), last_vertex)), // the last half-edge back around to the first one.
|result: Result<_, ValidationError>, half_edge| { if let Some(half_edge) = self.half_edges.first_mut() {
let (mut half_edges, previous_vertex) = result?; let back_vertex = previous_vertex.unwrap_or_default();
let half_edge = half_edge *half_edge = half_edge.clone().merge_with(
.update_partial(|half_edge| { PartialHalfEdge::default().with_back_vertex(
let [back, _] = half_edge.vertices(); PartialVertex::default().with_surface_form(back_vertex),
let back = back.update_partial(|partial| { ),
partial.with_surface_form(previous_vertex) );
}); }
half_edge.with_back_vertex(Some(back)) // All connections made! All that's left is to build the half-edges.
}) let mut half_edges = Vec::new();
.into_full(objects)?; for half_edge in self.half_edges {
let half_edge = half_edge.into_full(objects)?;
let front = half_edge.front().surface_form().clone();
half_edges.push(half_edge); half_edges.push(half_edge);
}
Ok((half_edges, Some(front)))
},
)?;
half_edges
};
Ok(objects.cycles.insert(Cycle::new(half_edges))?) Ok(objects.cycles.insert(Cycle::new(half_edges))?)
} }

View File

@ -47,82 +47,70 @@ impl PartialHalfEdge {
} }
/// 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: Handle<Surface>) -> Self {
if let Some(surface) = surface { self.curve = self
self.curve = self.curve.update_partial(|curve| { .curve
curve.with_surface(Some(surface.clone())) .update_partial(|curve| curve.with_surface(Some(surface.clone())));
});
self.vertices = self.vertices.map(|vertex| { self.vertices = self.vertices.map(|vertex| {
vertex.update_partial(|vertex| { vertex.update_partial(|vertex| {
let surface_form = vertex.surface_form().update_partial( let surface_form =
|surface_vertex| { vertex.surface_form().update_partial(|surface_vertex| {
surface_vertex.with_surface(Some(surface.clone())) surface_vertex.with_surface(Some(surface.clone()))
}, });
);
vertex.with_surface_form(Some(surface_form)) vertex.with_surface_form(surface_form)
}) })
}); });
}
self self
} }
/// Update the partial half-edge with the given curve /// Update the partial half-edge with the given curve
pub fn with_curve( pub fn with_curve(mut self, curve: impl Into<MaybePartial<Curve>>) -> Self {
mut self,
curve: Option<impl Into<MaybePartial<Curve>>>,
) -> Self {
if let Some(curve) = curve {
self.curve = curve.into(); self.curve = curve.into();
}
self self
} }
/// Update the partial half-edge with the given back 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: impl Into<MaybePartial<Vertex>>,
) -> Self { ) -> Self {
if let Some(vertex) = vertex {
let [from, _] = &mut self.vertices; let [from, _] = &mut self.vertices;
*from = vertex.into(); *from = vertex.into();
}
self self
} }
/// Update the partial half-edge with the given front 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: impl Into<MaybePartial<Vertex>>,
) -> Self { ) -> Self {
if let Some(vertex) = vertex {
let [_, to] = &mut self.vertices; let [_, to] = &mut self.vertices;
*to = vertex.into(); *to = vertex.into();
}
self self
} }
/// Update the partial half-edge with the given vertices /// Update the partial half-edge with the given vertices
pub fn with_vertices( pub fn with_vertices(
mut self, mut self,
vertices: Option<[impl Into<MaybePartial<Vertex>>; 2]>, vertices: [impl Into<MaybePartial<Vertex>>; 2],
) -> Self { ) -> Self {
let vertices = vertices.map(|vertices| vertices.map(Into::into)); self.vertices = vertices.map(Into::into);
if let Some([back, front]) = vertices {
self.vertices = [back, front];
}
self self
} }
/// Update the partial half-edge with the given global form /// Update the partial half-edge with the given global form
pub fn with_global_form( pub fn with_global_form(
mut self, mut self,
global_form: Option<impl Into<MaybePartial<GlobalEdge>>>, global_form: impl Into<MaybePartial<GlobalEdge>>,
) -> Self { ) -> Self {
if let Some(global_form) = global_form {
self.global_form = global_form.into(); self.global_form = global_form.into();
}
self self
} }
@ -143,7 +131,7 @@ impl PartialHalfEdge {
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
.update_partial(|vertex| vertex.with_curve(Some(curve.clone()))) .update_partial(|vertex| vertex.with_curve(curve.clone()))
.into_full(objects) .into_full(objects)
})?; })?;

View File

@ -46,24 +46,17 @@ impl PartialVertex {
} }
/// Provide a curve for the partial vertex /// Provide a curve for the partial vertex
pub fn with_curve( pub fn with_curve(mut self, curve: impl Into<MaybePartial<Curve>>) -> Self {
mut self,
curve: Option<impl Into<MaybePartial<Curve>>>,
) -> Self {
if let Some(curve) = curve {
self.curve = curve.into(); self.curve = curve.into();
}
self self
} }
/// Provide a surface form for the partial vertex /// Provide a surface form for the partial vertex
pub fn with_surface_form( pub fn with_surface_form(
mut self, mut self,
surface_form: Option<impl Into<MaybePartial<SurfaceVertex>>>, surface_form: impl Into<MaybePartial<SurfaceVertex>>,
) -> Self { ) -> Self {
if let Some(surface_form) = surface_form {
self.surface_form = surface_form.into(); self.surface_form = surface_form.into();
}
self self
} }

View File

@ -217,7 +217,7 @@ mod tests {
vertices[1] = vertices[1] vertices[1] = vertices[1]
.to_partial() .to_partial()
// Arranging for an equal but not identical curve here. // Arranging for an equal but not identical curve here.
.with_curve(Some(valid.curve().to_partial())) .with_curve(valid.curve().to_partial())
.build(&objects)?; .build(&objects)?;
HalfEdge::new(vertices, valid.global_form().clone()) HalfEdge::new(vertices, valid.global_form().clone())

View File

@ -191,11 +191,11 @@ mod tests {
let valid = Vertex::partial() let valid = Vertex::partial()
.with_position(Some([0.])) .with_position(Some([0.]))
.with_curve(Some( .with_curve(
Curve::partial() Curve::partial()
.with_surface(Some(objects.surfaces.xy_plane())) .with_surface(Some(objects.surfaces.xy_plane()))
.update_as_u_axis(), .update_as_u_axis(),
)) )
.build(&objects)?; .build(&objects)?;
let invalid = Vertex::new( let invalid = Vertex::new(
valid.position(), valid.position(),
@ -219,11 +219,11 @@ mod tests {
let valid = Vertex::partial() let valid = Vertex::partial()
.with_position(Some([0.])) .with_position(Some([0.]))
.with_curve(Some( .with_curve(
Curve::partial() Curve::partial()
.with_surface(Some(objects.surfaces.xy_plane())) .with_surface(Some(objects.surfaces.xy_plane()))
.update_as_u_axis(), .update_as_u_axis(),
)) )
.build(&objects)?; .build(&objects)?;
let invalid = Vertex::new( let invalid = Vertex::new(
valid.position(), valid.position(),

View File

@ -28,7 +28,7 @@ impl Shape for fj::Sketch {
// none need to be added here. // none need to be added here.
let half_edge = HalfEdge::partial() let half_edge = HalfEdge::partial()
.with_surface(Some(surface)) .with_surface(surface)
.update_as_circle_from_radius(circle.radius(), objects)? .update_as_circle_from_radius(circle.radius(), objects)?
.build(objects)?; .build(objects)?;
let cycle = objects.cycles.insert(Cycle::new([half_edge]))?; let cycle = objects.cycles.insert(Cycle::new([half_edge]))?;