mirror of https://github.com/hannobraun/Fornjot
Extract builder methods from `PartialCycle`
This commit is contained in:
parent
9a6c72caaf
commit
f4bf0aa8cf
|
@ -0,0 +1,134 @@
|
||||||
|
use fj_math::Point;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
objects::{Curve, HalfEdge, SurfaceVertex, Vertex},
|
||||||
|
partial::{HasPartial, MaybePartial, PartialCycle},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{CurveBuilder, HalfEdgeBuilder};
|
||||||
|
|
||||||
|
/// Builder API for [`PartialCycle`]
|
||||||
|
pub trait CycleBuilder {
|
||||||
|
/// Update the partial cycle with a polygonal chain from the provided points
|
||||||
|
fn with_poly_chain(
|
||||||
|
self,
|
||||||
|
vertices: impl IntoIterator<Item = MaybePartial<SurfaceVertex>>,
|
||||||
|
) -> Self;
|
||||||
|
|
||||||
|
/// Update the partial cycle with a polygonal chain from the provided points
|
||||||
|
fn with_poly_chain_from_points(
|
||||||
|
self,
|
||||||
|
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
||||||
|
) -> Self;
|
||||||
|
|
||||||
|
/// Update the partial cycle by closing it with a line segment
|
||||||
|
///
|
||||||
|
/// Builds a line segment from the last and first vertex, closing the cycle.
|
||||||
|
fn close_with_line_segment(self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CycleBuilder for PartialCycle {
|
||||||
|
fn with_poly_chain(
|
||||||
|
self,
|
||||||
|
vertices: impl IntoIterator<Item = MaybePartial<SurfaceVertex>>,
|
||||||
|
) -> Self {
|
||||||
|
let iter = self
|
||||||
|
.half_edges()
|
||||||
|
.last()
|
||||||
|
.map(|half_edge| {
|
||||||
|
let [_, last] = half_edge.vertices();
|
||||||
|
last.surface_form()
|
||||||
|
})
|
||||||
|
.into_iter()
|
||||||
|
.chain(vertices);
|
||||||
|
|
||||||
|
let mut previous: Option<MaybePartial<SurfaceVertex>> = None;
|
||||||
|
|
||||||
|
let mut half_edges = Vec::new();
|
||||||
|
for vertex_next in iter {
|
||||||
|
if let Some(vertex_prev) = previous {
|
||||||
|
let surface = self
|
||||||
|
.surface()
|
||||||
|
.clone()
|
||||||
|
.expect("Need surface to extend cycle with poly-chain");
|
||||||
|
|
||||||
|
let position_prev = vertex_prev
|
||||||
|
.position()
|
||||||
|
.expect("Need surface position to extend cycle");
|
||||||
|
let position_next = vertex_next
|
||||||
|
.position()
|
||||||
|
.expect("Need surface position to extend cycle");
|
||||||
|
|
||||||
|
let from = vertex_prev.update_partial(|partial| {
|
||||||
|
partial.with_surface(Some(surface.clone()))
|
||||||
|
});
|
||||||
|
let to = vertex_next.update_partial(|partial| {
|
||||||
|
partial.with_surface(Some(surface.clone()))
|
||||||
|
});
|
||||||
|
|
||||||
|
previous = Some(to.clone());
|
||||||
|
|
||||||
|
let curve = Curve::partial()
|
||||||
|
.with_surface(Some(surface.clone()))
|
||||||
|
.update_as_line_from_points([position_prev, position_next]);
|
||||||
|
|
||||||
|
let [from, to] =
|
||||||
|
[(0., from), (1., to)].map(|(position, surface_form)| {
|
||||||
|
Vertex::partial()
|
||||||
|
.with_curve(Some(curve.clone()))
|
||||||
|
.with_position(Some([position]))
|
||||||
|
.with_surface_form(Some(surface_form))
|
||||||
|
});
|
||||||
|
|
||||||
|
half_edges.push(
|
||||||
|
HalfEdge::partial()
|
||||||
|
.with_curve(Some(curve))
|
||||||
|
.with_vertices(Some([from, to])),
|
||||||
|
);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = Some(vertex_next);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.with_half_edges(half_edges)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_poly_chain_from_points(
|
||||||
|
self,
|
||||||
|
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
||||||
|
) -> Self {
|
||||||
|
self.with_poly_chain(points.into_iter().map(|position| {
|
||||||
|
SurfaceVertex::partial()
|
||||||
|
.with_position(Some(position))
|
||||||
|
.into()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close_with_line_segment(self) -> Self {
|
||||||
|
let first = self.half_edges().next();
|
||||||
|
let last = self.half_edges().last();
|
||||||
|
|
||||||
|
let vertices = [first, last]
|
||||||
|
.map(|option| option.map(|half_edge| half_edge.vertices()));
|
||||||
|
|
||||||
|
let [Some([first, _]), Some([_, last])] = vertices else {
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
let vertices = [last, first].map(|vertex| {
|
||||||
|
vertex
|
||||||
|
.surface_form()
|
||||||
|
.position()
|
||||||
|
.expect("Need surface position to close cycle")
|
||||||
|
});
|
||||||
|
let surface = self.surface().expect("Need surface to close cycle");
|
||||||
|
|
||||||
|
self.with_half_edges(Some(
|
||||||
|
HalfEdge::partial()
|
||||||
|
.with_surface(Some(surface))
|
||||||
|
.update_as_line_segment_from_points(vertices),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,8 @@ use crate::{
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::CycleBuilder;
|
||||||
|
|
||||||
/// API for building a [`Face`]
|
/// API for building a [`Face`]
|
||||||
///
|
///
|
||||||
/// Also see [`Face::builder`].
|
/// Also see [`Face::builder`].
|
||||||
|
|
|
@ -10,11 +10,13 @@ mod solid;
|
||||||
|
|
||||||
// These are new-style builders that build on top of the partial object API.
|
// These are new-style builders that build on top of the partial object API.
|
||||||
mod curve;
|
mod curve;
|
||||||
|
mod cycle;
|
||||||
mod edge;
|
mod edge;
|
||||||
mod vertex;
|
mod vertex;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
curve::CurveBuilder,
|
curve::CurveBuilder,
|
||||||
|
cycle::CycleBuilder,
|
||||||
edge::{GlobalEdgeBuilder, HalfEdgeBuilder},
|
edge::{GlobalEdgeBuilder, HalfEdgeBuilder},
|
||||||
face::FaceBuilder,
|
face::FaceBuilder,
|
||||||
shell::ShellBuilder,
|
shell::ShellBuilder,
|
||||||
|
|
|
@ -360,7 +360,7 @@ impl<T> Iterator for Iter<T> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::{CurveBuilder, HalfEdgeBuilder},
|
builder::{CurveBuilder, CycleBuilder, HalfEdgeBuilder},
|
||||||
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,
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
use fj_math::Point;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::{CurveBuilder, HalfEdgeBuilder},
|
objects::{Cycle, HalfEdge, Objects, Surface},
|
||||||
objects::{
|
partial::MaybePartial,
|
||||||
Curve, Cycle, HalfEdge, Objects, Surface, SurfaceVertex, Vertex,
|
|
||||||
},
|
|
||||||
partial::{HasPartial, MaybePartial},
|
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
@ -48,115 +43,6 @@ impl PartialCycle {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the partial cycle with a polygonal chain from the provided points
|
|
||||||
pub fn with_poly_chain(
|
|
||||||
self,
|
|
||||||
vertices: impl IntoIterator<Item = MaybePartial<SurfaceVertex>>,
|
|
||||||
) -> Self {
|
|
||||||
let iter = self
|
|
||||||
.half_edges()
|
|
||||||
.last()
|
|
||||||
.map(|half_edge| {
|
|
||||||
let [_, last] = half_edge.vertices();
|
|
||||||
last.surface_form()
|
|
||||||
})
|
|
||||||
.into_iter()
|
|
||||||
.chain(vertices);
|
|
||||||
|
|
||||||
let mut previous: Option<MaybePartial<SurfaceVertex>> = None;
|
|
||||||
|
|
||||||
let mut half_edges = Vec::new();
|
|
||||||
for vertex_next in iter {
|
|
||||||
if let Some(vertex_prev) = previous {
|
|
||||||
let surface = self
|
|
||||||
.surface()
|
|
||||||
.clone()
|
|
||||||
.expect("Need surface to extend cycle with poly-chain");
|
|
||||||
|
|
||||||
let position_prev = vertex_prev
|
|
||||||
.position()
|
|
||||||
.expect("Need surface position to extend cycle");
|
|
||||||
let position_next = vertex_next
|
|
||||||
.position()
|
|
||||||
.expect("Need surface position to extend cycle");
|
|
||||||
|
|
||||||
let from = vertex_prev.update_partial(|partial| {
|
|
||||||
partial.with_surface(Some(surface.clone()))
|
|
||||||
});
|
|
||||||
let to = vertex_next.update_partial(|partial| {
|
|
||||||
partial.with_surface(Some(surface.clone()))
|
|
||||||
});
|
|
||||||
|
|
||||||
previous = Some(to.clone());
|
|
||||||
|
|
||||||
let curve = Curve::partial()
|
|
||||||
.with_surface(Some(surface.clone()))
|
|
||||||
.update_as_line_from_points([position_prev, position_next]);
|
|
||||||
|
|
||||||
let [from, to] =
|
|
||||||
[(0., from), (1., to)].map(|(position, surface_form)| {
|
|
||||||
Vertex::partial()
|
|
||||||
.with_curve(Some(curve.clone()))
|
|
||||||
.with_position(Some([position]))
|
|
||||||
.with_surface_form(Some(surface_form))
|
|
||||||
});
|
|
||||||
|
|
||||||
half_edges.push(
|
|
||||||
HalfEdge::partial()
|
|
||||||
.with_curve(Some(curve))
|
|
||||||
.with_vertices(Some([from, to])),
|
|
||||||
);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
previous = Some(vertex_next);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.with_half_edges(half_edges)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update the partial cycle with a polygonal chain from the provided points
|
|
||||||
pub fn with_poly_chain_from_points(
|
|
||||||
self,
|
|
||||||
points: impl IntoIterator<Item = impl Into<Point<2>>>,
|
|
||||||
) -> Self {
|
|
||||||
self.with_poly_chain(points.into_iter().map(|position| {
|
|
||||||
SurfaceVertex::partial()
|
|
||||||
.with_position(Some(position))
|
|
||||||
.into()
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update the partial cycle by closing it with a line segment
|
|
||||||
///
|
|
||||||
/// Builds a line segment from the last and first vertex, closing the cycle.
|
|
||||||
pub fn close_with_line_segment(self) -> Self {
|
|
||||||
let first = self.half_edges().next();
|
|
||||||
let last = self.half_edges().last();
|
|
||||||
|
|
||||||
let vertices = [first, last]
|
|
||||||
.map(|option| option.map(|half_edge| half_edge.vertices()));
|
|
||||||
|
|
||||||
let [Some([first, _]), Some([_, last])] = vertices else {
|
|
||||||
return self;
|
|
||||||
};
|
|
||||||
|
|
||||||
let vertices = [last, first].map(|vertex| {
|
|
||||||
vertex
|
|
||||||
.surface_form()
|
|
||||||
.position()
|
|
||||||
.expect("Need surface position to close cycle")
|
|
||||||
});
|
|
||||||
let surface = self.surface().expect("Need surface to close cycle");
|
|
||||||
|
|
||||||
self.with_half_edges(Some(
|
|
||||||
HalfEdge::partial()
|
|
||||||
.with_surface(Some(surface))
|
|
||||||
.update_as_line_segment_from_points(vertices),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build a full [`Cycle`] from the partial cycle
|
/// Build a full [`Cycle`] from the partial cycle
|
||||||
pub fn build(
|
pub fn build(
|
||||||
mut self,
|
mut self,
|
||||||
|
|
Loading…
Reference in New Issue