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

Add GlobalEdge #999

Merged
merged 9 commits into from
Aug 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/fj-kernel/src/algorithms/approx/edges.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use fj_math::Point;

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

use super::Local;

pub fn approx_edge(
vertices: VerticesOfEdge,
vertices: VerticesOfEdge<Vertex>,
points: &mut Vec<Local<Point<1>>>,
) {
// Insert the exact vertices of this edge into the approximation. This means
Expand Down
1 change: 1 addition & 0 deletions crates/fj-kernel/src/algorithms/intersect/face_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ impl Intersect for (&Face, &Point<2>) {
}

/// The intersection between a face and a point
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum FacePointIntersection {
/// The point is inside of the face
Expand Down
1 change: 1 addition & 0 deletions crates/fj-kernel/src/algorithms/intersect/ray_face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ impl Intersect for (&HorizontalRayToTheRight<3>, &Face) {

/// A hit between a ray and a face
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[allow(clippy::large_enum_variant)]
pub enum RayFaceIntersection {
/// The ray hits the face itself
RayHitsFace,
Expand Down
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/algorithms/reverse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fn reverse_local_coordinates_in_cycle<'r>(
Curve::new(local, *edge.curve().global())
};

Edge::new(curve, *edge.vertices())
Edge::from_curve_and_vertices(curve, *edge.vertices())
});

Cycle::new(surface).with_edges(edges)
Expand Down
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/algorithms/sweep/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ fn create_non_continuous_side_face(
Vertex::new(Point::from([1.]), b.1),
]);

let edge = Edge::new(curve, vertices);
let edge = Edge::from_curve_and_vertices(curve, vertices);

edges.push(edge);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/algorithms/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl TransformObject for Edge {
let vertices =
self.vertices().map(|vertex| vertex.transform(transform));

Self::new(curve, vertices)
Self::from_curve_and_vertices(curve, vertices)
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/fj-kernel/src/builder/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl EdgeBuilder {
Vector::from([Scalar::ZERO, radius, Scalar::ZERO]),
)));

Edge::new(
Edge::from_curve_and_vertices(
Curve::new(curve_local, curve_global),
VerticesOfEdge::none(),
)
Expand Down Expand Up @@ -58,7 +58,7 @@ impl EdgeBuilder {
]
};

Edge::new(
Edge::from_curve_and_vertices(
Curve::new(curve_local, curve_global),
VerticesOfEdge::from_vertices(vertices),
)
Expand Down
137 changes: 111 additions & 26 deletions crates/fj-kernel/src/objects/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ use std::fmt;

use crate::builder::EdgeBuilder;

use super::{Curve, Vertex};
use super::{Curve, GlobalCurve, GlobalVertex, Vertex};

/// An edge
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Edge {
curve: Curve,
vertices: VerticesOfEdge,
vertices: VerticesOfEdge<Vertex>,
global: GlobalEdge,
}

impl Edge {
Expand All @@ -17,9 +18,43 @@ impl Edge {
EdgeBuilder
}

/// Create a new instance
pub fn new(curve: Curve, vertices: VerticesOfEdge) -> Self {
Self { curve, vertices }
/// Create a new instance of `Edge`
///
/// If you only have a curve and the edge vertices, please check out
/// [`Edge::from_curve_and_vertices`], which is a convenience wrapper around
/// this method, which creates an instance of [`GlobalEdge`].
///
/// # Panics
///
/// Panics, if the provided [`GlobalEdge`] instance doesn't refer to the
/// same [`GlobalCurve`] and [`GlobalVertex`] instances that the other
/// objects that are passed refer to.
pub fn new(
curve: Curve,
vertices: VerticesOfEdge<Vertex>,
global: GlobalEdge,
) -> Self {
assert_eq!(curve.global(), global.curve());
assert_eq!(&vertices.to_global(), global.vertices());

Self {
curve,
vertices,
global,
}
}

/// Create a new instance of `Edge` from a curve and vertices
///
/// The [`GlobalEdge`] instance is created from the provided curve and
/// vertices. Please refer to [`Edge::new`], if you already have a
/// [`GlobalEdge`] instance that you can provide.
pub fn from_curve_and_vertices(
curve: Curve,
vertices: VerticesOfEdge<Vertex>,
) -> Self {
let global = GlobalEdge::new(*curve.global(), vertices.to_global());
Self::new(curve, vertices, global)
}

/// Access the curve that defines the edge's geometry
Expand All @@ -36,9 +71,14 @@ impl Edge {
/// An edge has either two bounding vertices or none. The latter is possible
/// if the edge's curve is continuous (i.e. connects to itself), and defines
/// the whole edge.
pub fn vertices(&self) -> &VerticesOfEdge {
pub fn vertices(&self) -> &VerticesOfEdge<Vertex> {
&self.vertices
}

/// Access the global form of this edge
pub fn global(&self) -> &GlobalEdge {
&self.global
}
}

impl fmt::Display for Edge {
Expand All @@ -57,13 +97,51 @@ impl fmt::Display for Edge {
}
}

/// An edge, defined in global (3D) coordinates
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct GlobalEdge {
curve: GlobalCurve,
vertices: VerticesOfEdge<GlobalVertex>,
}

impl GlobalEdge {
/// Create a new instance
pub fn new(
curve: GlobalCurve,
vertices: VerticesOfEdge<GlobalVertex>,
) -> Self {
Self { curve, vertices }
}

/// Access the curve that defines the edge's geometry
///
/// The edge can be a segment of the curve that is bounded by two vertices,
/// or if the curve is continuous (i.e. connects to itself), the edge could
/// be defined by the whole curve, and have no bounding vertices.
pub fn curve(&self) -> &GlobalCurve {
&self.curve
}

/// Access the vertices that bound the edge on the curve
///
/// An edge has either two bounding vertices or none. The latter is possible
/// if the edge's curve is continuous (i.e. connects to itself), and defines
/// the whole edge.
pub fn vertices(&self) -> &VerticesOfEdge<GlobalVertex> {
&self.vertices
}
}

/// The vertices that bound an edge
///
/// This struct is generic over the actual vertex type used, but typically, `T`
/// will either be [`Vertex`] or [`GlobalVertex`].
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct VerticesOfEdge(Option<[Vertex; 2]>);
pub struct VerticesOfEdge<T>(Option<[T; 2]>);

impl VerticesOfEdge {
impl<T> VerticesOfEdge<T> {
/// Construct an instance of `VerticesOfEdge` from two vertices
pub fn from_vertices(vertices: [Vertex; 2]) -> Self {
pub fn from_vertices(vertices: [T; 2]) -> Self {
Self(Some(vertices))
}

Expand All @@ -73,7 +151,7 @@ impl VerticesOfEdge {
}

/// Access the vertices
pub fn get(&self) -> Option<[&Vertex; 2]> {
pub fn get(&self) -> Option<[&T; 2]> {
self.0.as_ref().map(|vertices| {
// Can be cleaned up once `each_ref` is stable:
// https://doc.rust-lang.org/std/primitive.array.html#method.each_ref
Expand All @@ -87,15 +165,33 @@ impl VerticesOfEdge {
/// # Panics
///
/// Panics, if the edge has no vertices.
pub fn get_or_panic(&self) -> [&Vertex; 2] {
pub fn get_or_panic(&self) -> [&T; 2] {
self.get().expect("Expected edge to have vertices")
}

/// Iterate over the vertices
pub fn iter(&self) -> impl Iterator<Item = &Vertex> {
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.0.iter().flatten()
}

/// Map each vertex using the provided function
pub fn map<F>(self, f: F) -> Self
where
F: FnMut(T) -> T,
{
Self(self.convert(f))
}

/// Convert each vertex using the provided function
pub fn convert<F, U>(self, f: F) -> Option<[U; 2]>
where
F: FnMut(T) -> U,
{
self.0.map(|vertices| vertices.map(f))
}
}

impl VerticesOfEdge<Vertex> {
/// Reverse the order of vertices
///
/// Makes sure that the local coordinates are still correct.
Expand All @@ -108,19 +204,8 @@ impl VerticesOfEdge {
}))
}

/// Map each vertex using the provided function
pub fn map<F>(self, f: F) -> Self
where
F: FnMut(Vertex) -> Vertex,
{
Self(self.convert(f))
}

/// Convert each vertex using the provided function
pub fn convert<F, T>(self, f: F) -> Option<[T; 2]>
where
F: FnMut(Vertex) -> T,
{
self.0.map(|vertices| vertices.map(f))
/// Convert this instance into its global variant
pub fn to_global(&self) -> VerticesOfEdge<GlobalVertex> {
VerticesOfEdge(self.convert(|vertex| *vertex.global()))
}
}
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/objects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod vertex;
pub use self::{
curve::{Curve, CurveKind, GlobalCurve},
cycle::Cycle,
edge::{Edge, VerticesOfEdge},
edge::{Edge, GlobalEdge, VerticesOfEdge},
face::Face,
shell::Shell,
sketch::Sketch,
Expand Down
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/validation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ mod tests {
let b = Vertex::new(Point::from([Scalar::ONE]), b);
let vertices = VerticesOfEdge::from_vertices([a, b]);

let edge = Edge::new(curve, vertices);
let edge = Edge::from_curve_and_vertices(curve, vertices);

let result = validate(
edge,
Expand Down
5 changes: 4 additions & 1 deletion crates/fj-operations/src/difference_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ fn add_cycle(cycle: Cycle, reverse: bool) -> Cycle {
*edge.vertices()
};

let edge = Edge::new(Curve::new(curve_local, curve_global), vertices);
let edge = Edge::from_curve_and_vertices(
Curve::new(curve_local, curve_global),
vertices,
);

edges.push(edge);
}
Expand Down