I have georeferenced data in longitude/latitude, and I want to plot them on a three-dimensional globe with the WGS84 datum, using the GLMakie and GeoMakie libraries.
You can download the data from here.
The grid is irregular in longitude-latitude. Each georeferenced data point corresponds to a cell whose corners or vertices have known longitude and latitude coordinates. I want each cell to be colored with a constant color (no color gradients) that corresponds to the data of the grid point in the cell.
asinghvi17 gave me a code that makes it but with non-constant color and with no cells, and I wonder even if it is possible what I want to do.
I have slightly modified it, but I get an error. See the comments in the code:
using NCDatasets # io
using GLMakie, GeoMakie # visualization
using Delaunator # fast meshing of 2d point clouds
using ProgressMeter
ds = NCDataset("/home/antonio/Documentos/codigo/grid_utils/N320_weights.nc")
## From here =======================================================
## Code that runs, but no constant cell color:
#t1 = Delaunator.triangulate(tuple.(ds["longitude"], ds["latitude"]))
#fig, ax, plt = mesh(
# t1.points, GLMakie.TriangleFace.(t1.triangles);
# color = replace(ds["spatial_weights"][:, 1], missing => NaN),
# shading = NoShading, # flat lighting on the mesh
# axis = (; type = GeoMakie.GlobeAxis, show_axis = false),
# figure = (; backgroundcolor = :black)
#)
## Until here, the code that runs
## Until here ========================================================
# From here =======================================================
# From here, the code that does not run. It is an attemt to make cell constant
#colors:
# For each grid point we have the cell surrounding it that is delimited by
# the longitudes bounds and latitudes bounds of that grid point.
# So, there is a two dimensional array. One dimension corresponds to the grid
# point, so that it is as long as the number of grid points. The other dimension
# is two, so that the elemen [1,1] is the upper latitude of the first cell and
# [1,2] is the lower latitude of the same cell. For the grid point number 238,
# the latitude boundaries are at [238,1] (upper) and [238,2] (lower), and so on.
# And analogously for the longitudes.
# So, we form the vertices and the faces as follows:
vertex = []
faces = []
@showprogress for i in 1:length(ds["longitude"])
push!( vertex, [ ds["lon_bnds"][i,1], ds["lat_bnds"][i,1] ] )
push!( vertex, [ ds["lon_bnds"][i,1], ds["lat_bnds"][i,2] ] )
push!( vertex, [ ds["lon_bnds"][i,2], ds["lat_bnds"][i,2] ] )
push!( vertex, [ ds["lon_bnds"][i,2], ds["lat_bnds"][i,1] ] )
vertex_len = length(vertex)
push!( faces, [ vertex_len-3, vertex_len-2, vertex_len-1 ])
push!( faces, [ vertex_len-3, vertex_len-1, vertex_len ])
end # for
vertex = vcat(vertex'...)
faces = vcat(faces'...)
fig, ax, plt = mesh(
vertex, faces;
color = replace(ds["spatial_weights"][:, 1], missing => NaN),
shading = NoShading, flat lighting on the mesh
axis = (; type = GeoMakie.GlobeAxis, show_axis = false),
figure = (; backgroundcolor = :black)
)
# Throws the error:
#ERROR: Buffer vertices does not have the same length as the other buffers.
# vertex_color has length 542080
# vertices has length 2168320
# Until here, the attempt that does nor run
# Until here ========================================================
# Plot coastlines, color black with 10% opacity, 20km above sea level
coastlines_plt = lines!(ax, GeoMakie.coastlines(); color = (:black, 0.1), zlevel = 20_000)
# Display the figure so you can see it and interact with it!
# GlobeAxis user controls are not the greatest at the moment but that
# will improve this summer.
fig
# Animate the whole thing
## first, add a title to the top
#title = Label(fig[0, 1]; text = "N320 spatial weights", tellwidth = false, tellheight = true, color = :white)
#sw = ds["spatial_weights"]
## then, simply loop over the frames and update the color of the mesh plot, and the title!
## Animation in Makie is really simple using Observables.
#record(fig, "over_time.mp4", 1:length(ds["valid_time"]), framerate = 60, px_per_unit = 2, update = false) do i
# plt.color[] = replace(msl[:, i], missing => NaN)
# title.text[] = string(ds["valid_time"][i])
#end