Merge pull request #1996 from hannobraun/approx

Refactor edge/curve representation
This commit is contained in:
Hanno Braun 2023-08-17 11:16:18 +02:00 committed by GitHub
commit b42ad3dc07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 22 deletions

View File

@ -0,0 +1,5 @@
//! Curve approximation
mod segment;
pub use self::segment::CurveApproxSegment;

View File

@ -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))
}
}

View File

@ -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;
@ -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.
//
@ -211,7 +211,7 @@ fn approx_edge(
ApproxPoint::new(point_curve, point_global)
})
.collect();
GlobalEdgeApprox { points }
CurveApproxSegment { boundary, points }
}
/// A cache for results of an approximation
@ -219,7 +219,7 @@ fn approx_edge(
pub struct EdgeCache {
edge_approx: BTreeMap<
(HandleWrapper<GlobalEdge>, CurveBoundary<Point<1>>),
GlobalEdgeApprox,
CurveApproxSegment,
>,
vertex_approx: BTreeMap<HandleWrapper<Vertex>, Point<3>>,
}
@ -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))
{
@ -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)
@ -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};

View File

@ -1,5 +1,6 @@
//! Approximation of objects
pub mod curve;
pub mod cycle;
pub mod edge;
pub mod face;