Merge pull request #1338 from hannobraun/partial

Simplify `PartialCurve`
This commit is contained in:
Hanno Braun 2022-11-11 15:15:08 +01:00 committed by GitHub
commit d6cde482da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 211 additions and 196 deletions

View File

@ -199,8 +199,8 @@ mod tests {
algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint}, algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint},
builder::CurveBuilder, builder::CurveBuilder,
insert::Insert, insert::Insert,
objects::{Curve, Objects, Surface}, objects::{Objects, Surface},
partial::HasPartial, partial::PartialCurve,
path::GlobalPath, path::GlobalPath,
}; };
@ -213,11 +213,12 @@ mod tests {
let surface = objects let surface = objects
.surfaces .surfaces
.insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?; .insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?;
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface)) surface: Some(surface),
.update_as_line_from_points([[1., 1.], [2., 1.]]) ..Default::default()
.build(&objects)? };
.insert(&objects)?; curve.update_as_line_from_points([[1., 1.], [2., 1.]]);
let curve = curve.build(&objects)?.insert(&objects)?;
let range = RangeOnPath::from([[0.], [1.]]); let range = RangeOnPath::from([[0.], [1.]]);
let approx = (&curve, range).approx(1.); let approx = (&curve, range).approx(1.);
@ -235,11 +236,12 @@ mod tests {
GlobalPath::circle_from_radius(1.), GlobalPath::circle_from_radius(1.),
[0., 0., 1.], [0., 0., 1.],
))?; ))?;
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface)) surface: Some(surface),
.update_as_line_from_points([[1., 1.], [1., 2.]]) ..Default::default()
.build(&objects)? };
.insert(&objects)?; curve.update_as_line_from_points([[1., 1.], [1., 2.]]);
let curve = curve.build(&objects)?.insert(&objects)?;
let range = RangeOnPath::from([[0.], [1.]]); let range = RangeOnPath::from([[0.], [1.]]);
let approx = (&curve, range).approx(1.); let approx = (&curve, range).approx(1.);
@ -255,11 +257,12 @@ mod tests {
let path = GlobalPath::circle_from_radius(1.); let path = GlobalPath::circle_from_radius(1.);
let surface = let surface =
objects.surfaces.insert(Surface::new(path, [0., 0., 1.]))?; objects.surfaces.insert(Surface::new(path, [0., 0., 1.]))?;
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface.clone())) surface: Some(surface.clone()),
.update_as_line_from_points([[0., 1.], [1., 1.]]) ..Default::default()
.build(&objects)? };
.insert(&objects)?; curve.update_as_line_from_points([[0., 1.], [1., 1.]]);
let curve = curve.build(&objects)?.insert(&objects)?;
let range = RangeOnPath::from([[0.], [TAU]]); let range = RangeOnPath::from([[0.], [TAU]]);
let tolerance = 1.; let tolerance = 1.;
@ -288,11 +291,12 @@ mod tests {
let surface = objects let surface = objects
.surfaces .surfaces
.insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?; .insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?;
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface)) surface: Some(surface),
.update_as_circle_from_radius(1.) ..Default::default()
.build(&objects)? };
.insert(&objects)?; curve.update_as_circle_from_radius(1.);
let curve = curve.build(&objects)?.insert(&objects)?;
let range = RangeOnPath::from([[0.], [TAU]]); let range = RangeOnPath::from([[0.], [TAU]]);
let tolerance = 1.; let tolerance = 1.;

View File

