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},
builder::HalfEdgeBuilder,
insert::Insert,
objects::{Cycle, Face, HalfEdge, Objects, SurfaceVertex, Vertex},
partial::HasPartial,
objects::{Cycle, Face, HalfEdge, Objects},
partial::{HasPartial, PartialSurfaceVertex, PartialVertex},
};
#[test]
@ -218,63 +218,75 @@ mod tests {
let face =
(half_edge, Color::default()).sweep([0., 0., 1.], &objects)?;
let expected_face =
{
let surface = objects.surfaces.xz_plane();
let expected_face = {
let surface = objects.surfaces.xz_plane();
let bottom = HalfEdge::partial()
.update_as_line_segment_from_points(
surface.clone(),
[[0., 0.], [1., 0.]],
)
.build(&objects)?
.insert(&objects)?;
let side_up = HalfEdge::partial()
.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)?
.insert(&objects)?;
let top = HalfEdge::partial()
.with_surface(surface.clone())
.with_back_vertex(Vertex::partial().with_surface_form(
SurfaceVertex::partial().with_position(Some([0., 1.])),
))
.with_front_vertex(Vertex::partial().with_surface_form(
side_up.front().surface_form().clone(),
))
.update_as_line_segment()
.build(&objects)?
.insert(&objects)?
.reverse(&objects)?;
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)?
.insert(&objects)?
.reverse(&objects)?;
let bottom = HalfEdge::partial()
.update_as_line_segment_from_points(
surface.clone(),
[[0., 0.], [1., 0.]],
)
.build(&objects)?
.insert(&objects)?;
let side_up = HalfEdge::partial()
.with_surface(surface.clone())
.with_back_vertex(PartialVertex {
surface_form: bottom.front().surface_form().clone().into(),
..Default::default()
})
.with_front_vertex(PartialVertex {
surface_form: PartialSurfaceVertex {
position: Some([1., 1.].into()),
..Default::default()
}
.into(),
..Default::default()
})
.update_as_line_segment()
.build(&objects)?
.insert(&objects)?;
let top = HalfEdge::partial()
.with_surface(surface.clone())
.with_back_vertex(PartialVertex {
surface_form: PartialSurfaceVertex {
position: Some([0., 1.].into()),
..Default::default()
}
.into(),
..Default::default()
})
.with_front_vertex(PartialVertex {
surface_form: side_up.front().surface_form().clone().into(),
..Default::default()
})
.update_as_line_segment()
.build(&objects)?
.insert(&objects)?
.reverse(&objects)?;
let side_down = HalfEdge::partial()
.with_surface(surface)
.with_back_vertex(PartialVertex {
surface_form: bottom.back().surface_form().clone().into(),
..Default::default()
})
.with_front_vertex(PartialVertex {
surface_form: top.front().surface_form().clone().into(),
..Default::default()
})
.update_as_line_segment()
.build(&objects)?
.insert(&objects)?
.reverse(&objects)?;
let cycle = objects
.cycles
.insert(Cycle::new([bottom, side_up, top, side_down]))?;
let cycle = objects
.cycles
.insert(Cycle::new([bottom, side_up, top, side_down]))?;
Face::partial()
.with_exterior(cycle)
.build(&objects)?
.insert(&objects)?
};
Face::partial()
.with_exterior(cycle)
.build(&objects)?
.insert(&objects)?
};
assert_eq!(face, expected_face);
Ok(())

View File

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

View File

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

View File

