Merge pull request #1339 from hannobraun/partial

Clean up partial vertex types
This commit is contained in:
Hanno Braun 2022-11-11 17:10:29 +01:00 committed by GitHub
commit f172d3ae50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 317 additions and 356 deletions

View File

@ -199,8 +199,8 @@ mod tests {
algorithms::{reverse::Reverse, sweep::Sweep}, algorithms::{reverse::Reverse, sweep::Sweep},
builder::HalfEdgeBuilder, builder::HalfEdgeBuilder,
insert::Insert, insert::Insert,
objects::{Cycle, Face, HalfEdge, Objects, SurfaceVertex, Vertex}, objects::{Cycle, Face, HalfEdge, Objects},
partial::HasPartial, partial::{HasPartial, PartialSurfaceVertex, PartialVertex},
}; };
#[test] #[test]
@ -218,8 +218,7 @@ 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()
@ -231,36 +230,49 @@ mod tests {
.insert(&objects)?; .insert(&objects)?;
let side_up = HalfEdge::partial() let side_up = HalfEdge::partial()
.with_surface(surface.clone()) .with_surface(surface.clone())
.with_back_vertex(Vertex::partial().with_surface_form( .with_back_vertex(PartialVertex {
bottom.front().surface_form().clone(), surface_form: bottom.front().surface_form().clone().into(),
)) ..Default::default()
.with_front_vertex(Vertex::partial().with_surface_form( })
SurfaceVertex::partial().with_position(Some([1., 1.])), .with_front_vertex(PartialVertex {
)) surface_form: PartialSurfaceVertex {
position: Some([1., 1.].into()),
..Default::default()
}
.into(),
..Default::default()
})
.update_as_line_segment() .update_as_line_segment()
.build(&objects)? .build(&objects)?
.insert(&objects)?; .insert(&objects)?;
let top = HalfEdge::partial() let top = HalfEdge::partial()
.with_surface(surface.clone()) .with_surface(surface.clone())
.with_back_vertex(Vertex::partial().with_surface_form( .with_back_vertex(PartialVertex {
SurfaceVertex::partial().with_position(Some([0., 1.])), surface_form: PartialSurfaceVertex {
)) position: Some([0., 1.].into()),
.with_front_vertex(Vertex::partial().with_surface_form( ..Default::default()
side_up.front().surface_form().clone(), }
)) .into(),
..Default::default()
})
.with_front_vertex(PartialVertex {
surface_form: side_up.front().surface_form().clone().into(),
..Default::default()
})
.update_as_line_segment() .update_as_line_segment()
.build(&objects)? .build(&objects)?
.insert(&objects)? .insert(&objects)?
.reverse(&objects)?; .reverse(&objects)?;
let side_down = let side_down = HalfEdge::partial()
HalfEdge::partial()
.with_surface(surface) .with_surface(surface)
.with_back_vertex(Vertex::partial().with_surface_form( .with_back_vertex(PartialVertex {
bottom.back().surface_form().clone(), surface_form: bottom.back().surface_form().clone().into(),
)) ..Default::default()
.with_front_vertex(Vertex::partial().with_surface_form( })
top.front().surface_form().clone(), .with_front_vertex(PartialVertex {
)) surface_form: top.front().surface_form().clone().into(),
..Default::default()
})
.update_as_line_segment() .update_as_line_segment()
.build(&objects)? .build(&objects)?
.insert(&objects)? .insert(&objects)?

View File

@ -170,8 +170,8 @@ mod tests {
algorithms::sweep::Sweep, algorithms::sweep::Sweep,
builder::{CurveBuilder, HalfEdgeBuilder}, builder::{CurveBuilder, HalfEdgeBuilder},
insert::Insert, insert::Insert,
objects::{HalfEdge, Objects, Vertex}, objects::{HalfEdge, Objects},
partial::{HasPartial, PartialCurve}, partial::{HasPartial, PartialCurve, PartialVertex},
}; };
#[test] #[test]
@ -185,9 +185,11 @@ mod tests {
}; };
curve.update_as_u_axis(); curve.update_as_u_axis();
let curve = curve.build(&objects)?.insert(&objects)?; let curve = curve.build(&objects)?.insert(&objects)?;
let vertex = Vertex::partial() let vertex = PartialVertex {
.with_position(Some([0.])) position: Some([0.].into()),
.with_curve(curve) curve: curve.into(),
..Default::default()
}
.build(&objects)? .build(&objects)?
.insert(&objects)?; .insert(&objects)?;