@ -76,8 +76,8 @@ mod tests {
use crate::{ use crate::{
builder::{CurveBuilder, HalfEdgeBuilder}, builder::{CurveBuilder, HalfEdgeBuilder},
objects::{Curve, HalfEdge, Objects}, objects::{HalfEdge, Objects},
partial::HasPartial, partial::{HasPartial, PartialCurve},
}; };
use super::CurveEdgeIntersection; use super::CurveEdgeIntersection;
@ -87,10 +87,12 @@ mod tests {
let objects = Objects::new(); let objects = Objects::new();
let surface = objects.surfaces.xy_plane(); let surface = objects.surfaces.xy_plane();
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface.clone())) surface: Some(surface.clone()),
.update_as_u_axis() ..Default::default()
.build(&objects)?; };
curve.update_as_u_axis();
let curve = curve.build(&objects)?;
let half_edge = HalfEdge::partial() let half_edge = HalfEdge::partial()
.update_as_line_segment_from_points(surface, [[1., -1.], [1., 1.]]) .update_as_line_segment_from_points(surface, [[1., -1.], [1., 1.]])
.build(&objects)?; .build(&objects)?;
@ -111,10 +113,12 @@ mod tests {
let objects = Objects::new(); let objects = Objects::new();
let surface = objects.surfaces.xy_plane(); let surface = objects.surfaces.xy_plane();
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface.clone())) surface: Some(surface.clone()),
.update_as_u_axis() ..Default::default()
.build(&objects)?; };
curve.update_as_u_axis();
let curve = curve.build(&objects)?;
let half_edge = HalfEdge::partial() let half_edge = HalfEdge::partial()
.update_as_line_segment_from_points( .update_as_line_segment_from_points(
surface, surface,
@ -138,10 +142,12 @@ mod tests {
let objects = Objects::new(); let objects = Objects::new();
let surface = objects.surfaces.xy_plane(); let surface = objects.surfaces.xy_plane();
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface.clone())) surface: Some(surface.clone()),
.update_as_u_axis() ..Default::default()
.build(&objects)?; };
curve.update_as_u_axis();
let curve = curve.build(&objects)?;
let half_edge = HalfEdge::partial() let half_edge = HalfEdge::partial()
.update_as_line_segment_from_points( .update_as_line_segment_from_points(
surface, surface,
@ -160,10 +166,12 @@ mod tests {
let objects = Objects::new(); let objects = Objects::new();
let surface = objects.surfaces.xy_plane(); let surface = objects.surfaces.xy_plane();
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface.clone())) surface: Some(surface.clone()),
.update_as_u_axis() ..Default::default()
.build(&objects)?; };
curve.update_as_u_axis();
let curve = curve.build(&objects)?;
let half_edge = HalfEdge::partial() let half_edge = HalfEdge::partial()
.update_as_line_segment_from_points(surface, [[-1., 0.], [1., 0.]]) .update_as_line_segment_from_points(surface, [[-1., 0.], [1., 0.]])
.build(&objects)?; .build(&objects)?;

View File

@ -151,8 +151,8 @@ where
mod tests { mod tests {
use crate::{ use crate::{
builder::{CurveBuilder, FaceBuilder}, builder::{CurveBuilder, FaceBuilder},
objects::{Curve, Face, Objects}, objects::{Face, Objects},
partial::HasPartial, partial::{HasPartial, PartialCurve},
}; };
use super::CurveFaceIntersection; use super::CurveFaceIntersection;
@ -163,10 +163,12 @@ mod tests {
let surface = objects.surfaces.xy_plane(); let surface = objects.surfaces.xy_plane();
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface.clone())) surface: Some(surface.clone()),
.update_as_line_from_points([[-3., 0.], [-2., 0.]]) ..Default::default()
.build(&objects)?; };
curve.update_as_line_from_points([[-3., 0.], [-2., 0.]]);
let curve = curve.build(&objects)?;
#[rustfmt::skip] #[rustfmt::skip]
let exterior = [ let exterior = [

View File

@ -72,8 +72,8 @@ mod tests {
algorithms::intersect::CurveFaceIntersection, algorithms::intersect::CurveFaceIntersection,
builder::{CurveBuilder, FaceBuilder}, builder::{CurveBuilder, FaceBuilder},
insert::Insert, insert::Insert,
objects::{Curve, Face, Objects}, objects::{Face, Objects},
partial::HasPartial, partial::{HasPartial, PartialCurve},
validate::ValidationError, validate::ValidationError,
}; };
@ -129,11 +129,12 @@ mod tests {
let expected_curves = let expected_curves =
surfaces.try_map_ext(|surface| -> Result<_, ValidationError> { surfaces.try_map_ext(|surface| -> Result<_, ValidationError> {
Ok(Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface)) surface: Some(surface),
.update_as_line_from_points([[0., 0.], [1., 0.]]) ..Default::default()
.build(&objects)? };
.insert(&objects)?) curve.update_as_line_from_points([[0., 0.], [1., 0.]]);
Ok(curve.build(&objects)?.insert(&objects)?)
})?; })?;
let expected_intervals = let expected_intervals =
CurveFaceIntersection::from_intervals([[[-1.], [1.]]]); CurveFaceIntersection::from_intervals([[[-1.], [1.]]]);

