Skip to content

Commit

Permalink
Merge pull request #1108 from hannobraun/store
Browse files Browse the repository at this point in the history
Implement centralized object storage
  • Loading branch information
hannobraun authored Sep 19, 2022
2 parents ffbb835 + 398f650 commit 0bff9d4
Show file tree
Hide file tree
Showing 41 changed files with 1,145 additions and 336 deletions.
34 changes: 22 additions & 12 deletions crates/fj-kernel/src/algorithms/approx/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::collections::BTreeMap;
use crate::{
objects::{Curve, GlobalCurve},
path::{GlobalPath, SurfacePath},
stores::Handle,
};

use super::{path::RangeOnPath, Approx, ApproxPoint, Tolerance};
Expand All @@ -29,8 +30,8 @@ impl Approx for (&Curve, RangeOnPath) {
) -> Self::Approximation {
let (curve, range) = self;

let cache_key = (*curve.global_form(), range);
let global_curve_approx = match cache.get(cache_key) {
let cache_key = (curve.global_form().clone(), range);
let global_curve_approx = match cache.get(cache_key.clone()) {
Some(approx) => approx,
None => {
let approx = approx_global_curve(curve, range, tolerance);
Expand Down Expand Up @@ -151,7 +152,7 @@ impl CurveApprox {
/// A cache for results of an approximation
#[derive(Default)]
pub struct CurveCache {
inner: BTreeMap<(GlobalCurve, RangeOnPath), GlobalCurveApprox>,
inner: BTreeMap<(Handle<GlobalCurve>, RangeOnPath), GlobalCurveApprox>,
}

impl CurveCache {
Expand All @@ -163,7 +164,7 @@ impl CurveCache {
/// Insert the approximation of a [`GlobalCurve`]
pub fn insert(
&mut self,
key: (GlobalCurve, RangeOnPath),
key: (Handle<GlobalCurve>, RangeOnPath),
approx: GlobalCurveApprox,
) -> GlobalCurveApprox {
self.inner.insert(key, approx.clone());
Expand All @@ -173,7 +174,7 @@ impl CurveCache {
/// Access the approximation for the given [`GlobalCurve`], if available
pub fn get(
&self,
key: (GlobalCurve, RangeOnPath),
key: (Handle<GlobalCurve>, RangeOnPath),
) -> Option<GlobalCurveApprox> {
self.inner.get(&key).cloned()
}
Expand All @@ -196,15 +197,18 @@ mod tests {
algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint},
objects::{Curve, Surface},
path::GlobalPath,
stores::Stores,
};

use super::CurveApprox;

#[test]
fn approx_line_on_flat_surface() {
let stores = Stores::new();

let surface = Surface::new(GlobalPath::x_axis(), [0., 0., 1.]);
let curve =
Curve::build(surface).line_from_points([[1., 1.], [2., 1.]]);
let curve = Curve::build(&stores, surface)
.line_from_points([[1., 1.], [2., 1.]]);
let range = RangeOnPath::from([[0.], [1.]]);

let approx = (&curve, range).approx(1.);
Expand All @@ -214,10 +218,12 @@ mod tests {

#[test]
fn approx_line_on_curved_surface_but_not_along_curve() {
let stores = Stores::new();

let surface =
Surface::new(GlobalPath::circle_from_radius(1.), [0., 0., 1.]);
let curve =
Curve::build(surface).line_from_points([[1., 1.], [1., 2.]]);
let curve = Curve::build(&stores, surface)
.line_from_points([[1., 1.], [1., 2.]]);
let range = RangeOnPath::from([[0.], [1.]]);

let approx = (&curve, range).approx(1.);
Expand All @@ -227,10 +233,12 @@ mod tests {

#[test]
fn approx_line_on_curved_surface_along_curve() {
let stores = Stores::new();

let path = GlobalPath::circle_from_radius(1.);
let surface = Surface::new(path, [0., 0., 1.]);
let curve =
Curve::build(surface).line_from_points([[0., 1.], [1., 1.]]);
let curve = Curve::build(&stores, surface)
.line_from_points([[0., 1.], [1., 1.]]);

let range = RangeOnPath::from([[0.], [TAU]]);
let tolerance = 1.;
Expand All @@ -253,8 +261,10 @@ mod tests {

#[test]
fn approx_circle_on_flat_surface() {
let stores = Stores::new();

let surface = Surface::new(GlobalPath::x_axis(), [0., 0., 1.]);
let curve = Curve::build(surface).circle_from_radius(1.);
let curve = Curve::build(&stores, surface).circle_from_radius(1.);

let range = RangeOnPath::from([[0.], [TAU]]);
let tolerance = 1.;
Expand Down
29 changes: 20 additions & 9 deletions crates/fj-kernel/src/algorithms/intersect/curve_edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,20 @@ impl CurveEdgeIntersection {
mod tests {
use fj_math::Point;

use crate::objects::{Curve, HalfEdge, Surface};
use crate::{
objects::{Curve, HalfEdge, Surface},
stores::Stores,
};

use super::CurveEdgeIntersection;

#[test]
fn compute_edge_in_front_of_curve_origin() {
let stores = Stores::new();

let surface = Surface::xy_plane();
let curve = Curve::build(surface).u_axis();
let half_edge = HalfEdge::build(surface)
let curve = Curve::build(&stores, surface).u_axis();
let half_edge = HalfEdge::build(&stores, surface)
.line_segment_from_points([[1., -1.], [1., 1.]]);

let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
Expand All @@ -97,9 +102,11 @@ mod tests {

#[test]
fn compute_edge_behind_curve_origin() {
let stores = Stores::new();

let surface = Surface::xy_plane();
let curve = Curve::build(surface).u_axis();
let half_edge = HalfEdge::build(surface)
let curve = Curve::build(&stores, surface).u_axis();
let half_edge = HalfEdge::build(&stores, surface)
.line_segment_from_points([[-1., -1.], [-1., 1.]]);

let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
Expand All @@ -114,9 +121,11 @@ mod tests {

#[test]
fn compute_edge_parallel_to_curve() {
let stores = Stores::new();

let surface = Surface::xy_plane();
let curve = Curve::build(surface).u_axis();
let half_edge = HalfEdge::build(surface)
let curve = Curve::build(&stores, surface).u_axis();
let half_edge = HalfEdge::build(&stores, surface)
.line_segment_from_points([[-1., -1.], [1., -1.]]);

let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
Expand All @@ -126,9 +135,11 @@ mod tests {

#[test]
fn compute_edge_on_curve() {
let stores = Stores::new();

let surface = Surface::xy_plane();
let curve = Curve::build(surface).u_axis();
let half_edge = HalfEdge::build(surface)
let curve = Curve::build(&stores, surface).u_axis();
let half_edge = HalfEdge::build(&stores, surface)
.line_segment_from_points([[-1., 0.], [1., 0.]]);

let intersection = CurveEdgeIntersection::compute(&curve, &half_edge);
Expand Down
16 changes: 11 additions & 5 deletions crates/fj-kernel/src/algorithms/intersect/curve_face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,21 @@ where

#[cfg(test)]
mod tests {
use crate::objects::{Curve, Face, Surface};
use crate::{
objects::{Curve, Face, Surface},
stores::Stores,
};

use super::CurveFaceIntersection;

#[test]
fn compute() {
let stores = Stores::new();

let surface = Surface::xy_plane();

let curve =
Curve::build(surface).line_from_points([[-3., 0.], [-2., 0.]]);
let curve = Curve::build(&stores, surface)
.line_from_points([[-3., 0.], [-2., 0.]]);

#[rustfmt::skip]
let exterior = [
Expand All @@ -181,9 +186,10 @@ mod tests {
[-1., 1.],
];

let face = Face::build(surface)
let face = Face::build(&stores, surface)
.polygon_from_points(exterior)
.with_hole(interior);
.with_hole(interior)
.into_face();

let expected =
CurveFaceIntersection::from_intervals([[[1.], [2.]], [[4.], [5.]]]);
Expand Down
30 changes: 22 additions & 8 deletions crates/fj-kernel/src/algorithms/intersect/face_face.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::objects::{Curve, Face};
use crate::{
objects::{Curve, Face},
stores::Stores,
};

use super::{CurveFaceIntersection, SurfaceSurfaceIntersection};

Expand All @@ -21,11 +24,12 @@ pub struct FaceFaceIntersection {

impl FaceFaceIntersection {
/// Compute the intersections between two faces
pub fn compute(faces: [&Face; 2]) -> Option<Self> {
pub fn compute(faces: [&Face; 2], stores: &Stores) -> Option<Self> {
let surfaces = faces.map(|face| face.surface());

let intersection_curves =
SurfaceSurfaceIntersection::compute(surfaces)?.intersection_curves;
SurfaceSurfaceIntersection::compute(surfaces, stores)?
.intersection_curves;

// Can be cleaned up, once `zip` is stable:
// https://doc.rust-lang.org/std/primitive.array.html#method.zip
Expand Down Expand Up @@ -61,12 +65,15 @@ mod tests {
use crate::{
algorithms::intersect::CurveFaceIntersection,
objects::{Curve, Face, Surface},
stores::Stores,
};

use super::FaceFaceIntersection;

#[test]
fn compute_no_intersection() {
let stores = Stores::new();

#[rustfmt::skip]
let points = [
[1., 1.],
Expand All @@ -76,16 +83,20 @@ mod tests {
];
let surfaces = [Surface::xy_plane(), Surface::xz_plane()];
let [a, b] = surfaces.map(|surface| {
Face::build(surface).polygon_from_points(points).into_face()
Face::build(&stores, surface)
.polygon_from_points(points)
.into_face()
});

let intersection = FaceFaceIntersection::compute([&a, &b]);
let intersection = FaceFaceIntersection::compute([&a, &b], &stores);

assert!(intersection.is_none());
}

#[test]
fn compute_one_intersection() {
let stores = Stores::new();

#[rustfmt::skip]
let points = [
[-1., -1.],
Expand All @@ -95,13 +106,16 @@ mod tests {
];
let surfaces = [Surface::xy_plane(), Surface::xz_plane()];
let [a, b] = surfaces.map(|surface| {
Face::build(surface).polygon_from_points(points).into_face()
Face::build(&stores, surface)
.polygon_from_points(points)
.into_face()
});

let intersection = FaceFaceIntersection::compute([&a, &b]);
let intersection = FaceFaceIntersection::compute([&a, &b], &stores);

let expected_curves = surfaces.map(|surface| {
Curve::build(surface).line_from_points([[0., 0.], [1., 0.]])
Curve::build(&stores, surface)
.line_from_points([[0., 0.], [1., 0.]])
});
let expected_intervals =
CurveFaceIntersection::from_intervals([[[-1.], [1.]]]);
Expand Down
33 changes: 25 additions & 8 deletions crates/fj-kernel/src/algorithms/intersect/face_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,14 @@ mod tests {
algorithms::intersect::{face_point::FacePointIntersection, Intersect},
iter::ObjectIters,
objects::{Face, Surface},
stores::Stores,
};

#[test]
fn point_is_outside_face() {
let face = Face::build(Surface::xy_plane())
let stores = Stores::new();

let face = Face::build(&stores, Surface::xy_plane())
.polygon_from_points([[0., 0.], [1., 1.], [0., 2.]])
.into_face();
let point = Point::from([2., 1.]);
Expand All @@ -150,7 +153,9 @@ mod tests {

#[test]
fn ray_hits_vertex_while_passing_outside() {
let face = Face::build(Surface::xy_plane())
let stores = Stores::new();

let face = Face::build(&stores, Surface::xy_plane())
.polygon_from_points([[0., 0.], [2., 1.], [0., 2.]])
.into_face();
let point = Point::from([1., 1.]);
Expand All @@ -164,7 +169,9 @@ mod tests {

#[test]
fn ray_hits_vertex_at_cycle_seam() {
let face = Face::build(Surface::xy_plane())
let stores = Stores::new();

let face = Face::build(&stores, Surface::xy_plane())
.polygon_from_points([[4., 2.], [0., 4.], [0., 0.]])
.into_face();
let point = Point::from([1., 2.]);
Expand All @@ -178,7 +185,9 @@ mod tests {

#[test]
fn ray_hits_vertex_while_staying_inside() {
let face = Face::build(Surface::xy_plane())
let stores = Stores::new();

let face = Face::build(&stores, Surface::xy_plane())
.polygon_from_points([[0., 0.], [2., 1.], [3., 0.], [3., 4.]])
.into_face();
let point = Point::from([1., 1.]);
Expand All @@ -192,7 +201,9 @@ mod tests {

#[test]
fn ray_hits_parallel_edge_and_leaves_face_at_vertex() {
let face = Face::build(Surface::xy_plane())
let stores = Stores::new();

let face = Face::build(&stores, Surface::xy_plane())
.polygon_from_points([[0., 0.], [2., 1.], [3., 1.], [0., 2.]])
.into_face();
let point = Point::from([1., 1.]);
Expand All @@ -206,7 +217,9 @@ mod tests {

#[test]
fn ray_hits_parallel_edge_and_does_not_leave_face_there() {
let face = Face::build(Surface::xy_plane())
let stores = Stores::new();

let face = Face::build(&stores, Surface::xy_plane())
.polygon_from_points([
[0., 0.],
[2., 1.],
Expand All @@ -226,7 +239,9 @@ mod tests {

#[test]
fn point_is_coincident_with_edge() {
let face = Face::build(Surface::xy_plane())
let stores = Stores::new();

let face = Face::build(&stores, Surface::xy_plane())
.polygon_from_points([[0., 0.], [2., 0.], [0., 1.]])
.into_face();
let point = Point::from([1., 0.]);
Expand All @@ -249,7 +264,9 @@ mod tests {

#[test]
fn point_is_coincident_with_vertex() {
let face = Face::build(Surface::xy_plane())
let stores = Stores::new();

let face = Face::build(&stores, Surface::xy_plane())
.polygon_from_points([[0., 0.], [1., 0.], [0., 1.]])
.into_face();
let point = Point::from([1., 0.]);
Expand Down
Loading

0 comments on commit 0bff9d4

Please sign in to comment.