diff --git a/CHANGELOG.md b/CHANGELOG.md index e1f513b6e5e..45f82637f21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - `plotfunc()` and `func2type()` support functions ending with `!` [#4275](https://github.com/MakieOrg/Makie.jl/pull/4275). - Fixed Boundserror in clipped multicolor lines in CairoMakie [#4313](https://github.com/MakieOrg/Makie.jl/pull/4313) - Fix float precision based assertions error in GLMakie.volume [#4311](https://github.com/MakieOrg/Makie.jl/pull/4311) + - Support images with reversed axes [#4338](https://github.com/MakieOrg/Makie.jl/pull/4338) ## [0.21.9] - 2024-08-27 diff --git a/CairoMakie/src/primitives.jl b/CairoMakie/src/primitives.jl index 4048a346b67..a87386c5ce9 100644 --- a/CairoMakie/src/primitives.jl +++ b/CairoMakie/src/primitives.jl @@ -730,14 +730,14 @@ function draw_atomic(scene::Scene, screen::Screen{RT}, @nospecialize(primitive:: image = primitive[3][] xs, ys = primitive[1][], primitive[2][] if xs isa Makie.EndPoints - l, r = extrema(xs) + l, r = xs N = size(image, 1) xs = range(l, r, length = N+1) else xs = regularly_spaced_array_to_range(xs) end if ys isa Makie.EndPoints - l, r = extrema(ys) + l, r = ys N = size(image, 2) ys = range(l, r, length = N+1) else diff --git a/GLMakie/src/drawing_primitives.jl b/GLMakie/src/drawing_primitives.jl index 53bb504c7a6..9147fce4b6d 100644 --- a/GLMakie/src/drawing_primitives.jl +++ b/GLMakie/src/drawing_primitives.jl @@ -691,8 +691,8 @@ end function draw_image(screen::Screen, scene::Scene, plot::Union{Heatmap, Image}) return cached_robj!(screen, scene, plot) do gl_attributes position = lift(plot, plot[1], plot[2]) do x, y - xmin, xmax = extrema(x) - ymin, ymax = extrema(y) + xmin, xmax = x + ymin, ymax = y rect = Rect2(xmin, ymin, xmax - xmin, ymax - ymin) return decompose(Point2d, rect) end diff --git a/ReferenceTests/src/tests/primitives.jl b/ReferenceTests/src/tests/primitives.jl index f514d9de174..87cfce9a10c 100644 --- a/ReferenceTests/src/tests/primitives.jl +++ b/ReferenceTests/src/tests/primitives.jl @@ -818,3 +818,31 @@ end end f end + +@reference_test "Reverse image, heatmap and surface axes" begin + img = [2 0 0 3; 0 0 0 0; 1 1 0 0; 1 1 0 4] + + f = Figure(size = (600, 400)) + + for (i, interp) in enumerate((true, false)) + for (j, plot_func) in enumerate(( + (fp, x, y, cs, interp) -> image(fp, x, y, cs, colormap = :viridis, interpolate = interp), + (fp, x, y, cs, interp) -> heatmap(fp, x, y, cs, colormap = :viridis, interpolate = interp), + (fp, x, y, cs, interp) -> surface(fp, x, y, zeros(size(cs)), color = cs, colormap = :viridis, interpolate = interp, shading = NoShading) + )) + + gl = GridLayout(f[i, j]) + + a, p = plot_func(gl[1, 1], 1:4, 1:4, img, interp) + hidedecorations!(a) + a, p = plot_func(gl[2, 1], 1:4, 4..1, img, interp) + hidedecorations!(a) + a, p = plot_func(gl[1, 2], 4:-1:1, 1:4, img, interp) + hidedecorations!(a) + a, p = plot_func(gl[2, 2], 4:-1:1, [4, 3, 2, 1], img, interp) + hidedecorations!(a) + end + end + + f +end \ No newline at end of file diff --git a/WGLMakie/src/imagelike.jl b/WGLMakie/src/imagelike.jl index 62d365ac929..b286e055e79 100644 --- a/WGLMakie/src/imagelike.jl +++ b/WGLMakie/src/imagelike.jl @@ -129,7 +129,7 @@ end -xy_convert(x::Makie.EndPoints, n) = LinRange(extrema(x)..., n + 1) +xy_convert(x::Makie.EndPoints, n) = LinRange(x..., n + 1) xy_convert(x::AbstractArray, n) = x # TODO, speed up GeometryBasics @@ -166,8 +166,8 @@ function limits_to_uvmesh(plot, f32c) py = lift(identity, plot, py; ignore_equal_values=true) if px[] isa Makie.EndPoints && py[] isa Makie.EndPoints && Makie.is_identity_transform(t) rect = lift(plot, px, py) do x, y - xmin, xmax = extrema(x) - ymin, ymax = extrema(y) + xmin, xmax = x + ymin, ymax = y return Rect2f(xmin, ymin, xmax - xmin, ymax - ymin) end ps = lift(rect -> decompose(Point2f, rect), plot, rect) diff --git a/src/conversions.jl b/src/conversions.jl index 752cb19c38c..6516860f0a5 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -365,12 +365,10 @@ function to_endpoints(x::Tuple{<:Real,<:Real}) T = float_type(x...) return EndPoints(T.(x)) end -to_endpoints(x::ClosedInterval) = to_endpoints(endpoints(x)) -function to_endpoints(x::Union{Interval,AbstractVector,ClosedInterval}) - return to_endpoints((minimum(x), maximum(x))) -end +to_endpoints(x::Interval) = to_endpoints(endpoints(x)) +to_endpoints(x::EndPoints) = x +to_endpoints(x::AbstractVector) = to_endpoints((first(x), last(x))) function to_endpoints(x, dim) - # having minimum and maximum here actually invites bugs x isa AbstractVector && !(x isa EndPoints) && print_range_warning(dim, x) return to_endpoints(x) end @@ -698,7 +696,8 @@ end # Helper Functions # ################################################################################ -to_linspace(interval, N) = range(minimum(interval), stop = maximum(interval), length = N) +to_linspace(interval::Interval, N) = range(leftendpoint(interval), stop = rightendpoint(interval), length = N) +to_linspace(x, N) = range(first(x), stop = last(x), length = N) """ Converts the element array type to `T1` without making a copy if the element type matches diff --git a/test/boundingboxes.jl b/test/boundingboxes.jl index 66897c8444f..88cda42f179 100644 --- a/test/boundingboxes.jl +++ b/test/boundingboxes.jl @@ -92,6 +92,11 @@ end @test bb.origin ≈ Point3f(0) @test bb.widths ≈ Vec3f(10.0, 10.0, 0) + fig, ax, p = image(1..0, 1:10, rand(10, 10)) + bb = boundingbox(p) + @test bb.origin ≈ Point3f(0, 1, 0) + @test bb.widths ≈ Vec3f(1.0, 9.0, 0) + # text transforms to pixel space atm (TODO) fig = Figure(size = (400, 400)) ax = Axis(fig[1, 1]) diff --git a/test/conversions.jl b/test/conversions.jl index 2d60f0cc5d9..118dde2ad66 100644 --- a/test/conversions.jl +++ b/test/conversions.jl @@ -342,9 +342,11 @@ end v1 = collect(1:10) v2 = collect(1:6) + v3 = reverse(v1) i1 = 1 .. 10 i2 = 1 .. 6 + i3 = 10 .. 1 o3 = Float32.(m3) @@ -354,6 +356,8 @@ end @test convert_arguments(Image, m3) == ((0.0f0, 10.0f0), (0.0f0, 6.0f0), o3) @test convert_arguments(Image, v1, r2, m3) == ((1.0f0, 10.0f0), (1.0f0, 6.0f0), o3) @test convert_arguments(Image, i1, v2, m3) == ((1.0f0, 10.0f0), (1.0f0, 6.0f0), o3) + @test convert_arguments(Image, v3, i1, m3) == ((10, 1), (1, 10), o3) + @test convert_arguments(Image, v1, i3, m3) == ((1, 10), (10, 1), o3) @test convert_arguments(Image, m1, m2, m3) === (m1, m2, m3) @test convert_arguments(Heatmap, m1, m2) === (m1, m2) end