Skip to content

Commit

Permalink
Merge pull request #2008 from hannobraun/approx
Browse files Browse the repository at this point in the history
Prepare for more sophisticated curve approximation caching
  • Loading branch information
hannobraun authored Sep 5, 2023
2 parents 2c1ea36 + a202d4d commit c0b6264
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 34 deletions.
3 changes: 2 additions & 1 deletion crates/fj-core/src/algorithms/approx/curve.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Curve approximation

mod cache;
mod segment;

pub use self::segment::CurveApproxSegment;
pub use self::{cache::CurveApproxCache, segment::CurveApproxSegment};
53 changes: 53 additions & 0 deletions crates/fj-core/src/algorithms/approx/curve/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use std::collections::BTreeMap;

use fj_math::Point;

use crate::{
geometry::CurveBoundary,
objects::Curve,
storage::{Handle, HandleWrapper},
};

use super::CurveApproxSegment;

/// Cache for curve approximations
#[derive(Default)]
pub struct CurveApproxCache {
inner: BTreeMap<
(HandleWrapper<Curve>, CurveBoundary<Point<1>>),
CurveApproxSegment,
>,
}

impl CurveApproxCache {
/// Get an approximation from the cache
pub fn get(
&self,
curve: &Handle<Curve>,
boundary: &CurveBoundary<Point<1>>,
) -> Option<CurveApproxSegment> {
if let Some(approx) = self.inner.get(&(curve.clone().into(), *boundary))
{
return Some(approx.clone());
}
if let Some(approx) =
self.inner.get(&(curve.clone().into(), boundary.reverse()))
{
// If we have a cache entry for the reverse boundary, we need to use
// that too!
return Some(approx.clone().reverse());
}

None
}

/// Insert an approximated segment of the curve into the cache
pub fn insert(
&mut self,
curve: Handle<Curve>,
new_segment: CurveApproxSegment,
) -> Option<CurveApproxSegment> {
self.inner
.insert((curve.into(), new_segment.boundary), new_segment)
}
}
43 changes: 10 additions & 33 deletions crates/fj-core/src/algorithms/approx/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ use crate::{
storage::{Handle, HandleWrapper},
};

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

impl Approx for (&Edge, &Surface) {
type Approximation = EdgeApprox;
Expand Down Expand Up @@ -86,17 +89,13 @@ impl Approx for (&Edge, &Surface) {
let approx = match cached_approx {
Some(approx) => approx,
None => {
let approx = approx_edge(
let approx = approx_curve(
&edge.path(),
surface,
edge.boundary(),
tolerance,
);
cache.insert_curve_approx(
edge.curve().clone(),
edge.boundary(),
approx,
)
cache.insert_curve_approx(edge.curve().clone(), approx)
}
};

Expand Down Expand Up @@ -138,7 +137,7 @@ impl EdgeApprox {
}
}

fn approx_edge(
fn approx_curve(
path: &SurfacePath,
surface: &Surface,
boundary: CurveBoundary<Point<1>>,
Expand Down Expand Up @@ -218,18 +217,10 @@ fn approx_edge(
#[derive(Default)]
pub struct EdgeApproxCache {
start_position_approx: BTreeMap<HandleWrapper<Vertex>, Point<3>>,
curve_approx: BTreeMap<
(HandleWrapper<Curve>, CurveBoundary<Point<1>>),
CurveApproxSegment,
>,
curve_approx: CurveApproxCache,
}

impl EdgeApproxCache {
/// Create an empty cache
pub fn new() -> Self {
Self::default()
}

fn get_start_position_approx(
&self,
handle: &Handle<Vertex>,
Expand All @@ -254,30 +245,16 @@ impl EdgeApproxCache {
handle: Handle<Curve>,
boundary: CurveBoundary<Point<1>>,
) -> Option<CurveApproxSegment> {
if let Some(approx) =
self.curve_approx.get(&(handle.clone().into(), boundary))
{
return Some(approx.clone());
}
if let Some(approx) =
self.curve_approx.get(&(handle.into(), boundary.reverse()))
{
// If we have a cache entry for the reverse boundary, we need to use
// that too!
return Some(approx.clone().reverse());
}

None
self.curve_approx.get(&handle, &boundary)
}

fn insert_curve_approx(
&mut self,
handle: Handle<Curve>,
boundary: CurveBoundary<Point<1>>,
approx: CurveApproxSegment,
) -> CurveApproxSegment {
self.curve_approx
.insert((handle.into(), boundary), approx.clone())
.insert(handle, approx.clone())
.unwrap_or(approx)
}
}
Expand Down

0 comments on commit c0b6264

Please sign in to comment.