View File

@ -22,10 +22,10 @@ impl TransformObject for PartialHalfEdge {
.into(); .into();
let vertices = self.vertices().try_map_ext( let vertices = self.vertices().try_map_ext(
|vertex| -> Result<_, ValidationError> { |vertex| -> Result<_, ValidationError> {
Ok(vertex let mut vertex =
.into_partial() vertex.into_partial().transform(transform, objects)?;
.transform(transform, objects)? vertex.curve = curve.clone();
.with_curve(curve.clone())) Ok(vertex)
}, },
)?; )?;
let global_form = self let global_form = self

View File

@ -14,18 +14,19 @@ impl TransformObject for PartialVertex {
transform: &Transform, transform: &Transform,
objects: &Objects, objects: &Objects,
) -> Result<Self, ValidationError> { ) -> Result<Self, ValidationError> {
let curve = self.curve().transform(transform, objects)?; let curve = self.curve.transform(transform, objects)?;
let surface_form = self let surface_form = self
.surface_form() .surface_form
.into_partial() .into_partial()
.transform(transform, objects)?; .transform(transform, objects)?;
// 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 {
.with_position(self.position()) position: self.position,
.with_curve(curve) curve,
.with_surface_form(surface_form)) surface_form: surface_form.into(),
})
} }
} }
@ -36,17 +37,19 @@ impl TransformObject for PartialSurfaceVertex {
objects: &Objects, objects: &Objects,
) -> Result<Self, ValidationError> { ) -> Result<Self, ValidationError> {
let surface = self let surface = self
.surface() .surface
.clone()
.map(|surface| surface.transform(transform, objects)) .map(|surface| surface.transform(transform, objects))
.transpose()?; .transpose()?;
let global_form = self.global_form().transform(transform, objects)?; let global_form = self.global_form.transform(transform, objects)?;
// Don't need to transform `self.position`, as that is in surface // Don't need to transform `self.position`, as that is in surface
// coordinates and thus transforming the surface takes care of it. // coordinates and thus transforming the surface takes care of it.
Ok(Self::default() Ok(Self {
.with_position(self.position()) position: self.position,
.with_surface(surface) surface,
.with_global_form(Some(global_form))) global_form,
})
} }
} }
@ -57,9 +60,9 @@ impl TransformObject for PartialGlobalVertex {
_: &Objects, _: &Objects,
) -> Result<Self, ValidationError> { ) -> Result<Self, ValidationError> {
let position = self let position = self
.position() .position
.map(|position| transform.transform_point(&position)); .map(|position| transform.transform_point(&position));
Ok(Self::default().with_position(position)) Ok(Self { position })
} }
} }

View File

@ -1,8 +1,11 @@
use fj_math::Point; use fj_math::Point;
use crate::{ use crate::{
objects::{HalfEdge, Surface, SurfaceVertex, Vertex}, objects::{HalfEdge, Surface, SurfaceVertex},
partial::{HasPartial, MaybePartial, PartialCurve, PartialCycle}, partial::{
HasPartial, MaybePartial, PartialCurve, PartialCycle,
PartialSurfaceVertex, PartialVertex,
},
storage::Handle, storage::Handle,
}; };
@ -72,11 +75,10 @@ impl CycleBuilder for PartialCycle {
.update_as_line_from_points([position_prev, position_next]); .update_as_line_from_points([position_prev, position_next]);
let vertices = [(0., vertex_prev), (1., vertex_next)].map( let vertices = [(0., vertex_prev), (1., vertex_next)].map(
|(position, surface_form)| { |(position, surface_form)| PartialVertex {
Vertex::partial() position: Some([position].into()),
.with_curve(curve.clone()) curve: curve.clone().into(),
.with_position(Some([position])) surface_form,
.with_surface_form(surface_form)
}, },
); );
@ -101,9 +103,11 @@ impl CycleBuilder for PartialCycle {
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() PartialSurfaceVertex {
.with_surface(Some(surface.clone())) position: Some(position.into()),
.with_position(Some(position)) surface: Some(surface.clone()),
..Default::default()
}
})) }))
} }

View File