View File

@ -91,11 +91,8 @@ mod tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use crate::{ use crate::{
algorithms::transform::TransformObject, algorithms::transform::TransformObject, builder::CurveBuilder,
builder::CurveBuilder, insert::Insert, objects::Objects, partial::PartialCurve,
insert::Insert,
objects::{Curve, Objects},
partial::HasPartial,
}; };
use super::SurfaceSurfaceIntersection; use super::SurfaceSurfaceIntersection;
@ -122,16 +119,18 @@ mod tests {
None, None,
); );
let expected_xy = Curve::partial() let mut expected_xy = PartialCurve {
.with_surface(Some(xy.clone())) surface: Some(xy.clone()),
.update_as_u_axis() ..Default::default()
.build(&objects)? };
.insert(&objects)?; expected_xy.update_as_u_axis();
let expected_xz = Curve::partial() let expected_xy = expected_xy.build(&objects)?.insert(&objects)?;
.with_surface(Some(xz.clone())) let mut expected_xz = PartialCurve {
.update_as_u_axis() surface: Some(xz.clone()),
.build(&objects)? ..Default::default()
.insert(&objects)?; };
expected_xz.update_as_u_axis();
let expected_xz = expected_xz.build(&objects)?.insert(&objects)?;
assert_eq!( assert_eq!(
SurfaceSurfaceIntersection::compute([xy, xz], &objects)?, SurfaceSurfaceIntersection::compute([xy, xz], &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::{Curve, HalfEdge, Objects, Vertex}, objects::{HalfEdge, Objects, Vertex},
partial::HasPartial, partial::{HasPartial, PartialCurve},
}; };
#[test] #[test]
@ -179,11 +179,12 @@ mod tests {
let objects = Objects::new(); let objects = Objects::new();
let surface = objects.surfaces.xz_plane(); let surface = objects.surfaces.xz_plane();
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface.clone())) surface: Some(surface.clone()),
.update_as_u_axis() ..Default::default()
.build(&objects)? };
.insert(&objects)?; curve.update_as_u_axis();
let curve = curve.build(&objects)?.insert(&objects)?;
let vertex = Vertex::partial() let vertex = Vertex::partial()
.with_position(Some([0.])) .with_position(Some([0.]))
.with_curve(curve) .with_curve(curve)

View File

@ -29,19 +29,20 @@ impl TransformObject for PartialCurve {
objects: &Objects, objects: &Objects,
) -> Result<Self, ValidationError> { ) -> Result<Self, ValidationError> {
let surface = self let surface = self
.surface() .surface
.map(|surface| surface.transform(transform, objects)) .map(|surface| surface.transform(transform, objects))
.transpose()?; .transpose()?;
let global_form = self let global_form = self
.global_form() .global_form
.map(|global_form| global_form.transform(transform, objects)) .map(|global_form| global_form.transform(transform, objects))
.transpose()?; .transpose()?;
// Don't need to transform `self.path`, as that's defined in surface // Don't need to transform `self.path`, as that's defined in surface
// coordinates, and thus transforming `surface` takes care of it. // coordinates, and thus transforming `surface` takes care of it.
Ok(Self::default() Ok(PartialCurve {
.with_surface(surface) path: self.path,
.with_path(self.path()) surface,
.with_global_form(global_form)) global_form,
})
} }
} }

View File

