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 <keavon@keavon.com>
This commit is contained in:
0HyperCube 2024-02-04 17:16:16 +00:00 committed by GitHub
parent 5f72a6a8a1
commit aed30d78b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 16 additions and 9 deletions

1
Cargo.lock generated
View File

@ -584,6 +584,7 @@ version = "0.4.0"
dependencies = [ dependencies = [
"dyn-any", "dyn-any",
"glam", "glam",
"log",
"serde", "serde",
] ]

View File

@ -18,3 +18,4 @@ glam = { version = "0.24", features = ["serde"] }
dyn-any = { version = "0.3.0", path = "../dyn-any", optional = true } dyn-any = { version = "0.3.0", path = "../dyn-any", optional = true }
serde = { version = "1.0", workspace = true, optional = true } serde = { version = "1.0", workspace = true, optional = true }
log = { workspace = true, optional = true }

View File

@ -105,7 +105,11 @@ pub fn poisson_disk_sample(
// Intersecting the shape's border // Intersecting the shape's border
else { 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 // 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)) 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 point_in_shape = point_in_shape_checker(corner);
let square_edges_intersect_shape = square_edges_intersect_shape_checker(corner, square_size); 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_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)) square_not_outside_shape.then_some(ActiveSquare::new(corner, square_in_shape))
}) })
.collect(); .collect();

View File

@ -160,12 +160,12 @@ impl<ManipulatorGroupId: crate::Identifier> Subpath<ManipulatorGroupId> {
for bezier in self.iter() { 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 // 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(); 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)) 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 && corner1.y < bezier_corner2.y
&& corner2.y >= bezier_corner1.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.y < bezier_corner1.y) && (bezier_corner1.y < corner2.y) || (corner1.y < bezier_corner2.y) && (bezier_corner2.y < corner2.y))
&& corner1.x <= bezier_corner2.x && corner1.x < bezier_corner2.x
&& corner2.x >= bezier_corner1.x) && corner2.x > bezier_corner1.x)
{ {
continue; continue;
} }