Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the meshimage recipe to the new syntax #249

Merged
merged 2 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/GeoMakie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ using Reexport
using GeometryBasics, Colors, ImageIO

using Makie
using Makie.MakieCore

import Makie: convert_arguments, convert_attribute, to_value, automatic
using Makie, Makie.FileIO, Makie.GridLayoutBase, Makie.DocStringExtensions
Expand Down
36 changes: 20 additions & 16 deletions src/mesh_image.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ This file contains the implementation of the `MeshImage` recipe.
using Makie: GeometryBasics

"""
meshimage([xs, ys,] zs)
meshimage!(ax, [xs, ys,] zs)
meshimage([xs, ys,] img)
meshimage!(ax, [xs, ys,] img)

Plots an image on a mesh.

Expand All @@ -18,23 +18,25 @@ but a smaller mesh can still represent the inherent
nonlinearity of the space.

This basically plots a mesh with uv coordinates, and textures it by
the provided image. Its conversion trait is `Image` (TODO: change this to DiscreteSurfaceLike).
the provided image. Its conversion trait is `ImageLike`.

For now, it only accepts RGB images. This could be changed in the future.
!!! tip
You can control the density of the mesh by the `npoints` attribute.

## Attributes
$(Makie.ATTRIBUTES)
"""
@recipe(MeshImage) do scene
Attributes(
npoints = 100,
space = :data,
)
@recipe MeshImage (x, y, img) begin
"""
The number of points the mesh should have per side.
Can be an Integer or a 2-tuple of integers representing number of points per side.
"""
npoints = 100
MakieCore.mixin_generic_plot_attributes()...
MakieCore.mixin_colormap_attributes()...
end

# this inherits all conversions for `Image`,
# if no specialized conversion for `MeshImage` is found.
Makie.conversion_trait(::Type{<: MeshImage}) = ImageLike()
Makie.conversion_trait(::Type{<: MeshImage}) = Makie.ImageLike()
# There really is no difference between this and Image,
# except the implementation under the hood.

Expand All @@ -58,18 +60,19 @@ function Makie.plot!(plot::MeshImage)
if npoints != old_npoints[]
# We need a new StructArray to hold all the points.
# TODO: resize the old structarray instead!
points_observable.val = Vector{Point2f}(undef, npoints^2)
points_observable.val = Vector{Point2f}(undef, first(npoints) * last(npoints))
# This constructs an efficient triangulation of a rectangle (all images are rectangles).
rect = GeometryBasics.Tesselation(Rect2f(0, 0, 1, 1), (npoints, npoints))
rect = GeometryBasics.Tesselation(Rect2f(0, 0, 1, 1), (first(npoints), last(npoints)))
# This decomposes that Tesselation to actual triangles, with integer index values.
faces_observable.val = GeometryBasics.decompose(Makie.GLTriangleFace, rect)
# This holds the UVs for the mesh. These are reversed, so that the image is plotted correctly.
uv_observable.val = map(x -> Vec2f(x[1], 1f0 - x[2]), GeometryBasics.decompose_uv(rect))
end

# These are the ranges for the points.
xs = LinRange(extrema(x_in)..., npoints)
ys = LinRange(extrema(y_in)..., npoints)
# `first` and `last` are used to get the number of points per side, if that's provided as a tuple.
xs = LinRange(extrema(x_in)..., first(npoints))
ys = LinRange(extrema(y_in)..., last(npoints))
poval = points_observable[]
# The array is in a grid, so we have to update them on a grid as well.
for (linear_ind, cartesian_ind) in enumerate(CartesianIndices((npoints, npoints)))
Expand Down Expand Up @@ -100,6 +103,7 @@ function Makie.plot!(plot::MeshImage)
plot,
final_mesh;
color = plot[3],
MakieCore.colormap_attributes(plot)...,
shading = NoShading,
transformation = Transformation() # since the points are pre transformed, we don't need to transform them again
)
Expand Down
12 changes: 12 additions & 0 deletions test/meshimage.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Test
using Makie, GeoMakie

@testset "Meshimage color attribute passthrough" begin
img = rand(10, 10)
f, a, p = meshimage(0..1, 0..1, img)
@test p.colormap[] == :viridis
@test p.plots[1].colormap[] == :viridis
p.colormap[] = :jet
@test p.colormap[] == :jet
@test p.plots[1].colormap[] == :jet
end
41 changes: 4 additions & 37 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Makie.set_theme!(Theme(
))

@testset "GeoMakie" begin
@testset "MeshImage" begin
include("meshimage.jl")
end

@testset "Basics" begin
lons = -180:180
lats = -90:90
Expand All @@ -30,41 +34,4 @@ Makie.set_theme!(Theme(
@test GeoMakie.coastlines(ga) isa Observable
@test GeoMakie.coastlines(ga)[][1] isa GeometryBasics.LineString
end

# @testset "Examples" begin
# geomakie_path = dirname(dirname(pathof(GeoMakie)))
# examples = readdir(joinpath(geomakie_path, "examples"); join = true)
# filenames = filter(x-> isfile(x) && endswith(x, ".jl"), examples)

# test_path = mkpath(joinpath(geomakie_path, "test_images"))
# cd(test_path) do
# for filename in filenames
# example_name = splitext(splitdir(filename)[2])[1]
# printstyled("Running ", bold = true, color = :cyan)
# println(example_name)

# @testset "$example_name" begin
# @test begin
# print(rpad("Include: ", 9))
# @time include(filename)
# true
# end
# @test begin
# savepath = "$example_name.png"
# print(rpad("PNG: ", 9))
# @time CairoMakie.save(savepath, Makie.current_figure(); px_per_unit=2);
# isfile(savepath) && filesize(savepath) > 1000

# end
# @test begin
# savepath = "$example_name.pdf"
# print(rpad("PDF: ", 9))
# @time CairoMakie.save(savepath, Makie.current_figure());
# isfile(savepath) && filesize(savepath) > 1000
# end
# haskey(ENV, "CI") && rm("$example_name.pdf")
# end
# end
# end
# end
end
Loading