mirror of https://github.com/hannobraun/Fornjot
Merge pull request #736 from hannobraun/handle
Replace `Handle`s between objects with direct ownership
This commit is contained in:
commit
2ecf632e6a
|
@ -13,7 +13,7 @@ pub fn approx_edge(
|
||||||
// the same vertex would be understood to refer to very close, but distinct
|
// the same vertex would be understood to refer to very close, but distinct
|
||||||
// vertices.
|
// vertices.
|
||||||
let vertices = vertices.convert(|vertex| {
|
let vertices = vertices.convert(|vertex| {
|
||||||
geometry::Point::new(*vertex.local(), vertex.canonical().get().point)
|
geometry::Point::new(*vertex.local(), vertex.canonical().point)
|
||||||
});
|
});
|
||||||
if let Some([a, b]) = vertices {
|
if let Some([a, b]) = vertices {
|
||||||
points.insert(0, a);
|
points.insert(0, a);
|
||||||
|
@ -49,8 +49,8 @@ mod test {
|
||||||
let c = Point::from([3., 5., 8.]);
|
let c = Point::from([3., 5., 8.]);
|
||||||
let d = Point::from([5., 8., 13.]);
|
let d = Point::from([5., 8., 13.]);
|
||||||
|
|
||||||
let v1 = Vertex::builder(&mut shape).build_from_point(a);
|
let v1 = Vertex::builder(&mut shape).build_from_point(a).get();
|
||||||
let v2 = Vertex::builder(&mut shape).build_from_point(d);
|
let v2 = Vertex::builder(&mut shape).build_from_point(d).get();
|
||||||
|
|
||||||
let vertices = VerticesOfEdge::from_vertices([
|
let vertices = VerticesOfEdge::from_vertices([
|
||||||
LocalForm::new(Point::from([0.]), v1),
|
LocalForm::new(Point::from([0.]), v1),
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
objects::{
|
objects::{
|
||||||
Curve, Cycle, CyclesInFace, Edge, Face, Surface, Vertex, VerticesOfEdge,
|
Curve, Cycle, CyclesInFace, Edge, Face, Surface, Vertex, VerticesOfEdge,
|
||||||
},
|
},
|
||||||
shape::{LocalForm, Shape},
|
shape::LocalForm,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{transform::transform_cycles, CycleApprox, Tolerance};
|
use super::{transform::transform_cycles, CycleApprox, Tolerance};
|
||||||
|
@ -61,8 +61,6 @@ fn create_bottom_faces(
|
||||||
is_sweep_along_negative_direction: bool,
|
is_sweep_along_negative_direction: bool,
|
||||||
target: &mut Vec<Face>,
|
target: &mut Vec<Face>,
|
||||||
) {
|
) {
|
||||||
let mut tmp = Shape::new();
|
|
||||||
|
|
||||||
let mut surface = face.surface();
|
let mut surface = face.surface();
|
||||||
|
|
||||||
let mut exteriors = face.brep().exteriors.clone();
|
let mut exteriors = face.brep().exteriors.clone();
|
||||||
|
@ -75,8 +73,6 @@ fn create_bottom_faces(
|
||||||
interiors = reverse_local_coordinates_in_cycle(&interiors);
|
interiors = reverse_local_coordinates_in_cycle(&interiors);
|
||||||
};
|
};
|
||||||
|
|
||||||
let surface = tmp.insert(surface);
|
|
||||||
|
|
||||||
let face = Face::new(
|
let face = Face::new(
|
||||||
surface,
|
surface,
|
||||||
exteriors.as_local_form().cloned(),
|
exteriors.as_local_form().cloned(),
|
||||||
|
@ -111,9 +107,6 @@ fn create_top_face(
|
||||||
interiors = reverse_local_coordinates_in_cycle(&interiors);
|
interiors = reverse_local_coordinates_in_cycle(&interiors);
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut tmp = Shape::new();
|
|
||||||
let surface = tmp.insert(surface);
|
|
||||||
|
|
||||||
let face = Face::new(
|
let face = Face::new(
|
||||||
surface,
|
surface,
|
||||||
exteriors.as_local_form().cloned(),
|
exteriors.as_local_form().cloned(),
|
||||||
|
@ -156,8 +149,6 @@ fn create_non_continuous_side_face(
|
||||||
color: [u8; 4],
|
color: [u8; 4],
|
||||||
target: &mut Vec<Face>,
|
target: &mut Vec<Face>,
|
||||||
) {
|
) {
|
||||||
let mut tmp = Shape::new();
|
|
||||||
|
|
||||||
let vertices = {
|
let vertices = {
|
||||||
let vertices_top = vertices_bottom.map(|vertex| {
|
let vertices_top = vertices_bottom.map(|vertex| {
|
||||||
let point = vertex.point + path;
|
let point = vertex.point + path;
|
||||||
|
@ -166,20 +157,17 @@ fn create_non_continuous_side_face(
|
||||||
|
|
||||||
let [[a, b], [c, d]] = [vertices_bottom, vertices_top];
|
let [[a, b], [c, d]] = [vertices_bottom, vertices_top];
|
||||||
|
|
||||||
let vertices = if is_sweep_along_negative_direction {
|
if is_sweep_along_negative_direction {
|
||||||
[b, a, c, d]
|
[b, a, c, d]
|
||||||
} else {
|
} else {
|
||||||
[a, b, d, c]
|
[a, b, d, c]
|
||||||
};
|
}
|
||||||
|
|
||||||
vertices.map(|vertex| tmp.get_handle_or_insert(vertex))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let surface = {
|
let surface = {
|
||||||
let [a, b, _, c] = vertices.clone().map(|vertex| vertex.get().point);
|
let [a, b, _, c] = vertices.map(|vertex| vertex.point);
|
||||||
Surface::plane_from_points([a, b, c])
|
Surface::plane_from_points([a, b, c])
|
||||||
};
|
};
|
||||||
let surface = tmp.get_handle_or_insert(surface);
|
|
||||||
|
|
||||||
let cycle = {
|
let cycle = {
|
||||||
let [a, b, c, d] = vertices;
|
let [a, b, c, d] = vertices;
|
||||||
|
@ -201,16 +189,15 @@ fn create_non_continuous_side_face(
|
||||||
let curve = {
|
let curve = {
|
||||||
let local = Curve::line_from_points([a.0, b.0]);
|
let local = Curve::line_from_points([a.0, b.0]);
|
||||||
|
|
||||||
let global = [a, b].map(|vertex| vertex.1.get().point);
|
let global = [a, b].map(|vertex| vertex.1.point);
|
||||||
let global = Curve::line_from_points(global);
|
let global = Curve::line_from_points(global);
|
||||||
let global = tmp.get_handle_or_insert(global);
|
|
||||||
|
|
||||||
LocalForm::new(local, global)
|
LocalForm::new(local, global)
|
||||||
};
|
};
|
||||||
|
|
||||||
let vertices = VerticesOfEdge::from_vertices([
|
let vertices = VerticesOfEdge::from_vertices([
|
||||||
LocalForm::new(Point::from([0.]), a.1.clone()),
|
LocalForm::new(Point::from([0.]), a.1),
|
||||||
LocalForm::new(Point::from([1.]), b.1.clone()),
|
LocalForm::new(Point::from([1.]), b.1),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let edge = {
|
let edge = {
|
||||||
|
@ -223,7 +210,6 @@ fn create_non_continuous_side_face(
|
||||||
curve: LocalForm::canonical_only(curve.canonical()),
|
curve: LocalForm::canonical_only(curve.canonical()),
|
||||||
vertices,
|
vertices,
|
||||||
};
|
};
|
||||||
let global = tmp.get_handle_or_insert(global);
|
|
||||||
|
|
||||||
LocalForm::new(local, global)
|
LocalForm::new(local, global)
|
||||||
};
|
};
|
||||||
|
@ -236,7 +222,6 @@ fn create_non_continuous_side_face(
|
||||||
|
|
||||||
let global =
|
let global =
|
||||||
Cycle::new(local.edges.iter().map(|edge| edge.canonical()));
|
Cycle::new(local.edges.iter().map(|edge| edge.canonical()));
|
||||||
let global = tmp.get_handle_or_insert(global);
|
|
||||||
|
|
||||||
LocalForm::new(local, global)
|
LocalForm::new(local, global)
|
||||||
};
|
};
|
||||||
|
@ -257,8 +242,6 @@ fn create_continuous_side_face(
|
||||||
) {
|
) {
|
||||||
let translation = Transform::translation(path);
|
let translation = Transform::translation(path);
|
||||||
|
|
||||||
let mut tmp = Shape::new();
|
|
||||||
let edge = tmp.merge(edge);
|
|
||||||
let cycle = Cycle::new(vec![edge]);
|
let cycle = Cycle::new(vec![edge]);
|
||||||
let approx = CycleApprox::new(&cycle, tolerance);
|
let approx = CycleApprox::new(&cycle, tolerance);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use fj_math::Transform;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{Cycle, CyclesInFace, Edge, Face, FaceBRep, Vertex},
|
objects::{Cycle, CyclesInFace, Edge, Face, FaceBRep, Vertex},
|
||||||
shape::{LocalForm, Shape},
|
shape::LocalForm,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Transform a shape
|
/// Transform a shape
|
||||||
|
@ -12,9 +12,7 @@ pub fn transform(faces: &[Face], transform: &Transform) -> Vec<Face> {
|
||||||
for face in faces {
|
for face in faces {
|
||||||
let face = match face {
|
let face = match face {
|
||||||
Face::Face(face) => {
|
Face::Face(face) => {
|
||||||
let mut tmp = Shape::new();
|
let surface = face.surface.transform(transform);
|
||||||
let surface = face.surface.get().transform(transform);
|
|
||||||
let surface = tmp.insert(surface);
|
|
||||||
|
|
||||||
let exteriors = transform_cycles(&face.exteriors, transform);
|
let exteriors = transform_cycles(&face.exteriors, transform);
|
||||||
let interiors = transform_cycles(&face.interiors, transform);
|
let interiors = transform_cycles(&face.interiors, transform);
|
||||||
|
@ -49,8 +47,6 @@ pub fn transform_cycles(
|
||||||
cycles: &CyclesInFace,
|
cycles: &CyclesInFace,
|
||||||
transform: &Transform,
|
transform: &Transform,
|
||||||
) -> CyclesInFace {
|
) -> CyclesInFace {
|
||||||
let mut tmp = Shape::new();
|
|
||||||
|
|
||||||
let cycles = cycles.as_local_form().map(|cycle| {
|
let cycles = cycles.as_local_form().map(|cycle| {
|
||||||
let edges_local = cycle
|
let edges_local = cycle
|
||||||
.local()
|
.local()
|
||||||
|
@ -58,65 +54,62 @@ pub fn transform_cycles(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|edge| {
|
.map(|edge| {
|
||||||
let curve_local = *edge.local().curve.local();
|
let curve_local = *edge.local().curve.local();
|
||||||
let curve_canonical = tmp
|
let curve_canonical =
|
||||||
.merge(edge.canonical().get().curve().transform(transform));
|
edge.canonical().curve().transform(transform);
|
||||||
|
|
||||||
let vertices = edge.canonical().get().vertices.map(|vertex| {
|
let vertices = edge.canonical().vertices.map(|vertex| {
|
||||||
let point = vertex.canonical().get().point;
|
let point = vertex.canonical().point;
|
||||||
let point = transform.transform_point(&point);
|
let point = transform.transform_point(&point);
|
||||||
|
|
||||||
let local = *vertex.local();
|
let local = *vertex.local();
|
||||||
let canonical = tmp.merge(Vertex { point });
|
let canonical = Vertex { point };
|
||||||
|
|
||||||
LocalForm::new(local, canonical)
|
LocalForm::new(local, canonical)
|
||||||
});
|
});
|
||||||
|
|
||||||
let edge_local = Edge {
|
let edge_local = Edge {
|
||||||
curve: LocalForm::new(curve_local, curve_canonical.clone()),
|
curve: LocalForm::new(curve_local, curve_canonical),
|
||||||
vertices: vertices.clone(),
|
vertices: vertices.clone(),
|
||||||
};
|
};
|
||||||
let edge_canonical = tmp.merge(Edge {
|
let edge_canonical = Edge {
|
||||||
curve: LocalForm::canonical_only(curve_canonical),
|
curve: LocalForm::canonical_only(curve_canonical),
|
||||||
vertices,
|
vertices,
|
||||||
});
|
};
|
||||||
|
|
||||||
LocalForm::new(edge_local, edge_canonical)
|
LocalForm::new(edge_local, edge_canonical)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let edges_canonical = cycle
|
let edges_canonical = cycle
|
||||||
.canonical()
|
.canonical()
|
||||||
.get()
|
|
||||||
.edges
|
.edges
|
||||||
.iter()
|
.iter()
|
||||||
.map(|edge| {
|
.map(|edge| {
|
||||||
let edge = edge.canonical().get();
|
let edge = edge.canonical();
|
||||||
|
|
||||||
let curve = {
|
let curve = {
|
||||||
let curve = edge.curve().transform(transform);
|
let curve = edge.curve().transform(transform);
|
||||||
|
|
||||||
let curve = tmp.merge(curve);
|
|
||||||
LocalForm::canonical_only(curve)
|
LocalForm::canonical_only(curve)
|
||||||
};
|
};
|
||||||
let vertices = edge.vertices.map(|vertex| {
|
let vertices = edge.vertices.map(|vertex| {
|
||||||
let point = vertex.canonical().get().point;
|
let point = vertex.canonical().point;
|
||||||
let point = transform.transform_point(&point);
|
let point = transform.transform_point(&point);
|
||||||
|
|
||||||
let local = *vertex.local();
|
let local = *vertex.local();
|
||||||
let canonical = tmp.merge(Vertex { point });
|
let canonical = Vertex { point };
|
||||||
|
|
||||||
LocalForm::new(local, canonical)
|
LocalForm::new(local, canonical)
|
||||||
});
|
});
|
||||||
|
|
||||||
let edge = tmp.merge(Edge { curve, vertices });
|
let edge = Edge { curve, vertices };
|
||||||
LocalForm::canonical_only(edge)
|
LocalForm::canonical_only(edge)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let cycle_local = Cycle { edges: edges_local };
|
let cycle_local = Cycle { edges: edges_local };
|
||||||
|
|
||||||
let cycle_canonical = tmp.merge(Cycle {
|
let cycle_canonical = Cycle {
|
||||||
edges: edges_canonical,
|
edges: edges_canonical,
|
||||||
});
|
};
|
||||||
|
|
||||||
LocalForm::new(cycle_local, cycle_canonical)
|
LocalForm::new(cycle_local, cycle_canonical)
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub fn triangulate(
|
||||||
for face in faces {
|
for face in faces {
|
||||||
match &face {
|
match &face {
|
||||||
Face::Face(brep) => {
|
Face::Face(brep) => {
|
||||||
let surface = brep.surface.get();
|
let surface = brep.surface;
|
||||||
let approx = FaceApprox::new(&face, tolerance);
|
let approx = FaceApprox::new(&face, tolerance);
|
||||||
|
|
||||||
let points: Vec<_> = approx
|
let points: Vec<_> = approx
|
||||||
|
|
|
@ -51,21 +51,20 @@ impl<'r> EdgeBuilder<'r> {
|
||||||
a: Vector::from([radius, Scalar::ZERO]),
|
a: Vector::from([radius, Scalar::ZERO]),
|
||||||
b: Vector::from([Scalar::ZERO, radius]),
|
b: Vector::from([Scalar::ZERO, radius]),
|
||||||
});
|
});
|
||||||
let curve_canonical =
|
let curve_canonical = Curve::Circle(Circle {
|
||||||
self.shape.get_handle_or_insert(Curve::Circle(Circle {
|
|
||||||
center: Point::origin(),
|
center: Point::origin(),
|
||||||
a: Vector::from([radius, Scalar::ZERO, Scalar::ZERO]),
|
a: Vector::from([radius, Scalar::ZERO, Scalar::ZERO]),
|
||||||
b: Vector::from([Scalar::ZERO, radius, Scalar::ZERO]),
|
b: Vector::from([Scalar::ZERO, radius, Scalar::ZERO]),
|
||||||
}));
|
});
|
||||||
|
|
||||||
let edge_local = Edge {
|
let edge_local = Edge {
|
||||||
curve: LocalForm::new(curve_local, curve_canonical.clone()),
|
curve: LocalForm::new(curve_local, curve_canonical),
|
||||||
vertices: VerticesOfEdge::none(),
|
vertices: VerticesOfEdge::none(),
|
||||||
};
|
};
|
||||||
let edge_canonical = self.shape.get_handle_or_insert(Edge {
|
let edge_canonical = Edge {
|
||||||
curve: LocalForm::canonical_only(curve_canonical),
|
curve: LocalForm::canonical_only(curve_canonical),
|
||||||
vertices: VerticesOfEdge::none(),
|
vertices: VerticesOfEdge::none(),
|
||||||
});
|
};
|
||||||
|
|
||||||
LocalForm::new(edge_local, edge_canonical)
|
LocalForm::new(edge_local, edge_canonical)
|
||||||
}
|
}
|
||||||
|
@ -75,10 +74,10 @@ impl<'r> EdgeBuilder<'r> {
|
||||||
self,
|
self,
|
||||||
vertices: [impl Into<Point<3>>; 2],
|
vertices: [impl Into<Point<3>>; 2],
|
||||||
) -> Handle<Edge<3>> {
|
) -> Handle<Edge<3>> {
|
||||||
// Can be cleaned up with `try_map`, once that is stable:
|
let vertices = vertices.map(|point| {
|
||||||
// https://doc.rust-lang.org/std/primitive.array.html#method.try_map
|
let point = point.into();
|
||||||
let vertices = vertices
|
Vertex { point }
|
||||||
.map(|point| Vertex::builder(self.shape).build_from_point(point));
|
});
|
||||||
|
|
||||||
self.build_line_segment_from_vertices(vertices)
|
self.build_line_segment_from_vertices(vertices)
|
||||||
}
|
}
|
||||||
|
@ -86,12 +85,11 @@ impl<'r> EdgeBuilder<'r> {
|
||||||
/// Build a line segment from two vertices
|
/// Build a line segment from two vertices
|
||||||
pub fn build_line_segment_from_vertices(
|
pub fn build_line_segment_from_vertices(
|
||||||
self,
|
self,
|
||||||
[a, b]: [Handle<Vertex>; 2],
|
[a, b]: [Vertex; 2],
|
||||||
) -> Handle<Edge<3>> {
|
) -> Handle<Edge<3>> {
|
||||||
let curve = {
|
let curve = {
|
||||||
let points = [&a, &b].map(|vertex| vertex.get().point);
|
let points = [a, b].map(|vertex| vertex.point);
|
||||||
let curve = Curve::Line(Line::from_points(points));
|
Curve::Line(Line::from_points(points))
|
||||||
self.shape.get_handle_or_insert(curve)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let vertices = [
|
let vertices = [
|
||||||
|
@ -142,14 +140,15 @@ impl<'r> CycleBuilder<'r> {
|
||||||
let points_canonical = points
|
let points_canonical = points
|
||||||
.map(|point| self.surface.point_from_surface_coords(point));
|
.map(|point| self.surface.point_from_surface_coords(point));
|
||||||
let edge_canonical = Edge::builder(self.shape)
|
let edge_canonical = Edge::builder(self.shape)
|
||||||
.build_line_segment_from_points(points_canonical);
|
.build_line_segment_from_points(points_canonical)
|
||||||
|
.get();
|
||||||
|
|
||||||
let edge_local = Edge {
|
let edge_local = Edge {
|
||||||
curve: LocalForm::new(
|
curve: LocalForm::new(
|
||||||
Curve::Line(Line::from_points(points)),
|
Curve::Line(Line::from_points(points)),
|
||||||
edge_canonical.get().curve.canonical(),
|
edge_canonical.curve.canonical(),
|
||||||
),
|
),
|
||||||
vertices: edge_canonical.get().vertices,
|
vertices: edge_canonical.vertices.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
edges.push(LocalForm::new(edge_local, edge_canonical));
|
edges.push(LocalForm::new(edge_local, edge_canonical));
|
||||||
|
@ -160,8 +159,7 @@ impl<'r> CycleBuilder<'r> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let edges_canonical = edges.into_iter().map(|edge| edge.canonical());
|
let edges_canonical = edges.into_iter().map(|edge| edge.canonical());
|
||||||
let canonical =
|
let canonical = Cycle::new(edges_canonical);
|
||||||
self.shape.get_handle_or_insert(Cycle::new(edges_canonical));
|
|
||||||
|
|
||||||
LocalForm::new(local, canonical)
|
LocalForm::new(local, canonical)
|
||||||
}
|
}
|
||||||
|
@ -225,7 +223,7 @@ impl<'r> FaceBuilder<'r> {
|
||||||
|
|
||||||
/// Build the face
|
/// Build the face
|
||||||
pub fn build(self) -> Handle<Face> {
|
pub fn build(self) -> Handle<Face> {
|
||||||
let surface = self.shape.get_handle_or_insert(self.surface);
|
let surface = self.surface;
|
||||||
|
|
||||||
let mut exteriors = Vec::new();
|
let mut exteriors = Vec::new();
|
||||||
if let Some(points) = self.exterior {
|
if let Some(points) = self.exterior {
|
||||||
|
|
|
@ -463,8 +463,7 @@ mod tests {
|
||||||
let mut shape = Shape::new();
|
let mut shape = Shape::new();
|
||||||
let cycle = Cycle::builder(Surface::xy_plane(), &mut shape)
|
let cycle = Cycle::builder(Surface::xy_plane(), &mut shape)
|
||||||
.build_polygon([[0., 0.], [1., 0.], [0., 1.]])
|
.build_polygon([[0., 0.], [1., 0.], [0., 1.]])
|
||||||
.canonical()
|
.canonical();
|
||||||
.get();
|
|
||||||
|
|
||||||
assert_eq!(3, cycle.curve_iter().count());
|
assert_eq!(3, cycle.curve_iter().count());
|
||||||
assert_eq!(1, cycle.cycle_iter().count());
|
assert_eq!(1, cycle.cycle_iter().count());
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::CycleBuilder,
|
builder::CycleBuilder,
|
||||||
shape::{Handle, LocalForm, Shape},
|
shape::{LocalForm, Shape},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Edge, Surface};
|
use super::{Edge, Surface};
|
||||||
|
@ -11,11 +11,6 @@ use super::{Edge, Surface};
|
||||||
/// edge. The end of the last edge must connect to the beginning of the first
|
/// edge. The end of the last edge must connect to the beginning of the first
|
||||||
/// one.
|
/// one.
|
||||||
///
|
///
|
||||||
/// # Equality
|
|
||||||
///
|
|
||||||
/// Please refer to [`crate::kernel::topology`] for documentation on the
|
|
||||||
/// equality of topological objects.
|
|
||||||
///
|
|
||||||
/// # Validation
|
/// # Validation
|
||||||
///
|
///
|
||||||
/// A cycle that is part of a [`Shape`] must be structurally sound. That means
|
/// A cycle that is part of a [`Shape`] must be structurally sound. That means
|
||||||
|
@ -28,7 +23,7 @@ pub struct Cycle<const D: usize> {
|
||||||
|
|
||||||
impl Cycle<3> {
|
impl Cycle<3> {
|
||||||
/// Construct a `Cycle`
|
/// Construct a `Cycle`
|
||||||
pub fn new(edges: impl IntoIterator<Item = Handle<Edge<3>>>) -> Self {
|
pub fn new(edges: impl IntoIterator<Item = Edge<3>>) -> Self {
|
||||||
let edges = edges.into_iter().map(LocalForm::canonical_only).collect();
|
let edges = edges.into_iter().map(LocalForm::canonical_only).collect();
|
||||||
|
|
||||||
Self { edges }
|
Self { edges }
|
||||||
|
@ -44,6 +39,6 @@ impl Cycle<3> {
|
||||||
/// This is a convenience method that saves the caller from dealing with the
|
/// This is a convenience method that saves the caller from dealing with the
|
||||||
/// [`Handle`]s.
|
/// [`Handle`]s.
|
||||||
pub fn edges(&self) -> impl Iterator<Item = Edge<3>> + '_ {
|
pub fn edges(&self) -> impl Iterator<Item = Edge<3>> + '_ {
|
||||||
self.edges.iter().map(|handle| handle.canonical().get())
|
self.edges.iter().map(|handle| handle.canonical())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,6 @@ use super::{Curve, Vertex};
|
||||||
|
|
||||||
/// An edge of a shape
|
/// An edge of a shape
|
||||||
///
|
///
|
||||||
/// # Equality
|
|
||||||
///
|
|
||||||
/// Please refer to [`crate::kernel::topology`] for documentation on the
|
|
||||||
/// equality of topological objects.
|
|
||||||
///
|
|
||||||
/// # Validation
|
/// # Validation
|
||||||
///
|
///
|
||||||
/// An edge that is part of a [`Shape`] must be structurally sound. That means
|
/// An edge that is part of a [`Shape`] must be structurally sound. That means
|
||||||
|
@ -43,7 +38,7 @@ impl<const D: usize> Edge<D> {
|
||||||
/// This is a convenience method that saves the caller from dealing with the
|
/// This is a convenience method that saves the caller from dealing with the
|
||||||
/// [`Handle`].
|
/// [`Handle`].
|
||||||
pub fn curve(&self) -> Curve<3> {
|
pub fn curve(&self) -> Curve<3> {
|
||||||
self.curve.canonical().get()
|
self.curve.canonical()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the vertices that the edge refers to
|
/// Access the vertices that the edge refers to
|
||||||
|
@ -54,7 +49,7 @@ impl<const D: usize> Edge<D> {
|
||||||
self.vertices
|
self.vertices
|
||||||
.0
|
.0
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|[a, b]| [a.canonical().get(), b.canonical().get()])
|
.map(|[a, b]| [a.canonical(), b.canonical()])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +109,7 @@ impl VerticesOfEdge {
|
||||||
[a.canonical(), b.canonical()]
|
[a.canonical(), b.canonical()]
|
||||||
};
|
};
|
||||||
|
|
||||||
return [a.clone(), b.clone()] == other || [b, a] == other;
|
return [a, b] == other || [b, a] == other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use fj_math::Triangle;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::FaceBuilder,
|
builder::FaceBuilder,
|
||||||
shape::{Handle, LocalForm, Shape},
|
shape::{LocalForm, Shape},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Cycle, Surface};
|
use super::{Cycle, Surface};
|
||||||
|
@ -41,7 +41,7 @@ pub enum Face {
|
||||||
impl Face {
|
impl Face {
|
||||||
/// Construct a new instance of `Face`
|
/// Construct a new instance of `Face`
|
||||||
pub fn new(
|
pub fn new(
|
||||||
surface: Handle<Surface>,
|
surface: Surface,
|
||||||
exteriors: impl IntoIterator<Item = LocalForm<Cycle<2>, Cycle<3>>>,
|
exteriors: impl IntoIterator<Item = LocalForm<Cycle<2>, Cycle<3>>>,
|
||||||
interiors: impl IntoIterator<Item = LocalForm<Cycle<2>, Cycle<3>>>,
|
interiors: impl IntoIterator<Item = LocalForm<Cycle<2>, Cycle<3>>>,
|
||||||
color: [u8; 4],
|
color: [u8; 4],
|
||||||
|
@ -119,7 +119,7 @@ impl Face {
|
||||||
#[derive(Clone, Debug, Eq, Ord, PartialOrd)]
|
#[derive(Clone, Debug, Eq, Ord, PartialOrd)]
|
||||||
pub struct FaceBRep {
|
pub struct FaceBRep {
|
||||||
/// The surface that defines this face
|
/// The surface that defines this face
|
||||||
pub surface: Handle<Surface>,
|
pub surface: Surface,
|
||||||
|
|
||||||
/// The cycles that bound the face on the outside
|
/// The cycles that bound the face on the outside
|
||||||
///
|
///
|
||||||
|
@ -152,7 +152,7 @@ impl FaceBRep {
|
||||||
/// This is a convenience method that saves the caller from dealing with the
|
/// This is a convenience method that saves the caller from dealing with the
|
||||||
/// [`Handle`].
|
/// [`Handle`].
|
||||||
pub fn surface(&self) -> Surface {
|
pub fn surface(&self) -> Surface {
|
||||||
self.surface.get()
|
self.surface
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the exterior cycles that the face refers to
|
/// Access the exterior cycles that the face refers to
|
||||||
|
@ -211,11 +211,6 @@ impl CyclesInFace {
|
||||||
|
|
||||||
/// Access an iterator over the canonical forms of the cycles
|
/// Access an iterator over the canonical forms of the cycles
|
||||||
pub fn as_canonical(&self) -> impl Iterator<Item = Cycle<3>> + '_ {
|
pub fn as_canonical(&self) -> impl Iterator<Item = Cycle<3>> + '_ {
|
||||||
self.as_handle().map(|cycle| cycle.get())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Access an iterator over handles to the cycles
|
|
||||||
pub fn as_handle(&self) -> impl Iterator<Item = Handle<Cycle<3>>> + '_ {
|
|
||||||
self.0.iter().map(|cycle| cycle.canonical())
|
self.0.iter().map(|cycle| cycle.canonical())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,6 @@ use crate::{builder::VertexBuilder, shape::Shape};
|
||||||
/// Points, on the other hand, might be used to approximate a shape for various
|
/// Points, on the other hand, might be used to approximate a shape for various
|
||||||
/// purposes, without presenting any deeper truth about the shape's structure.
|
/// purposes, without presenting any deeper truth about the shape's structure.
|
||||||
///
|
///
|
||||||
/// # Equality
|
|
||||||
///
|
|
||||||
/// Please refer to [`crate::kernel::topology`] for documentation on the
|
|
||||||
/// equality of topological objects.
|
|
||||||
///
|
|
||||||
/// # Validation
|
/// # Validation
|
||||||
///
|
///
|
||||||
/// Vertices must be unique within a shape, meaning an identical vertex must not
|
/// Vertices must be unique within a shape, meaning an identical vertex must not
|
||||||
|
|
|
@ -177,7 +177,7 @@ mod tests {
|
||||||
|
|
||||||
let vertex = Vertex { point };
|
let vertex = Vertex { point };
|
||||||
let edge = Edge {
|
let edge = Edge {
|
||||||
curve: LocalForm::canonical_only(curve),
|
curve: LocalForm::canonical_only(curve.get()),
|
||||||
vertices: VerticesOfEdge::none(),
|
vertices: VerticesOfEdge::none(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -190,13 +190,14 @@ mod tests {
|
||||||
assert!(shape.get_handle(&vertex.get()).as_ref() == Some(&vertex));
|
assert!(shape.get_handle(&vertex.get()).as_ref() == Some(&vertex));
|
||||||
assert!(shape.get_handle(&edge.get()).as_ref() == Some(&edge));
|
assert!(shape.get_handle(&edge.get()).as_ref() == Some(&edge));
|
||||||
|
|
||||||
let cycle = Cycle::new(vec![edge]);
|
let cycle = Cycle::new(vec![edge.get()]);
|
||||||
assert!(shape.get_handle(&cycle).is_none());
|
assert!(shape.get_handle(&cycle).is_none());
|
||||||
|
|
||||||
let cycle = shape.insert(cycle);
|
let cycle = shape.insert(cycle);
|
||||||
assert!(shape.get_handle(&cycle.get()).as_ref() == Some(&cycle));
|
assert!(shape.get_handle(&cycle.get()).as_ref() == Some(&cycle));
|
||||||
|
|
||||||
let face = Face::new(surface, Vec::new(), Vec::new(), [0, 0, 0, 0]);
|
let face =
|
||||||
|
Face::new(surface.get(), Vec::new(), Vec::new(), [0, 0, 0, 0]);
|
||||||
assert!(shape.get_handle(&face).is_none());
|
assert!(shape.get_handle(&face).is_none());
|
||||||
|
|
||||||
let face = shape.insert(face);
|
let face = shape.insert(face);
|
||||||
|
|
|
@ -1,23 +1,14 @@
|
||||||
use std::hash::{Hash, Hasher};
|
use super::Object;
|
||||||
|
|
||||||
use super::{Handle, Object};
|
|
||||||
|
|
||||||
/// A reference to an object, which includes a local form
|
/// A reference to an object, which includes a local form
|
||||||
///
|
///
|
||||||
/// This type is used by topological objects to reference other objects, while
|
/// This type is used by topological objects to reference other objects, while
|
||||||
/// also keeping track of a local representation of that object, which is often
|
/// also keeping track of a local representation of that object, which is often
|
||||||
/// more appropriate for various tasks.
|
/// more appropriate for various tasks.
|
||||||
///
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||||
/// # Equality
|
|
||||||
///
|
|
||||||
/// Since `LocalForm` is used by topological objects, its equality is defined in
|
|
||||||
/// terms that are useful to those objects. Two instances of `LocalForm` are
|
|
||||||
/// equal, if both the local and the canonical forms are equal. The equality of
|
|
||||||
/// the handle that refers to the canonical form is disregarded.
|
|
||||||
#[derive(Clone, Debug, Eq, Ord, PartialOrd)]
|
|
||||||
pub struct LocalForm<Local, Canonical: Object> {
|
pub struct LocalForm<Local, Canonical: Object> {
|
||||||
local: Local,
|
local: Local,
|
||||||
canonical: Handle<Canonical>,
|
canonical: Canonical,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Local, Canonical: Object> LocalForm<Local, Canonical> {
|
impl<Local, Canonical: Object> LocalForm<Local, Canonical> {
|
||||||
|
@ -25,7 +16,7 @@ impl<Local, Canonical: Object> LocalForm<Local, Canonical> {
|
||||||
///
|
///
|
||||||
/// It is the caller's responsibility to make sure that the local and
|
/// It is the caller's responsibility to make sure that the local and
|
||||||
/// canonical forms passed to this method actually match.
|
/// canonical forms passed to this method actually match.
|
||||||
pub fn new(local: Local, canonical: Handle<Canonical>) -> Self {
|
pub fn new(local: Local, canonical: Canonical) -> Self {
|
||||||
Self { local, canonical }
|
Self { local, canonical }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +26,7 @@ impl<Local, Canonical: Object> LocalForm<Local, Canonical> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the canonical form of the referenced object
|
/// Access the canonical form of the referenced object
|
||||||
pub fn canonical(&self) -> Handle<Canonical> {
|
pub fn canonical(&self) -> Canonical {
|
||||||
self.canonical.clone()
|
self.canonical.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,29 +37,7 @@ impl<Canonical: Object> LocalForm<Canonical, Canonical> {
|
||||||
/// It's possible that an object's local and canonical forms are the same.
|
/// It's possible that an object's local and canonical forms are the same.
|
||||||
/// This is a convenience constructor that constructs a `LocalForm` instance
|
/// This is a convenience constructor that constructs a `LocalForm` instance
|
||||||
/// for such a situation.
|
/// for such a situation.
|
||||||
pub fn canonical_only(canonical: Handle<Canonical>) -> Self {
|
pub fn canonical_only(canonical: Canonical) -> Self {
|
||||||
Self::new(canonical.get(), canonical)
|
Self::new(canonical.clone(), canonical)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Local, Canonical: Object> PartialEq for LocalForm<Local, Canonical>
|
|
||||||
where
|
|
||||||
Local: PartialEq,
|
|
||||||
Canonical: PartialEq,
|
|
||||||
{
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.local == other.local
|
|
||||||
&& self.canonical.get() == other.canonical.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Local, Canonical: Object> Hash for LocalForm<Local, Canonical>
|
|
||||||
where
|
|
||||||
Local: Hash,
|
|
||||||
Canonical: Hash,
|
|
||||||
{
|
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
||||||
self.local.hash(state);
|
|
||||||
self.canonical.get().hash(state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,12 +44,12 @@ impl Object for Edge<3> {
|
||||||
|
|
||||||
let vertices = self.vertices.convert(|vertex| {
|
let vertices = self.vertices.convert(|vertex| {
|
||||||
let canonical = vertex.canonical();
|
let canonical = vertex.canonical();
|
||||||
let canonical = canonical.get().merge_into(shape);
|
let canonical = canonical.merge_into(shape);
|
||||||
LocalForm::new(*vertex.local(), canonical)
|
LocalForm::new(*vertex.local(), canonical.get())
|
||||||
});
|
});
|
||||||
|
|
||||||
shape.get_handle_or_insert(Edge {
|
shape.get_handle_or_insert(Edge {
|
||||||
curve: LocalForm::canonical_only(curve),
|
curve: LocalForm::canonical_only(curve.get()),
|
||||||
vertices: VerticesOfEdge::new(vertices),
|
vertices: VerticesOfEdge::new(vertices),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,8 @@ impl Object for Cycle<3> {
|
||||||
let mut edges = Vec::new();
|
let mut edges = Vec::new();
|
||||||
for edge in self.edges {
|
for edge in self.edges {
|
||||||
let edge = edge.canonical();
|
let edge = edge.canonical();
|
||||||
let edge = edge.get().merge_into(shape);
|
let edge = edge.merge_into(shape);
|
||||||
edges.push(edge);
|
edges.push(edge.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
shape.get_handle_or_insert(Cycle::new(edges))
|
shape.get_handle_or_insert(Cycle::new(edges))
|
||||||
|
@ -72,22 +72,31 @@ impl Object for Face {
|
||||||
fn merge_into(self, shape: &mut Shape) -> Handle<Self> {
|
fn merge_into(self, shape: &mut Shape) -> Handle<Self> {
|
||||||
match self {
|
match self {
|
||||||
Face::Face(face) => {
|
Face::Face(face) => {
|
||||||
let surface = face.surface.get().merge_into(shape);
|
let surface = face.surface.merge_into(shape);
|
||||||
|
|
||||||
let mut exts = Vec::new();
|
let mut exts = Vec::new();
|
||||||
for cycle in face.exteriors.as_local_form() {
|
for cycle in face.exteriors.as_local_form() {
|
||||||
let merged = cycle.canonical().get().merge_into(shape);
|
let merged = cycle.canonical().merge_into(shape);
|
||||||
exts.push(LocalForm::new(cycle.local().clone(), merged));
|
exts.push(LocalForm::new(
|
||||||
|
cycle.local().clone(),
|
||||||
|
merged.get(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ints = Vec::new();
|
let mut ints = Vec::new();
|
||||||
for cycle in face.interiors.as_local_form() {
|
for cycle in face.interiors.as_local_form() {
|
||||||
let merged = cycle.canonical().get().merge_into(shape);
|
let merged = cycle.canonical().merge_into(shape);
|
||||||
ints.push(LocalForm::new(cycle.local().clone(), merged));
|
ints.push(LocalForm::new(
|
||||||
|
cycle.local().clone(),
|
||||||
|
merged.get(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
shape.get_handle_or_insert(Face::new(
|
shape.get_handle_or_insert(Face::new(
|
||||||
surface, exts, ints, face.color,
|
surface.get(),
|
||||||
|
exts,
|
||||||
|
ints,
|
||||||
|
face.color,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Face::Triangles(_) => shape.get_handle_or_insert(self),
|
Face::Triangles(_) => shape.get_handle_or_insert(self),
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub fn validate_edge(
|
||||||
for vertex in edge.vertices.iter() {
|
for vertex in edge.vertices.iter() {
|
||||||
let local = *vertex.local();
|
let local = *vertex.local();
|
||||||
let local_as_canonical = edge.curve().point_from_curve_coords(local);
|
let local_as_canonical = edge.curve().point_from_curve_coords(local);
|
||||||
let canonical = vertex.canonical().get().point;
|
let canonical = vertex.canonical().point;
|
||||||
let distance = (local_as_canonical - canonical).magnitude();
|
let distance = (local_as_canonical - canonical).magnitude();
|
||||||
|
|
||||||
if distance > max_distance {
|
if distance > max_distance {
|
||||||
|
|
|
@ -232,18 +232,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn coherence_edge() {
|
fn coherence_edge() {
|
||||||
let mut tmp = Shape::new();
|
|
||||||
|
|
||||||
let a = Point::from([0., 0., 0.]);
|
let a = Point::from([0., 0., 0.]);
|
||||||
let b = Point::from([1., 0., 0.]);
|
let b = Point::from([1., 0., 0.]);
|
||||||
|
|
||||||
let curve = {
|
let curve = {
|
||||||
let curve = tmp.insert(Curve::line_from_points([a, b]));
|
let curve = Curve::line_from_points([a, b]);
|
||||||
LocalForm::canonical_only(curve)
|
LocalForm::canonical_only(curve)
|
||||||
};
|
};
|
||||||
|
|
||||||
let a = tmp.insert(Vertex { point: a });
|
let a = Vertex { point: a };
|
||||||
let b = tmp.insert(Vertex { point: b });
|
let b = Vertex { point: b };
|
||||||
|
|
||||||
let deviation = Scalar::from_f64(0.25);
|
let deviation = Scalar::from_f64(0.25);
|
||||||
|
|
||||||
|
@ -279,15 +277,17 @@ mod tests {
|
||||||
|
|
||||||
// Trying to refer to edge that is not from the same shape. Should fail.
|
// Trying to refer to edge that is not from the same shape. Should fail.
|
||||||
let edge = Edge::builder(&mut other)
|
let edge = Edge::builder(&mut other)
|
||||||
.build_line_segment_from_points([[0., 0., 0.], [1., 0., 0.]]);
|
.build_line_segment_from_points([[0., 0., 0.], [1., 0., 0.]])
|
||||||
|
.get();
|
||||||
shape.insert(Cycle::new(vec![edge.clone()]));
|
shape.insert(Cycle::new(vec![edge.clone()]));
|
||||||
let err =
|
let err =
|
||||||
validate(shape.clone(), &ValidationConfig::default()).unwrap_err();
|
validate(shape.clone(), &ValidationConfig::default()).unwrap_err();
|
||||||
assert!(err.missing_edge(&edge.get()));
|
assert!(err.missing_edge(&edge));
|
||||||
|
|
||||||
// Referring to edge that *is* from the same shape. Should work.
|
// Referring to edge that *is* from the same shape. Should work.
|
||||||
let edge = Edge::builder(&mut shape)
|
let edge = Edge::builder(&mut shape)
|
||||||
.build_line_segment_from_points([[0., 0., 0.], [1., 0., 0.]]);
|
.build_line_segment_from_points([[0., 0., 0.], [1., 0., 0.]])
|
||||||
|
.get();
|
||||||
shape.insert(Cycle::new(vec![edge]));
|
shape.insert(Cycle::new(vec![edge]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,27 +296,35 @@ mod tests {
|
||||||
let mut shape = Shape::new();
|
let mut shape = Shape::new();
|
||||||
let mut other = Shape::new();
|
let mut other = Shape::new();
|
||||||
|
|
||||||
let curve = other.insert(Curve::x_axis());
|
let curve = Curve::x_axis();
|
||||||
let a = Vertex::builder(&mut other).build_from_point([1., 0., 0.]);
|
let a = Vertex::builder(&mut other)
|
||||||
let b = Vertex::builder(&mut other).build_from_point([2., 0., 0.]);
|
.build_from_point([1., 0., 0.])
|
||||||
|
.get();
|
||||||
|
let b = Vertex::builder(&mut other)
|
||||||
|
.build_from_point([2., 0., 0.])
|
||||||
|
.get();
|
||||||
|
|
||||||
let a = LocalForm::new(Point::from([1.]), a);
|
let a = LocalForm::new(Point::from([1.]), a);
|
||||||
let b = LocalForm::new(Point::from([2.]), b);
|
let b = LocalForm::new(Point::from([2.]), b);
|
||||||
|
|
||||||
// Shouldn't work. Nothing has been added to `shape`.
|
// Shouldn't work. Nothing has been added to `shape`.
|
||||||
shape.insert(Edge {
|
shape.insert(Edge {
|
||||||
curve: LocalForm::canonical_only(curve.clone()),
|
curve: LocalForm::canonical_only(curve),
|
||||||
vertices: VerticesOfEdge::from_vertices([a.clone(), b.clone()]),
|
vertices: VerticesOfEdge::from_vertices([a.clone(), b.clone()]),
|
||||||
});
|
});
|
||||||
let err =
|
let err =
|
||||||
validate(shape.clone(), &ValidationConfig::default()).unwrap_err();
|
validate(shape.clone(), &ValidationConfig::default()).unwrap_err();
|
||||||
assert!(err.missing_curve(&curve.get()));
|
assert!(err.missing_curve(&curve));
|
||||||
assert!(err.missing_vertex(&a.canonical().get()));
|
assert!(err.missing_vertex(&a.canonical()));
|
||||||
assert!(err.missing_vertex(&b.canonical().get()));
|
assert!(err.missing_vertex(&b.canonical()));
|
||||||
|
|
||||||
let curve = shape.insert(Curve::x_axis());
|
let curve = Curve::x_axis();
|
||||||
let a = Vertex::builder(&mut shape).build_from_point([1., 0., 0.]);
|
let a = Vertex::builder(&mut shape)
|
||||||
let b = Vertex::builder(&mut shape).build_from_point([2., 0., 0.]);
|
.build_from_point([1., 0., 0.])
|
||||||
|
.get();
|
||||||
|
let b = Vertex::builder(&mut shape)
|
||||||
|
.build_from_point([2., 0., 0.])
|
||||||
|
.get();
|
||||||
|
|
||||||
let a = LocalForm::new(Point::from([1.]), a);
|
let a = LocalForm::new(Point::from([1.]), a);
|
||||||
let b = LocalForm::new(Point::from([2.]), b);
|
let b = LocalForm::new(Point::from([2.]), b);
|
||||||
|
@ -335,25 +343,23 @@ mod tests {
|
||||||
|
|
||||||
let triangle = [[0., 0.], [1., 0.], [0., 1.]];
|
let triangle = [[0., 0.], [1., 0.], [0., 1.]];
|
||||||
|
|
||||||
let surface = other.insert(Surface::xy_plane());
|
let surface = Surface::xy_plane();
|
||||||
let cycle =
|
let cycle = Cycle::builder(surface, &mut other).build_polygon(triangle);
|
||||||
Cycle::builder(surface.get(), &mut other).build_polygon(triangle);
|
|
||||||
|
|
||||||
// Nothing has been added to `shape`. Should fail.
|
// Nothing has been added to `shape`. Should fail.
|
||||||
shape.insert(Face::new(
|
shape.insert(Face::new(
|
||||||
surface.clone(),
|
surface,
|
||||||
vec![cycle.clone()],
|
vec![cycle.clone()],
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
[255, 0, 0, 255],
|
[255, 0, 0, 255],
|
||||||
));
|
));
|
||||||
let err =
|
let err =
|
||||||
validate(shape.clone(), &ValidationConfig::default()).unwrap_err();
|
validate(shape.clone(), &ValidationConfig::default()).unwrap_err();
|
||||||
assert!(err.missing_surface(&surface.get()));
|
assert!(err.missing_surface(&surface));
|
||||||
assert!(err.missing_cycle(&cycle.canonical().get()));
|
assert!(err.missing_cycle(&cycle.canonical()));
|
||||||
|
|
||||||
let surface = shape.insert(Surface::xy_plane());
|
let surface = Surface::xy_plane();
|
||||||
let cycle =
|
let cycle = Cycle::builder(surface, &mut shape).build_polygon(triangle);
|
||||||
Cycle::builder(surface.get(), &mut shape).build_polygon(triangle);
|
|
||||||
|
|
||||||
// Everything has been added to `shape` now. Should work!
|
// Everything has been added to `shape` now. Should work!
|
||||||
shape.insert(Face::new(
|
shape.insert(Face::new(
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub fn validate_edge(
|
||||||
let mut missing_vertices = HashSet::new();
|
let mut missing_vertices = HashSet::new();
|
||||||
|
|
||||||
if !curves.contains(&edge.curve()) {
|
if !curves.contains(&edge.curve()) {
|
||||||
missing_curve = Some(edge.curve.canonical().get());
|
missing_curve = Some(edge.curve.canonical());
|
||||||
}
|
}
|
||||||
for vertex in edge.vertices().into_iter().flatten() {
|
for vertex in edge.vertices().into_iter().flatten() {
|
||||||
if !vertices.contains(&vertex) {
|
if !vertices.contains(&vertex) {
|
||||||
|
@ -61,7 +61,7 @@ pub fn validate_face(
|
||||||
let mut missing_cycles = HashSet::new();
|
let mut missing_cycles = HashSet::new();
|
||||||
|
|
||||||
if !surfaces.contains(&face.surface()) {
|
if !surfaces.contains(&face.surface()) {
|
||||||
missing_surface = Some(face.surface.get());
|
missing_surface = Some(face.surface);
|
||||||
}
|
}
|
||||||
for cycle in face.all_cycles() {
|
for cycle in face.all_cycles() {
|
||||||
if !cycles.contains(&cycle) {
|
if !cycles.contains(&cycle) {
|
||||||
|
|
|
@ -27,9 +27,9 @@ impl ToShape for fj::Circle {
|
||||||
let cycle_local = Cycle {
|
let cycle_local = Cycle {
|
||||||
edges: vec![edge.clone()],
|
edges: vec![edge.clone()],
|
||||||
};
|
};
|
||||||
let cycle_canonical = tmp.insert(Cycle::new(vec![edge.canonical()]));
|
let cycle_canonical = Cycle::new(vec![edge.canonical()]);
|
||||||
|
|
||||||
let surface = tmp.insert(Surface::xy_plane());
|
let surface = Surface::xy_plane();
|
||||||
let face = tmp
|
let face = tmp
|
||||||
.insert(Face::new(
|
.insert(Face::new(
|
||||||
surface,
|
surface,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use fj_kernel::{
|
||||||
algorithms::Tolerance,
|
algorithms::Tolerance,
|
||||||
iter::ObjectIters,
|
iter::ObjectIters,
|
||||||
objects::{Cycle, Edge, Face},
|
objects::{Cycle, Edge, Face},
|
||||||
shape::{LocalForm, Shape},
|
shape::LocalForm,
|
||||||
validation::{validate, Validated, ValidationConfig, ValidationError},
|
validation::{validate, Validated, ValidationConfig, ValidationError},
|
||||||
};
|
};
|
||||||
use fj_math::Aabb;
|
use fj_math::Aabb;
|
||||||
|
@ -36,13 +36,13 @@ impl ToShape for fj::Difference2d {
|
||||||
if let Some(face) = a.face_iter().next() {
|
if let Some(face) = a.face_iter().next() {
|
||||||
// If there's at least one face to subtract from, we can proceed.
|
// If there's at least one face to subtract from, we can proceed.
|
||||||
|
|
||||||
let surface = face.brep().surface.clone();
|
let surface = face.brep().surface;
|
||||||
|
|
||||||
for face in a.face_iter() {
|
for face in a.face_iter() {
|
||||||
let face = face.brep();
|
let face = face.brep();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
surface.get(),
|
surface,
|
||||||
face.surface(),
|
face.surface(),
|
||||||
"Trying to subtract faces with different surfaces.",
|
"Trying to subtract faces with different surfaces.",
|
||||||
);
|
);
|
||||||
|
@ -61,7 +61,7 @@ impl ToShape for fj::Difference2d {
|
||||||
let face = face.brep();
|
let face = face.brep();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
surface.get(),
|
surface,
|
||||||
face.surface(),
|
face.surface(),
|
||||||
"Trying to subtract faces with different surfaces.",
|
"Trying to subtract faces with different surfaces.",
|
||||||
);
|
);
|
||||||
|
@ -95,8 +95,6 @@ fn add_cycle(
|
||||||
cycle: LocalForm<Cycle<2>, Cycle<3>>,
|
cycle: LocalForm<Cycle<2>, Cycle<3>>,
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
) -> LocalForm<Cycle<2>, Cycle<3>> {
|
) -> LocalForm<Cycle<2>, Cycle<3>> {
|
||||||
let mut tmp = Shape::new();
|
|
||||||
|
|
||||||
let mut edges = Vec::new();
|
let mut edges = Vec::new();
|
||||||
for edge in cycle.local().edges.clone() {
|
for edge in cycle.local().edges.clone() {
|
||||||
let curve_local = *edge.local().curve.local();
|
let curve_local = *edge.local().curve.local();
|
||||||
|
@ -106,13 +104,12 @@ fn add_cycle(
|
||||||
curve_local
|
curve_local
|
||||||
};
|
};
|
||||||
|
|
||||||
let curve_canonical = edge.canonical().get().curve();
|
let curve_canonical = edge.canonical().curve();
|
||||||
let curve_canonical = if reverse {
|
let curve_canonical = if reverse {
|
||||||
curve_canonical.reverse()
|
curve_canonical.reverse()
|
||||||
} else {
|
} else {
|
||||||
curve_canonical
|
curve_canonical
|
||||||
};
|
};
|
||||||
let curve_canonical = tmp.insert(curve_canonical);
|
|
||||||
|
|
||||||
let vertices = if reverse {
|
let vertices = if reverse {
|
||||||
edge.local().vertices.clone().reverse()
|
edge.local().vertices.clone().reverse()
|
||||||
|
@ -121,13 +118,13 @@ fn add_cycle(
|
||||||
};
|
};
|
||||||
|
|
||||||
let edge_local = Edge {
|
let edge_local = Edge {
|
||||||
curve: LocalForm::new(curve_local, curve_canonical.clone()),
|
curve: LocalForm::new(curve_local, curve_canonical),
|
||||||
vertices: vertices.clone(),
|
vertices: vertices.clone(),
|
||||||
};
|
};
|
||||||
let edge_canonical = tmp.merge(Edge {
|
let edge_canonical = Edge {
|
||||||
curve: LocalForm::canonical_only(curve_canonical),
|
curve: LocalForm::canonical_only(curve_canonical),
|
||||||
vertices,
|
vertices,
|
||||||
});
|
};
|
||||||
|
|
||||||
edges.push(LocalForm::new(edge_local, edge_canonical));
|
edges.push(LocalForm::new(edge_local, edge_canonical));
|
||||||
}
|
}
|
||||||
|
@ -140,7 +137,7 @@ fn add_cycle(
|
||||||
edges: edges.clone(),
|
edges: edges.clone(),
|
||||||
};
|
};
|
||||||
let cycle_canonical =
|
let cycle_canonical =
|
||||||
tmp.insert(Cycle::new(edges.into_iter().map(|edge| edge.canonical())));
|
Cycle::new(edges.into_iter().map(|edge| edge.canonical()));
|
||||||
|
|
||||||
LocalForm::new(cycle_local, cycle_canonical)
|
LocalForm::new(cycle_local, cycle_canonical)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue