Skip to content

Commit

Permalink
support images with reversed axes (#4338)
Browse files Browse the repository at this point in the history
* support images with reversed axes

* changelog

* add reference tests

* fix reverse heatmap

* squash refimages and also test surface

* fix typo

---------

Co-authored-by: Simon <[email protected]>
Co-authored-by: ffreyer <[email protected]>
  • Loading branch information
3 people authored Sep 23, 2024
1 parent efc2fcc commit da86824
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions CairoMakie/src/primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions GLMakie/src/drawing_primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 28 additions & 0 deletions ReferenceTests/src/tests/primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 3 additions & 3 deletions WGLMakie/src/imagelike.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
11 changes: 5 additions & 6 deletions src/conversions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions test/boundingboxes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
4 changes: 4 additions & 0 deletions test/conversions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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
Expand Down

0 comments on commit da86824

Please sign in to comment.