From aed30d78b8f5e9973ad343871bf19aac5b52724c Mon Sep 17 00:00:00 2001 From: 0HyperCube <78500760+0HyperCube@users.noreply.github.com> Date: Sun, 4 Feb 2024 17:16:16 +0000 Subject: [PATCH] Fix floating point error with Poisson-disk points being sampled outside shape (#1596) * Check opposite corner * Commets and test * Fix compiling --------- Co-authored-by: Keavon Chambers --- Cargo.lock | 1 + libraries/bezier-rs/Cargo.toml | 1 + libraries/bezier-rs/src/poisson_disk.rs | 11 ++++++++--- libraries/bezier-rs/src/subpath/solvers.rs | 12 ++++++------ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0ef61933..5c248249 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -584,6 +584,7 @@ version = "0.4.0" dependencies = [ "dyn-any", "glam", + "log", "serde", ] diff --git a/libraries/bezier-rs/Cargo.toml b/libraries/bezier-rs/Cargo.toml index d2bd9905..1d9874da 100644 --- a/libraries/bezier-rs/Cargo.toml +++ b/libraries/bezier-rs/Cargo.toml @@ -18,3 +18,4 @@ glam = { version = "0.24", features = ["serde"] } dyn-any = { version = "0.3.0", path = "../dyn-any", optional = true } serde = { version = "1.0", workspace = true, optional = true } +log = { workspace = true, optional = true } diff --git a/libraries/bezier-rs/src/poisson_disk.rs b/libraries/bezier-rs/src/poisson_disk.rs index 8e3d6f7e..cd2d8d45 100644 --- a/libraries/bezier-rs/src/poisson_disk.rs +++ b/libraries/bezier-rs/src/poisson_disk.rs @@ -105,7 +105,11 @@ pub fn poisson_disk_sample( // Intersecting the shape's border else { // The sub-square is fully inside the shape if its top-left corner is inside and its edges don't intersect the shape border - let sub_square_fully_inside_shape = !square_edges_intersect_shape_checker(sub_square, subdivided_size) && point_in_shape_checker(sub_square); + let sub_square_fully_inside_shape = + !square_edges_intersect_shape_checker(sub_square, subdivided_size) && point_in_shape_checker(sub_square) && point_in_shape_checker(sub_square + subdivided_size); + // if !square_edges_intersect_shape_checker(sub_square, subdivided_size) { assert_eq!(point_in_shape_checker(sub_square), point_in_shape_checker(sub_square + subdivided_size)); } + // Sometimes this fails so it is necessary to also check the bottom right corner. + Some(ActiveSquare::new(sub_square, sub_square_fully_inside_shape)) } }); @@ -219,8 +223,9 @@ impl ActiveListLevel { let point_in_shape = point_in_shape_checker(corner); let square_edges_intersect_shape = square_edges_intersect_shape_checker(corner, square_size); let square_not_outside_shape = point_in_shape || square_edges_intersect_shape; - let square_in_shape = point_in_shape && !square_edges_intersect_shape; - + let square_in_shape = point_in_shape_checker(corner + square_size) && !square_edges_intersect_shape; + // if !square_edges_intersect_shape { assert_eq!(point_in_shape_checker(corner), point_in_shape_checker(corner + square_size)); } + // Sometimes this fails so it is necessary to also check the bottom right corner. square_not_outside_shape.then_some(ActiveSquare::new(corner, square_in_shape)) }) .collect(); diff --git a/libraries/bezier-rs/src/subpath/solvers.rs b/libraries/bezier-rs/src/subpath/solvers.rs index 7f2eb992..94a941af 100644 --- a/libraries/bezier-rs/src/subpath/solvers.rs +++ b/libraries/bezier-rs/src/subpath/solvers.rs @@ -160,12 +160,12 @@ impl Subpath { for bezier in self.iter() { // Check that the two bounding boxes don't intersect, since we can avoid doing intersection's cubic root finding in that case let [bezier_corner1, bezier_corner2] = bezier.bounding_box_of_anchors_and_handles(); - if !(((corner1.x <= bezier_corner1.x) && (bezier_corner1.x <= corner2.x) || (corner1.x <= bezier_corner2.x) && (bezier_corner2.x <= corner2.x)) - && corner1.y <= bezier_corner2.y - && corner2.y >= bezier_corner1.y - || ((corner1.y <= bezier_corner1.y) && (bezier_corner1.y <= corner2.y) || (corner1.y <= bezier_corner2.y) && (bezier_corner2.y <= corner2.y)) - && corner1.x <= bezier_corner2.x - && corner2.x >= bezier_corner1.x) + if !(((corner1.x < bezier_corner1.x) && (bezier_corner1.x < corner2.x) || (corner1.x < bezier_corner2.x) && (bezier_corner2.x < corner2.x)) + && corner1.y < bezier_corner2.y + && corner2.y > bezier_corner1.y + || ((corner1.y < bezier_corner1.y) && (bezier_corner1.y < corner2.y) || (corner1.y < bezier_corner2.y) && (bezier_corner2.y < corner2.y)) + && corner1.x < bezier_corner2.x + && corner2.x > bezier_corner1.x) { continue; }