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

Refactor edge/curve representation #1996

Merged
merged 7 commits into from
Aug 17, 2023
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
5 changes: 5 additions & 0 deletions crates/fj-core/src/algorithms/approx/curve.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//! Curve approximation

mod segment;

pub use self::segment::CurveApproxSegment;
50 changes: 50 additions & 0 deletions crates/fj-core/src/algorithms/approx/curve/segment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use std::cmp;

use fj_math::Point;

use crate::{algorithms::approx::ApproxPoint, geometry::CurveBoundary};

/// A segment of a curve approximation
///
/// A curve is potentially infinite (at least its local coordinate space is
/// infinite, even if the curve itself isn't; a circle is an example of that).
/// This means a curve can only be approximated locally, at a number of
/// segments. This struct represents on such segment.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct CurveApproxSegment {
/// The boundary within which this segment approximates the curve
pub boundary: CurveBoundary<Point<1>>,

/// The points that approximate the curve segment
pub points: Vec<ApproxPoint<1>>,
}

impl CurveApproxSegment {
/// Reverse the orientation of the approximation
#[must_use]
pub fn reverse(mut self) -> Self {
self.boundary = self.boundary.reverse();
self.points.reverse();
self
}
}

impl Ord for CurveApproxSegment {
fn cmp(&self, other: &Self) -> cmp::Ordering {
let [a_start, a_end] = self.boundary.inner;
let [b_start, b_end] = other.boundary.inner;

let by_start = a_start.cmp(&b_start);
if by_start.is_ne() {
return by_start;
}

a_end.cmp(&b_end)
}
}

impl PartialOrd for CurveApproxSegment {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
29 changes: 7 additions & 22 deletions crates/fj-core/src/algorithms/approx/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
storage::{Handle, HandleWrapper},
};

use super::{Approx, ApproxPoint, Tolerance};
use super::{curve::CurveApproxSegment, Approx, ApproxPoint, Tolerance};

impl Approx for (&HalfEdge, &Surface) {
type Approximation = HalfEdgeApprox;
Expand Down Expand Up @@ -143,7 +143,7 @@ fn approx_edge(
surface: &Surface,
boundary: CurveBoundary<Point<1>>,
tolerance: impl Into<Tolerance>,
) -> GlobalEdgeApprox {
) -> CurveApproxSegment {
// There are different cases of varying complexity. Circles are the hard
// part here, as they need to be approximated, while lines don't need to be.
//
Expand Down Expand Up @@ -211,15 +211,15 @@ fn approx_edge(
ApproxPoint::new(point_curve, point_global)
})
.collect();
GlobalEdgeApprox { points }
CurveApproxSegment { boundary, points }
}

/// A cache for results of an approximation
#[derive(Default)]
pub struct EdgeCache {
edge_approx: BTreeMap<
(HandleWrapper<GlobalEdge>, CurveBoundary<Point<1>>),
GlobalEdgeApprox,
CurveApproxSegment,
>,
vertex_approx: BTreeMap<HandleWrapper<Vertex>, Point<3>>,
}
Expand All @@ -235,7 +235,7 @@ impl EdgeCache {
&self,
handle: Handle<GlobalEdge>,
boundary: CurveBoundary<Point<1>>,
) -> Option<GlobalEdgeApprox> {
) -> Option<CurveApproxSegment> {
if let Some(approx) =
self.edge_approx.get(&(handle.clone().into(), boundary))
{
Expand All @@ -257,8 +257,8 @@ impl EdgeCache {
&mut self,
handle: Handle<GlobalEdge>,
boundary: CurveBoundary<Point<1>>,
approx: GlobalEdgeApprox,
) -> GlobalEdgeApprox {
approx: CurveApproxSegment,
) -> CurveApproxSegment {
self.edge_approx
.insert((handle.into(), boundary), approx.clone())
.unwrap_or(approx)
Expand All @@ -279,21 +279,6 @@ impl EdgeCache {
}
}

/// An approximation of a [`GlobalEdge`]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
struct GlobalEdgeApprox {
/// The points that approximate the edge
points: Vec<ApproxPoint<1>>,
}

impl GlobalEdgeApprox {
/// Reverse the order of the approximation
fn reverse(mut self) -> Self {
self.points.reverse();
self
}
}

#[cfg(test)]
mod tests {
use std::{f64::consts::TAU, ops::Deref};
Expand Down
1 change: 1 addition & 0 deletions crates/fj-core/src/algorithms/approx/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Approximation of objects

pub mod curve;
pub mod cycle;
pub mod edge;
pub mod face;
Expand Down