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

Implement centralized object storage #1108

Merged
merged 16 commits into from
Sep 19, 2022
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