From a165fef1a0c8bc86156ae4c772bfa83068f31828 Mon Sep 17 00:00:00 2001 From: Andrew Gene Brown Date: Tue, 21 Nov 2023 01:04:11 -0800 Subject: [PATCH 1/2] Add `gpkg_create_spatial_view()` for #6 --- DESCRIPTION | 2 +- NAMESPACE | 1 + NEWS.md | 4 +++ R/gpkg-view.R | 32 ++++++++++++++++++++++++ man/gpkg_create_spatial_view.Rd | 43 +++++++++++++++++++++++++++++++++ misc/gpkg-view-voronoi.R | 33 +++++++++++++++++++++++++ 6 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 R/gpkg-view.R create mode 100644 man/gpkg_create_spatial_view.Rd create mode 100644 misc/gpkg-view-voronoi.R diff --git a/DESCRIPTION b/DESCRIPTION index 693978a..70d44cd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: gpkg Type: Package Title: Utilities for the Open Geospatial Consortium 'GeoPackage' Format -Version: 0.0.7 +Version: 0.0.8 Authors@R: person(given="Andrew", family="Brown", email="brown.andrewg@gmail.com", role = c("aut", "cre")) Maintainer: Andrew Brown Description: Build Open Geospatial Consortium 'GeoPackage' files (). 'GDAL' utilities for reading and writing spatial data are provided by the 'terra' package. Additional 'GeoPackage' and 'SQLite' features for attributes and tabular data are implemented with the 'RSQLite' package. diff --git a/NAMESPACE b/NAMESPACE index cc7b133..7087dfe 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -28,6 +28,7 @@ export(gpkg_connect) export(gpkg_contents) export(gpkg_create_contents) export(gpkg_create_dummy_features) +export(gpkg_create_spatial_view) export(gpkg_delete_contents) export(gpkg_disconnect) export(gpkg_execute) diff --git a/NEWS.md b/NEWS.md index 22ca252..148d0a5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# gpkg 0.0.8 + + - Added `gpkg_create_spatial_view()` for creating spatial views, which dynamic layers that are accessible as if they were typical static geometry layers (for #6). + # gpkg 0.0.7 - Added `gpkg_bbox()` as an application of `gpkg_ogr_query()` diff --git a/R/gpkg-view.R b/R/gpkg-view.R new file mode 100644 index 0000000..1c2f89a --- /dev/null +++ b/R/gpkg-view.R @@ -0,0 +1,32 @@ +#' Create a Spatial View +#' +#' @param g a `geopackage` +#' @param viewname _character_. Name of view. +#' @param viewquery _character_. Query for view contents. +#' @param geom_column _character_. Column name of view geometry. Default: `"geom"` +#' @param geometry_type_name _character_. View geometry type. Default: `"GEOMETRY"` +#' @param data_type _character_. View data type. Default `"features"` +#' @param srs_id _integer_. Spatial Reference System ID. Default: `4326` (WGS84) +#' @param z _integer_. Default: `0` +#' @param m _integer_. Default: `0` +#' +#' @return _integer_. Returns `1` if a new record in `gpkg_geometry_columns` is successfully made. +#' @export +#' +gpkg_create_spatial_view <- function(g, + viewname, + viewquery, + geom_column = "geom", + geometry_type_name = "GEOMETRY", + data_type = "features", + srs_id = 4326, + z = 0, + m = 0) { +gpkg_execute(g, sprintf("CREATE VIEW %s AS %s", viewname, viewquery)) +gpkg_execute(g, sprintf("INSERT INTO gpkg_contents (table_name, identifier, data_type, srs_id) + VALUES ('%s', '%s', '%s', %s)", + viewname, viewname, data_type, srs_id)) +gpkg_execute(g, sprintf("INSERT INTO gpkg_geometry_columns (table_name, column_name, geometry_type_name, srs_id, z, m) + VALUES ('%s', '%s', '%s', %s, %s, %s)", + viewname, geom_column, geometry_type_name, srs_id, z, m)) +} \ No newline at end of file diff --git a/man/gpkg_create_spatial_view.Rd b/man/gpkg_create_spatial_view.Rd new file mode 100644 index 0000000..91d3089 --- /dev/null +++ b/man/gpkg_create_spatial_view.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/gpkg-view.R +\name{gpkg_create_spatial_view} +\alias{gpkg_create_spatial_view} +\title{Create a Spatial View} +\usage{ +gpkg_create_spatial_view( + g, + viewname, + viewquery, + geom_column = "geom", + geometry_type_name = "GEOMETRY", + data_type = "features", + srs_id = 4326, + z = 0, + m = 0 +) +} +\arguments{ +\item{g}{a \code{geopackage}} + +\item{viewname}{\emph{character}. Name of view.} + +\item{viewquery}{\emph{character}. Query for view contents.} + +\item{geom_column}{\emph{character}. Column name of view geometry. Default: \code{"geom"}} + +\item{geometry_type_name}{\emph{character}. View geometry type. Default: \code{"GEOMETRY"}} + +\item{data_type}{\emph{character}. View data type. Default \code{"features"}} + +\item{srs_id}{integer. Spatial Reference System ID. Default: \code{4326} (WGS84)} + +\item{z}{integer. Default: \code{0}} + +\item{m}{integer. Default: \code{0}} +} +\value{ +\code{1} if a new record in \code{gpkg_geometry_columns} is successfully made. +} +\description{ +Create a Spatial View +} diff --git a/misc/gpkg-view-voronoi.R b/misc/gpkg-view-voronoi.R new file mode 100644 index 0000000..e15f850 --- /dev/null +++ b/misc/gpkg-view-voronoi.R @@ -0,0 +1,33 @@ +library(gpkg) +library(terra) + +gpkg_tmp <- tempfile(fileext = ".gpkg") + +if (file.exists(gpkg_tmp)) + file.remove(gpkg_tmp) + +v <- vect(system.file("ex", "lux.shp", package = "terra")) + +gpkg_write(list(lux = v), destfile = gpkg_tmp, append = TRUE) + +g <- geopackage(gpkg_tmp, connect = TRUE) + +gpkg_create_spatial_view(g, "my_vor", "SELECT lux.fid AS OGC_FID, + lux.fid AS fid, + ST_VoronojDiagram(geom) AS geom2 + FROM lux WHERE ID_2 <= 3", + geom_column = "geom2", + geometry_type_name = "MULTIPOLYGON") + # NB: terra::vect() sensitive to geom type +gpkg_contents(g) + +plot(gpkg_vect(g, "my_vor")) +gpkg_vect(g, "lux") |> + subset(ID_2 <= 3, NSE = TRUE) |> + as.lines() |> + plot(col = "BLUE", lwd = 2, add = TRUE) + +# compare to: +plot(sf::st_read(g$dsn, layer = "my_vor")) +plot(svc(g$dsn, layer = "my_vor")[1]) +plot(query(vect(g$dsn, layer = "my_vor", proxy = TRUE))) From 82465ebc12a2607a66abc5af4f56066e9b7e678c Mon Sep 17 00:00:00 2001 From: "Andrew G. Brown" Date: Wed, 6 Dec 2023 21:35:19 -0800 Subject: [PATCH 2/2] Add toggle for gdal_spatialite_computed_geom_column entries for #6 --- R/gpkg-view.R | 9 +++++++++ man/gpkg_create_spatial_view.Rd | 14 ++++++++++---- misc/gpkg-view-voronoi.R | 3 ++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/R/gpkg-view.R b/R/gpkg-view.R index 1c2f89a..4b46ed8 100644 --- a/R/gpkg-view.R +++ b/R/gpkg-view.R @@ -5,6 +5,10 @@ #' @param viewquery _character_. Query for view contents. #' @param geom_column _character_. Column name of view geometry. Default: `"geom"` #' @param geometry_type_name _character_. View geometry type. Default: `"GEOMETRY"` +#' @param spatialite_computed _logical_. Register definition of `geom_column` as +#' the result of a Spatialite spatial function via +#' `"gdal_spatialite_computed_geom_column"` extension. +#' Default: `FALSE` #' @param data_type _character_. View data type. Default `"features"` #' @param srs_id _integer_. Spatial Reference System ID. Default: `4326` (WGS84) #' @param z _integer_. Default: `0` @@ -18,6 +22,7 @@ gpkg_create_spatial_view <- function(g, viewquery, geom_column = "geom", geometry_type_name = "GEOMETRY", + spatialite_computed = FALSE, data_type = "features", srs_id = 4326, z = 0, @@ -29,4 +34,8 @@ gpkg_execute(g, sprintf("INSERT INTO gpkg_contents (table_name, identifier, data gpkg_execute(g, sprintf("INSERT INTO gpkg_geometry_columns (table_name, column_name, geometry_type_name, srs_id, z, m) VALUES ('%s', '%s', '%s', %s, %s, %s)", viewname, geom_column, geometry_type_name, srs_id, z, m)) +if (spatialite_computed) + gpkg_execute(g, sprintf("INSERT INTO gpkg_extensions (table_name, column_name, extension_name, definition, scope) + VALUES ('%s', '%s', 'gdal_spatialite_computed_geom_column', 'https://gdal.org/drivers/vector/gpkg_spatialite_computed_geom_column.html', 'read-write');", + viewname, geom_column)) } \ No newline at end of file diff --git a/man/gpkg_create_spatial_view.Rd b/man/gpkg_create_spatial_view.Rd index 91d3089..688c60c 100644 --- a/man/gpkg_create_spatial_view.Rd +++ b/man/gpkg_create_spatial_view.Rd @@ -10,6 +10,7 @@ gpkg_create_spatial_view( viewquery, geom_column = "geom", geometry_type_name = "GEOMETRY", + spatialite_computed = FALSE, data_type = "features", srs_id = 4326, z = 0, @@ -27,16 +28,21 @@ gpkg_create_spatial_view( \item{geometry_type_name}{\emph{character}. View geometry type. Default: \code{"GEOMETRY"}} +\item{spatialite_computed}{\emph{logical}. Register definition of \code{geom_column} as +the result of a Spatialite spatial function via +\code{"gdal_spatialite_computed_geom_column"} extension. +Default: \code{FALSE}} + \item{data_type}{\emph{character}. View data type. Default \code{"features"}} -\item{srs_id}{integer. Spatial Reference System ID. Default: \code{4326} (WGS84)} +\item{srs_id}{\emph{integer}. Spatial Reference System ID. Default: \code{4326} (WGS84)} -\item{z}{integer. Default: \code{0}} +\item{z}{\emph{integer}. Default: \code{0}} -\item{m}{integer. Default: \code{0}} +\item{m}{\emph{integer}. Default: \code{0}} } \value{ -\code{1} if a new record in \code{gpkg_geometry_columns} is successfully made. +\emph{integer}. Returns \code{1} if a new record in \code{gpkg_geometry_columns} is successfully made. } \description{ Create a Spatial View diff --git a/misc/gpkg-view-voronoi.R b/misc/gpkg-view-voronoi.R index e15f850..04610da 100644 --- a/misc/gpkg-view-voronoi.R +++ b/misc/gpkg-view-voronoi.R @@ -17,7 +17,8 @@ gpkg_create_spatial_view(g, "my_vor", "SELECT lux.fid AS OGC_FID, ST_VoronojDiagram(geom) AS geom2 FROM lux WHERE ID_2 <= 3", geom_column = "geom2", - geometry_type_name = "MULTIPOLYGON") + geometry_type_name = "MULTIPOLYGON", + spatialite_computed = TRUE) # NB: terra::vect() sensitive to geom type gpkg_contents(g)