using FileIO, GeometryBasics, Colors, GDAL, ZipFile using GeometryBasics: Vec2f0, Rect3D using AbstractPlotting env = get(ENV, "LD_LIBRARY_PATH", "") #= This example requires the GDAL package, from https://github.com/JuliaGeo/GDAL.jl For more information about GDAL, see the official documentation at: https://gdal.org/ =# # register GDAL drivers GDAL.gdalallregister() # function to check if a file is a .tif file istiff(x) = endswith(x, ".tif") # set up 7zip function unzip(input, out) dir = ZipFile.Reader(input) mkpath(out) for file in dir.files open(joinpath(out, file.name), "w") do io Base.write(io, read(file)) end end close(dir) end # function to read the raster data from the GeoTIFF function loadf0(x) img = GDAL.gdalopen(x, GDAL.GA_ReadOnly) band = GDAL.gdalgetrasterband(img, 1) xsize = GDAL.gdalgetrasterbandxsize(band) ysize = GDAL.gdalgetrasterbandysize(band) data = Array{Float32}(undef, xsize, ysize) GDAL.gdalrasterio(band, GDAL.GF_Read, 0, 0, xsize, ysize, data, xsize, ysize, GDAL.GDT_Float32, 0, 0) data' end # since we cannot re-distribute the dataset, this function grabs the dataset from the host server function load_dataset(name) # get the dataset from: # http://worldclim.org/version2 """ This is WorldClim 2.0 Beta version 1 (June 2016) downloaded from http://worldclim.org They represent average monthly climate data for 1970-2000. The data were created by Steve Fick and Robert Hijmans You are not allowed to redistribute these data. """ if !isfile("$name.zip") # This might fail on windows - just try again a couple of times -.- # download with curl breaks if julia is in LD_LIBRARY_PATH # which GDAL is putting there ENV["LD_LIBRARY_PATH"] = "" download("http://biogeo.ucdavis.edu/data/worldclim/v2.0/tif/base/wc2.0_10m_$name.zip", "$name.zip") end if !isdir(name) unzip("$name.zip", name) end ENV["LD_LIBRARY_PATH"] = env loadf0.(filter(istiff, joinpath.(name, readdir(name)))) end # load the actual datasets! water = load_dataset("prec") temperature = load_dataset("tmax") # calculate geometries m = uv_normal_mesh(Tesselation(Sphere(Point3f0(0), 1f0), 200)) points = GeometryBasics.coordinates(m) GeometryBasics.pointmeta(m, color=rand(length(points))) GeometryBasics.pop_pointmeta(m, :uv) p = decompose(Point3f0, m) uv = decompose_uv(m) norms = decompose_normals(m) # plot the temperature as color map on the globe cmap = [:darkblue, :deepskyblue2, :deepskyblue, :gold, :tomato3, :red, :darkred] # function to scale precipitation to a suitable marker size function watermap(uv, water, normalization = 908f0 * 4f0) markersize = map(uv) do uv wsize = reverse(size(water)) wh = wsize .- 1 x, y = round.(Int, Tuple(uv) .* wh) .+ 1 val = water[size(water)[1] - (y - 1), x] / normalization val < 0.0 ? -1f0 : val end end scene = Scene(resolution = (800, 800)) scene = mesh!(m, color = temperature[10], colorrange = (-50, 50), colormap = cmap, shading = true, show_axis = false) temp_plot = scene[end]; # plot precipitation as vertical bars watervals = watermap(uv, water[1]) extrema(watervals) xyw = 0.01 meshscatter!(scene, p, rotations = norms, marker = Rect3D(Vec3f0(0), Vec3f0(1)), markersize = Vec3f0.(xyw, xyw, watervals), raw = true, color = watervals, colormap = [(:black, 0.0), (:skyblue2, 0.6)], shading = false ) wplot = scene[end] # update eye position eye_position, lookat, upvector = Vec3f0(0.5, 0.8, 2.5), Vec3f0(0), Vec3f0(0, 1, 0) update_cam!(scene, eye_position, lookat, upvector) scene scene.center = false # save animation r = record(scene, "worldclim_visualization.mp4", 0:(11*4)) do i # Make simulation slower. TODO figure out how do this nicely with ffmpeg if i % 4 == 0 i2 = (i รท 4) + 1 temp_plot[:color] = temperature[i2] watervals = watermap(uv, water[i2]) wplot[:color] = watervals wplot[:markersize][] .= Vec3f0.(xyw, xyw, watervals) # since we modify markersize inplace above, we need to notify the signal AbstractPlotting.notify!(wplot[:markersize]) end end ENV["LD_LIBRARY_PATH"] = "" r