Skip to content

Commit

Permalink
Merge pull request #1011 from hannobraun/approx3
Browse files Browse the repository at this point in the history
Remove `Local`; replace its uses using simpler means
  • Loading branch information
hannobraun authored Aug 29, 2022
2 parents c28aecf + d2d11b2 commit d9292f6
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 115 deletions.
15 changes: 9 additions & 6 deletions crates/fj-kernel/src/algorithms/approx/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ use fj_math::{Circle, Point, Scalar};

use crate::objects::{Curve, CurveKind, GlobalCurve};

use super::{Approx, Local, Tolerance};
use super::{Approx, Tolerance};

impl Approx for Curve {
type Approximation = Vec<Local<Point<1>>>;
type Approximation = Vec<(Point<1>, Point<3>)>;

fn approx(&self, tolerance: Tolerance) -> Self::Approximation {
self.global().approx(tolerance)
}
}

impl Approx for GlobalCurve {
type Approximation = Vec<Local<Point<1>>>;
type Approximation = Vec<(Point<1>, Point<3>)>;

/// Approximate the global curve
///
Expand Down Expand Up @@ -45,7 +45,7 @@ pub fn approx_circle(
circle: &Circle<3>,
between: [impl Into<Point<1>>; 2],
tolerance: Tolerance,
) -> Vec<Local<Point<1>>> {
) -> Vec<(Point<1>, Point<3>)> {
let mut points = Vec::new();

let radius = circle.a().magnitude();
Expand All @@ -64,8 +64,11 @@ pub fn approx_circle(
for i in 0..n {
let angle =
start.t + (Scalar::TAU / n as f64 * i as f64) * range.sign();
let point = circle.point_from_circle_coords([angle]);
points.push(Local::new([angle], point));

let point_curve = Point::from([angle]);
let point_global = circle.point_from_circle_coords(point_curve);

points.push((point_curve, point_global));
}

points
Expand Down
22 changes: 12 additions & 10 deletions crates/fj-kernel/src/algorithms/approx/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use fj_math::{Point, Segment};

use crate::objects::Cycle;

use super::{Approx, Local, Tolerance};
use super::{Approx, Tolerance};

impl Approx for Cycle {
type Approximation = CycleApprox;
Expand All @@ -14,17 +14,17 @@ impl Approx for Cycle {
let edge_points = edge.approx(tolerance);

points.extend(edge_points.into_iter().map(|point| {
let local = edge
.curve()
.kind()
.point_from_curve_coords(*point.local_form());
Local::new(local, *point.global_form())
let (point_curve, point_global) = point;

let point_surface =
edge.curve().kind().point_from_curve_coords(point_curve);
(point_surface, point_global)
}));
}

// Can't just rely on `dedup`, as the conversion from curve coordinates
// could lead to subtly different surface coordinates.
points.dedup_by(|a, b| a.global_form() == b.global_form());
points.dedup_by(|(_, a), (_, b)| a == b);

CycleApprox { points }
}
Expand All @@ -34,7 +34,7 @@ impl Approx for Cycle {
#[derive(Debug, Eq, PartialEq, Hash)]
pub struct CycleApprox {
/// The points that approximate the cycle
pub points: Vec<Local<Point<2>>>,
pub points: Vec<(Point<2>, Point<3>)>,
}

impl CycleApprox {
Expand All @@ -47,8 +47,10 @@ impl CycleApprox {
// up, once `array_windows` is stable.
let segment = [segment[0], segment[1]];

segments
.push(Segment::from(segment.map(|point| *point.global_form())));
segments.push(Segment::from(segment.map(|point| {
let (_, point_global) = point;
point_global
})));
}

segments
Expand Down
24 changes: 10 additions & 14 deletions crates/fj-kernel/src/algorithms/approx/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use fj_math::Point;

use crate::objects::{Edge, Vertex, VerticesOfEdge};

use super::{Approx, Local};
use super::Approx;

impl Approx for Edge {
type Approximation = Vec<Local<Point<1>>>;
type Approximation = Vec<(Point<1>, Point<3>)>;

fn approx(&self, tolerance: super::Tolerance) -> Self::Approximation {
let mut points = self.curve().approx(tolerance);
Expand All @@ -17,7 +17,7 @@ impl Approx for Edge {

pub fn approx_edge(
vertices: VerticesOfEdge<Vertex>,
points: &mut Vec<Local<Point<1>>>,
points: &mut Vec<(Point<1>, Point<3>)>,
) {
// Insert the exact vertices of this edge into the approximation. This means
// we don't rely on the curve approximation to deliver accurate
Expand All @@ -27,9 +27,8 @@ pub fn approx_edge(
// would lead to bugs in the approximation, as points that should refer to
// the same vertex would be understood to refer to very close, but distinct
// vertices.
let vertices = vertices.convert(|vertex| {
Local::new(vertex.position(), vertex.global().position())
});
let vertices = vertices
.convert(|vertex| (vertex.position(), vertex.global().position()));
if let Some([a, b]) = vertices {
points.insert(0, a);
points.push(b);
Expand All @@ -49,10 +48,7 @@ pub fn approx_edge(
mod test {
use fj_math::Point;

use crate::{
algorithms::approx::Local,
objects::{GlobalVertex, Vertex, VerticesOfEdge},
};
use crate::objects::{GlobalVertex, Vertex, VerticesOfEdge};

#[test]
fn approx_edge() {
Expand All @@ -69,10 +65,10 @@ mod test {
Vertex::new(Point::from([1.]), v2),
]);

let a = Local::new([0.0], a);
let b = Local::new([0.25], b);
let c = Local::new([0.75], c);
let d = Local::new([1.0], d);
let a = (Point::from([0.0]), a);
let b = (Point::from([0.25]), b);
let c = (Point::from([0.75]), c);
let d = (Point::from([1.0]), d);

// Regular edge
let mut points = vec![b, c];
Expand Down
22 changes: 11 additions & 11 deletions crates/fj-kernel/src/algorithms/approx/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use fj_math::Point;

use crate::objects::Face;

use super::{Approx, CycleApprox, Local, Tolerance};
use super::{Approx, CycleApprox, Tolerance};

impl Approx for Face {
type Approximation = FaceApprox;
Expand Down Expand Up @@ -67,7 +67,7 @@ pub struct FaceApprox {
///
/// These could be actual vertices from the model, points that approximate
/// an edge, or points that approximate a face.
pub points: HashSet<Local<Point<2>>>,
pub points: HashSet<(Point<2>, Point<3>)>,

/// Approximation of the exterior cycle
pub exterior: CycleApprox,
Expand All @@ -82,7 +82,7 @@ mod tests {
use map_macro::set;

use crate::{
algorithms::approx::{Approx, Local},
algorithms::approx::Approx,
objects::{Face, Surface},
};

Expand All @@ -109,14 +109,14 @@ mod tests {
.polygon_from_points([a, b, c, d])
.with_hole([e, f, g, h]);

let a = Local::new(a, a.to_xyz());
let b = Local::new(b, b.to_xyz());
let c = Local::new(c, c.to_xyz());
let d = Local::new(d, d.to_xyz());
let e = Local::new(e, e.to_xyz());
let f = Local::new(f, f.to_xyz());
let g = Local::new(g, g.to_xyz());
let h = Local::new(h, h.to_xyz());
let a = (a, a.to_xyz());
let b = (b, b.to_xyz());
let c = (c, c.to_xyz());
let d = (d, d.to_xyz());
let e = (e, e.to_xyz());
let f = (f, f.to_xyz());
let g = (g, g.to_xyz());
let h = (h, h.to_xyz());

let approx = face.approx(tolerance);
let expected = FaceApprox {
Expand Down
57 changes: 0 additions & 57 deletions crates/fj-kernel/src/algorithms/approx/local.rs

This file was deleted.

2 changes: 0 additions & 2 deletions crates/fj-kernel/src/algorithms/approx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ mod curve;
mod cycle;
mod edge;
mod face;
mod local;
mod tolerance;

pub use self::{
cycle::CycleApprox,
face::FaceApprox,
local::{Local, LocalForm},
tolerance::{InvalidTolerance, Tolerance},
};

Expand Down
24 changes: 15 additions & 9 deletions crates/fj-kernel/src/algorithms/triangulate/delaunay.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use fj_math::{Point, Scalar, Triangle, Winding};
use spade::HasPosition;

use crate::algorithms::approx::Local;

/// Create a Delaunay triangulation of all points
pub fn triangulate(points: Vec<Local<Point<2>>>) -> Vec<[Local<Point<2>>; 3]> {
pub fn triangulate(
points: Vec<TriangulationPoint>,
) -> Vec<[TriangulationPoint; 3]> {
use spade::Triangulation as _;

let triangulation = spade::DelaunayTriangulation::<_>::bulk_load(points)
Expand All @@ -14,9 +14,9 @@ pub fn triangulate(points: Vec<Local<Point<2>>>) -> Vec<[Local<Point<2>>; 3]> {
for triangle in triangulation.inner_faces() {
let [v0, v1, v2] = triangle.vertices().map(|vertex| *vertex.data());
let orientation = Triangle::<2>::from_points([
*v0.local_form(),
*v1.local_form(),
*v2.local_form(),
v0.point_surface,
v1.point_surface,
v2.point_surface,
])
.expect("invalid triangle")
.winding_direction();
Expand All @@ -32,14 +32,20 @@ pub fn triangulate(points: Vec<Local<Point<2>>>) -> Vec<[Local<Point<2>>; 3]> {
triangles
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct TriangulationPoint {
pub point_surface: Point<2>,
pub point_global: Point<3>,
}

// Enables the use of `LocalPoint` in the triangulation.
impl HasPosition for Local<Point<2>> {
impl HasPosition for TriangulationPoint {
type Scalar = Scalar;

fn position(&self) -> spade::Point2<Self::Scalar> {
spade::Point2 {
x: self.local_form().u,
y: self.local_form().v,
x: self.point_surface.u,
y: self.point_surface.v,
}
}
}
22 changes: 16 additions & 6 deletions crates/fj-kernel/src/algorithms/triangulate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use fj_math::Point;

use crate::objects::Face;

use self::polygon::Polygon;
use self::{delaunay::TriangulationPoint, polygon::Polygon};

use super::approx::{Approx, Tolerance};

Expand All @@ -29,29 +29,39 @@ pub fn triangulate(
let surface = face.surface();
let approx = face.approx(tolerance);

let points: Vec<_> = approx.points.into_iter().collect();
let points: Vec<_> = approx
.points
.into_iter()
.map(|(point_surface, point_global)| TriangulationPoint {
point_surface,
point_global,
})
.collect();
let face_as_polygon = Polygon::new(*surface)
.with_exterior(
approx
.exterior
.points
.into_iter()
.map(|point| *point.local_form()),
.map(|(point_surface, _)| point_surface),
)
.with_interiors(approx.interiors.into_iter().map(|interior| {
interior.points.into_iter().map(|point| *point.local_form())
interior
.points
.into_iter()
.map(|(point_surface, _)| point_surface)
}));

let mut triangles = delaunay::triangulate(points);
triangles.retain(|triangle| {
face_as_polygon.contains_triangle(
triangle.map(|point| *point.local_form()),
triangle.map(|point| point.point_surface),
debug_info,
)
});

for triangle in triangles {
let points = triangle.map(|point| *point.global_form());
let points = triangle.map(|point| point.point_global);
mesh.push_triangle(points, face.color());
}
}
Expand Down

0 comments on commit d9292f6

Please sign in to comment.