use fj_math::Point;
use crate::{
objects::{Curve, GlobalVertex, Surface, SurfaceVertex, Vertex},
partial::{HasPartial, MaybePartial},
stores::{Handle, Stores},
};
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct PartialVertex {
pub position: Option<Point<1>>,
pub curve: Option<MaybePartial<Handle<Curve>>>,
pub surface_form: Option<MaybePartial<SurfaceVertex>>,
pub global_form: Option<MaybePartial<Handle<GlobalVertex>>>,
}
impl PartialVertex {
pub fn with_position(
mut self,
position: Option<impl Into<Point<1>>>,
) -> Self {
if let Some(position) = position {
self.position = Some(position.into());
}
self
}
pub fn with_curve(
mut self,
curve: Option<impl Into<MaybePartial<Handle<Curve>>>>,
) -> Self {
if let Some(curve) = curve {
self.curve = Some(curve.into());
}
self
}
pub fn with_surface_form(
mut self,
surface_form: Option<impl Into<MaybePartial<SurfaceVertex>>>,
) -> Self {
if let Some(surface_form) = surface_form {
self.surface_form = Some(surface_form.into());
}
self
}
pub fn with_global_form(
mut self,
global_form: Option<impl Into<MaybePartial<Handle<GlobalVertex>>>>,
) -> Self {
if let Some(global_form) = global_form {
self.global_form = Some(global_form.into());
}
self
}
pub fn build(self, stores: &Stores) -> Vertex {
let position = self
.position
.expect("Cant' build `Vertex` without position");
let curve = self
.curve
.expect("Can't build `Vertex` without `Curve`")
.into_full(stores);
let surface_form = self
.surface_form
.unwrap_or_else(|| SurfaceVertex::partial().into())
.update_partial(|partial| {
let position = partial.position.unwrap_or_else(|| {
curve.path().point_from_path_coords(position)
});
partial
.with_position(Some(position))
.with_surface(Some(curve.surface().clone()))
.with_global_form(self.global_form)
})
.into_full(stores);
Vertex::new(position, curve, surface_form)
}
}
impl From<&Vertex> for PartialVertex {
fn from(vertex: &Vertex) -> Self {
Self {
position: Some(vertex.position()),
curve: Some(vertex.curve().clone().into()),
surface_form: Some(vertex.surface_form().clone().into()),
global_form: Some((vertex.global_form().clone()).into()),
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct PartialSurfaceVertex {
pub position: Option<Point<2>>,
pub surface: Option<Handle<Surface>>,
pub global_form: Option<MaybePartial<Handle<GlobalVertex>>>,
}
impl PartialSurfaceVertex {
pub fn with_position(
mut self,
position: Option<impl Into<Point<2>>>,
) -> Self {
if let Some(position) = position {
self.position = Some(position.into());
}
self
}
pub fn with_surface(mut self, surface: Option<Handle<Surface>>) -> Self {
if let Some(surface) = surface {
self.surface = Some(surface);
}
self
}
pub fn with_global_form(
mut self,
global_form: Option<impl Into<MaybePartial<Handle<GlobalVertex>>>>,
) -> Self {
if let Some(global_form) = global_form {
self.global_form = Some(global_form.into());
}
self
}
pub fn build(self, stores: &Stores) -> SurfaceVertex {
let position = self
.position
.expect("Can't build `SurfaceVertex` without position");
let surface = self
.surface
.expect("Can't build `SurfaceVertex` without `Surface`");
let global_form = self
.global_form
.unwrap_or_else(|| {
Handle::<GlobalVertex>::partial()
.from_surface_and_position(&surface, position)
.into()
})
.into_full(stores);
SurfaceVertex::new(position, surface, global_form)
}
}
impl From<&SurfaceVertex> for PartialSurfaceVertex {
fn from(surface_vertex: &SurfaceVertex) -> Self {
Self {
position: Some(surface_vertex.position()),
surface: Some(surface_vertex.surface().clone()),
global_form: Some((surface_vertex.global_form().clone()).into()),
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct PartialGlobalVertex {
pub position: Option<Point<3>>,
}
impl PartialGlobalVertex {
pub fn with_position(
mut self,
position: Option<impl Into<Point<3>>>,
) -> Self {
if let Some(position) = position {
self.position = Some(position.into());
}
self
}
pub fn from_curve_and_position(
self,
curve: impl Into<MaybePartial<Handle<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)
}
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
}
pub fn build(self, stores: &Stores) -> Handle<GlobalVertex> {
let position = self
.position
.expect("Can't build a `GlobalVertex` without a position");
GlobalVertex::from_position(position, stores)
}
}
impl From<&Handle<GlobalVertex>> for PartialGlobalVertex {
fn from(global_vertex: &Handle<GlobalVertex>) -> Self {
Self {
position: Some(global_vertex.position()),
}
}
}