Move approximation caching code to edge module

This commit is contained in:
Hanno Braun 2023-02-22 13:34:31 +01:00
parent f28c2655ae
commit 087401bf21
8 changed files with 68 additions and 89 deletions

View File

@ -1,76 +0,0 @@
//! Curve approximation
//!
//! Since curves are infinite (even circles have an infinite coordinate space,
//! even though they connect to themselves in global coordinates), a range must
//! be provided to approximate them. The approximation then returns points
//! within that range.
//!
//! The boundaries of the range are not included in the approximation. This is
//! done, to give the caller (who knows the boundary anyway) more options on how
//! to further process the approximation.
use std::collections::BTreeMap;
use crate::{
objects::GlobalCurve,
storage::{Handle, ObjectId},
};
use super::{path::RangeOnPath, ApproxPoint};
/// A cache for results of an approximation
#[derive(Default)]
pub struct CurveCache {
inner: BTreeMap<(ObjectId, RangeOnPath), GlobalCurveApprox>,
}
impl CurveCache {
/// Create an empty cache
pub fn new() -> Self {
Self::default()
}
/// Insert the approximation of a [`GlobalCurve`]
pub fn insert(
&mut self,
handle: Handle<GlobalCurve>,
range: RangeOnPath,
approx: GlobalCurveApprox,
) -> GlobalCurveApprox {
self.inner.insert((handle.id(), range), approx.clone());
approx
}
/// Access the approximation for the given [`GlobalCurve`], if available
pub fn get(
&self,
handle: Handle<GlobalCurve>,
range: RangeOnPath,
) -> Option<GlobalCurveApprox> {
if let Some(approx) = self.inner.get(&(handle.id(), range)) {
return Some(approx.clone());
}
if let Some(approx) = self.inner.get(&(handle.id(), range.reverse())) {
// If we have a cache entry for the reverse range, we need to use
// that too!
return Some(approx.clone().reverse());
}
None
}
}
/// An approximation of a [`GlobalCurve`]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct GlobalCurveApprox {
/// The points that approximate the curve
pub points: Vec<ApproxPoint<1>>,
}
impl GlobalCurveApprox {
/// Reverse the order of the approximation
pub fn reverse(mut self) -> Self {
self.points.reverse();
self
}
}

View File

@ -7,7 +7,8 @@ use fj_math::Segment;
use crate::objects::{Cycle, Surface};
use super::{
curve::CurveCache, edge::HalfEdgeApprox, Approx, ApproxPoint, Tolerance,
edge::{CurveCache, HalfEdgeApprox},
Approx, ApproxPoint, Tolerance,
};
impl Approx for (&Cycle, &Surface) {

View File

@ -5,17 +5,15 @@
//! approximations are usually used to build cycle approximations, and this way,
//! the caller doesn't have to call with duplicate vertices.
use std::collections::BTreeMap;
use crate::{
geometry::path::{GlobalPath, SurfacePath},
objects::{Curve, HalfEdge, Surface},
storage::Handle,
objects::{Curve, GlobalCurve, HalfEdge, Surface},
storage::{Handle, ObjectId},
};
use super::{
curve::{CurveCache, GlobalCurveApprox},
path::RangeOnPath,
Approx, ApproxPoint, Tolerance,
};
use super::{path::RangeOnPath, Approx, ApproxPoint, Tolerance};
impl Approx for (&Handle<HalfEdge>, &Surface) {
type Approximation = HalfEdgeApprox;
@ -180,6 +178,63 @@ fn approx_edge(
GlobalCurveApprox { points }
}
/// A cache for results of an approximation
#[derive(Default)]
pub struct CurveCache {
inner: BTreeMap<(ObjectId, RangeOnPath), GlobalCurveApprox>,
}
impl CurveCache {
/// Create an empty cache
pub fn new() -> Self {
Self::default()
}
/// Insert the approximation of a [`GlobalCurve`]
pub fn insert(
&mut self,
handle: Handle<GlobalCurve>,
range: RangeOnPath,
approx: GlobalCurveApprox,
) -> GlobalCurveApprox {
self.inner.insert((handle.id(), range), approx.clone());
approx
}
/// Access the approximation for the given [`GlobalCurve`], if available
pub fn get(
&self,
handle: Handle<GlobalCurve>,
range: RangeOnPath,
) -> Option<GlobalCurveApprox> {
if let Some(approx) = self.inner.get(&(handle.id(), range)) {
return Some(approx.clone());
}
if let Some(approx) = self.inner.get(&(handle.id(), range.reverse())) {
// If we have a cache entry for the reverse range, we need to use
// that too!
return Some(approx.clone().reverse());
}
None
}
}
/// An approximation of a [`GlobalCurve`]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct GlobalCurveApprox {
/// The points that approximate the curve
pub points: Vec<ApproxPoint<1>>,
}
impl GlobalCurveApprox {
/// Reverse the order of the approximation
pub fn reverse(mut self) -> Self {
self.points.reverse();
self
}
}
#[cfg(test)]
mod tests {
use std::{f64::consts::TAU, ops::Deref};

View File

@ -12,7 +12,7 @@ use crate::{
};
use super::{
curve::CurveCache, cycle::CycleApprox, Approx, ApproxPoint, Tolerance,
cycle::CycleApprox, edge::CurveCache, Approx, ApproxPoint, Tolerance,
};
impl Approx for &FaceSet {

View File

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

View File

@ -4,7 +4,7 @@ use std::collections::BTreeSet;
use crate::objects::Shell;
use super::{curve::CurveCache, face::FaceApprox, Approx, Tolerance};
use super::{edge::CurveCache, face::FaceApprox, Approx, Tolerance};
impl Approx for &Shell {
type Approximation = BTreeSet<FaceApprox>;

View File

@ -4,7 +4,7 @@ use std::collections::BTreeSet;
use crate::objects::Sketch;
use super::{curve::CurveCache, face::FaceApprox, Approx, Tolerance};
use super::{edge::CurveCache, face::FaceApprox, Approx, Tolerance};
impl Approx for &Sketch {
type Approximation = BTreeSet<FaceApprox>;

View File

@ -4,7 +4,7 @@ use std::collections::BTreeSet;
use crate::objects::Solid;
use super::{curve::CurveCache, face::FaceApprox, Approx, Tolerance};
use super::{edge::CurveCache, face::FaceApprox, Approx, Tolerance};
impl Approx for &Solid {
type Approximation = BTreeSet<FaceApprox>;