From c8a149d0b832dcb152e37bb46cd2064a45c1640c Mon Sep 17 00:00:00 2001 From: Daniel VandenHeuvel <95613936+DanielVandH@users.noreply.github.com> Date: Sat, 10 Aug 2024 17:11:27 +0100 Subject: [PATCH] Make triangulations unique to fix refimages issues. Also tweak examples used for refimages (#4044) * Make triangulations unique * Update CHANGELOG.md Co-authored-by: Anshul Singhvi * Bit more protection --------- Co-authored-by: Anshul Singhvi Co-authored-by: Simon Co-authored-by: Anshul Singhvi Co-authored-by: Frederic Freyer --- CHANGELOG.md | 1 + ReferenceTests/src/tests/examples2d.jl | 108 ++++++++++++------------- src/basic_recipes/tricontourf.jl | 2 +- src/basic_recipes/triplot.jl | 2 +- src/basic_recipes/voronoiplot.jl | 7 +- 5 files changed, 56 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e9de8ffd00..a6c7a52ff30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Fix error with automatic `highclip` or `lowclip` and scalar colors [#4048](https://github.com/MakieOrg/Makie.jl/pull/4048). - Correct a bug in the `project` function when projecting using a `Scene`. [#3909](https://github.com/MakieOrg/Makie.jl/pull/3909). - Correct a method ambiguity in `insert!` which was causing `PlotList` to fail on CairoMakie. [#4038](https://github.com/MakieOrg/Makie.jl/pull/4038) +- Delaunay triangulations created via `tricontourf`, `triplot`, and `voronoiplot` no longer use any randomisation in the point insertion order so that results are unique. [#4044](https://github.com/MakieOrg/Makie.jl/pull/4044) - Improve content scaling support for Wayland and fix incorrect mouse scaling on mac [#4062](https://github.com/MakieOrg/Makie.jl/pull/4062) - Fix: `band` ignored its `alpha` argument in CairoMakie - Fix `marker=FastPixel()` makersize and markerspace, improve `spy` recipe [#4043](https://github.com/MakieOrg/Makie.jl/pull/4043). diff --git a/ReferenceTests/src/tests/examples2d.jl b/ReferenceTests/src/tests/examples2d.jl index ed0bd143939..fbb9d9d72d4 100644 --- a/ReferenceTests/src/tests/examples2d.jl +++ b/ReferenceTests/src/tests/examples2d.jl @@ -1222,59 +1222,57 @@ end fig end -# TODO: as noted in https://github.com/MakieOrg/Makie.jl/pull/3520#issuecomment-1873382060 -# this test has some issues with random number generation across Julia 1.6 and 1, for now -# it's disabled until someone has time to look into it - -# @reference_test "Triplot of a constrained triangulation with holes and a custom bounding box" begin -# curve_1 = [[ -# (0.0, 0.0), (4.0, 0.0), (8.0, 0.0), (12.0, 0.0), (12.0, 4.0), -# (12.0, 8.0), (14.0, 10.0), (16.0, 12.0), (16.0, 16.0), -# (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0), -# (8.0, 28.0), (4.0, 28.0), (0.0, 28.0), (-2.0, 26.0), (0.0, 22.0), -# (0.0, 18.0), (0.0, 10.0), (0.0, 8.0), (0.0, 4.0), (-4.0, 4.0), -# (-4.0, 0.0), (0.0, 0.0), -# ]] -# curve_2 = [[ -# (4.0, 26.0), (8.0, 26.0), (10.0, 26.0), (10.0, 24.0), -# (10.0, 22.0), (10.0, 20.0), (8.0, 20.0), (6.0, 20.0), -# (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0) -# ]] -# curve_3 = [[(4.0, 16.0), (12.0, 16.0), (12.0, 14.0), (4.0, 14.0), (4.0, 16.0)]] -# curve_4 = [[(4.0, 8.0), (10.0, 8.0), (8.0, 6.0), (6.0, 6.0), (4.0, 8.0)]] -# curves = [curve_1, curve_2, curve_3, curve_4] -# points = [ -# (2.0, 26.0), (2.0, 24.0), (6.0, 24.0), (6.0, 22.0), (8.0, 24.0), (8.0, 22.0), -# (2.0, 22.0), (0.0, 26.0), (10.0, 18.0), (8.0, 18.0), (4.0, 18.0), (2.0, 16.0), -# (2.0, 12.0), (6.0, 12.0), (2.0, 8.0), (2.0, 4.0), (4.0, 2.0), -# (-2.0, 2.0), (4.0, 6.0), (10.0, 2.0), (10.0, 6.0), (8.0, 10.0), (4.0, 10.0), -# (10.0, 12.0), (12.0, 12.0), (14.0, 26.0), (16.0, 24.0), (18.0, 28.0), -# (16.0, 20.0), (18.0, 12.0), (16.0, 8.0), (14.0, 4.0), (14.0, -2.0), -# (6.0, -2.0), (2.0, -4.0), (-4.0, -2.0), (-2.0, 8.0), (-2.0, 16.0), -# (-4.0, 22.0), (-4.0, 26.0), (-2.0, 28.0), (6.0, 15.0), (7.0, 15.0), -# (8.0, 15.0), (9.0, 15.0), (10.0, 15.0), (6.2, 7.8), -# (5.6, 7.8), (5.6, 7.6), (5.6, 7.4), (6.2, 7.4), (6.0, 7.6), -# (7.0, 7.8), (7.0, 7.4)] -# boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points) -# tri = triangulate(points; boundary_nodes=boundary_nodes, rng = RNG.STABLE_RNG) -# refine!(tri, max_area = 1e-3get_total_area(tri), rng = RNG.STABLE_RNG) -# fig, ax, sc = triplot(tri, -# show_points=true, -# show_constrained_edges=true, -# constrained_edge_linewidth=2, -# strokewidth=0.2, -# markersize=15, -# point_color=:blue, -# show_ghost_edges=true, # not as good because the outer boundary is not convex, but just testing -# marker='x', -# bounding_box = (-5,20,-5,35)) # also testing the conversion to Float64 for bbox here -# fig -# end +@reference_test "Triplot of a constrained triangulation with holes and a custom bounding box" begin + curve_1 = [[ + (0.0, 0.0), (4.0, 0.0), (8.0, 0.0), (12.0, 0.0), (12.0, 4.0), + (12.0, 8.0), (14.0, 10.0), (16.0, 12.0), (16.0, 16.0), + (14.0, 18.0), (12.0, 20.0), (12.0, 24.0), (12.0, 28.0), + (8.0, 28.0), (4.0, 28.0), (0.0, 28.0), (-2.0, 26.0), (0.0, 22.0), + (0.0, 18.0), (0.0, 10.0), (0.0, 8.0), (0.0, 4.0), (-4.0, 4.0), + (-4.0, 0.0), (0.0, 0.0), + ]] + curve_2 = [[ + (4.0, 26.0), (8.0, 26.0), (10.0, 26.0), (10.0, 24.0), + (10.0, 22.0), (10.0, 20.0), (8.0, 20.0), (6.0, 20.0), + (4.0, 20.0), (4.0, 22.0), (4.0, 24.0), (4.0, 26.0) + ]] + curve_3 = [[(4.0, 16.0), (12.0, 16.0), (12.0, 14.0), (4.0, 14.0), (4.0, 16.0)]] + curve_4 = [[(4.0, 8.0), (10.0, 8.0), (8.0, 6.0), (6.0, 6.0), (4.0, 8.0)]] + curves = [curve_1, curve_2, curve_3, curve_4] + points = [ + (2.0, 26.0), (2.0, 24.0), (6.0, 24.0), (6.0, 22.0), (8.0, 24.0), (8.0, 22.0), + (2.0, 22.0), (0.0, 26.0), (10.0, 18.0), (8.0, 18.0), (4.0, 18.0), (2.0, 16.0), + (2.0, 12.0), (6.0, 12.0), (2.0, 8.0), (2.0, 4.0), (4.0, 2.0), + (-2.0, 2.0), (4.0, 6.0), (10.0, 2.0), (10.0, 6.0), (8.0, 10.0), (4.0, 10.0), + (10.0, 12.0), (12.0, 12.0), (14.0, 26.0), (16.0, 24.0), (18.0, 28.0), + (16.0, 20.0), (18.0, 12.0), (16.0, 8.0), (14.0, 4.0), (14.0, -2.0), + (6.0, -2.0), (2.0, -4.0), (-4.0, -2.0), (-2.0, 8.0), (-2.0, 16.0), + (-4.0, 22.0), (-4.0, 26.0), (-2.0, 28.0), (6.0, 15.0), (7.0, 15.0), + (8.0, 15.0), (9.0, 15.0), (10.0, 15.0), (6.2, 7.8), + (5.6, 7.8), (5.6, 7.6), (5.6, 7.4), (6.2, 7.4), (6.0, 7.6), + (7.0, 7.8), (7.0, 7.4)] + boundary_nodes, points = convert_boundary_points_to_indices(curves; existing_points=points) + tri = triangulate(points; randomise = false, boundary_nodes=boundary_nodes, rng = RNG.STABLE_RNG) + fig, ax, sc = triplot(tri, + show_points=true, + show_constrained_edges=true, + constrained_edge_linewidth=2, + strokewidth=0.2, + markersize=15, + markercolor=:blue, + show_ghost_edges=true, # not as good because the outer boundary is not convex, but just testing + marker='x', + bounding_box = (-5,20,-5,35)) # also testing the conversion to Float64 for bbox here + fig +end @reference_test "Triplot with nonlinear transformation" begin f = Figure() ax = PolarAxis(f[1, 1]) - points = Point2f[(phi, r) for r in 1:10 for phi in range(0, 2pi, length=36)[1:35]] + points = Point2f[(phi, r) for r in 1:10 for phi in range(0, 2pi, length=36)[1:35]] + noise = i -> 1f-4 * (isodd(i) ? 1 : -1) * i/sqrt(50) # should have small discrepancy + points = points .+ [Point2f(noise(i), noise(i)) for i in eachindex(points)] + # The noise forces the triangulation to be unique. Not using RNG to not disrupt the RNG stream later tr = triplot!(ax, points) f end @@ -1312,9 +1310,8 @@ end end @reference_test "Voronoiplot for a centroidal tessellation with an automatic colormap" begin - points = [(0.0,0.0),(1.0,0.0),(1.0,1.0),(0.0,1.0)] + points = [(0.0,0.0),(1.0,0.0),(1.0,1.0),(0.0,1.0),(0.2,0.2),(0.25,0.6),(0.5,0.3),(0.1,0.15)] tri = triangulate(points; boundary_nodes = [1,2,3,4,1], rng = RNG.STABLE_RNG) - refine!(tri; max_area=1e-2, min_angle = 29.871, rng = RNG.STABLE_RNG) vorn = voronoi(tri) smooth_vorn = centroidal_smooth(vorn; maxiters = 250, rng = RNG.STABLE_RNG) cmap = cgrad(:matter) @@ -1356,15 +1353,12 @@ end fig end -#= - -After DelaunayTriangulation@1.0.4, this test started to show slightly randomized triangulations. -Until this gets fixed, we're disabling it. - @reference_test "Voronoiplot with a nonlinear transform" begin f = Figure() ax = PolarAxis(f[1, 1], theta_as_x = false) points = Point2d[(r, phi) for r in 1:10 for phi in range(0, 2pi, length=36)[1:35]] + noise = i -> 1f-4 * (isodd(i) ? 1 : -1) * i/sqrt(50) # should have small discrepancy + points = points .+ [Point2f(noise(i), noise(i)) for i in eachindex(points)] # make triangulation unique polygon_color = [r for r in 1:10 for phi in range(0, 2pi, length=36)[1:35]] polygon_color_2 = [phi for r in 1:10 for phi in range(0, 2pi, length=36)[1:35]] tr = voronoiplot!(ax, points, smooth = false, show_generators = false, color = polygon_color) @@ -1374,7 +1368,7 @@ Until this gets fixed, we're disabling it. Makie.rlims!(ax, 12) f end -=# + @reference_test "Voronoiplot with some custom bounding boxes may not contain all data sites" begin points = [(-3.0, 7.0), (1.0, 6.0), (-1.0, 3.0), (-2.0, 4.0), (3.0, -2.0), (5.0, 5.0), (-4.0, -3.0), (3.0, 8.0)] diff --git a/src/basic_recipes/tricontourf.jl b/src/basic_recipes/tricontourf.jl index 1c4ff3b91a9..cb770e59370 100644 --- a/src/basic_recipes/tricontourf.jl +++ b/src/basic_recipes/tricontourf.jl @@ -63,7 +63,7 @@ function Makie.convert_arguments(::Type{<:Tricontourf}, x::AbstractVector{<:Real z = elconvert(T, z) points = [elconvert(T, x)'; elconvert(T, y)'] if triangulation isa DelaunayTriangulation - tri = DelTri.triangulate(points) + tri = DelTri.triangulate(points, randomise = false) elseif !(triangulation isa DelTri.Triangulation) # Wrap user's provided triangulation into a Triangulation. Their triangulation must be such that DelTri.add_triangle! is defined. if typeof(triangulation) <: AbstractMatrix{<:Int} && size(triangulation, 1) != 3 diff --git a/src/basic_recipes/triplot.jl b/src/basic_recipes/triplot.jl index 8b248c215ed..cbaaa32cb39 100644 --- a/src/basic_recipes/triplot.jl +++ b/src/basic_recipes/triplot.jl @@ -181,7 +181,7 @@ function Makie.plot!(p::Triplot{<:Tuple{<:Vector{<:Point}}}) # Handle transform_func early so tessellation is in cartesian space. tri = map(p, p.transformation.transform_func, p[1]) do tf, ps transformed = Makie.apply_transform(tf, ps) - return DelTri.triangulate(transformed) + return DelTri.triangulate(transformed, randomise = false) end attr[:transformation] = Transformation(p.transformation; transform_func=identity) diff --git a/src/basic_recipes/voronoiplot.jl b/src/basic_recipes/voronoiplot.jl index 42796a25b52..94dae4a197a 100644 --- a/src/basic_recipes/voronoiplot.jl +++ b/src/basic_recipes/voronoiplot.jl @@ -133,11 +133,8 @@ function plot!(p::Voronoiplot{<:Tuple{<:Vector{<:Point{N}}}}) where {N} # Handle transform_func early so tessellation is in cartesian space. vorn = map(p, p.transformation.transform_func, ps, smooth) do tf, ps, smooth transformed = Makie.apply_transform(tf, ps) - tri = DelTri.triangulate(transformed) - vorn = DelTri.voronoi(tri) - if smooth - vorn = DelTri.centroidal_smooth(vorn) - end + tri = DelTri.triangulate(transformed, randomise = false) + vorn = DelTri.voronoi(tri, clip = smooth, smooth = smooth, randomise = false) return vorn end