Skip to content

Instantly share code, notes, and snippets.

View mdsumner's full-sized avatar

Michael Sumner mdsumner

  • Integrated Digital East Antarctica, Australian Antarctic Division
  • Hobart, Australia
View GitHub Profile
  library(gdalraster)
#> GDAL 3.13.0dev-0e4f0cadf6 (released 2026-01-20), GEOS 3.12.1, PROJ 9.7.0
dsn <- "WMTS:https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/WMTS/1.0.0/WMTSCapabilities.xml,layer=World_Imagery"

ds <- new(GDALRaster, dsn)
d <- read_ds(ds, out_xsize = 1024, out_ysize = 1024, bands = 1:3)
bb <- ds$bbox()
plot(NA, xlim = bb[c(1, 3)], ylim = bb[c(2, 4)], asp = 1, xlab = "", ylab = "")
a <- aperm(array(d, c(1024, 1024, 3)), c(2,1 ,3))
I'm working on a GDAL backend for xarray: https://github.com/mdsumner/gdx I've figured out a bunch of issues that should make it perform better with dask, still early but if anyone is interested I'm using it with CMEMs Zarr stores that I catalogue with https://github.com/hypertidy/cmemsarco This combo for me is (finally!) a clean set of features that I wanted for GDAL compared to Zarr/xarray. I'm now proficient enough to actually get into the details of dask, and I've seen GDAL be more efficient with virtualized remote stores like Thredds (I think connection pooling is smarter, but of course this is stuff that Icechunk is racing ahead with too in yet another format variant so we'll see how things play out). I don't really see any Zarr work in R, but GDAL provides a very good foundation (we don't need fsspec or numcodecs etc because GDAL has those as part of its Abstraction) and gdalraster has a good framework for leveraging that. Multidimensional is really overkill for something simple like a regular array of

Title Fix: respect const return type of GDALGetMetadata (build with GDAL 3.13+)

Body Summary GDAL changed the prototype of GDALGetMetadata to return a const-qualified list (CSLConstList / const char * const *). When compiling gdalraster against newer GDAL (CI used GDAL 3.13.0dev) this leads to compilation errors like:

invalid conversion from 'CSLConstList' {aka 'const char* const*'} to 'char**' [-fpermissive] CI reference

failing Actions run: https://github.com/hypertidy/vsils/actions/runs/21079839585/job/60630624861 commit/ref used in that run: 719a99cf0307da5194dd8422df8fac13a4e9be0c Cause GDALGetMetadata now returns a const-qualified pointer; existing gdalraster source assigns its return value to char** (mutable), which is not compatible with the new signature and fails to compile with modern C++/GCC.

import React, { useRef, useEffect, useState, useCallback } from 'react';
import * as THREE from 'three';
// Simplified world countries - key ones for demonstration
const COUNTRIES_URL = 'https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_110m_admin_0_countries.geojson';
export default function GlobeComparison() {
const containerRef = useRef(null);
const sceneRef = useRef(null);
const cameraRef = useRef(null);

proj4js Wrapper with Authority Code Resolution

A thin wrapper around proj4 that accepts multiple CRS input formats and automatically resolves authority codes via spatialreference.org.

Supported Input Formats

Format Example Handling
Proj4 string +proj=stere +lat_0=-90 ... Native proj4js
WKT1 PROJCS["Antarctic",...] Native proj4js

IBCSO digital chart textured across a wide meriodional range to Mercator.

library(anglr)  ## hypertidy/anglr

library(raster)
library(curl)
library(rgl)
## download IBCSO
ibcso_url <- "https://github.com/mdsumner/ibcso-cog/raw/refs/heads/main/IBCSO_v2_digital_chart.tif"

In these CMEMs ZARR there's evidence of the dummy "crs" var used via "grid_mapping" in NetCDF, but there's no such var.

https://data.marine.copernicus.eu/product/SEALEVEL_GLO_PHY_L4_MY_008_047/description

curl -s "https://s3.waw3-1.cloudferro.com/mdl-arco-time-045/arco/SEALEVEL_GLO_PHY_L4_MY_008_047/cmems_obs-sl_glo_phy-ssh_my_allsat-demo-l4-duacs-0.125deg_P1D-i_202511/timeChunked.zarr/.zmetadata" | grep -i "grid_mapping\|crs\|spatial_ref"
      "grid_mapping": "crs",
      "grid_mapping": "crs",
      "grid_mapping": "crs",
  xx <- seq(100, 220, by = 5)
yy <- seq(-60, -30, by = 10)
x <- cbind(expand.grid(xmin = head(xx, -1), ymax = tail(yy, -1)), 
  expand.grid(xmax = tail(xx, -1), ymin = head(yy, -1)))

library(wk)
library(PROJ)
library(geos)
## source, then target

a plumber2 function to get imagery for a website from a URI (/vsizip//vsicurl/ vsiaz, WMTS: etc etc)

#* @get /tile
#* @serializer image/png
function(query) {

Sys.setenv(
  GDAL_CACHEMAX = "2048",           # MB for block cache
  VSI_CACHE = "TRUE",              # Cache remote reads