@ -5,44 +5,52 @@ use crate::{partial::PartialCurve, path::SurfacePath};
/// Builder API for [`PartialCurve`] /// Builder API for [`PartialCurve`]
pub trait CurveBuilder { pub trait CurveBuilder {
/// Update partial curve to represent the u-axis /// Update partial curve to represent the u-axis
fn update_as_u_axis(self) -> Self; fn update_as_u_axis(&mut self) -> &mut Self;
/// Update partial curve to represent the v-axis /// Update partial curve to represent the v-axis
fn update_as_v_axis(self) -> Self; fn update_as_v_axis(&mut self) -> &mut Self;
/// Update partial curve as a circle, from the provided radius /// Update partial curve as a circle, from the provided radius
fn update_as_circle_from_radius(self, radius: impl Into<Scalar>) -> Self; fn update_as_circle_from_radius(
&mut self,
radius: impl Into<Scalar>,
) -> &mut Self;
/// Update partial curve as a line, from the provided points /// Update partial curve as a line, from the provided points
fn update_as_line_from_points( fn update_as_line_from_points(
self, &mut self,
points: [impl Into<Point<2>>; 2], points: [impl Into<Point<2>>; 2],
) -> Self; ) -> &mut Self;
} }
impl CurveBuilder for PartialCurve { impl CurveBuilder for PartialCurve {
fn update_as_u_axis(self) -> Self { fn update_as_u_axis(&mut self) -> &mut Self {
let a = Point::origin(); let a = Point::origin();
let b = a + Vector::unit_u(); let b = a + Vector::unit_u();
self.update_as_line_from_points([a, b]) self.update_as_line_from_points([a, b])
} }
fn update_as_v_axis(self) -> Self { fn update_as_v_axis(&mut self) -> &mut Self {
let a = Point::origin(); let a = Point::origin();
let b = a + Vector::unit_v(); let b = a + Vector::unit_v();
self.update_as_line_from_points([a, b]) self.update_as_line_from_points([a, b])
} }
fn update_as_circle_from_radius(self, radius: impl Into<Scalar>) -> Self { fn update_as_circle_from_radius(
self.with_path(Some(SurfacePath::circle_from_radius(radius))) &mut self,
radius: impl Into<Scalar>,
) -> &mut Self {
self.path = Some(SurfacePath::circle_from_radius(radius));
self
} }
fn update_as_line_from_points( fn update_as_line_from_points(
self, &mut self,
points: [impl Into<Point<2>>; 2], points: [impl Into<Point<2>>; 2],
) -> Self { ) -> &mut Self {
self.with_path(Some(SurfacePath::line_from_points(points))) self.path = Some(SurfacePath::line_from_points(points));
self
} }
} }

View File