@ -3,13 +3,10 @@ use iter_fixed::IntoIteratorFixed;
use crate::{ use crate::{
insert::Insert, insert::Insert,
objects::{ objects::{Curve, Objects, Surface, Vertex, VerticesInNormalizedOrder},
Curve, GlobalVertex, Objects, Surface, SurfaceVertex, Vertex,
VerticesInNormalizedOrder,
},
partial::{ partial::{
HasPartial, MaybePartial, PartialCurve, PartialGlobalEdge, MaybePartial, PartialCurve, PartialGlobalEdge, PartialGlobalVertex,
PartialHalfEdge, PartialHalfEdge, PartialSurfaceVertex, PartialVertex,
}, },
storage::Handle, storage::Handle,
validate::ValidationError, validate::ValidationError,
@ -82,23 +79,26 @@ impl HalfEdgeBuilder for PartialHalfEdge {
.vertices() .vertices()
.map(|[global_form, _]| global_form) .map(|[global_form, _]| global_form)
.unwrap_or_else(|| { .unwrap_or_else(|| {
GlobalVertex::partial() PartialGlobalVertex::from_curve_and_position(
.update_from_curve_and_position(curve.clone(), a_curve) curve.clone(),
a_curve,
)
.into() .into()
}); });
let surface_vertex = SurfaceVertex::partial() let surface_vertex = PartialSurfaceVertex {
.with_position(Some(path.point_from_path_coords(a_curve))) position: Some(path.point_from_path_coords(a_curve)),
.with_surface(curve.surface.clone()) surface: curve.surface.clone(),
.with_global_form(Some(global_vertex)) global_form: global_vertex,
}
.build(objects)? .build(objects)?
.insert(objects)?; .insert(objects)?;
let [back, front] = [a_curve, b_curve].map(|point_curve| { let [back, front] =
Vertex::partial() [a_curve, b_curve].map(|point_curve| PartialVertex {
.with_position(Some(point_curve)) position: Some(point_curve),
.with_curve(curve.clone()) curve: curve.clone().into(),
.with_surface_form(surface_vertex.clone()) surface_form: surface_vertex.clone().into(),
}); });
Ok(self.with_curve(curve).with_vertices([back, front])) Ok(self.with_curve(curve).with_vertices([back, front]))
@ -110,11 +110,16 @@ impl HalfEdgeBuilder for PartialHalfEdge {
points: [impl Into<Point<2>>; 2], points: [impl Into<Point<2>>; 2],
) -> Self { ) -> Self {
let vertices = points.map(|point| { let vertices = points.map(|point| {
let surface_form = SurfaceVertex::partial() let surface_form = PartialSurfaceVertex {
.with_surface(Some(surface.clone())) position: Some(point.into()),
.with_position(Some(point)); surface: Some(surface.clone()),
..Default::default()
};
Vertex::partial().with_surface_form(surface_form) PartialVertex {
surface_form: surface_form.into(),
..Default::default()
}
}); });
self.with_surface(surface) self.with_surface(surface)
@ -148,10 +153,10 @@ impl HalfEdgeBuilder for PartialHalfEdge {
let [back, front] = { let [back, front] = {
let vertices = [(from, 0.), (to, 1.)].map(|(vertex, position)| { let vertices = [(from, 0.), (to, 1.)].map(|(vertex, position)| {
vertex.update_partial(|vertex| { vertex.update_partial(|mut vertex| {
vertex.position = Some([position].into());
vertex.curve = curve.clone().into();
vertex vertex
.with_position(Some([position]))
.with_curve(curve.clone())
}) })
}); });
@ -195,14 +200,16 @@ impl HalfEdgeBuilder for PartialHalfEdge {
.zip(global_forms) .zip(global_forms)
.collect::<[_; 2]>() .collect::<[_; 2]>()
.map(|(vertex, global_form)| { .map(|(vertex, global_form)| {
vertex.update_partial(|vertex| { vertex.update_partial(|mut vertex| {
vertex.clone().with_surface_form( vertex.surface_form = vertex
vertex.surface_form().update_partial( .surface_form
|surface_vertex| { .update_partial(|mut surface_vertex| {
surface_vertex.with_global_form(global_form) if let Some(global_form) = global_form {
}, surface_vertex.global_form = global_form;
), }
) surface_vertex
});
vertex
}) })
}) })
}; };

View File

@ -8,11 +8,8 @@ use crate::{
algorithms::transform::TransformObject, algorithms::transform::TransformObject,
builder::{FaceBuilder, HalfEdgeBuilder}, builder::{FaceBuilder, HalfEdgeBuilder},
insert::Insert, insert::Insert,
objects::{ objects::{Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface},
Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface, SurfaceVertex, partial::{HasPartial, PartialCurve, PartialSurfaceVertex, PartialVertex},
Vertex,
},
partial::{HasPartial, PartialCurve},
storage::Handle, storage::Handle,
}; };
@ -114,14 +111,22 @@ impl<'a> ShellBuilder<'a> {
let [_, from] = bottom.vertices(); let [_, from] = bottom.vertices();
let from = from.surface_form().clone(); let from = from.surface_form().clone();
let to = SurfaceVertex::partial() let to = PartialSurfaceVertex {
.with_position(Some(from.position() + [Z, edge_length])) position: Some(from.position() + [Z, edge_length]),
.with_surface(Some(surface.clone())); surface: Some(surface.clone()),
..Default::default()
};
HalfEdge::partial() HalfEdge::partial()
.with_vertices([ .with_vertices([
Vertex::partial().with_surface_form(from), PartialVertex {
Vertex::partial().with_surface_form(to), surface_form: from.into(),
..Default::default()
},
PartialVertex {
surface_form: to.into(),
..Default::default()
},
]) ])
.update_as_line_segment() .update_as_line_segment()
.build(self.objects) .build(self.objects)
@ -145,12 +150,11 @@ impl<'a> ShellBuilder<'a> {
let [to, _] = bottom.vertices(); let [to, _] = bottom.vertices();
let to = to.surface_form().clone(); let to = to.surface_form().clone();
let from = SurfaceVertex::partial() let from = PartialSurfaceVertex {
.with_position(Some( position: Some(to.position() + [Z, edge_length]),
to.position() + [Z, edge_length], surface: Some(surface.clone()),
)) global_form: from.global_form().clone().into(),
.with_surface(Some(surface.clone())) };
.with_global_form(Some(from.global_form().clone()));
let curve = PartialCurve { let curve = PartialCurve {
global_form: Some( global_form: Some(
@ -166,8 +170,14 @@ impl<'a> ShellBuilder<'a> {
HalfEdge::partial() HalfEdge::partial()
.with_curve(curve) .with_curve(curve)
.with_vertices([ .with_vertices([
Vertex::partial().with_surface_form(from), PartialVertex {
Vertex::partial().with_surface_form(to), surface_form: from.into(),
..Default::default()
},
PartialVertex {
surface_form: to.into(),
..Default::default()
},
]) ])
.update_as_line_segment() .update_as_line_segment()
.build(self.objects) .build(self.objects)
@ -189,8 +199,14 @@ 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(from); let from = PartialVertex {
let to = Vertex::partial().with_surface_form(to); surface_form: from.into(),
..Default::default()
};
let to = PartialVertex {
surface_form: to.into(),
..Default::default()
};
HalfEdge::partial() HalfEdge::partial()
.with_vertices([from, to]) .with_vertices([from, to])
@ -250,12 +266,11 @@ impl<'a> ShellBuilder<'a> {
.map(|(point, edge)| { .map(|(point, edge)| {
let vertex = edge.back(); let vertex = edge.back();
SurfaceVertex::partial() PartialSurfaceVertex {
.with_position(Some(point)) position: Some(point.into()),
.with_surface(Some(surface.clone())) surface: Some(surface.clone()),
.with_global_form(Some( global_form: vertex.global_form().clone().into(),
vertex.global_form().clone(), }
))
.build(self.objects) .build(self.objects)
.unwrap() .unwrap()
.insert(self.objects) .insert(self.objects)
@ -277,10 +292,10 @@ impl<'a> ShellBuilder<'a> {
.into_iter_fixed() .into_iter_fixed()
.zip(surface_vertices.clone()) .zip(surface_vertices.clone())
.collect::<[_; 2]>() .collect::<[_; 2]>()
.map(|(vertex, surface_form)| { .map(|(vertex, surface_form)| PartialVertex {
Vertex::partial() position: Some(vertex.position()),
.with_position(Some(vertex.position())) surface_form: surface_form.into(),
.with_surface_form(surface_form) ..Default::default()
}); });
edges.push( edges.push(

View File

@ -11,47 +11,46 @@ use crate::{
/// Builder API for [`PartialVertex`] /// Builder API for [`PartialVertex`]
pub trait VertexBuilder { pub trait VertexBuilder {
/// Remove the surface form of the partial vertex, inferring it on build /// Remove the surface form of the partial vertex, inferring it on build
fn infer_surface_form(self) -> Self; fn infer_surface_form(&mut self) -> &mut Self;
} }
impl VertexBuilder for PartialVertex { impl VertexBuilder for PartialVertex {
fn infer_surface_form(self) -> Self { fn infer_surface_form(&mut self) -> &mut Self {
self.with_surface_form(PartialSurfaceVertex::default()) self.surface_form = PartialSurfaceVertex::default().into();
self
} }
} }
/// Builder API for [`PartialSurfaceVertex`] /// Builder API for [`PartialSurfaceVertex`]
pub trait SurfaceVertexBuilder { pub trait SurfaceVertexBuilder {
/// Infer the global form of the partial vertex /// Infer the global form of the partial vertex
fn infer_global_form(self) -> Self; fn infer_global_form(&mut self) -> &mut Self;
} }
impl SurfaceVertexBuilder for PartialSurfaceVertex { impl SurfaceVertexBuilder for PartialSurfaceVertex {
fn infer_global_form(self) -> Self { fn infer_global_form(&mut self) -> &mut Self {
self.with_global_form(Some(GlobalVertex::partial())) self.global_form = GlobalVertex::partial().into();
self
} }
} }
/// Builder API for [`PartialGlobalVertex`] /// Builder API for [`PartialGlobalVertex`]
pub trait GlobalVertexBuilder { pub trait GlobalVertexBuilder {
/// Update partial global vertex from the given curve and position on it /// Update partial global vertex from the given curve and position on it
fn update_from_curve_and_position( fn from_curve_and_position(
self,
curve: impl Into<MaybePartial<Curve>>, curve: impl Into<MaybePartial<Curve>>,
position: impl Into<Point<1>>, position: impl Into<Point<1>>,
) -> Self; ) -> Self;
/// Update partial global vertex from the given surface and position on it /// Update partial global vertex from the given surface and position on it
fn update_from_surface_and_position( fn from_surface_and_position(
self,
surface: &Surface, surface: &Surface,
position: impl Into<Point<2>>, position: impl Into<Point<2>>,
) -> Self; ) -> Self;
} }
impl GlobalVertexBuilder for PartialGlobalVertex { impl GlobalVertexBuilder for PartialGlobalVertex {
fn update_from_curve_and_position( fn from_curve_and_position(
self,
curve: impl Into<MaybePartial<Curve>>, curve: impl Into<MaybePartial<Curve>>,
position: impl Into<Point<1>>, position: impl Into<Point<1>>,
) -> Self { ) -> Self {
@ -65,14 +64,16 @@ impl GlobalVertexBuilder for PartialGlobalVertex {
); );
let position_surface = path.point_from_path_coords(position); let position_surface = path.point_from_path_coords(position);
self.update_from_surface_and_position(&surface, position_surface)
Self::from_surface_and_position(&surface, position_surface)
} }
fn update_from_surface_and_position( fn from_surface_and_position(
self,
surface: &Surface, surface: &Surface,
position: impl Into<Point<2>>, position: impl Into<Point<2>>,
) -> Self { ) -> Self {
self.with_position(Some(surface.point_from_surface_coords(position))) PartialGlobalVertex {
position: Some(surface.point_from_surface_coords(position)),
}
} }
} }

View File

@ -217,7 +217,7 @@ impl MaybePartial<SurfaceVertex> {
pub fn position(&self) -> Option<Point<2>> { pub fn position(&self) -> Option<Point<2>> {
match self { match self {
Self::Full(full) => Some(full.position()), Self::Full(full) => Some(full.position()),
Self::Partial(partial) => partial.position(), Self::Partial(partial) => partial.position,
} }
} }
@ -225,7 +225,7 @@ impl MaybePartial<SurfaceVertex> {
pub fn surface(&self) -> Option<Handle<Surface>> { pub fn surface(&self) -> Option<Handle<Surface>> {
match self { match self {
Self::Full(full) => Some(full.surface().clone()), Self::Full(full) => Some(full.surface().clone()),
Self::Partial(partial) => partial.surface(), Self::Partial(partial) => partial.surface.clone(),
} }
} }
@ -233,7 +233,7 @@ impl MaybePartial<SurfaceVertex> {
pub fn global_form(&self) -> MaybePartial<GlobalVertex> { pub fn global_form(&self) -> MaybePartial<GlobalVertex> {
match self { match self {
Self::Full(full) => full.global_form().clone().into(), Self::Full(full) => full.global_form().clone().into(),
Self::Partial(partial) => partial.global_form(), Self::Partial(partial) => partial.global_form.clone(),
} }
} }
} }
@ -243,7 +243,7 @@ impl MaybePartial<Vertex> {
pub fn surface_form(&self) -> MaybePartial<SurfaceVertex> { pub fn surface_form(&self) -> MaybePartial<SurfaceVertex> {
match self { match self {
Self::Full(full) => full.surface_form().clone().into(), Self::Full(full) => full.surface_form().clone().into(),
Self::Partial(partial) => partial.surface_form(), Self::Partial(partial) => partial.surface_form.clone(),
} }
} }
} }

View File

@ -96,9 +96,14 @@ impl PartialCycle {
*half_edge = half_edge.clone().merge_with( *half_edge = half_edge.clone().merge_with(
PartialHalfEdge::default().with_vertices([ PartialHalfEdge::default().with_vertices([
PartialVertex::default().with_surface_form(back_vertex), PartialVertex {
PartialVertex::default() surface_form: back_vertex,
.with_surface_form(front_vertex.clone()), ..Default::default()
},
PartialVertex {
surface_form: front_vertex.clone().into(),
..Default::default()
},
]), ]),
); );
@ -111,9 +116,10 @@ impl PartialCycle {
let back_vertex = previous_vertex.unwrap_or_default(); let back_vertex = previous_vertex.unwrap_or_default();
*half_edge = half_edge.clone().merge_with( *half_edge = half_edge.clone().merge_with(
PartialHalfEdge::default().with_back_vertex( PartialHalfEdge::default().with_back_vertex(PartialVertex {
PartialVertex::default().with_surface_form(back_vertex), surface_form: back_vertex,
), ..Default::default()
}),
); );
} }

View File

@ -54,13 +54,16 @@ impl PartialHalfEdge {
}); });
self.vertices = self.vertices.map(|vertex| { self.vertices = self.vertices.map(|vertex| {
vertex.update_partial(|vertex| { vertex.update_partial(|mut vertex| {
let surface_form = let surface_form = vertex.surface_form.clone().update_partial(
vertex.surface_form().update_partial(|surface_vertex| { |mut surface_vertex| {
surface_vertex.with_surface(Some(surface.clone())) surface_vertex.surface = Some(surface.clone());
}); surface_vertex
},
);
vertex.with_surface_form(surface_form) vertex.surface_form = surface_form;
vertex
}) })
}); });
@ -98,7 +101,10 @@ 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(curve.clone())) .update_partial(|mut vertex| {
vertex.curve = curve.clone().into();
vertex
})
.into_full(objects) .into_full(objects)
})?; })?;

View File

@ -13,53 +13,17 @@ use crate::{
/// See [`crate::partial`] for more information. /// See [`crate::partial`] for more information.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct PartialVertex { pub struct PartialVertex {
position: Option<Point<1>>, /// The position of the [`Vertex`]
curve: MaybePartial<Curve>, pub position: Option<Point<1>>,
surface_form: MaybePartial<SurfaceVertex>,
/// The curve that the [`Vertex`] is defined in
pub curve: MaybePartial<Curve>,
/// The surface form of the [`Vertex`]
pub surface_form: MaybePartial<SurfaceVertex>,
} }
impl PartialVertex { impl PartialVertex {
/// Access the position of the [`Vertex`] on the curve
pub fn position(&self) -> Option<Point<1>> {
self.position
}
/// Access the curve that the [`Vertex`] is defined in
pub fn curve(&self) -> MaybePartial<Curve> {
self.curve.clone()
}
/// Access the surface form of the [`Vertex`]
pub fn surface_form(&self) -> MaybePartial<SurfaceVertex> {
self.surface_form.clone()
}
/// Provide a position for the partial vertex
pub fn with_position(
mut self,
position: Option<impl Into<Point<1>>>,
) -> Self {
if let Some(position) = position {
self.position = Some(position.into());
}
self
}
/// Provide a curve for the partial vertex
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: impl Into<MaybePartial<SurfaceVertex>>,
) -> Self {
self.surface_form = surface_form.into();
self
}
/// Build a full [`Vertex`] from the partial vertex /// Build a full [`Vertex`] from the partial vertex
/// ///
/// # Panics /// # Panics
@ -75,14 +39,15 @@ impl PartialVertex {
let surface_form = self let surface_form = self
.surface_form .surface_form
.update_partial(|partial| { .update_partial(|mut partial| {
let position = partial.position.unwrap_or_else(|| { let position = partial.position.unwrap_or_else(|| {
curve.path().point_from_path_coords(position) curve.path().point_from_path_coords(position)
}); });
partial.position = Some(position);
partial.surface = Some(curve.surface().clone());
partial partial
.with_position(Some(position))
.with_surface(Some(curve.surface().clone()))
}) })
.into_full(objects)?; .into_full(objects)?;
@ -117,57 +82,17 @@ impl From<&Vertex> for PartialVertex {
/// See [`crate::partial`] for more information. /// See [`crate::partial`] for more information.
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] #[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct PartialSurfaceVertex { pub struct PartialSurfaceVertex {
position: Option<Point<2>>, /// The position of the [`SurfaceVertex`]
surface: Option<Handle<Surface>>, pub position: Option<Point<2>>,
global_form: MaybePartial<GlobalVertex>,
/// The surface that the [`SurfaceVertex`] is defined in
pub surface: Option<Handle<Surface>>,
/// The global form of the [`SurfaceVertex`]
pub global_form: MaybePartial<GlobalVertex>,
} }
impl PartialSurfaceVertex { impl PartialSurfaceVertex {
/// Access the position of the [`SurfaceVertex`]
pub fn position(&self) -> Option<Point<2>> {
self.position
}
/// Access the surface that the [`SurfaceVertex`] is defined in
pub fn surface(&self) -> Option<Handle<Surface>> {
self.surface.clone()
}
/// Access the global form of the [`SurfaceVertex`]
pub fn global_form(&self) -> MaybePartial<GlobalVertex> {
self.global_form.clone()
}
/// Provide a position for the partial surface vertex
pub fn with_position(
mut self,
position: Option<impl Into<Point<2>>>,
) -> Self {
if let Some(position) = position {
self.position = Some(position.into());
}
self
}
/// Provide a surface for the partial surface vertex
pub fn with_surface(mut self, surface: Option<Handle<Surface>>) -> Self {
if let Some(surface) = surface {
self.surface = Some(surface);
}
self
}
/// Provide a global form for the partial surface vertex
pub fn with_global_form(
mut self,
global_form: Option<impl Into<MaybePartial<GlobalVertex>>>,
) -> Self {
if let Some(global_form) = global_form {
self.global_form = global_form.into();
}
self
}
/// 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,
@ -182,9 +107,9 @@ impl PartialSurfaceVertex {
let global_form = self let global_form = self
.global_form .global_form
.update_partial(|global_form| { .merge_with(PartialGlobalVertex::from_surface_and_position(
global_form.update_from_surface_and_position(&surface, position) &surface, position,
}) ))
.into_full(objects)?; .into_full(objects)?;
Ok(SurfaceVertex::new(position, surface, global_form)) Ok(SurfaceVertex::new(position, surface, global_form))
@ -218,26 +143,11 @@ impl From<&SurfaceVertex> for PartialSurfaceVertex {
/// See [`crate::partial`] for more information. /// See [`crate::partial`] for more information.
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] #[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct PartialGlobalVertex { pub struct PartialGlobalVertex {
position: Option<Point<3>>, /// The position of the [`GlobalVertex`]
pub position: Option<Point<3>>,
} }
impl PartialGlobalVertex { impl PartialGlobalVertex {
/// Access the position of the [`GlobalVertex`]
pub fn position(&self) -> Option<Point<3>> {
self.position
}
/// Provide a position for the partial global vertex
pub fn with_position(
mut self,
position: Option<impl Into<Point<3>>>,
) -> Self {
if let Some(position) = position {
self.position = Some(position.into());
}
self
}
/// Build a full [`GlobalVertex`] from the partial global vertex /// Build a full [`GlobalVertex`] from the partial global vertex
pub fn build(self, _: &Objects) -> Result<GlobalVertex, ValidationError> { pub fn build(self, _: &Objects) -> Result<GlobalVertex, ValidationError> {
let position = self let position = self

View File

@ -95,7 +95,8 @@ mod tests {
// Sever connection between the last and first half-edge in the // Sever connection between the last and first half-edge in the
// cycle. // cycle.
let first_vertex = first_vertex.into_partial().infer_surface_form(); let mut first_vertex = first_vertex.into_partial();
first_vertex.infer_surface_form();
*first_half_edge = first_half_edge *first_half_edge = first_half_edge
.clone() .clone()
.with_back_vertex(first_vertex) .with_back_vertex(first_vertex)

View File

@ -220,12 +220,10 @@ mod tests {
.build(&objects)?; .build(&objects)?;
let invalid = { let invalid = {
let mut vertices = valid.vertices().clone(); let mut vertices = valid.vertices().clone();
vertices[1] = vertices[1] let mut vertex = 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(valid.curve().to_partial()) vertex.curve = valid.curve().to_partial().into();
.build(&objects)? vertices[1] = vertex.build(&objects)?.insert(&objects)?;
.insert(&objects)?;
HalfEdge::new(vertices, valid.global_form().clone()) HalfEdge::new(vertices, valid.global_form().clone())
}; };
@ -308,12 +306,10 @@ mod tests {
let invalid = HalfEdge::new( let invalid = HalfEdge::new(
valid.vertices().clone().try_map_ext( valid.vertices().clone().try_map_ext(
|vertex| -> anyhow::Result<_, ValidationError> { |vertex| -> anyhow::Result<_, ValidationError> {
Ok(vertex let mut vertex = vertex.to_partial();
.to_partial() vertex.position = Some([0.].into());
.with_position(Some([0.])) vertex.infer_surface_form();
.infer_surface_form() Ok(vertex.build(&objects)?.insert(&objects)?)
.build(&objects)?
.insert(&objects)?)
}, },
)?, )?,
valid.global_form().clone(), valid.global_form().clone(),

View File

@ -182,7 +182,9 @@ mod tests {
builder::{CurveBuilder, SurfaceVertexBuilder}, builder::{CurveBuilder, SurfaceVertexBuilder},
insert::Insert, insert::Insert,
objects::{GlobalVertex, Objects, SurfaceVertex, Vertex}, objects::{GlobalVertex, Objects, SurfaceVertex, Vertex},
partial::{HasPartial, PartialCurve}, partial::{
HasPartial, PartialCurve, PartialSurfaceVertex, PartialVertex,
},
validate::Validate, validate::Validate,
}; };
@ -196,20 +198,17 @@ mod tests {
}; };
curve.update_as_u_axis(); curve.update_as_u_axis();
let valid = Vertex::partial() let valid = PartialVertex {
.with_position(Some([0.])) position: Some([0.].into()),
.with_curve(curve) curve: curve.into(),
..Default::default()
}
.build(&objects)?; .build(&objects)?;
let invalid = Vertex::new( let invalid = Vertex::new(valid.position(), valid.curve().clone(), {
valid.position(), let mut tmp = valid.surface_form().to_partial();
valid.curve().clone(), tmp.surface = Some(objects.surfaces.xz_plane());
valid tmp.build(&objects)?.insert(&objects)?
.surface_form() });
.to_partial()
.with_surface(Some(objects.surfaces.xz_plane()))
.build(&objects)?
.insert(&objects)?,
);
assert!(valid.validate().is_ok()); assert!(valid.validate().is_ok());
assert!(invalid.validate().is_err()); assert!(invalid.validate().is_err());
@ -228,22 +227,19 @@ mod tests {
}; };
curve.update_as_u_axis(); curve.update_as_u_axis();
Vertex::partial() PartialVertex {
.with_position(Some([0.])) position: Some([0.].into()),
.with_curve(curve) curve: curve.into(),
..Default::default()
}
.build(&objects)? .build(&objects)?
}; };
let invalid = Vertex::new( let invalid = Vertex::new(valid.position(), valid.curve().clone(), {
valid.position(), let mut tmp = valid.surface_form().to_partial();
valid.curve().clone(), tmp.position = Some([1., 0.].into());
valid tmp.infer_global_form();
.surface_form() tmp.build(&objects)?.insert(&objects)?
.to_partial() });
.with_position(Some([1., 0.]))
.infer_global_form()
.build(&objects)?
.insert(&objects)?,
);
assert!(valid.validate().is_ok()); assert!(valid.validate().is_ok());
assert!(invalid.validate().is_err()); assert!(invalid.validate().is_err());
@ -255,9 +251,11 @@ mod tests {
fn surface_vertex_position_mismatch() -> anyhow::Result<()> { fn surface_vertex_position_mismatch() -> anyhow::Result<()> {
let objects = Objects::new(); let objects = Objects::new();
let valid = SurfaceVertex::partial() let valid = PartialSurfaceVertex {
.with_position(Some([0., 0.])) position: Some([0., 0.].into()),
.with_surface(Some(objects.surfaces.xy_plane())) surface: Some(objects.surfaces.xy_plane()),
..Default::default()
}
.build(&objects)?; .build(&objects)?;
let invalid = SurfaceVertex::new( let invalid = SurfaceVertex::new(
valid.position(), valid.position(),