Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename geometry::Point to LocalPoint; clean it up #753

Merged
merged 11 commits into from
Jun 30, 2022
16 changes: 8 additions & 8 deletions crates/fj-kernel/src/algorithms/approx/curves.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::cmp::max;

use fj_math::{Circle, Scalar};

use crate::{geometry, objects::Curve};
use crate::{geometry::LocalPoint, objects::Curve};

use super::Tolerance;

Expand All @@ -20,10 +20,10 @@ use super::Tolerance;
///
/// The `approximate_between` methods of the curves then need to make sure to
/// only return points in between those vertices, not the vertices themselves.
pub fn approx_curve<const D: usize>(
curve: &Curve<D>,
pub fn approx_curve(
curve: &Curve<3>,
tolerance: Tolerance,
out: &mut Vec<geometry::Point<1, D>>,
out: &mut Vec<LocalPoint<1>>,
) {
match curve {
Curve::Circle(curve) => approx_circle(curve, tolerance, out),
Expand All @@ -35,10 +35,10 @@ pub fn approx_curve<const D: usize>(
///
/// `tolerance` specifies how much the approximation is allowed to deviate
/// from the circle.
pub fn approx_circle<const D: usize>(
circle: &Circle<D>,
pub fn approx_circle(
circle: &Circle<3>,
tolerance: Tolerance,
out: &mut Vec<geometry::Point<1, D>>,
out: &mut Vec<LocalPoint<1>>,
) {
let radius = circle.a.magnitude();

Expand All @@ -53,7 +53,7 @@ pub fn approx_circle<const D: usize>(
for i in 0..n {
let angle = Scalar::PI * 2. / n as f64 * i as f64;
let point = circle.point_from_circle_coords([angle]);
out.push(geometry::Point::new([angle], point));
out.push(LocalPoint::new([angle], point));
}
}

Expand Down
10 changes: 4 additions & 6 deletions crates/fj-kernel/src/algorithms/approx/cycles.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use fj_math::Segment;

use crate::{geometry, objects::Cycle};
use crate::{geometry::LocalPoint, objects::Cycle};

use super::{curves::approx_curve, edges::approx_edge, Tolerance};

/// An approximation of a [`Cycle`]
#[derive(Debug, Eq, PartialEq, Hash)]
pub struct CycleApprox {
/// The points that approximate the cycle
pub points: Vec<geometry::Point<3, 3>>,
pub points: Vec<LocalPoint<3>>,
}

impl CycleApprox {
Expand All @@ -29,9 +29,7 @@ impl CycleApprox {

let mut points: Vec<_> = points
.into_iter()
.map(|point| {
geometry::Point::new(point.canonical(), point.canonical())
})
.map(|point| LocalPoint::new(point.global(), point.global()))
.collect();

points.dedup();
Expand All @@ -48,7 +46,7 @@ impl CycleApprox {
// up, once `array_windows` is stable.
let segment = [segment[0], segment[1]];

let segment = segment.map(|point| point.canonical());
let segment = segment.map(|point| point.global());
segments.push(Segment::from(segment));
}

Expand Down
19 changes: 8 additions & 11 deletions crates/fj-kernel/src/algorithms/approx/edges.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use crate::{geometry, objects::VerticesOfEdge};
use crate::{geometry::LocalPoint, objects::VerticesOfEdge};

pub fn approx_edge(
vertices: VerticesOfEdge,
points: &mut Vec<geometry::Point<1, 3>>,
) {
pub fn approx_edge(vertices: VerticesOfEdge, points: &mut Vec<LocalPoint<1>>) {
// Insert the exact vertices of this edge into the approximation. This means
// we don't rely on the curve approximation to deliver accurate
// representations of these vertices, which they might not be able to do.
Expand All @@ -13,7 +10,7 @@ pub fn approx_edge(
// the same vertex would be understood to refer to very close, but distinct
// vertices.
let vertices = vertices.convert(|vertex| {
geometry::Point::new(vertex.position(), vertex.global().position())
LocalPoint::new(vertex.position(), vertex.global().position())
});
if let Some([a, b]) = vertices {
points.insert(0, a);
Expand All @@ -35,7 +32,7 @@ mod test {
use fj_math::Point;

use crate::{
geometry,
geometry::LocalPoint,
objects::{GlobalVertex, Vertex, VerticesOfEdge},
};

Expand All @@ -54,10 +51,10 @@ mod test {
Vertex::new(Point::from([1.]), v2),
]);

let a = geometry::Point::new([0.0], a);
let b = geometry::Point::new([0.25], b);
let c = geometry::Point::new([0.75], c);
let d = geometry::Point::new([1.0], d);
let a = LocalPoint::new([0.0], a);
let b = LocalPoint::new([0.25], b);
let c = LocalPoint::new([0.75], c);
let d = LocalPoint::new([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/faces.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashSet;

use crate::{geometry, objects::Face};
use crate::{geometry::LocalPoint, objects::Face};

use super::{CycleApprox, Tolerance};

Expand All @@ -11,7 +11,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<geometry::Point<3, 3>>,
pub points: HashSet<LocalPoint<3>>,

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

use crate::{
geometry,
geometry::LocalPoint,
objects::{Face, Surface},
};

Expand Down Expand Up @@ -118,14 +118,14 @@ mod tests {
let g = g.to_xyz();
let h = h.to_xyz();

let a = geometry::Point::new(a, a);
let b = geometry::Point::new(b, b);
let c = geometry::Point::new(c, c);
let d = geometry::Point::new(d, d);
let e = geometry::Point::new(e, e);
let f = geometry::Point::new(f, f);
let g = geometry::Point::new(g, g);
let h = geometry::Point::new(h, h);
let a = LocalPoint::new(a, a);
let b = LocalPoint::new(b, b);
let c = LocalPoint::new(c, c);
let d = LocalPoint::new(d, d);
let e = LocalPoint::new(e, e);
let f = LocalPoint::new(f, f);
let g = LocalPoint::new(g, g);
let h = LocalPoint::new(h, h);

let approx = FaceApprox::new(&face, tolerance);
let expected = FaceApprox {
Expand Down
10 changes: 4 additions & 6 deletions crates/fj-kernel/src/algorithms/triangulate/delaunay.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use fj_math::{Scalar, Triangle, Winding};
use spade::HasPosition;

use crate::geometry;
use crate::geometry::LocalPoint;

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

let triangulation = spade::DelaunayTriangulation::<_>::bulk_load(points)
Expand All @@ -30,8 +28,8 @@ pub fn triangulate(
triangles
}

// Enables the use of `geometry::Point` in the triangulation.
impl HasPosition for geometry::Point<2, 3> {
// Enables the use of `LocalPoint` in the triangulation.
impl HasPosition for LocalPoint<2> {
type Scalar = Scalar;

fn position(&self) -> spade::Point2<Self::Scalar> {
Expand Down
8 changes: 4 additions & 4 deletions crates/fj-kernel/src/algorithms/triangulate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub fn triangulate(
.map(|vertex| {
// Can't panic, unless the approximation wrongfully
// generates points that are not in the surface.
surface.point_to_surface_coords(vertex.canonical())
surface.point_to_surface_coords(vertex.global())
})
.collect();
let face_as_polygon = Polygon::new(surface)
Expand All @@ -40,7 +40,7 @@ pub fn triangulate(
// Can't panic, unless the approximation wrongfully
// generates points that are not in the surface.
surface
.point_to_surface_coords(point.canonical())
.point_to_surface_coords(point.global())
.local()
},
))
Expand All @@ -51,7 +51,7 @@ pub fn triangulate(
// wrongfully generates points that are not in
// the surface.
surface
.point_to_surface_coords(point.canonical())
.point_to_surface_coords(point.global())
.local()
})
},
Expand All @@ -66,7 +66,7 @@ pub fn triangulate(
});

for triangle in triangles {
let points = triangle.map(|point| point.canonical());
let points = triangle.map(|point| point.global());
mesh.push_triangle(points, brep.color);
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/geometry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

mod points;

pub use self::points::Point;
pub use self::points::LocalPoint;
55 changes: 30 additions & 25 deletions crates/fj-kernel/src/geometry/points.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,55 @@
/// A point that stores a local and a canonical form
/// A point that stores a local and a global form
///
/// The local form of a point is whatever representation is most appropriate in
/// the current context. The canonical form is the representation that the
/// local form was created from.
///
/// Typically, the canonical form is more general and has higher dimensionality
/// (for example, a point in a 3D space), while the local form is more specific
/// and has lower dimensionality (for example, the point in 2D surface
/// coordinates, on surface within that 3D space).
/// the current context, which might be a curve or surface. The global form is
/// the global 3D form of the same point.
///
/// The purpose of storing both forms is to be able to losslessly convert the
/// point back to its canonical form. Even if this conversion can be computed on
/// the fly, such a conversion might not result in the original canonical form,
/// due to floating point accuracy issues. Hence, such a conversion would not be
/// point back to its global form. Even if this conversion can be computed on
/// the fly, such a conversion might not result in the original global form, due
/// to floating point accuracy issues. Hence, such a conversion would not be
/// lossless, which could result in bugs.
///
/// The `N` parameter defines the dimensionality of the local form, while the
/// `C` parameter defines the dimensionality of the canonical form.
/// The `D` parameter defines the dimensionality of the local form.
///
/// # `LocalPoint` and [`Vertex`]
///
/// `LocalPoint` is similar to `Vertex`, but there is a key differences:
/// `Vertex` is an object in the boundary representation of a shape, while
/// `LocalPoint` can refer to any point. This distinction is important in the
/// case of approximation, for example, as points might be generated to
/// approximate a curve or surface, without those generated points referring to
/// any vertices.
///
/// [`Vertex`]: crate::objects::Vertex
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Point<const N: usize, const C: usize> {
local: fj_math::Point<N>,
canonical: fj_math::Point<C>,
pub struct LocalPoint<const D: usize> {
local: fj_math::Point<D>,
global: fj_math::Point<3>,
}

impl<const N: usize, const C: usize> Point<N, C> {
impl<const D: usize> LocalPoint<D> {
/// Construct a new instance
///
/// Both the local and the canonical form must be provided. The caller must
/// Both the local and the global form must be provided. The caller must
/// guarantee that both of them match, i.e. define the same point.
pub fn new(
local: impl Into<fj_math::Point<N>>,
canonical: impl Into<fj_math::Point<C>>,
local: impl Into<fj_math::Point<D>>,
global: impl Into<fj_math::Point<3>>,
) -> Self {
Self {
local: local.into(),
canonical: canonical.into(),
global: global.into(),
}
}

/// Access the point's local form
pub fn local(&self) -> fj_math::Point<N> {
pub fn local(&self) -> fj_math::Point<D> {
self.local
}

/// Access the point's canonical form
pub fn canonical(&self) -> fj_math::Point<C> {
self.canonical
/// Access the point's global form
pub fn global(&self) -> fj_math::Point<3> {
self.global
}
}
18 changes: 6 additions & 12 deletions crates/fj-kernel/src/objects/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use std::fmt;

use fj_math::{Circle, Line, Point, Transform, Vector};

use crate::geometry;

/// A one-dimensional shape
///
/// The word "curve" is used as an umbrella term for all one-dimensional shapes,
Expand Down Expand Up @@ -61,17 +59,13 @@ impl<const D: usize> Curve<D> {
pub fn point_to_curve_coords(
&self,
point: impl Into<Point<D>>,
) -> geometry::Point<1, D> {
let point_canonical = point.into();

let point_local = match self {
Self::Circle(curve) => {
curve.point_to_circle_coords(point_canonical)
}
Self::Line(curve) => curve.point_to_line_coords(point_canonical),
};
) -> Point<1> {
let point = point.into();

geometry::Point::new(point_local, point_canonical)
match self {
Self::Circle(curve) => curve.point_to_circle_coords(point),
Self::Line(curve) => curve.point_to_line_coords(point),
}
}

/// Convert a point on the curve into model coordinates
Expand Down
8 changes: 4 additions & 4 deletions crates/fj-kernel/src/objects/surface.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use fj_math::{Line, Point, Transform, Vector};

use crate::geometry;
use crate::geometry::LocalPoint;

use super::Curve;

Expand Down Expand Up @@ -68,7 +68,7 @@ impl Surface {
pub fn point_to_surface_coords(
&self,
point_3d: impl Into<Point<3>>,
) -> geometry::Point<2, 3> {
) -> LocalPoint<2> {
let point_3d = point_3d.into();

let point_2d = match self {
Expand All @@ -77,7 +77,7 @@ impl Surface {
}
};

geometry::Point::new(point_2d, point_3d)
LocalPoint::new(point_2d, point_3d)
}

/// Convert a point in surface coordinates to model coordinates
Expand Down Expand Up @@ -138,7 +138,7 @@ impl SweptCurve {
) -> Point<2> {
let point = point.into();

let u = self.curve.point_to_curve_coords(point).local().t;
let u = self.curve.point_to_curve_coords(point).t;
let v = self.path_to_line().point_to_line_coords(point).t;

Point::from([u, v])
Expand Down