mirror of
https://github.com/hannobraun/Fornjot
synced 2025-02-25 00:25:51 +00:00
Merge pull request #418 from hannobraun/builder
Extend builder API, use it to simplify approximation tests
This commit is contained in:
commit
a53c275ddd
@ -120,7 +120,7 @@ mod tests {
|
||||
use crate::{
|
||||
geometry::Surface,
|
||||
shape::Shape,
|
||||
topology::{Cycle, Edge, Face, Vertex},
|
||||
topology::{Cycle, Face, Vertex},
|
||||
};
|
||||
|
||||
use super::Approximation;
|
||||
@ -162,23 +162,7 @@ mod tests {
|
||||
let c = Point::from([3., 5., 8.]);
|
||||
let d = Point::from([5., 8., 13.]);
|
||||
|
||||
let v1 = Vertex::build(&mut shape).from_point(a)?;
|
||||
let v2 = Vertex::build(&mut shape).from_point(b)?;
|
||||
let v3 = Vertex::build(&mut shape).from_point(c)?;
|
||||
let v4 = Vertex::build(&mut shape).from_point(d)?;
|
||||
|
||||
let ab = Edge::build(&mut shape)
|
||||
.line_segment_from_vertices([v1.clone(), v2.clone()])?;
|
||||
let bc = Edge::build(&mut shape)
|
||||
.line_segment_from_vertices([v2, v3.clone()])?;
|
||||
let cd = Edge::build(&mut shape)
|
||||
.line_segment_from_vertices([v3, v4.clone()])?;
|
||||
let da =
|
||||
Edge::build(&mut shape).line_segment_from_vertices([v4, v1])?;
|
||||
|
||||
let abcd = shape.insert(Cycle {
|
||||
edges: vec![ab, bc, cd, da],
|
||||
})?;
|
||||
let abcd = Cycle::build(&mut shape).polygon([a, b, c, d])?;
|
||||
|
||||
let surface = shape.insert(Surface::x_y_plane())?;
|
||||
let face = Face::Face {
|
||||
|
@ -326,7 +326,7 @@ mod tests {
|
||||
use crate::{
|
||||
geometry::{Surface, SweptCurve},
|
||||
shape::{Handle, Shape},
|
||||
topology::{Cycle, Edge, Face, Vertex},
|
||||
topology::{Cycle, Edge, Face},
|
||||
};
|
||||
|
||||
use super::sweep_shape;
|
||||
@ -377,32 +377,24 @@ mod tests {
|
||||
}
|
||||
|
||||
impl Triangle {
|
||||
fn new([a, b, c]: [impl Into<Point<3>>; 3]) -> anyhow::Result<Self> {
|
||||
fn new(points: [impl Into<Point<3>>; 3]) -> anyhow::Result<Self> {
|
||||
let mut shape = Shape::new();
|
||||
|
||||
let a = shape.insert(a.into())?;
|
||||
let b = shape.insert(b.into())?;
|
||||
let c = shape.insert(c.into())?;
|
||||
let [a, b, c] = points.map(|point| point.into());
|
||||
|
||||
let a = shape.insert(Vertex { point: a })?;
|
||||
let b = shape.insert(Vertex { point: b })?;
|
||||
let c = shape.insert(Vertex { point: c })?;
|
||||
|
||||
let ab = Edge::build(&mut shape)
|
||||
.line_segment_from_vertices([a.clone(), b.clone()])?;
|
||||
let bc = Edge::build(&mut shape)
|
||||
.line_segment_from_vertices([b.clone(), c.clone()])?;
|
||||
let ca = Edge::build(&mut shape)
|
||||
.line_segment_from_vertices([c.clone(), a.clone()])?;
|
||||
let ab =
|
||||
Edge::build(&mut shape).line_segment_from_points([a, b])?;
|
||||
let bc =
|
||||
Edge::build(&mut shape).line_segment_from_points([b, c])?;
|
||||
let ca =
|
||||
Edge::build(&mut shape).line_segment_from_points([c, a])?;
|
||||
|
||||
let cycles = shape.insert(Cycle {
|
||||
edges: vec![ab, bc, ca],
|
||||
})?;
|
||||
|
||||
let surface = shape.insert(Surface::SweptCurve(
|
||||
SweptCurve::plane_from_points(
|
||||
[a, b, c].map(|vertex| vertex.get().point()),
|
||||
),
|
||||
SweptCurve::plane_from_points([a, b, c]),
|
||||
))?;
|
||||
let abc = Face::Face {
|
||||
surface,
|
||||
|
@ -191,15 +191,13 @@ mod tests {
|
||||
}
|
||||
|
||||
fn add_edge(&mut self) -> anyhow::Result<Handle<Edge>> {
|
||||
let vertices = [(); 2].map(|()| {
|
||||
let points = [(); 2].map(|()| {
|
||||
let point = self.next_point;
|
||||
self.next_point.x += Scalar::ONE;
|
||||
|
||||
let point = self.insert(point).unwrap();
|
||||
self.insert(Vertex { point }).unwrap()
|
||||
point
|
||||
});
|
||||
let edge = Edge::build(&mut self.inner)
|
||||
.line_segment_from_vertices(vertices)?;
|
||||
.line_segment_from_points(points)?;
|
||||
|
||||
Ok(edge)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
shape::{Handle, Shape, ValidationResult},
|
||||
};
|
||||
|
||||
use super::{Edge, Vertex};
|
||||
use super::{Cycle, Edge, Vertex};
|
||||
|
||||
/// API for building a [`Vertex`]
|
||||
pub struct VertexBuilder<'r> {
|
||||
@ -19,12 +19,15 @@ impl<'r> VertexBuilder<'r> {
|
||||
}
|
||||
|
||||
/// Build a [`Vertex`] from a point
|
||||
///
|
||||
/// If an identical point or vertex are already part of the shape, those
|
||||
/// objects are re-used.
|
||||
pub fn from_point(
|
||||
self,
|
||||
point: impl Into<Point<3>>,
|
||||
) -> ValidationResult<Vertex> {
|
||||
let point = self.shape.insert(point.into())?;
|
||||
let vertex = self.shape.insert(Vertex { point })?;
|
||||
let point = self.shape.get_handle_or_insert(point.into())?;
|
||||
let vertex = self.shape.get_handle_or_insert(Vertex { point })?;
|
||||
|
||||
Ok(vertex)
|
||||
}
|
||||
@ -55,6 +58,25 @@ impl<'r> EdgeBuilder<'r> {
|
||||
Ok(edge)
|
||||
}
|
||||
|
||||
/// Build a line segment from two points
|
||||
pub fn line_segment_from_points(
|
||||
self,
|
||||
vertices: [impl Into<Point<3>>; 2],
|
||||
) -> ValidationResult<Edge> {
|
||||
// Can be cleaned up with `try_map`, once that is stable:
|
||||
// https://doc.rust-lang.org/std/primitive.array.html#method.try_map
|
||||
let vertices =
|
||||
vertices.map(|point| Vertex::build(self.shape).from_point(point));
|
||||
let vertices = match vertices {
|
||||
[Ok(a), Ok(b)] => Ok([a, b]),
|
||||
[Err(err), _] | [_, Err(err)] => Err(err),
|
||||
}?;
|
||||
|
||||
let edge = self.line_segment_from_vertices(vertices)?;
|
||||
|
||||
Ok(edge)
|
||||
}
|
||||
|
||||
/// Build a line segment from two vertices
|
||||
pub fn line_segment_from_vertices(
|
||||
self,
|
||||
@ -71,3 +93,42 @@ impl<'r> EdgeBuilder<'r> {
|
||||
Ok(edge)
|
||||
}
|
||||
}
|
||||
|
||||
/// API for building a [`Cycle`]
|
||||
pub struct CycleBuilder<'r> {
|
||||
shape: &'r mut Shape,
|
||||
}
|
||||
|
||||
impl<'r> CycleBuilder<'r> {
|
||||
/// Construct a new instance of `CycleBuilder`
|
||||
pub fn new(shape: &'r mut Shape) -> Self {
|
||||
Self { shape }
|
||||
}
|
||||
|
||||
/// Build a polygon from a list of points
|
||||
pub fn polygon(
|
||||
self,
|
||||
points: impl IntoIterator<Item = impl Into<Point<3>>>,
|
||||
) -> ValidationResult<Cycle> {
|
||||
// A polygon is closed, so we need to add the first point at the end
|
||||
// again, for the next step.
|
||||
let mut points: Vec<_> = points.into_iter().map(Into::into).collect();
|
||||
if let Some(point) = points.first().cloned() {
|
||||
points.push(point);
|
||||
}
|
||||
|
||||
let mut edges = Vec::new();
|
||||
for ab in points.windows(2) {
|
||||
// Can't panic, as we passed `2` to `windows`.
|
||||
//
|
||||
// Can be cleaned up, once `array_windows` is stable.
|
||||
let points = [ab[0], ab[1]];
|
||||
|
||||
let edge =
|
||||
Edge::build(self.shape).line_segment_from_points(points)?;
|
||||
edges.push(edge);
|
||||
}
|
||||
|
||||
self.shape.insert(Cycle { edges })
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
shape::{Handle, Shape},
|
||||
};
|
||||
|
||||
use super::{vertices::Vertex, EdgeBuilder};
|
||||
use super::{builder::CycleBuilder, vertices::Vertex, EdgeBuilder};
|
||||
|
||||
/// A cycle of connected edges
|
||||
///
|
||||
@ -29,6 +29,11 @@ pub struct Cycle {
|
||||
}
|
||||
|
||||
impl Cycle {
|
||||
/// Build a cycle using the [`CycleBuilder`] API
|
||||
pub fn build(shape: &mut Shape) -> CycleBuilder {
|
||||
CycleBuilder::new(shape)
|
||||
}
|
||||
|
||||
/// Access the edges that this cycle refers to
|
||||
///
|
||||
/// This is a convenience method that saves the caller from dealing with the
|
||||
|
Loading…
Reference in New Issue
Block a user