duckspatial: new geometry functions, MVT/MBTiles export, and more
R
spatial
duckspatial
Highlights from duckspatial v1.1.2 and v1.2.0
Author
Adrián Cidre
Published
July 4, 2026
1 Introduction
Two versions of {duckspatial} have shipped since the last update: v1.1.2 and v1.2.0. Both are now on CRAN, so let’s go through the highlights together.
Snaps coordinates to a grid to shrink geometry size. The next example reduces the precision of argentina boundary to 1 degree (e.g. 62.4328 degrees would shrink to 62 degrees).
A full set of extent helpers landed too: ddbs_xmax(), ddbs_xmin(), ddbs_ymax(), ddbs_ymin(), plus the Z/M equivalents. By default they work by_feature = TRUE adding a new column per feature (useful for maintaining workflows within duckdb, and apply filters):
ddbs_point() creates POINT geometries directly from coordinate vectors, with 2D/3D/4D support and CRS assignment:
cities_ddbs<-ddbs_point( x =c(-58.3816, -64.1811), y =c(-34.6037, -31.4201), another_column =c("A", "B"), crs =4326)cities_ddbs
# A duckspatial lazy spatial table
# ● CRS: EPSG:4326
# ● Geometry column: geometry
# ● Geometry type: POINT
# ● Bounding box: xmin: -64.181 ymin: -34.604 xmax: -58.382 ymax: -31.42
# Data backed by DuckDB (dbplyr lazy evaluation)
# Use ddbs_collect() or st_as_sf() to materialize to sf
#
# Source: table<temp_table_a7614852_e444_4ae3_adf4_77eb75c593ae> [?? x 2]
# Database: DuckDB 1.5.4 [cidre@Linux 7.0.0-22-generic:R 4.6.0/:memory:]
another_column geometry
<chr> <wk_wkb>
1 A <POINT (-58.3816 -34.6037)>
2 B <POINT (-64.1811 -31.4201)>
For line work, ddbs_shortest_line() returns the connecting LINESTRING between the closest points of two geometries, and ddbs_line_locate_point() gives the fractional position (0–1) of the closest point on a line to a reference point. ddbs_line_node() is the batch version: it nodes a set of lines, splitting them at every crossing into a fully noded MULTILINESTRING.
ddbs_azimuth() computes the clockwise bearing between two sets of points, in radians by default or degrees via unit = "degrees".
On the aggregation side, ddbs_intersection_agg() joins ddbs_union_agg() as the intersection counterpart — computes the common area of a set of geometries, optionally grouped by column.
polys_inters (the black point): intersects all four polygons together (ignoring grp). Since each square is shifted diagonally by 1 unit and only 3×3 in size, the only area common to all four is that single point at (3,3).
polys_inters_grp: the intersection computed within each group (by = "grp"). The two transparent red squares (grp = "a") overlap in the red square; the two transparent teal squares (grp = "b") overlap in the teal square.
ddbs_as_geojson() itself got more useful: it now carries all non-geometry columns as feature properties instead of dropping them, and returns a single FeatureCollection by default — matching geojsonsf::sf_geojson(). Pass feature_collection = FALSE if you want one Feature per row instead.
5 Vector tiles
Two new functions bring Mapbox Vector Tile support into {duckspatial}: ddbs_as_mvt_geom() transforms geometries into MVT coordinate space, clipping to a tile’s bounding box. ddbs_write_mbtiles() goes further and generates a full tile pyramid from a spatial dataset, writing it straight to an MBTiles file — ready to serve or convert to PMTiles.
6 Extension management
ddbs_extension_info() prints a glimpse() of a DuckDB extension’s row from duckdb_extensions() — installed/loaded status, version, install path — for the spatial extension by default:
ddbs_install() gains a repos argument to pull an extension from a specific DuckDB repository ("core", "core_nightly", "community"). Leaving it NULL keeps the previous fallback behavior (core, then community).
7 Bug fixes
ddbs_install() had a broken “already on the latest version” check — it referenced a column DuckDB doesn’t provide and compared install_mode with the wrong case, so it silently never triggered. Removed.
A mistake in the startup message is fixed.
ddbs_union_agg() gains a mem argument: set mem = TRUE to use ST_MemUnion_Agg() instead of ST_Union_Agg() — slower, but lighter on memory for large unions.
8 Wrapping up
That’s about 20 new functions across the two releases, plus some quality-of-life fixes for extension installation and GeoJSON export. As always, full changelogs are on GitHub, and the package is on CRAN.
Feedback and issues are very welcome — open one here if you run into anything.
9 Session Information
Analyses were conducted using the R Statistical language (version 4.6.0; R Core Team, 2026) on Ubuntu 26.04 LTS, using the packages duckspatial (version 1.2.0; Cidre González A et al., 2026), sf (version 1.1.1; Pebesma E, Bivand R, 2023), mapgl (version 0.5.0; Walker K, 2026), ggplot2 (version 4.0.3; Wickham H, 2016) and dplyr (version 1.2.1.9000; Wickham H et al., 2026).
Wickham H (2016). ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. ISBN 978-3-319-24277-4. https://ggplot2.tidyverse.org.
Wickham H, François R, Henry L, Müller K, Vaughan D (2026). dplyr: A Grammar of Data Manipulation. R package version 1.2.1.9000, commit d5e94e7fa8fd4a5f79c1a707d1842216bb4c691f, https://github.com/tidyverse/dplyr.