@ -1,8 +1,8 @@
use fj_math::Point; use fj_math::Point;
use crate::{ use crate::{
objects::{Curve, HalfEdge, Surface, SurfaceVertex, Vertex}, objects::{HalfEdge, Surface, SurfaceVertex, Vertex},
partial::{HasPartial, MaybePartial, PartialCycle}, partial::{HasPartial, MaybePartial, PartialCurve, PartialCycle},
storage::Handle, storage::Handle,
}; };
@ -64,8 +64,11 @@ impl CycleBuilder for PartialCycle {
previous = Some(vertex_next.clone()); previous = Some(vertex_next.clone());
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface.clone())) surface: Some(surface.clone()),
..Default::default()
};
curve
.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(

View File

@ -7,7 +7,10 @@ use crate::{
Curve, GlobalVertex, Objects, Surface, SurfaceVertex, Vertex, Curve, GlobalVertex, Objects, Surface, SurfaceVertex, Vertex,
VerticesInNormalizedOrder, VerticesInNormalizedOrder,
}, },
partial::{HasPartial, MaybePartial, PartialGlobalEdge, PartialHalfEdge}, partial::{
HasPartial, MaybePartial, PartialCurve, PartialGlobalEdge,
PartialHalfEdge,
},
storage::Handle, storage::Handle,
validate::ValidationError, validate::ValidationError,
}; };
@ -65,13 +68,11 @@ impl HalfEdgeBuilder for PartialHalfEdge {
radius: impl Into<Scalar>, radius: impl Into<Scalar>,
objects: &Objects, objects: &Objects,
) -> Result<Self, ValidationError> { ) -> Result<Self, ValidationError> {
let curve = self let mut curve = self.curve().into_partial();
.curve() curve.global_form = Some(self.extract_global_curve());
.into_partial() curve.update_as_circle_from_radius(radius);
.with_global_form(Some(self.extract_global_curve()))
.update_as_circle_from_radius(radius);
let path = curve.path().expect("Expected path that was just created"); let path = curve.path.expect("Expected path that was just created");
let [a_curve, b_curve] = let [a_curve, b_curve] =
[Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord]));
@ -88,7 +89,7 @@ impl HalfEdgeBuilder for PartialHalfEdge {
let surface_vertex = SurfaceVertex::partial() let surface_vertex = SurfaceVertex::partial()
.with_position(Some(path.point_from_path_coords(a_curve))) .with_position(Some(path.point_from_path_coords(a_curve)))
.with_surface(curve.surface()) .with_surface(curve.surface.clone())
.with_global_form(Some(global_vertex)) .with_global_form(Some(global_vertex))
.build(objects)? .build(objects)?
.insert(objects)?; .insert(objects)?;
@ -138,10 +139,12 @@ impl HalfEdgeBuilder for PartialHalfEdge {
.expect("Can't infer line segment without surface position") .expect("Can't infer line segment without surface position")
}); });
let curve = Curve::partial() let mut curve = PartialCurve {
.with_global_form(Some(self.extract_global_curve())) surface: Some(surface),
.with_surface(Some(surface)) global_form: Some(self.extract_global_curve()),
.update_as_line_from_points(points); ..Default::default()
};
curve.update_as_line_from_points(points);
let [back, front] = { let [back, front] = {
let vertices = [(from, 0.), (to, 1.)].map(|(vertex, position)| { let vertices = [(from, 0.), (to, 1.)].map(|(vertex, position)| {

View File

@ -9,10 +9,10 @@ use crate::{
builder::{FaceBuilder, HalfEdgeBuilder}, builder::{FaceBuilder, HalfEdgeBuilder},
insert::Insert, insert::Insert,
objects::{ objects::{
Curve, Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface, Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface, SurfaceVertex,
SurfaceVertex, Vertex, Vertex,
}, },
partial::HasPartial, partial::{HasPartial, PartialCurve},
storage::Handle, storage::Handle,
}; };
@ -152,9 +152,16 @@ impl<'a> ShellBuilder<'a> {
.with_surface(Some(surface.clone())) .with_surface(Some(surface.clone()))
.with_global_form(Some(from.global_form().clone())); .with_global_form(Some(from.global_form().clone()));
let curve = Curve::partial().with_global_form(Some( let curve = PartialCurve {
side_up_prev.curve().global_form().clone(), global_form: Some(
)); side_up_prev
.curve()
.global_form()
.clone()
.into(),
),
..Default::default()
};
HalfEdge::partial() HalfEdge::partial()
.with_curve(curve) .with_curve(curve)

View File

@ -57,10 +57,10 @@ impl GlobalVertexBuilder for PartialGlobalVertex {
) -> Self { ) -> Self {
let curve = curve.into().into_partial(); let curve = curve.into().into_partial();
let path = curve.path().expect( let path = curve.path.expect(
"Need path to create `GlobalVertex` from curve and position", "Need path to create `GlobalVertex` from curve and position",
); );
let surface = curve.surface().expect( let surface = curve.surface.expect(
"Need surface to create `GlobalVertex` from curve and position", "Need surface to create `GlobalVertex` from curve and position",
); );

View File

@ -363,10 +363,10 @@ mod tests {
builder::{CurveBuilder, CycleBuilder, FaceBuilder, HalfEdgeBuilder}, builder::{CurveBuilder, CycleBuilder, FaceBuilder, HalfEdgeBuilder},
insert::Insert, insert::Insert,
objects::{ objects::{
Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Objects, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Objects, Shell,
Shell, Sketch, Solid, SurfaceVertex, Vertex, Sketch, Solid, SurfaceVertex, Vertex,
}, },
partial::HasPartial, partial::{HasPartial, PartialCurve},
}; };
use super::ObjectIters as _; use super::ObjectIters as _;
@ -376,11 +376,12 @@ mod tests {
let objects = Objects::new(); let objects = Objects::new();
let surface = objects.surfaces.xy_plane(); let surface = objects.surfaces.xy_plane();
let object = Curve::partial() let mut object = PartialCurve {
.with_surface(Some(surface)) surface: Some(surface),
.update_as_u_axis() ..Default::default()
.build(&objects)? };
.insert(&objects)?; object.update_as_u_axis();
let object = object.build(&objects)?.insert(&objects)?;
assert_eq!(1, object.curve_iter().count()); assert_eq!(1, object.curve_iter().count());
assert_eq!(0, object.cycle_iter().count()); assert_eq!(0, object.cycle_iter().count());
@ -616,11 +617,12 @@ mod tests {
let objects = Objects::new(); let objects = Objects::new();
let surface = objects.surfaces.xy_plane(); let surface = objects.surfaces.xy_plane();
let curve = Curve::partial() let mut curve = PartialCurve {
.with_surface(Some(surface.clone())) surface: Some(surface.clone()),
.update_as_u_axis() ..Default::default()
.build(&objects)? };
.insert(&objects)?; curve.update_as_u_axis();
let curve = curve.build(&objects)?.insert(&objects)?;
let global_vertex = objects let global_vertex = objects
.global_vertices .global_vertices
.insert(GlobalVertex::from_position([0., 0., 0.]))?; .insert(GlobalVertex::from_position([0., 0., 0.]))?;

View File

@ -142,7 +142,7 @@ impl MaybePartial<Curve> {
pub fn path(&self) -> Option<SurfacePath> { pub fn path(&self) -> Option<SurfacePath> {
match self { match self {
MaybePartial::Full(full) => Some(full.path()), MaybePartial::Full(full) => Some(full.path()),
MaybePartial::Partial(partial) => partial.path(), MaybePartial::Partial(partial) => partial.path,
} }
} }
@ -150,7 +150,7 @@ impl MaybePartial<Curve> {
pub fn surface(&self) -> Option<Handle<Surface>> { pub fn surface(&self) -> Option<Handle<Surface>> {
match self { match self {
MaybePartial::Full(full) => Some(full.surface().clone()), MaybePartial::Full(full) => Some(full.surface().clone()),
MaybePartial::Partial(partial) => partial.surface(), MaybePartial::Partial(partial) => partial.surface.clone(),
} }
} }
@ -158,7 +158,7 @@ impl MaybePartial<Curve> {
pub fn global_form(&self) -> Option<MaybePartial<GlobalCurve>> { pub fn global_form(&self) -> Option<MaybePartial<GlobalCurve>> {
match self { match self {
Self::Full(full) => Some(full.global_form().clone().into()), Self::Full(full) => Some(full.global_form().clone().into()),
Self::Partial(partial) => partial.global_form(), Self::Partial(partial) => partial.global_form.clone(),
} }
} }
} }

View File

@ -11,54 +11,23 @@ use crate::{
/// See [`crate::partial`] for more information. /// See [`crate::partial`] for more information.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct PartialCurve { pub struct PartialCurve {
path: Option<SurfacePath>, /// The path that defines the [`Curve`]
surface: Option<Handle<Surface>>, pub path: Option<SurfacePath>,
global_form: Option<MaybePartial<GlobalCurve>>,
/// The surface that the [`Curve`] is defined in
pub surface: Option<Handle<Surface>>,
/// The global form of the [`Curve`]
///
/// # Implementation Note
///
/// This can in principle be simplified to just `MaybePartial<GlobalForm`,
/// but as of this writing, there's still some code that relies on this
/// being an `Option`.
pub global_form: Option<MaybePartial<GlobalCurve>>,
} }
impl PartialCurve { impl PartialCurve {
/// Access the path that defines the [`Curve`]
pub fn path(&self) -> Option<SurfacePath> {
self.path
}
/// Access the surface that the [`Curve`] is defined in
pub fn surface(&self) -> Option<Handle<Surface>> {
self.surface.clone()
}
/// Access the global form of the [`Curve`]
pub fn global_form(&self) -> Option<MaybePartial<GlobalCurve>> {
self.global_form.clone()
}
/// Provide a path for the partial curve
pub fn with_path(mut self, path: Option<SurfacePath>) -> Self {
if let Some(path) = path {
self.path = Some(path);
}
self
}
/// Provide a surface for the partial curve
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 curve
pub fn with_global_form(
mut self,
global_form: Option<impl Into<MaybePartial<GlobalCurve>>>,
) -> Self {
if let Some(global_form) = global_form {
self.global_form = Some(global_form.into());
}
self
}
/// Build a full [`Curve`] from the partial curve /// Build a full [`Curve`] from the partial curve
pub fn build(self, objects: &Objects) -> Result<Curve, ValidationError> { pub fn build(self, objects: &Objects) -> Result<Curve, ValidationError> {
let path = self.path.expect("Can't build `Curve` without path"); let path = self.path.expect("Can't build `Curve` without path");

View File

@ -48,9 +48,10 @@ 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: Handle<Surface>) -> Self { pub fn with_surface(mut self, surface: Handle<Surface>) -> Self {
self.curve = self self.curve = self.curve.update_partial(|mut curve| {
.curve curve.surface = Some(surface.clone());
.update_partial(|curve| curve.with_surface(Some(surface.clone()))); curve
});
self.vertices = self.vertices.map(|vertex| { self.vertices = self.vertices.map(|vertex| {
vertex.update_partial(|vertex| { vertex.update_partial(|vertex| {

View File

@ -181,8 +181,8 @@ mod tests {
use crate::{ use crate::{
builder::{CurveBuilder, SurfaceVertexBuilder}, builder::{CurveBuilder, SurfaceVertexBuilder},
insert::Insert, insert::Insert,
objects::{Curve, GlobalVertex, Objects, SurfaceVertex, Vertex}, objects::{GlobalVertex, Objects, SurfaceVertex, Vertex},
partial::HasPartial, partial::{HasPartial, PartialCurve},
validate::Validate, validate::Validate,
}; };
@ -190,13 +190,15 @@ mod tests {
fn vertex_surface_mismatch() -> anyhow::Result<()> { fn vertex_surface_mismatch() -> anyhow::Result<()> {
let objects = Objects::new(); let objects = Objects::new();
let mut curve = PartialCurve {
surface: Some(objects.surfaces.xy_plane()),
..Default::default()
};
curve.update_as_u_axis();
let valid = Vertex::partial() let valid = Vertex::partial()
.with_position(Some([0.])) .with_position(Some([0.]))
.with_curve( .with_curve(curve)
Curve::partial()
.with_surface(Some(objects.surfaces.xy_plane()))
.update_as_u_axis(),
)
.build(&objects)?; .build(&objects)?;
let invalid = Vertex::new( let invalid = Vertex::new(
valid.position(), valid.position(),
@ -219,14 +221,18 @@ mod tests {
fn vertex_position_mismatch() -> anyhow::Result<()> { fn vertex_position_mismatch() -> anyhow::Result<()> {
let objects = Objects::new(); let objects = Objects::new();
let valid = Vertex::partial() let valid = {
let mut curve = PartialCurve {
surface: Some(objects.surfaces.xy_plane()),
..Default::default()
};
curve.update_as_u_axis();
Vertex::partial()
.with_position(Some([0.])) .with_position(Some([0.]))
.with_curve( .with_curve(curve)
Curve::partial() .build(&objects)?
.with_surface(Some(objects.surfaces.xy_plane())) };
.update_as_u_axis(),
)
.build(&objects)?;
let invalid = Vertex::new( let invalid = Vertex::new(
valid.position(), valid.position(),
valid.curve().clone(), valid.curve().clone(),