mirror of https://github.com/hannobraun/Fornjot
Merge pull request #1305 from hannobraun/partial
Start extracting new builder API from partial object API
This commit is contained in:
commit
412f1b26f0
|
@ -197,6 +197,7 @@ mod tests {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint},
|
algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint},
|
||||||
|
builder::CurveBuilder,
|
||||||
objects::{Curve, Objects, Surface},
|
objects::{Curve, Objects, Surface},
|
||||||
partial::HasPartial,
|
partial::HasPartial,
|
||||||
path::GlobalPath,
|
path::GlobalPath,
|
||||||
|
@ -213,7 +214,7 @@ mod tests {
|
||||||
.insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?;
|
.insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?;
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface))
|
.with_surface(Some(surface))
|
||||||
.as_line_from_points([[1., 1.], [2., 1.]])
|
.update_as_line_from_points([[1., 1.], [2., 1.]])
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let range = RangeOnPath::from([[0.], [1.]]);
|
let range = RangeOnPath::from([[0.], [1.]]);
|
||||||
|
|
||||||
|
@ -234,7 +235,7 @@ mod tests {
|
||||||
))?;
|
))?;
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface))
|
.with_surface(Some(surface))
|
||||||
.as_line_from_points([[1., 1.], [1., 2.]])
|
.update_as_line_from_points([[1., 1.], [1., 2.]])
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let range = RangeOnPath::from([[0.], [1.]]);
|
let range = RangeOnPath::from([[0.], [1.]]);
|
||||||
|
|
||||||
|
@ -253,7 +254,7 @@ mod tests {
|
||||||
objects.surfaces.insert(Surface::new(path, [0., 0., 1.]))?;
|
objects.surfaces.insert(Surface::new(path, [0., 0., 1.]))?;
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.with_surface(Some(surface.clone()))
|
||||||
.as_line_from_points([[0., 1.], [1., 1.]])
|
.update_as_line_from_points([[0., 1.], [1., 1.]])
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
|
|
||||||
let range = RangeOnPath::from([[0.], [TAU]]);
|
let range = RangeOnPath::from([[0.], [TAU]]);
|
||||||
|
@ -285,7 +286,7 @@ mod tests {
|
||||||
.insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?;
|
.insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?;
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface))
|
.with_surface(Some(surface))
|
||||||
.as_circle_from_radius(1.)
|
.update_as_circle_from_radius(1.)
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
|
|
||||||
let range = RangeOnPath::from([[0.], [TAU]]);
|
let range = RangeOnPath::from([[0.], [TAU]]);
|
||||||
|
|
|
@ -75,6 +75,7 @@ mod tests {
|
||||||
use fj_math::Point;
|
use fj_math::Point;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
builder::CurveBuilder,
|
||||||
objects::{Curve, HalfEdge, Objects},
|
objects::{Curve, HalfEdge, Objects},
|
||||||
partial::HasPartial,
|
partial::HasPartial,
|
||||||
};
|
};
|
||||||
|
@ -88,7 +89,7 @@ mod tests {
|
||||||
let surface = objects.surfaces.xy_plane();
|
let surface = objects.surfaces.xy_plane();
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.with_surface(Some(surface.clone()))
|
||||||
.as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(surface))
|
.with_surface(Some(surface))
|
||||||
|
@ -113,7 +114,7 @@ mod tests {
|
||||||
let surface = objects.surfaces.xy_plane();
|
let surface = objects.surfaces.xy_plane();
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.with_surface(Some(surface.clone()))
|
||||||
.as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(surface))
|
.with_surface(Some(surface))
|
||||||
|
@ -138,7 +139,7 @@ mod tests {
|
||||||
let surface = objects.surfaces.xy_plane();
|
let surface = objects.surfaces.xy_plane();
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.with_surface(Some(surface.clone()))
|
||||||
.as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(surface))
|
.with_surface(Some(surface))
|
||||||
|
@ -158,7 +159,7 @@ mod tests {
|
||||||
let surface = objects.surfaces.xy_plane();
|
let surface = objects.surfaces.xy_plane();
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.with_surface(Some(surface.clone()))
|
||||||
.as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let half_edge = HalfEdge::partial()
|
let half_edge = HalfEdge::partial()
|
||||||
.with_surface(Some(surface))
|
.with_surface(Some(surface))
|
||||||
|
|
|
@ -150,6 +150,7 @@ where
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
|
builder::CurveBuilder,
|
||||||
objects::{Curve, Face, Objects},
|
objects::{Curve, Face, Objects},
|
||||||
partial::HasPartial,
|
partial::HasPartial,
|
||||||
};
|
};
|
||||||
|
@ -164,7 +165,7 @@ mod tests {
|
||||||
|
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.with_surface(Some(surface.clone()))
|
||||||
.as_line_from_points([[-3., 0.], [-2., 0.]])
|
.update_as_line_from_points([[-3., 0.], [-2., 0.]])
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|
|
@ -67,6 +67,7 @@ mod tests {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algorithms::intersect::CurveFaceIntersection,
|
algorithms::intersect::CurveFaceIntersection,
|
||||||
|
builder::CurveBuilder,
|
||||||
objects::{Curve, Face, Objects},
|
objects::{Curve, Face, Objects},
|
||||||
partial::HasPartial,
|
partial::HasPartial,
|
||||||
};
|
};
|
||||||
|
@ -124,7 +125,7 @@ mod tests {
|
||||||
let expected_curves = surfaces.try_map_ext(|surface| {
|
let expected_curves = surfaces.try_map_ext(|surface| {
|
||||||
Curve::partial()
|
Curve::partial()
|
||||||
.with_surface(Some(surface))
|
.with_surface(Some(surface))
|
||||||
.as_line_from_points([[0., 0.], [1., 0.]])
|
.update_as_line_from_points([[0., 0.], [1., 0.]])
|
||||||
.build(&objects)
|
.build(&objects)
|
||||||
})?;
|
})?;
|
||||||
let expected_intervals =
|
let expected_intervals =
|
||||||
|
|
|
@ -92,6 +92,7 @@ mod tests {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algorithms::transform::TransformObject,
|
algorithms::transform::TransformObject,
|
||||||
|
builder::CurveBuilder,
|
||||||
objects::{Curve, Objects},
|
objects::{Curve, Objects},
|
||||||
partial::HasPartial,
|
partial::HasPartial,
|
||||||
};
|
};
|
||||||
|
@ -122,11 +123,11 @@ mod tests {
|
||||||
|
|
||||||
let expected_xy = Curve::partial()
|
let expected_xy = Curve::partial()
|
||||||
.with_surface(Some(xy.clone()))
|
.with_surface(Some(xy.clone()))
|
||||||
.as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let expected_xz = Curve::partial()
|
let expected_xz = Curve::partial()
|
||||||
.with_surface(Some(xz.clone()))
|
.with_surface(Some(xz.clone()))
|
||||||
.as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -168,6 +168,7 @@ mod tests {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algorithms::sweep::Sweep,
|
algorithms::sweep::Sweep,
|
||||||
|
builder::CurveBuilder,
|
||||||
objects::{Curve, HalfEdge, Objects, Vertex},
|
objects::{Curve, HalfEdge, Objects, Vertex},
|
||||||
partial::HasPartial,
|
partial::HasPartial,
|
||||||
};
|
};
|
||||||
|
@ -179,7 +180,7 @@ mod tests {
|
||||||
let surface = objects.surfaces.xz_plane();
|
let surface = objects.surfaces.xz_plane();
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.with_surface(Some(surface.clone()))
|
||||||
.as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let vertex = Vertex::partial()
|
let vertex = Vertex::partial()
|
||||||
.with_position(Some([0.]))
|
.with_position(Some([0.]))
|
||||||
|
|
|
@ -1,29 +1,24 @@
|
||||||
use fj_math::Transform;
|
use fj_math::Transform;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{GlobalCurve, Objects},
|
objects::Objects,
|
||||||
partial::PartialCurve,
|
partial::{PartialCurve, PartialGlobalCurve},
|
||||||
storage::Handle,
|
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::TransformObject;
|
use super::TransformObject;
|
||||||
|
|
||||||
impl TransformObject for Handle<GlobalCurve> {
|
impl TransformObject for PartialGlobalCurve {
|
||||||
fn transform(
|
fn transform(
|
||||||
self,
|
self,
|
||||||
_: &Transform,
|
_: &Transform,
|
||||||
objects: &Objects,
|
_: &Objects,
|
||||||
) -> Result<Self, ValidationError> {
|
) -> Result<Self, ValidationError> {
|
||||||
// `GlobalCurve` doesn't contain any internal geometry. If it did, that
|
// `GlobalCurve` doesn't contain any internal geometry. If it did, that
|
||||||
// would just be redundant with the geometry of other objects, and this
|
// would just be redundant with the geometry of other objects, and this
|
||||||
// other geometry is already being transformed by other implementations
|
// other geometry is already being transformed by other implementations
|
||||||
// of this trait.
|
// of this trait.
|
||||||
//
|
Ok(self)
|
||||||
// All we need to do here is create a new `GlobalCurve` instance, to
|
|
||||||
// make sure the transformed `GlobalCurve` has a different identity than
|
|
||||||
// the original one.
|
|
||||||
Ok(objects.global_curves.insert(GlobalCurve)?)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,20 +29,19 @@ 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.0.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 {
|
Ok(Self::default()
|
||||||
surface,
|
.with_surface(surface)
|
||||||
path: self.path,
|
.with_path(self.path())
|
||||||
global_form: global_form.map(Into::into),
|
.with_global_form(global_form))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,10 +57,7 @@ impl TransformObject for PartialGlobalEdge {
|
||||||
transform: &Transform,
|
transform: &Transform,
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
) -> Result<Self, ValidationError> {
|
) -> Result<Self, ValidationError> {
|
||||||
let curve = self
|
let curve = self.curve.transform(transform, objects)?;
|
||||||
.curve
|
|
||||||
.map(|curve| curve.0.transform(transform, objects))
|
|
||||||
.transpose()?;
|
|
||||||
let vertices = self
|
let vertices = self
|
||||||
.vertices
|
.vertices
|
||||||
.map(|vertices| {
|
.map(|vertices| {
|
||||||
|
@ -70,9 +67,6 @@ impl TransformObject for PartialGlobalEdge {
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self { curve, vertices })
|
||||||
curve: curve.map(Into::into),
|
|
||||||
vertices,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,20 +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)?
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
// Don't need to transform `self.position`, as that is in curve
|
// Don't need to transform `self.position`, as that is in curve
|
||||||
// coordinates and thus transforming the curve takes care of it.
|
// coordinates and thus transforming the curve takes care of it.
|
||||||
Ok(Self {
|
Ok(Self::default()
|
||||||
position: self.position,
|
.with_position(self.position())
|
||||||
curve,
|
.with_curve(Some(curve))
|
||||||
surface_form,
|
.with_surface_form(surface_form))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,18 +37,17 @@ impl TransformObject for PartialSurfaceVertex {
|
||||||
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.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 {
|
Ok(Self::default()
|
||||||
position: self.position,
|
.with_position(self.position())
|
||||||
surface,
|
.with_surface(surface)
|
||||||
global_form,
|
.with_global_form(Some(global_form)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +58,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 { position })
|
Ok(Self::default().with_position(position))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
use fj_math::{Point, Scalar, Vector};
|
||||||
|
|
||||||
|
use crate::{partial::PartialCurve, path::SurfacePath};
|
||||||
|
|
||||||
|
/// Builder API for [`PartialCurve`]
|
||||||
|
pub trait CurveBuilder {
|
||||||
|
/// Update partial curve to represent the u-axis
|
||||||
|
fn update_as_u_axis(self) -> Self;
|
||||||
|
|
||||||
|
/// Update partial curve to represent the v-axis
|
||||||
|
fn update_as_v_axis(self) -> Self;
|
||||||
|
|
||||||
|
/// Update partial curve as a circle, from the provided radius
|
||||||
|
fn update_as_circle_from_radius(self, radius: impl Into<Scalar>) -> Self;
|
||||||
|
|
||||||
|
/// Update partial curve as a line, from the provided points
|
||||||
|
fn update_as_line_from_points(
|
||||||
|
self,
|
||||||
|
points: [impl Into<Point<2>>; 2],
|
||||||
|
) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CurveBuilder for PartialCurve {
|
||||||
|
fn update_as_u_axis(self) -> Self {
|
||||||
|
let a = Point::origin();
|
||||||
|
let b = a + Vector::unit_u();
|
||||||
|
|
||||||
|
self.update_as_line_from_points([a, b])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_as_v_axis(self) -> Self {
|
||||||
|
let a = Point::origin();
|
||||||
|
let b = a + Vector::unit_v();
|
||||||
|
|
||||||
|
self.update_as_line_from_points([a, b])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_as_circle_from_radius(self, radius: impl Into<Scalar>) -> Self {
|
||||||
|
self.with_path(Some(SurfacePath::circle_from_radius(radius)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_as_line_from_points(
|
||||||
|
self,
|
||||||
|
points: [impl Into<Point<2>>; 2],
|
||||||
|
) -> Self {
|
||||||
|
self.with_path(Some(SurfacePath::line_from_points(points)))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,22 @@
|
||||||
//! API for building objects
|
//! API for building objects
|
||||||
|
|
||||||
|
// These are the old-style builders that need to be transferred to the partial
|
||||||
|
// object API. Issue:
|
||||||
|
// https://github.com/hannobraun/Fornjot/issues/1147
|
||||||
mod face;
|
mod face;
|
||||||
mod shell;
|
mod shell;
|
||||||
mod sketch;
|
mod sketch;
|
||||||
mod solid;
|
mod solid;
|
||||||
|
|
||||||
|
// These are new-style builders that build on top of the partial object API.
|
||||||
|
mod curve;
|
||||||
|
mod vertex;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
face::FaceBuilder, shell::ShellBuilder, sketch::SketchBuilder,
|
curve::CurveBuilder,
|
||||||
|
face::FaceBuilder,
|
||||||
|
shell::ShellBuilder,
|
||||||
|
sketch::SketchBuilder,
|
||||||
solid::SolidBuilder,
|
solid::SolidBuilder,
|
||||||
|
vertex::{GlobalVertexBuilder, SurfaceVertexBuilder, VertexBuilder},
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
use fj_math::Point;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
objects::{Curve, GlobalVertex, Surface},
|
||||||
|
partial::{
|
||||||
|
HasPartial, MaybePartial, PartialGlobalVertex, PartialSurfaceVertex,
|
||||||
|
PartialVertex,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VertexBuilder for PartialVertex {
|
||||||
|
fn infer_surface_form(self) -> Self {
|
||||||
|
self.with_surface_form(Some(PartialSurfaceVertex::default()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builder API for [`PartialSurfaceVertex`]
|
||||||
|
pub trait SurfaceVertexBuilder {
|
||||||
|
/// Infer the global form of the partial vertex
|
||||||
|
fn infer_global_form(self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SurfaceVertexBuilder for PartialSurfaceVertex {
|
||||||
|
fn infer_global_form(self) -> Self {
|
||||||
|
self.with_global_form(Some(GlobalVertex::partial()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
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,
|
||||||
|
surface: &Surface,
|
||||||
|
position: impl Into<Point<2>>,
|
||||||
|
) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalVertexBuilder for PartialGlobalVertex {
|
||||||
|
fn update_from_curve_and_position(
|
||||||
|
self,
|
||||||
|
curve: impl Into<MaybePartial<Curve>>,
|
||||||
|
position: impl Into<Point<1>>,
|
||||||
|
) -> Self {
|
||||||
|
let curve = curve.into().into_partial();
|
||||||
|
|
||||||
|
let path = curve.path().expect(
|
||||||
|
"Need path to create `GlobalVertex` from curve and position",
|
||||||
|
);
|
||||||
|
let surface = curve.surface().expect(
|
||||||
|
"Need surface to create `GlobalVertex` from curve and position",
|
||||||
|
);
|
||||||
|
|
||||||
|
let position_surface = path.point_from_path_coords(position);
|
||||||
|
self.update_from_surface_and_position(&surface, position_surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_from_surface_and_position(
|
||||||
|
self,
|
||||||
|
surface: &Surface,
|
||||||
|
position: impl Into<Point<2>>,
|
||||||
|
) -> Self {
|
||||||
|
self.with_position(Some(surface.point_from_surface_coords(position)))
|
||||||
|
}
|
||||||
|
}
|
|
@ -360,6 +360,7 @@ impl<T> Iterator for Iter<T> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
|
builder::CurveBuilder,
|
||||||
objects::{
|
objects::{
|
||||||
Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Objects,
|
Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Objects,
|
||||||
Shell, Sketch, Solid, SurfaceVertex, Vertex,
|
Shell, Sketch, Solid, SurfaceVertex, Vertex,
|
||||||
|
@ -376,7 +377,7 @@ mod tests {
|
||||||
let surface = objects.surfaces.xy_plane();
|
let surface = objects.surfaces.xy_plane();
|
||||||
let object = Curve::partial()
|
let object = Curve::partial()
|
||||||
.with_surface(Some(surface))
|
.with_surface(Some(surface))
|
||||||
.as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects);
|
.build(&objects);
|
||||||
|
|
||||||
assert_eq!(1, object.curve_iter().count());
|
assert_eq!(1, object.curve_iter().count());
|
||||||
|
@ -593,7 +594,7 @@ mod tests {
|
||||||
let surface = objects.surfaces.xy_plane();
|
let surface = objects.surfaces.xy_plane();
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.with_surface(Some(surface.clone()))
|
||||||
.as_u_axis()
|
.update_as_u_axis()
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let global_vertex = objects
|
let global_vertex = objects
|
||||||
.global_vertices
|
.global_vertices
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
||||||
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
||||||
Surface, SurfaceVertex, Vertex,
|
Surface, SurfaceVertex, Vertex,
|
||||||
},
|
},
|
||||||
|
path::SurfacePath,
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
@ -30,6 +31,24 @@ pub enum MaybePartial<T: HasPartial> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: HasPartial> MaybePartial<T> {
|
impl<T: HasPartial> MaybePartial<T> {
|
||||||
|
/// Indicate whether this is a full object
|
||||||
|
pub fn is_full(&self) -> bool {
|
||||||
|
if let Self::Full(_) = self {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Indicate whether this is a partial object
|
||||||
|
pub fn is_partial(&self) -> bool {
|
||||||
|
if let Self::Partial(_) = self {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/// If this is a partial object, update it
|
/// If this is a partial object, update it
|
||||||
///
|
///
|
||||||
/// This is useful whenever a partial object can infer something about its
|
/// This is useful whenever a partial object can infer something about its
|
||||||
|
@ -95,25 +114,37 @@ where
|
||||||
// `MaybePartial<T>`, as that would conflict.
|
// `MaybePartial<T>`, as that would conflict.
|
||||||
|
|
||||||
impl MaybePartial<Curve> {
|
impl MaybePartial<Curve> {
|
||||||
/// Access the global form
|
/// Access the path
|
||||||
pub fn global_form(&self) -> Option<Handle<GlobalCurve>> {
|
pub fn path(&self) -> Option<SurfacePath> {
|
||||||
match self {
|
match self {
|
||||||
Self::Full(full) => Some(full.global_form().clone()),
|
MaybePartial::Full(full) => Some(full.path()),
|
||||||
Self::Partial(partial) => {
|
MaybePartial::Partial(partial) => partial.path(),
|
||||||
partial.global_form.clone().map(Into::into)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Access the surface
|
||||||
|
pub fn surface(&self) -> Option<Handle<Surface>> {
|
||||||
|
match self {
|
||||||
|
MaybePartial::Full(full) => Some(full.surface().clone()),
|
||||||
|
MaybePartial::Partial(partial) => partial.surface(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Access the global form
|
||||||
|
pub fn global_form(&self) -> Option<MaybePartial<GlobalCurve>> {
|
||||||
|
match self {
|
||||||
|
Self::Full(full) => Some(full.global_form().clone().into()),
|
||||||
|
Self::Partial(partial) => partial.global_form(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MaybePartial<GlobalEdge> {
|
impl MaybePartial<GlobalEdge> {
|
||||||
/// Access the curve
|
/// Access the curve
|
||||||
pub fn curve(&self) -> Option<&Handle<GlobalCurve>> {
|
pub fn curve(&self) -> MaybePartial<GlobalCurve> {
|
||||||
match self {
|
match self {
|
||||||
Self::Full(full) => Some(full.curve()),
|
Self::Full(full) => full.curve().clone().into(),
|
||||||
Self::Partial(partial) => {
|
Self::Partial(partial) => partial.curve.clone(),
|
||||||
partial.curve.as_ref().map(|wrapper| &wrapper.0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,15 +185,15 @@ 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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the surface
|
/// Access the surface
|
||||||
pub fn surface(&self) -> Option<&Handle<Surface>> {
|
pub fn surface(&self) -> Option<Handle<Surface>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Full(full) => Some(full.surface()),
|
Self::Full(full) => Some(full.surface().clone()),
|
||||||
Self::Partial(partial) => partial.surface.as_ref(),
|
Self::Partial(partial) => partial.surface(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +203,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.clone(),
|
Self::Partial(partial) => partial.surface_form(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ mod traits;
|
||||||
pub use self::{
|
pub use self::{
|
||||||
maybe_partial::MaybePartial,
|
maybe_partial::MaybePartial,
|
||||||
objects::{
|
objects::{
|
||||||
curve::PartialCurve,
|
curve::{PartialCurve, PartialGlobalCurve},
|
||||||
cycle::PartialCycle,
|
cycle::PartialCycle,
|
||||||
edge::{PartialGlobalEdge, PartialHalfEdge},
|
edge::{PartialGlobalEdge, PartialHalfEdge},
|
||||||
vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex},
|
vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex},
|
||||||
|
|
|
@ -1,35 +1,37 @@
|
||||||
use fj_math::{Point, Scalar, Vector};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{Curve, GlobalCurve, Objects, Surface},
|
objects::{Curve, GlobalCurve, Objects, Surface},
|
||||||
|
partial::MaybePartial,
|
||||||
path::SurfacePath,
|
path::SurfacePath,
|
||||||
storage::{Handle, HandleWrapper},
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A partial [`Curve`]
|
/// A partial [`Curve`]
|
||||||
///
|
///
|
||||||
/// 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)]
|
||||||
pub struct PartialCurve {
|
pub struct PartialCurve {
|
||||||
/// The path that defines the [`Curve`]
|
path: Option<SurfacePath>,
|
||||||
///
|
surface: Option<Handle<Surface>>,
|
||||||
/// Must be provided before calling [`PartialCurve::build`].
|
global_form: Option<MaybePartial<GlobalCurve>>,
|
||||||
pub path: Option<SurfacePath>,
|
|
||||||
|
|
||||||
/// The surface that the [`Curve`] is defined in
|
|
||||||
///
|
|
||||||
/// Must be provided before calling [`PartialCurve::build`].
|
|
||||||
pub surface: Option<Handle<Surface>>,
|
|
||||||
|
|
||||||
/// The global form of the [`Curve`]
|
|
||||||
///
|
|
||||||
/// Will be computed from `path` and `surface` in [`PartialCurve::build`],
|
|
||||||
/// if not provided.
|
|
||||||
pub global_form: Option<HandleWrapper<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
|
/// Provide a path for the partial curve
|
||||||
pub fn with_path(mut self, path: Option<SurfacePath>) -> Self {
|
pub fn with_path(mut self, path: Option<SurfacePath>) -> Self {
|
||||||
if let Some(path) = path {
|
if let Some(path) = path {
|
||||||
|
@ -49,7 +51,7 @@ impl PartialCurve {
|
||||||
/// Provide a global form for the partial curve
|
/// Provide a global form for the partial curve
|
||||||
pub fn with_global_form(
|
pub fn with_global_form(
|
||||||
mut self,
|
mut self,
|
||||||
global_form: Option<impl Into<HandleWrapper<GlobalCurve>>>,
|
global_form: Option<impl Into<MaybePartial<GlobalCurve>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
if let Some(global_form) = global_form {
|
if let Some(global_form) = global_form {
|
||||||
self.global_form = Some(global_form.into());
|
self.global_form = Some(global_form.into());
|
||||||
|
@ -57,32 +59,6 @@ impl PartialCurve {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update partial curve to represent the u-axis
|
|
||||||
pub fn as_u_axis(self) -> Self {
|
|
||||||
let a = Point::origin();
|
|
||||||
let b = a + Vector::unit_u();
|
|
||||||
|
|
||||||
self.as_line_from_points([a, b])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update partial curve to represent the v-axis
|
|
||||||
pub fn as_v_axis(self) -> Self {
|
|
||||||
let a = Point::origin();
|
|
||||||
let b = a + Vector::unit_v();
|
|
||||||
|
|
||||||
self.as_line_from_points([a, b])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update partial curve as a circle, from the provided radius
|
|
||||||
pub fn as_circle_from_radius(self, radius: impl Into<Scalar>) -> Self {
|
|
||||||
self.with_path(Some(SurfacePath::circle_from_radius(radius)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update partial curve as a line, from the provided points
|
|
||||||
pub fn as_line_from_points(self, points: [impl Into<Point<2>>; 2]) -> Self {
|
|
||||||
self.with_path(Some(SurfacePath::line_from_points(points)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build a full [`Curve`] from the partial curve
|
/// Build a full [`Curve`] from the partial curve
|
||||||
pub fn build(
|
pub fn build(
|
||||||
self,
|
self,
|
||||||
|
@ -95,7 +71,8 @@ impl PartialCurve {
|
||||||
let global_form = match self.global_form {
|
let global_form = match self.global_form {
|
||||||
Some(global_form) => global_form,
|
Some(global_form) => global_form,
|
||||||
None => objects.global_curves.insert(GlobalCurve)?.into(),
|
None => objects.global_curves.insert(GlobalCurve)?.into(),
|
||||||
};
|
}
|
||||||
|
.into_full(objects)?;
|
||||||
|
|
||||||
Ok(objects
|
Ok(objects
|
||||||
.curves
|
.curves
|
||||||
|
@ -112,3 +89,31 @@ impl From<&Curve> for PartialCurve {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A partial [`GlobalCurve`]
|
||||||
|
///
|
||||||
|
/// This struct might seem unnecessary. [`GlobalCurve`] literally has nothing in
|
||||||
|
/// it. Why would we need to represent a part of nothing? However, having this
|
||||||
|
/// provides some regularity that helps simplify some things within the partial
|
||||||
|
/// object and builder APIs.
|
||||||
|
///
|
||||||
|
/// See [`crate::partial`] for more information.
|
||||||
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||||
|
pub struct PartialGlobalCurve;
|
||||||
|
|
||||||
|
impl PartialGlobalCurve {
|
||||||
|
/// Build a full [`GlobalCurve`] from the partial global curve
|
||||||
|
pub fn build(
|
||||||
|
self,
|
||||||
|
objects: &Objects,
|
||||||
|
) -> Result<Handle<GlobalCurve>, ValidationError> {
|
||||||
|
let global_curve = objects.global_curves.insert(GlobalCurve)?;
|
||||||
|
Ok(global_curve)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&GlobalCurve> for PartialGlobalCurve {
|
||||||
|
fn from(_: &GlobalCurve) -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use fj_math::Point;
|
use fj_math::Point;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
builder::CurveBuilder,
|
||||||
objects::{
|
objects::{
|
||||||
Curve, Cycle, HalfEdge, Objects, Surface, SurfaceVertex, Vertex,
|
Curve, Cycle, HalfEdge, Objects, Surface, SurfaceVertex, Vertex,
|
||||||
},
|
},
|
||||||
|
@ -12,7 +13,7 @@ use crate::{
|
||||||
/// A partial [`Cycle`]
|
/// A partial [`Cycle`]
|
||||||
///
|
///
|
||||||
/// 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)]
|
||||||
pub struct PartialCycle {
|
pub struct PartialCycle {
|
||||||
/// The surface that the [`Cycle`] is defined in
|
/// The surface that the [`Cycle`] is defined in
|
||||||
pub surface: Option<Handle<Surface>>,
|
pub surface: Option<Handle<Surface>>,
|
||||||
|
@ -82,7 +83,7 @@ impl PartialCycle {
|
||||||
|
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_surface(Some(surface.clone()))
|
.with_surface(Some(surface.clone()))
|
||||||
.as_line_from_points([position_prev, position_next]);
|
.update_as_line_from_points([position_prev, position_next]);
|
||||||
|
|
||||||
let [from, to] =
|
let [from, to] =
|
||||||
[(0., from), (1., to)].map(|(position, surface_form)| {
|
[(0., from), (1., to)].map(|(position, surface_form)| {
|
||||||
|
|
|
@ -2,19 +2,20 @@ use fj_interop::ext::ArrayExt;
|
||||||
use fj_math::{Point, Scalar};
|
use fj_math::{Point, Scalar};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
builder::{CurveBuilder, GlobalVertexBuilder},
|
||||||
objects::{
|
objects::{
|
||||||
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
||||||
Surface, SurfaceVertex, Vertex, VerticesInNormalizedOrder,
|
Surface, SurfaceVertex, Vertex, VerticesInNormalizedOrder,
|
||||||
},
|
},
|
||||||
partial::{HasPartial, MaybePartial},
|
partial::{HasPartial, MaybePartial},
|
||||||
storage::{Handle, HandleWrapper},
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A partial [`HalfEdge`]
|
/// A partial [`HalfEdge`]
|
||||||
///
|
///
|
||||||
/// 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)]
|
||||||
pub struct PartialHalfEdge {
|
pub struct PartialHalfEdge {
|
||||||
/// The surface that the [`HalfEdge`]'s [`Curve`] is defined in
|
/// The surface that the [`HalfEdge`]'s [`Curve`] is defined in
|
||||||
pub surface: Option<Handle<Surface>>,
|
pub surface: Option<Handle<Surface>>,
|
||||||
|
@ -35,10 +36,10 @@ impl PartialHalfEdge {
|
||||||
/// Extract the global curve from either the curve or global form
|
/// Extract the global curve from either the curve or global form
|
||||||
///
|
///
|
||||||
/// If a global curve is available through both, the curve is preferred.
|
/// If a global curve is available through both, the curve is preferred.
|
||||||
pub fn extract_global_curve(&self) -> Option<Handle<GlobalCurve>> {
|
pub fn extract_global_curve(&self) -> MaybePartial<GlobalCurve> {
|
||||||
self.curve
|
self.curve
|
||||||
.global_form()
|
.global_form()
|
||||||
.or_else(|| self.global_form.curve().cloned())
|
.unwrap_or_else(|| self.global_form.curve())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the vertices of the global form, if available
|
/// Access the vertices of the global form, if available
|
||||||
|
@ -127,11 +128,11 @@ impl PartialHalfEdge {
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
) -> Result<Self, ValidationError> {
|
) -> Result<Self, ValidationError> {
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_global_form(self.extract_global_curve())
|
.with_global_form(Some(self.extract_global_curve()))
|
||||||
.with_surface(self.surface.clone())
|
.with_surface(self.surface.clone())
|
||||||
.as_circle_from_radius(radius);
|
.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]));
|
||||||
|
@ -141,7 +142,7 @@ impl PartialHalfEdge {
|
||||||
.map(|[global_form, _]| global_form)
|
.map(|[global_form, _]| global_form)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
GlobalVertex::partial()
|
GlobalVertex::partial()
|
||||||
.from_curve_and_position(curve.clone(), a_curve)
|
.update_from_curve_and_position(curve.clone(), a_curve)
|
||||||
.into()
|
.into()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -190,11 +191,10 @@ impl PartialHalfEdge {
|
||||||
|
|
||||||
let surface = self
|
let surface = self
|
||||||
.surface
|
.surface
|
||||||
.as_ref()
|
.clone()
|
||||||
.or_else(|| from_surface.surface())
|
.or_else(|| from_surface.surface())
|
||||||
.or_else(|| to_surface.surface())
|
.or_else(|| to_surface.surface())
|
||||||
.expect("Can't infer line segment without a surface")
|
.expect("Can't infer line segment without a surface");
|
||||||
.clone();
|
|
||||||
let points = [&from_surface, &to_surface].map(|vertex| {
|
let points = [&from_surface, &to_surface].map(|vertex| {
|
||||||
vertex
|
vertex
|
||||||
.position()
|
.position()
|
||||||
|
@ -202,9 +202,9 @@ impl PartialHalfEdge {
|
||||||
});
|
});
|
||||||
|
|
||||||
let curve = Curve::partial()
|
let curve = Curve::partial()
|
||||||
.with_global_form(self.extract_global_curve())
|
.with_global_form(Some(self.extract_global_curve()))
|
||||||
.with_surface(Some(surface))
|
.with_surface(Some(surface))
|
||||||
.as_line_from_points(points);
|
.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)| {
|
||||||
|
@ -252,9 +252,11 @@ impl PartialHalfEdge {
|
||||||
vertices.zip_ext(global_forms).map(|(vertex, global_form)| {
|
vertices.zip_ext(global_forms).map(|(vertex, global_form)| {
|
||||||
vertex.update_partial(|vertex| {
|
vertex.update_partial(|vertex| {
|
||||||
vertex.clone().with_surface_form(Some(
|
vertex.clone().with_surface_form(Some(
|
||||||
vertex.surface_form.update_partial(|surface_vertex| {
|
vertex.surface_form().update_partial(
|
||||||
surface_vertex.with_global_form(global_form)
|
|surface_vertex| {
|
||||||
}),
|
surface_vertex.with_global_form(global_form)
|
||||||
|
},
|
||||||
|
),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -312,12 +314,12 @@ impl From<&HalfEdge> for PartialHalfEdge {
|
||||||
/// A partial [`GlobalEdge`]
|
/// A partial [`GlobalEdge`]
|
||||||
///
|
///
|
||||||
/// 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)]
|
||||||
pub struct PartialGlobalEdge {
|
pub struct PartialGlobalEdge {
|
||||||
/// The curve that the [`GlobalEdge`] is defined in
|
/// The curve that the [`GlobalEdge`] is defined in
|
||||||
///
|
///
|
||||||
/// Must be provided before [`PartialGlobalEdge::build`] is called.
|
/// Must be provided before [`PartialGlobalEdge::build`] is called.
|
||||||
pub curve: Option<HandleWrapper<GlobalCurve>>,
|
pub curve: MaybePartial<GlobalCurve>,
|
||||||
|
|
||||||
/// The vertices that bound the [`GlobalEdge`] in the curve
|
/// The vertices that bound the [`GlobalEdge`] in the curve
|
||||||
///
|
///
|
||||||
|
@ -327,9 +329,12 @@ pub struct PartialGlobalEdge {
|
||||||
|
|
||||||
impl PartialGlobalEdge {
|
impl PartialGlobalEdge {
|
||||||
/// Update the partial global edge with the given curve
|
/// Update the partial global edge with the given curve
|
||||||
pub fn with_curve(mut self, curve: Option<Handle<GlobalCurve>>) -> Self {
|
pub fn with_curve(
|
||||||
|
mut self,
|
||||||
|
curve: Option<impl Into<MaybePartial<GlobalCurve>>>,
|
||||||
|
) -> Self {
|
||||||
if let Some(curve) = curve {
|
if let Some(curve) = curve {
|
||||||
self.curve = Some(curve.into());
|
self.curve = curve.into();
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -362,9 +367,7 @@ impl PartialGlobalEdge {
|
||||||
self,
|
self,
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
) -> Result<Handle<GlobalEdge>, ValidationError> {
|
) -> Result<Handle<GlobalEdge>, ValidationError> {
|
||||||
let curve = self
|
let curve = self.curve.into_full(objects)?;
|
||||||
.curve
|
|
||||||
.expect("Can't build `GlobalEdge` without `GlobalCurve`");
|
|
||||||
let vertices = self
|
let vertices = self
|
||||||
.vertices
|
.vertices
|
||||||
.expect("Can't build `GlobalEdge` without vertices")
|
.expect("Can't build `GlobalEdge` without vertices")
|
||||||
|
@ -379,7 +382,7 @@ impl PartialGlobalEdge {
|
||||||
impl From<&GlobalEdge> for PartialGlobalEdge {
|
impl From<&GlobalEdge> for PartialGlobalEdge {
|
||||||
fn from(global_edge: &GlobalEdge) -> Self {
|
fn from(global_edge: &GlobalEdge) -> Self {
|
||||||
Self {
|
Self {
|
||||||
curve: Some(global_edge.curve().clone().into()),
|
curve: global_edge.curve().clone().into(),
|
||||||
vertices: Some(
|
vertices: Some(
|
||||||
global_edge
|
global_edge
|
||||||
.vertices()
|
.vertices()
|
||||||
|
|
|
@ -5,7 +5,7 @@ pub mod vertex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{
|
objects::{
|
||||||
Curve, Cycle, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
Curve, Cycle, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
||||||
SurfaceVertex, Vertex,
|
SurfaceVertex, Vertex,
|
||||||
},
|
},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
|
@ -13,8 +13,8 @@ use crate::{
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
HasPartial, MaybePartial, Partial, PartialCurve, PartialCycle,
|
HasPartial, MaybePartial, Partial, PartialCurve, PartialCycle,
|
||||||
PartialGlobalEdge, PartialGlobalVertex, PartialHalfEdge,
|
PartialGlobalCurve, PartialGlobalEdge, PartialGlobalVertex,
|
||||||
PartialSurfaceVertex, PartialVertex,
|
PartialHalfEdge, PartialSurfaceVertex, PartialVertex,
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! impl_traits {
|
macro_rules! impl_traits {
|
||||||
|
@ -49,6 +49,7 @@ macro_rules! impl_traits {
|
||||||
impl_traits!(
|
impl_traits!(
|
||||||
Curve, PartialCurve;
|
Curve, PartialCurve;
|
||||||
Cycle, PartialCycle;
|
Cycle, PartialCycle;
|
||||||
|
GlobalCurve, PartialGlobalCurve;
|
||||||
GlobalEdge, PartialGlobalEdge;
|
GlobalEdge, PartialGlobalEdge;
|
||||||
GlobalVertex, PartialGlobalVertex;
|
GlobalVertex, PartialGlobalVertex;
|
||||||
HalfEdge, PartialHalfEdge;
|
HalfEdge, PartialHalfEdge;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use fj_math::Point;
|
use fj_math::Point;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
builder::GlobalVertexBuilder,
|
||||||
objects::{Curve, GlobalVertex, Objects, Surface, SurfaceVertex, Vertex},
|
objects::{Curve, GlobalVertex, Objects, Surface, SurfaceVertex, Vertex},
|
||||||
partial::{HasPartial, MaybePartial},
|
partial::MaybePartial,
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
@ -10,26 +11,29 @@ use crate::{
|
||||||
/// A partial [`Vertex`]
|
/// A partial [`Vertex`]
|
||||||
///
|
///
|
||||||
/// 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)]
|
||||||
pub struct PartialVertex {
|
pub struct PartialVertex {
|
||||||
/// The position of the [`Vertex`] on the [`Curve`]
|
position: Option<Point<1>>,
|
||||||
///
|
curve: MaybePartial<Curve>,
|
||||||
/// Must be provided before [`PartialVertex::build`] is called.
|
surface_form: MaybePartial<SurfaceVertex>,
|
||||||
pub position: Option<Point<1>>,
|
|
||||||
|
|
||||||
/// The curve that the [`Vertex`] is defined in
|
|
||||||
///
|
|
||||||
/// Must be provided before [`PartialVertex::build`] is called.
|
|
||||||
pub curve: MaybePartial<Curve>,
|
|
||||||
|
|
||||||
/// The surface form of the [`Vertex`]
|
|
||||||
///
|
|
||||||
/// Can be provided, if already available, or computed from the position on
|
|
||||||
/// the [`Curve`].
|
|
||||||
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
|
/// Provide a position for the partial vertex
|
||||||
pub fn with_position(
|
pub fn with_position(
|
||||||
mut self,
|
mut self,
|
||||||
|
@ -63,19 +67,13 @@ impl PartialVertex {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the surface form of the partial vertex, inferring it on build
|
|
||||||
pub fn infer_surface_form(mut self) -> Self {
|
|
||||||
self.surface_form = SurfaceVertex::partial().into();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build a full [`Vertex`] from the partial vertex
|
/// Build a full [`Vertex`] from the partial vertex
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics, if no position has been provided.
|
/// Panics, if position has not been provided.
|
||||||
///
|
///
|
||||||
/// Panics, if no curve has been provided.
|
/// Panics, if curve has not been provided.
|
||||||
pub fn build(
|
pub fn build(
|
||||||
self,
|
self,
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
|
@ -121,24 +119,27 @@ 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 {
|
||||||
/// The position of the [`SurfaceVertex`] in the [`Surface`]
|
position: Option<Point<2>>,
|
||||||
///
|
surface: Option<Handle<Surface>>,
|
||||||
/// Must be provided before [`PartialSurfaceVertex::build`] is called.
|
global_form: MaybePartial<GlobalVertex>,
|
||||||
pub position: Option<Point<2>>,
|
|
||||||
|
|
||||||
/// The surface that the [`SurfaceVertex`] is defined in
|
|
||||||
///
|
|
||||||
/// Must be provided before [`PartialSurfaceVertex::build`] is called.
|
|
||||||
pub surface: Option<Handle<Surface>>,
|
|
||||||
|
|
||||||
/// The global form of the [`SurfaceVertex`]
|
|
||||||
///
|
|
||||||
/// Can be provided, if already available, or computed from the position on
|
|
||||||
/// the [`Surface`].
|
|
||||||
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
|
/// Provide a position for the partial surface vertex
|
||||||
pub fn with_position(
|
pub fn with_position(
|
||||||
mut self,
|
mut self,
|
||||||
|
@ -169,19 +170,7 @@ impl PartialSurfaceVertex {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the global form of the partial vertex, inferring it on build
|
|
||||||
pub fn infer_global_form(mut self) -> Self {
|
|
||||||
self.global_form = GlobalVertex::partial().into();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build a full [`SurfaceVertex`] from the partial surface vertex
|
/// Build a full [`SurfaceVertex`] from the partial surface vertex
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics, if no position has been provided.
|
|
||||||
///
|
|
||||||
/// Panics, if no surface has been provided.
|
|
||||||
pub fn build(
|
pub fn build(
|
||||||
self,
|
self,
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
|
@ -196,7 +185,7 @@ impl PartialSurfaceVertex {
|
||||||
let global_form = self
|
let global_form = self
|
||||||
.global_form
|
.global_form
|
||||||
.update_partial(|global_form| {
|
.update_partial(|global_form| {
|
||||||
global_form.from_surface_and_position(&surface, position)
|
global_form.update_from_surface_and_position(&surface, position)
|
||||||
})
|
})
|
||||||
.into_full(objects)?;
|
.into_full(objects)?;
|
||||||
|
|
||||||
|
@ -223,13 +212,15 @@ 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 {
|
||||||
/// The position of the [`GlobalVertex`]
|
position: Option<Point<3>>,
|
||||||
///
|
|
||||||
/// Must be provided before [`PartialGlobalVertex::build`] is called.
|
|
||||||
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
|
/// Provide a position for the partial global vertex
|
||||||
pub fn with_position(
|
pub fn with_position(
|
||||||
mut self,
|
mut self,
|
||||||
|
@ -241,35 +232,6 @@ impl PartialGlobalVertex {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update partial global vertex from the given curve and position on it
|
|
||||||
pub fn from_curve_and_position(
|
|
||||||
self,
|
|
||||||
curve: impl Into<MaybePartial<Curve>>,
|
|
||||||
position: impl Into<Point<1>>,
|
|
||||||
) -> Self {
|
|
||||||
let curve = curve.into().into_partial();
|
|
||||||
|
|
||||||
let path = curve.path.expect(
|
|
||||||
"Need path to create `GlobalVertex` from curve and position",
|
|
||||||
);
|
|
||||||
let surface = curve.surface.expect(
|
|
||||||
"Need surface to create `GlobalVertex` from curve and position",
|
|
||||||
);
|
|
||||||
|
|
||||||
let position_surface = path.point_from_path_coords(position);
|
|
||||||
self.from_surface_and_position(&surface, position_surface)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update partial global vertex from the given surface and position on it
|
|
||||||
pub fn from_surface_and_position(
|
|
||||||
mut self,
|
|
||||||
surface: &Surface,
|
|
||||||
position: impl Into<Point<2>>,
|
|
||||||
) -> Self {
|
|
||||||
self.position = Some(surface.point_from_surface_coords(position));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build a full [`GlobalVertex`] from the partial global vertex
|
/// Build a full [`GlobalVertex`] from the partial global vertex
|
||||||
pub fn build(
|
pub fn build(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -196,6 +196,7 @@ mod tests {
|
||||||
use fj_interop::ext::ArrayExt;
|
use fj_interop::ext::ArrayExt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
builder::VertexBuilder,
|
||||||
objects::{GlobalCurve, HalfEdge, Objects},
|
objects::{GlobalCurve, HalfEdge, Objects},
|
||||||
partial::HasPartial,
|
partial::HasPartial,
|
||||||
validate::Validate2,
|
validate::Validate2,
|
||||||
|
|
|
@ -179,6 +179,7 @@ impl SurfaceVertexValidationError {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
|
builder::{CurveBuilder, SurfaceVertexBuilder},
|
||||||
objects::{Curve, GlobalVertex, Objects, SurfaceVertex, Vertex},
|
objects::{Curve, GlobalVertex, Objects, SurfaceVertex, Vertex},
|
||||||
partial::HasPartial,
|
partial::HasPartial,
|
||||||
validate::Validate2,
|
validate::Validate2,
|
||||||
|
@ -193,7 +194,7 @@ mod tests {
|
||||||
.with_curve(Some(
|
.with_curve(Some(
|
||||||
Curve::partial()
|
Curve::partial()
|
||||||
.with_surface(Some(objects.surfaces.xy_plane()))
|
.with_surface(Some(objects.surfaces.xy_plane()))
|
||||||
.as_u_axis(),
|
.update_as_u_axis(),
|
||||||
))
|
))
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let invalid = Vertex::new(
|
let invalid = Vertex::new(
|
||||||
|
@ -221,7 +222,7 @@ mod tests {
|
||||||
.with_curve(Some(
|
.with_curve(Some(
|
||||||
Curve::partial()
|
Curve::partial()
|
||||||
.with_surface(Some(objects.surfaces.xy_plane()))
|
.with_surface(Some(objects.surfaces.xy_plane()))
|
||||||
.as_u_axis(),
|
.update_as_u_axis(),
|
||||||
))
|
))
|
||||||
.build(&objects)?;
|
.build(&objects)?;
|
||||||
let invalid = Vertex::new(
|
let invalid = Vertex::new(
|
||||||
|
|
Loading…
Reference in New Issue