@ -14,18 +14,19 @@ impl TransformObject for PartialVertex {
transform: &Transform,
objects: &Objects,
) -> Result<Self, ValidationError> {
let curve = self.curve().transform(transform, objects)?;
let curve = self.curve.transform(transform, objects)?;
let surface_form = self
.surface_form()
.surface_form
.into_partial()
.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(curve)
.with_surface_form(surface_form))
Ok(Self {
position: self.position,
curve,
surface_form: surface_form.into(),
})
}
}
@ -36,17 +37,19 @@ impl TransformObject for PartialSurfaceVertex {
objects: &Objects,
) -> Result<Self, ValidationError> {
let surface = self
.surface()
.surface
.clone()
.map(|surface| surface.transform(transform, objects))
.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
// coordinates and thus transforming the surface takes care of it.
Ok(Self::default()
.with_position(self.position())
.with_surface(surface)
.with_global_form(Some(global_form)))
Ok(Self {
position: self.position,
surface,
global_form,
})
}
}
@ -57,9 +60,9 @@ impl TransformObject for PartialGlobalVertex {
_: &Objects,
) -> Result<Self, ValidationError> {
let position = self
.position()
.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 crate::{
objects::{HalfEdge, Surface, SurfaceVertex, Vertex},
partial::{HasPartial, MaybePartial, PartialCurve, PartialCycle},
objects::{HalfEdge, Surface, SurfaceVertex},
partial::{
HasPartial, MaybePartial, PartialCurve, PartialCycle,
PartialSurfaceVertex, PartialVertex,
},
storage::Handle,
};
@ -72,11 +75,10 @@ impl CycleBuilder for PartialCycle {
.update_as_line_from_points([position_prev, position_next]);
let vertices = [(0., vertex_prev), (1., vertex_next)].map(
|(position, surface_form)| {
Vertex::partial()
.with_curve(curve.clone())
.with_position(Some([position]))
.with_surface_form(surface_form)
|(position, surface_form)| PartialVertex {
position: Some([position].into()),
curve: curve.clone().into(),
surface_form,
},
);
@ -101,9 +103,11 @@ impl CycleBuilder for PartialCycle {
points: impl IntoIterator<Item = impl Into<Point<2>>>,
) -> Self {
self.with_poly_chain(points.into_iter().map(|position| {
SurfaceVertex::partial()
.with_surface(Some(surface.clone()))
.with_position(Some(position))
PartialSurfaceVertex {
position: Some(position.into()),
surface: Some(surface.clone()),
..Default::default()
}
}))
}

View File

@ -3,13 +3,10 @@ use iter_fixed::IntoIteratorFixed;
use crate::{
insert::Insert,
objects::{
Curve, GlobalVertex, Objects, Surface, SurfaceVertex, Vertex,
VerticesInNormalizedOrder,
},
objects::{Curve, Objects, Surface, Vertex, VerticesInNormalizedOrder},
partial::{
HasPartial, MaybePartial, PartialCurve, PartialGlobalEdge,
PartialHalfEdge,
MaybePartial, PartialCurve, PartialGlobalEdge, PartialGlobalVertex,
PartialHalfEdge, PartialSurfaceVertex, PartialVertex,
},
storage::Handle,
validate::ValidationError,
@ -82,24 +79,27 @@ impl HalfEdgeBuilder for PartialHalfEdge {
.vertices()
.map(|[global_form, _]| global_form)
.unwrap_or_else(|| {
GlobalVertex::partial()
.update_from_curve_and_position(curve.clone(), a_curve)
.into()
PartialGlobalVertex::from_curve_and_position(
curve.clone(),
a_curve,
)
.into()
});
let surface_vertex = SurfaceVertex::partial()
.with_position(Some(path.point_from_path_coords(a_curve)))
.with_surface(curve.surface.clone())
.with_global_form(Some(global_vertex))
.build(objects)?
.insert(objects)?;
let surface_vertex = PartialSurfaceVertex {
position: Some(path.point_from_path_coords(a_curve)),
surface: curve.surface.clone(),
global_form: global_vertex,
}
.build(objects)?
.insert(objects)?;
let [back, front] = [a_curve, b_curve].map(|point_curve| {
Vertex::partial()
.with_position(Some(point_curve))
.with_curve(curve.clone())
.with_surface_form(surface_vertex.clone())
});
let [back, front] =
[a_curve, b_curve].map(|point_curve| PartialVertex {
position: Some(point_curve),
curve: curve.clone().into(),
surface_form: surface_vertex.clone().into(),
});
Ok(self.with_curve(curve).with_vertices([back, front]))
}
@ -110,11 +110,16 @@ impl HalfEdgeBuilder for PartialHalfEdge {
points: [impl Into<Point<2>>; 2],
) -> Self {
let vertices = points.map(|point| {
let surface_form = SurfaceVertex::partial()
.with_surface(Some(surface.clone()))
.with_position(Some(point));
let surface_form = PartialSurfaceVertex {
position: Some(point.into()),
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)
@ -148,10 +153,10 @@ impl HalfEdgeBuilder for PartialHalfEdge {
let [back, front] = {
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
.with_position(Some([position]))
.with_curve(curve.clone())
})
});
@ -195,14 +200,16 @@ impl HalfEdgeBuilder for PartialHalfEdge {
.zip(global_forms)
.collect::<[_; 2]>()
.map(|(vertex, global_form)| {
vertex.update_partial(|vertex| {
vertex.clone().with_surface_form(
vertex.surface_form().update_partial(
|surface_vertex| {
surface_vertex.with_global_form(global_form)
},
),
)
vertex.update_partial(|mut vertex| {
vertex.surface_form = vertex
.surface_form
.update_partial(|mut surface_vertex| {
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,
builder::{FaceBuilder, HalfEdgeBuilder},
insert::Insert,
objects::{
Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface, SurfaceVertex,
Vertex,
},
partial::{HasPartial, PartialCurve},
objects::{Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface},
partial::{HasPartial, PartialCurve, PartialSurfaceVertex, PartialVertex},
storage::Handle,
};
@ -114,14 +111,22 @@ impl<'a> ShellBuilder<'a> {
let [_, from] = bottom.vertices();
let from = from.surface_form().clone();
let to = SurfaceVertex::partial()
.with_position(Some(from.position() + [Z, edge_length]))
.with_surface(Some(surface.clone()));
let to = PartialSurfaceVertex {
position: Some(from.position() + [Z, edge_length]),
surface: Some(surface.clone()),
..Default::default()
};
HalfEdge::partial()
.with_vertices([
Vertex::partial().with_surface_form(from),
Vertex::partial().with_surface_form(to),
PartialVertex {
surface_form: from.into(),
..Default::default()
},
PartialVertex {
surface_form: to.into(),
..Default::default()
},
])
.update_as_line_segment()
.build(self.objects)
@ -145,12 +150,11 @@ impl<'a> ShellBuilder<'a> {
let [to, _] = bottom.vertices();
let to = to.surface_form().clone();
let from = SurfaceVertex::partial()
.with_position(Some(
to.position() + [Z, edge_length],
))
.with_surface(Some(surface.clone()))
.with_global_form(Some(from.global_form().clone()));
let from = PartialSurfaceVertex {
position: Some(to.position() + [Z, edge_length]),
surface: Some(surface.clone()),
global_form: from.global_form().clone().into(),
};
let curve = PartialCurve {
global_form: Some(
@ -166,8 +170,14 @@ impl<'a> ShellBuilder<'a> {
HalfEdge::partial()
.with_curve(curve)
.with_vertices([
Vertex::partial().with_surface_form(from),
Vertex::partial().with_surface_form(to),
PartialVertex {
surface_form: from.into(),
..Default::default()
},
PartialVertex {
surface_form: to.into(),
..Default::default()
},
])
.update_as_line_segment()
.build(self.objects)
@ -189,8 +199,14 @@ impl<'a> ShellBuilder<'a> {
let from = from.surface_form().clone();
let to = to.surface_form().clone();
let from = Vertex::partial().with_surface_form(from);
let to = Vertex::partial().with_surface_form(to);
let from = PartialVertex {
surface_form: from.into(),
..Default::default()
};
let to = PartialVertex {
surface_form: to.into(),
..Default::default()
};
HalfEdge::partial()
.with_vertices([from, to])
@ -250,16 +266,15 @@ impl<'a> ShellBuilder<'a> {
.map(|(point, edge)| {
let vertex = edge.back();
SurfaceVertex::partial()
.with_position(Some(point))
.with_surface(Some(surface.clone()))
.with_global_form(Some(
vertex.global_form().clone(),
))
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()
PartialSurfaceVertex {
position: Some(point.into()),
surface: Some(surface.clone()),
global_form: vertex.global_form().clone().into(),
}
.build(self.objects)
.unwrap()
.insert(self.objects)
.unwrap()
});
[a.clone(), b, c, d, a]
@ -277,10 +292,10 @@ impl<'a> ShellBuilder<'a> {
.into_iter_fixed()
.zip(surface_vertices.clone())
.collect::<[_; 2]>()
.map(|(vertex, surface_form)| {
Vertex::partial()
.with_position(Some(vertex.position()))
.with_surface_form(surface_form)
.map(|(vertex, surface_form)| PartialVertex {
position: Some(vertex.position()),
surface_form: surface_form.into(),
..Default::default()
});
edges.push(

View File

@ -11,47 +11,46 @@ use crate::{
/// Builder API for [`PartialVertex`]
pub trait VertexBuilder {
/// 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 {
fn infer_surface_form(self) -> Self {
self.with_surface_form(PartialSurfaceVertex::default())
fn infer_surface_form(&mut self) -> &mut Self {
self.surface_form = PartialSurfaceVertex::default().into();
self
}
}
/// Builder API for [`PartialSurfaceVertex`]
pub trait SurfaceVertexBuilder {
/// 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 {
fn infer_global_form(self) -> Self {
self.with_global_form(Some(GlobalVertex::partial()))
fn infer_global_form(&mut self) -> &mut Self {
self.global_form = GlobalVertex::partial().into();
self
}
}
/// Builder API for [`PartialGlobalVertex`]
pub trait GlobalVertexBuilder {
/// Update partial global vertex from the given curve and position on it
fn update_from_curve_and_position(
self,
fn from_curve_and_position(
curve: impl Into<MaybePartial<Curve>>,
position: impl Into<Point<1>>,
) -> Self;
/// Update partial global vertex from the given surface and position on it
fn update_from_surface_and_position(
self,
fn from_surface_and_position(
surface: &Surface,
position: impl Into<Point<2>>,
) -> Self;
}
impl GlobalVertexBuilder for PartialGlobalVertex {
fn update_from_curve_and_position(
self,
fn from_curve_and_position(
curve: impl Into<MaybePartial<Curve>>,
position: impl Into<Point<1>>,
) -> Self {
@ -65,14 +64,16 @@ impl GlobalVertexBuilder for PartialGlobalVertex {
);
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(
self,
fn from_surface_and_position(
surface: &Surface,
position: impl Into<Point<2>>,
) -> 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>> {
match self {
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>> {
match self {
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> {
match self {
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> {
match self {
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(
PartialHalfEdge::default().with_vertices([
PartialVertex::default().with_surface_form(back_vertex),
PartialVertex::default()
.with_surface_form(front_vertex.clone()),
PartialVertex {
surface_form: back_vertex,
..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();
*half_edge = half_edge.clone().merge_with(
PartialHalfEdge::default().with_back_vertex(
PartialVertex::default().with_surface_form(back_vertex),
),
PartialHalfEdge::default().with_back_vertex(PartialVertex {
surface_form: back_vertex,
..Default::default()
}),
);
}

View File

@ -54,13 +54,16 @@ impl PartialHalfEdge {
});
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.update_partial(|mut vertex| {
let surface_form = vertex.surface_form.clone().update_partial(
|mut surface_vertex| {
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 vertices = self.vertices.try_map_ext(|vertex| {
vertex
.update_partial(|vertex| vertex.with_curve(curve.clone()))
.update_partial(|mut vertex| {
vertex.curve = curve.clone().into();
vertex
})
.into_full(objects)
})?;

View File

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

View File

@ -95,7 +95,8 @@ mod tests {
// Sever connection between the last and first half-edge in the
// 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
.clone()
.with_back_vertex(first_vertex)

View File

@ -220,12 +220,10 @@ mod tests {
.build(&objects)?;
let invalid = {
let mut vertices = valid.vertices().clone();
vertices[1] = vertices[1]
.to_partial()
// Arranging for an equal but not identical curve here.
.with_curve(valid.curve().to_partial())
.build(&objects)?
.insert(&objects)?;
let mut vertex = vertices[1].to_partial();
// Arranging for an equal but not identical curve here.
vertex.curve = valid.curve().to_partial().into();
vertices[1] = vertex.build(&objects)?.insert(&objects)?;
HalfEdge::new(vertices, valid.global_form().clone())
};
@ -308,12 +306,10 @@ mod tests {
let invalid = HalfEdge::new(
valid.vertices().clone().try_map_ext(
|vertex| -> anyhow::Result<_, ValidationError> {
Ok(vertex
.to_partial()
.with_position(Some([0.]))
.infer_surface_form()
.build(&objects)?
.insert(&objects)?)
let mut vertex = vertex.to_partial();
vertex.position = Some([0.].into());
vertex.infer_surface_form();
Ok(vertex.build(&objects)?.insert(&objects)?)
},
)?,
valid.global_form().clone(),

View File

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