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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,7 +16,7 @@ pub trait VertexBuilder {
impl VertexBuilder for PartialVertex {
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
pub fn merge_with(self, other: Self) -> Self {
match (self, other) {
pub fn merge_with(self, other: impl Into<Self>) -> Self {
match (self, other.into()) {
(Self::Full(_), Self::Full(_)) => {
panic!("Can't merge two full objects")
}

View File

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

View File

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

View File

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

View File

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

View File

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