GDALVector
provides an interface for accessing a vector layer in a GDAL
dataset and calling methods on the underlying OGRLayer
object.
An object of class GDALVector
persists an open connection to the dataset,
and exposes methods for retrieving layer information, setting attribute and
spatial filters, and reading/writing feature data.
See https://gdal.org/api/index.html for details of the GDAL
Vector API.
Class GDALVector
is currently under development. An initial
implementation supporting read access was added in gdalraster 1.11.1.9100.
A working document with draft specifications is available at:
https://usdaforestservice.github.io/gdalraster/articles/gdalvector-draft.html
and discussion thread/status updates at:
https://github.com/USDAForestService/gdalraster/issues/241.
Arguments
- dsn
Character string containing the data source name (DSN), usually a filename or database connection string.
- layer
Character string containing the name of a layer within the data source. May also be given as an SQL SELECT statement to be executed against the data source, defining a layer as the result set.
- read_only
Logical scalar.
TRUE
to open the layer read-only (the default), orFALSE
to open with write access.- open_options
Optional character vector of
NAME=VALUE
pairs specifying dataset open options.- spatial_filter
Optional character string containing a geometry in Well Known Text (WKT) format which represents a spatial filter.
- dialect
Optional character string to control the statement dialect when SQL is used to define the layer. By default, the OGR SQL engine will be used, except for RDBMS drivers that will use their dedicated SQL engine, unless
"OGRSQL"
is explicitly passed as the dialect. The"SQLITE"
dialect can also be used.
Value
An object of class GDALVector
which contains pointers to the
opened layer and the dataset that owns it, and methods that operate on
the layer as described in Details. GDALVector
is a C++ class exposed
directly to R (via RCPP_EXPOSED_CLASS
). Fields and methods of the class
are accessed using the $
operator. Note that all arguments to exposed
class methods are required (but do not have to be named). The read/write
fields are per-object settings which can be changed as needed during the
lifetime of the object.
Usage (see Details)
## Constructors
# for single-layer file formats such as shapefile
lyr <- new(GDALVector, dsn)
# specifying the layer name, or SQL statement defining the layer
lyr <- new(GDALVector, dsn, layer)
# for update access
lyr <- new(GDALVector, dsn, layer, read_only = FALSE)
# using dataset open options
lyr <- new(GDALVector, dsn, layer, read_only, open_options)
# setting a spatial filter and/or specifying the SQL dialect
lyr <- new(GDALVector, dsn, layer, read_only, open_options, spatial_filter, dialect)
## Read/write fields (per-object settings)
lyr$defaultGeomFldName
lyr$promoteToMulti
lyr$quiet
lyr$returnGeomAs
lyr$wkbByteOrder
## Methods
lyr$open(read_only)
lyr$isOpen()
lyr$getDsn()
lyr$getFileList()
lyr$getDriverShortName()
lyr$getDriverLongName()
lyr$getName()
lyr$getFieldNames()
lyr$testCapability()
lyr$getFIDColumn()
lyr$getGeomType()
lyr$getGeometryColumn()
lyr$getSpatialRef()
lyr$bbox()
lyr$getLayerDefn()
lyr$setAttributeFilter(query)
lyr$getAttributeFilter()
lyr$setIgnoredFields(fields)
lyr$setSelectedFields(fields)
lyr$setSpatialFilter(wkt)
lyr$setSpatialFilterRect(bbox)
lyr$getSpatialFilter()
lyr$clearSpatialFilter()
lyr$getFeatureCount()
lyr$getNextFeature()
lyr$setNextByIndex(i)
lyr$getFeature(fid)
lyr$resetReading()
lyr$fetch(n)
lyr$setFeature(feature)
lyr$createFeature(feature)
lyr$upsertFeature(feature)
lyr$getLastWriteFID()
lyr$deleteFeature(fid)
lyr$syncToDisk()
lyr$startTransaction(force)
lyr$commitTransaction()
lyr$rollbackTransaction()
ds$getMetadata()
ds$setMetadata(metadata)
ds$getMetadataItem(mdi_name)
lyr$close()
Details
Constructors
new(GDALVector, dsn)
The first layer by index is assumed if the layer
argument is omitted, so
this form of the constructor might be used for single-layer formats like
shapefile.
new(GDALVector, dsn, layer)
Constructor specifying the name of a layer to open. The layer
argument
may also be given as an SQL SELECT statement to define a layer as the result
set.
new(GDALVector, dsn, layer, read_only)
Constructor specifying read/write access (read_only = {TRUE|FALSE})
.
The layer
argument is required in this form of the constructor, but may be
given as empty string (""
), in which case the first layer by index will be
assumed.
new(GDALVector, dsn, layer, read_only, open_options)
Constructor specifying dataset open options as a character vector of
NAME=VALUE
pairs.
new(GDALVector, dsn, layer, read_only, open_options, spatial_filter, dialect))
Constructor to specify a spatial filter and/or SQL dialect. All arguments
are required in this form of the constructor, but open_options
may be
NULL
, and spatial_filter
or dialect
may be an empty string (""
).
Read/write fields
$defaultGeomFldName
Character string specifying a name to use for returned columns when the
geometry column name in the source layer is empty, like with shapefiles etc.
Defaults to "geometry"
.
$promoteToMulti
A logical value specifying whether to automatically promote geometries from
Polygon to MultiPolygon, Point to MultiPoint, or LineString to
MultiLineString during read operations (i.e., with methods $getFeature()
,
$getNextFeature()
, $fetch()
). Defaults to FALSE
. Setting to TRUE
may
be useful when reading from layers such as shapefiles that mix, e.g.,
Polygons and MultiPolygons.
$quiet
A logical value, FALSE
by default. Set to TRUE
to suppress various
messages and warnings.
$returnGeomAs
Character string specifying the return format of feature geometries.
Must be one of WKB
(the default), WKB_ISO
, WKT
, WKT_ISO
, BBOX
, or
NONE
.
Using WKB
/WKT
exports as 99-402 extended dimension (Z) types for Point,
LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon and
GeometryCollection. For other geometry types, it is equivalent to using
WKB_ISO
/WKT_ISO
(see https://libgeos.org/specifications/wkb/).
Using BBOX
exports as a list of numeric vectors, each of length 4 with values
xmin, ymin, xmax, ymax
. If an empty geometry is encountered these values will
be NA_real_
in the corresponding location.
Using NONE
will result in no geometry value being present in the feature
returned.
$wkbByteOrder
Character string specifying the byte order for WKB geometries.
Must be either LSB
(Least Significant Byte first, the default) or
MSB
(Most Significant Byte first).
Methods
$open(read_only)
(Re-)opens the vector layer on the existing DSN. Use this method to
open a layer that has been closed using $close()
. May be used to
re-open a layer with a different read/write access (read_only
set to
TRUE
or FALSE
). The method will first close an open dataset, so it is
not required to call $close()
explicitly in this case.
No return value, called for side effects.
$isOpen()
Returns a logical
scalar indicating whether the vector dataset is open.
$getDsn()
Returns a character string containing the dsn
associated with this
GDALVector
object (dsn
originally used to open the layer).
$getFileList()
Returns a character vector of files believed to be part of the data source.
If it returns an empty string (""
) it means there is believed to be no
local file system files associated with the dataset (e.g., a virtual file
system). The returned filenames will normally be relative or absolute
paths depending on the path used to originally open the dataset.
$getDriverShortName()
Returns the short name of the vector format driver.
$getDriverLongName()
Returns the long name of the vector format driver.
$getName()
Returns the layer name.
$getFieldNames()
Returns a character vector of the layer's field names.
$testCapability()
Tests whether the layer supports named capabilities based on the current
read/write access. Returns a list of capabilities with values TRUE
or
FALSE
. The returned list contains the following named elements:
RandomRead
, SequentialWrite
, RandomWrite
, UpsertFeature
,
FastSpatialFilter
, FastFeatureCount
, FastGetExtent
,
FastSetNextByIndex
, CreateField
, CreateGeomField
, DeleteField
,
ReorderFields
, AlterFieldDefn
, AlterGeomFieldDefn
, DeleteFeature
,
StringsAsUTF8
, Transactions
, CurveGeometries
.
(See the GDAL documentation for
OGR_L_TestCapability()
.)
$getFIDColumn()
Returns the name of the underlying database column being used as the FID
column, or empty string (""
) if not supported.
$getGeomType()
Returns the well known name of the layer geometry type as character string.
For layers with multiple geometry fields, this method only returns the
geometry type of the first geometry column. For other columns, use
$getLayerDefn()
. For layers without any geometry field, this method
returns "NONE"
.
$getGeometryColumn()
Returns he name of the underlying database column being used as the geometry
column, or an empty string (""
) if not supported.
For layers with multiple geometry fields, this method only returns the
name of the first geometry column. For other columns, use $getLayerDefn()
.
$getSpatialRef()
Returns a WKT string containing the spatial reference system for this layer,
or empty string (""
) if no spatial reference exists.
$bbox()
Returns a numeric vector of length four containing the bounding box
for this layer (xmin, ymin, xmax, ymax). Note that bForce = true
is set in
the underlying API call to OGR_L_GetExtent()
, so the entire layer may be
scanned to compute a minimum bounding rectangle (see FastGetExtent
in the
list returned by $testCapability()
). Depending on the format driver, a
spatial filter may or may not be taken into account, so it is safer to call
$bbox()
without setting a spatial filter.
$getLayerDefn()
Returns a list containing the OGR feature class definition for this layer
(a.k.a. layer definition). The list contains zero or more attribute field
definitions, along with one or more geometry field definitions.
See ogr_define for details of the field and feature class definitions.
$setAttributeFilter(query)
Sets an attribute query string to be used when fetching features via the
$getNextFeature()
or $fetch()
methods.
Only features for which query
evaluates as true will be returned.
The query string should be in the format of an SQL WHERE clause, described
in the "WHERE"
section of the OGR SQL dialect documentation (e.g.,
"population > 1000000 and population < 5000000"
, where population
is an
attribute in the layer).
In some cases (RDBMS backed drivers, SQLite, GeoPackage) the native
capabilities of the database may be used to to interpret the WHERE clause,
in which case the capabilities will be broader than those of OGR SQL.
Note that installing a query string will generally result in resetting the
current reading position (as with $resetReading()
described below).
The query
parameter may be set to empty string (""
) to clear the current
attribute filter.
$getAttributeFilter()
Returns the attribute query string currently in use, or empty string (""
)
if an attribute filter is not set.
$setIgnoredFields(fields)
Set which fields can be omitted when retrieving features from the layer.
The fields
argument is a character vector of field names. Passing an
empty string (""
) for fields
will reset to no ignored fields.
If the format driver supports this functionality (testable using
$testCapability()$IgnoreFields
), it will not fetch the specified fields
in subsequent calls to $getFeature()
/ $getNextFeature()
/ $fetch()
,
and thus save some processing time and/or bandwidth. Besides field names of
the layer, the following special fields can be passed: "OGR_GEOMETRY"
to
ignore geometry and "OGR_STYLE"
to ignore layer style. By default, no
fields are ignored. Note that fields that are used in an attribute filter
should generally not be set as ignored fields, as most drivers (such as
those relying on the OGR SQL engine) will be unable to correctly evaluate
the attribute filter. No return value, called for side effects.
$setSelectedFields(fields)
Set which fields will be included when retrieving features from the layer.
The fields
argument is a character vector of field names. Passing an
empty string (""
) for fields
will reset to no ignored fields.
See the $setIgnoredFields()
method above for more information. The data
source must provide IgnoreFields capability in order to set selected
fields. Note that geometry fields, if desired, must be specified when setting
selected fields, either by including named geometry field(s) or the special
field "OGR_GEOMETRY"
in the fields
argument.
No return value, called for side effects.
$setSpatialFilter(wkt)
Sets a new spatial filter from a geometry in WKT format. This method sets
the geometry to be used as a spatial filter when fetching features via the
$getNextFeature()
or $fetch()
methods. Only features that geometrically
intersect the filter geometry will be returned. Currently this test may be
inaccurately implemented (depending on the vector format driver), but it is
guaranteed that all features whose envelope overlaps the envelope of the
spatial filter will be returned. This can result in more shapes being
returned that should strictly be the case.
wkt
is a character string containing a WKT geometry in the same coordinate
system as the layer. An empty string (""
) may be passed indicating that
the current spatial filter should be cleared, but no new one instituted.
$setSpatialFilterRect(bbox)
Sets a new rectangular spatial filter. This method sets a rectangle to be
used as a spatial filter when fetching features via the $getNextFeature()
or $fetch()
methods. Only features that geometrically intersect the given
rectangle will be returned.
bbox
is a numeric vector of length four containing xmin, ymin, xmax, ymax
in the same coordinate system as the layer as a whole (as returned by
$getSpatialRef()
).
$getSpatialFilter()
Returns the current spatial filter geometry as a WKT string, or empty string
(""
) if a spatial filter is not set.
$clearSpatialFilter()
Clears a spatial filter that was set with $setSpatialFilterRect()
.
No return value, called for that side effect.
$getFeatureCount()
Returns the number of features in the layer. For dynamic databases the count
may not be exact. This method forces a count in the underlying API call
(i.e., bForce = TRUE
in the call to OGR_L_GetFeatureCount()
). Note that
some vector drivers will actually scan the entire layer once to count
features. The FastFeatureCount
element in the list returned by
the $testCapability()
method can be checked if this might be a concern.
The number of features returned takes into account the spatial and/or
attribute filters. Some driver implementations of this method may alter the
read cursor of the layer.
$getNextFeature()
Fetch the next available feature from this layer. Only features matching the
current spatial and/or attribute filter (if defined) will be returned.
This method implements sequential access to the features of a layer.
The $resetReading()
method can be used to start at the beginning again.
Returns a list with the unique feature identifier (FID), the attribute and
geometry field names, and their values. The returned list carries the
OGRFeature
class attribute with S3 methods for for print()
and plot()
.
NULL
is returned if no more features are available.
$setNextByIndex(i)
Moves the read cursor to the i
th feature in the current result set
(with 0-based indexing).
This method allows positioning of a layer such that a call to
$getNextFeature()
or fetch()
will read the requested feature(s), where
i
is an absolute index into the current result set. So, setting i = 3
would mean the next feature read with $getNextFeature()
would have been
the 4th feature read if sequential reading took place from the beginning of
the layer, including accounting for spatial and attribute filters.
This method is not implemented efficiently by all vector format drivers. The
default implementation simply resets reading to the beginning and then calls
GetNextFeature()
i
times.
To determine if fast seeking is available on the current layer, check
the FastSetNextByIndex
element in the list returned by the
$testCapability()
method. No return value, called for side effect.
$getFeature(fid)
Returns a feature by its identifier. The value of fid
must be a numeric
scalar, optionally carrying the bit64::integer64
class attribute.
Success or failure of this operation is unaffected by any spatial or
attribute filters that may be in effect.
The RandomRead
element in the list returned by $testCapability()
can
be checked to establish if this layer supports efficient random access
reading; however, the call should always work if the feature exists since a
fallback implementation just scans all the features in the layer looking for
the desired feature. Returns a list with the unique feature identifier (FID),
the attribute and geometry field names, and their values, or NULL
on
failure. Note that sequential reads (with $getNextFeature()
) are generally
considered interrupted by a call to $getFeature()
.
$resetReading()
Reset feature reading to start on the first feature. No return value, called
for that side effect.
$fetch(n)
Fetches the next n
features from the layer and returns them as a data
frame. This allows retrieving the entire set of features, one page of
features at a time, or the remaining features (from the current cursor
position). Returns a data frame with as many rows as features were fetched,
and as many columns as attribute plus geometry fields in the result set,
even if the result is a single value or has one or zero rows.
The returned data frame carries the OGRFeatureSet
class attribute with S3
methods for for print()
and plot()
.
This method is an analog of
DBI::dbFetch()
.
The n
argument is the maximum number of features to retrieve per fetch
given as integer
or numeric
but assumed to be a whole number (will
be truncated). Use n = -1
or n = Inf
to retrieve all pending features
(resets reading to the first feature).
Otherwise, $fetch()
can be called multiple times to perform forward paging
from the current cursor position. Passing n = NA
is also supported and
returns the remaining features.
Fetching zero features is possible to retrieve the structure of the feature
set as a data frame (columns fully typed).
OGR field types are returned as the following R types (NA
for OGR NULL
values):
OFTInteger
:integer
OFTInteger
subtypeOFSTBoolean
:logical
OFTIntegerList
: vector ofinteger
(list column)OFTInteger64
:numeric
carrying"integer64"
class attribute {bit64}OFTInteger64
subtypeOFSTBoolean
:logical
OFTInteger64List
: vector ofbit64::integer64
(list column)OFTReal
:numeric
OFTRealList
: vector ofnumeric
(list column)OFTString
:character
stringOFTStringList
: vector ofcharacter
strings (list column)OFTDate
: class"Date"
(numeric
)OFTDateTime
: class"POSIXct"
(numeric
, millisecond accuracy)OFTTime
:character
string ("HH:MM:SS"
)OFTBinary
:raw
vector (list column,NULL
entries for OGR NULL values)
Geometries are not returned if the field returnGeomAs
is set to NONE
.
Omitting the geometries may be beneficial for performance and memory usage
when access only to feature attributes is needed. Geometries are returned
as raw
vectors in a data frame list column when returnGeomAs
is set to
WKB
(the default) or WKB_ISO
, or as character
strings when
returnGeomAs
is set to one of WKT
or WKT_ISO
.
Note that $getFeatureCount()
is called internally when fetching the full
feature set or all remaining features (but not for a page of features).
$setFeature(feature)
Rewrites/replaces an existing feature. This method writes a feature based on
the feature id within the input feature. The feature
argument is a named
list of fields and their values, and must include a $FID
element
referencing the existing feature to rewrite. The RandomWrite
element in
the list returned by $testCapability()
can be checked to establish if this
layer supports random access writing via $setFeature()
.
The way omitted fields in the passed feature
are processed is driver
dependent:
SQL-based drivers which implement set feature through SQL UPDATE will skip unset fields, and thus the content of the existing feature will be preserved.
The shapefile driver will write a NULL value in the DBF file.
The GeoJSON driver will take into account unset fields to remove the corresponding JSON member.
Returns logical TRUE
upon successful completion, or FALSE
if setting the
feature did not succeed. The FID of the last feature written to the layer
may be obtained with the method $getLastWriteFID()
(see below). To set a
feature, but create it if it doesn't exist see the $upsertFeature()
method.
$createFeature(feature)
Creates and writes a new feature within the layer. The feature
argument is
a named list of fields and their values.
The passed feature is written to the layer as a new feature, rather than
overwriting an existing one. If the feature has a $FID
element other than
NA
, then the vector format driver may use that as the feature id of the
new feature, but not necessarily. The FID of the last feature written
to the layer may be obtained with the method $getLastWriteFID()
(see
below).
Returns logical TRUE
upon successful completion, or FALSE
if creating
the feature did not succeed. To create a feature, but set it if it already
exists see the $upsertFeature()
method.
$upsertFeature(feature)
Rewrites/replaces an existing feature or creates a new feature within the
layer. This method will write a feature to the layer, based on the feature
id within the input feature. The feature
argument is a named list of
fields and their values, potentially including a $FID
element referencing
an existing feature to rewrite. If the feature id doesn't exist a new
feature will be written. Otherwise, the existing feature will be rewritten.
The UpsertFeature
element in the list returned by $testCapability()
can
be checked to determine if this layer supports upsert writing. See
$setFeature()
above for a description of how omitted fields in the passed
feature
are processed.
Returns logical TRUE
upon successful completion, or FALSE
if upserting
the feature did not succeed. Requires GDAL >= 3.6.
$getLastWriteFID()
Returns the FID of the last feature written (either newly created or updated
existing). NULL
is returned if no features have been written in the layer.
Note that OGRNullFID (-1
) may be returned after writing a feature in some
formats. This is the case if a FID has not been assigned yet, and generally
does not indicate an error (e.g., formats that do not store a persistent FID
and assign FIDs upon a sequential read operation). The returned FID is a
numeric scalar carrying the bit64::integer64
class attribute.
$deleteFeature(fid)
Deletes a feature from the layer. The feature with the indicated feature ID
is deleted from the layer if supported by the format driver. The value of
fid
must be a numeric scalar, optionally carrying the bit64::integer64
class attribute (should be a whole number, will be truncated).
The DeleteFeature
element in the list returned by $testCapability()
can
be checked to establish if this layer has delete feature capability. Returns
logical TRUE
if the operation succeeds, or FALSE
on failure.
$syncToDisk()
Flushes pending changes to disk. This call is intended to force the layer to
flush any pending writes to disk, and leave the disk file in a consistent
state. It would not normally have any effect on read-only datasources. Some
formats do not implement this method, and will still return no error. An
error is only returned if an error occurs while attempting to flush to disk.
In any event, you should always close any opened datasource with $close()
which will ensure all data is correctly flushed. Returns logical TRUE
if
no error occurs (even if nothing is done) or FALSE
on error.
$startTransaction(force)
Creates a transaction if supported by the vector data source. The force
argument is a logical value. If force = FALSE
, only "efficient"
transactions will be attempted. Some drivers may offer an emulation of
transactions, but sometimes with significant overhead, in which case the
user must explicitly allow for such an emulation by setting force =TRUE
.
The function ogr_ds_test_cap()
can be used to determine whether a vector
data source supports efficient or emulated transactions.
All changes done after the start of the transaction are definitely applied
in the data source if $commitTransaction()
is called. They can be canceled
by calling rollbackTransaction()
instead.
Nested transactions are not supported. Transactions are implemented at the
dataset level, so multiple GDALVector
objects using the same data source
should not have transactions active at the same time.
In case $startTransaction()
fails, neither $commitTransaction()
nor
$rollbackTransaction()
should be called.
If an error occurs after a successful $startTransaction()
, the whole
transaction may or may not be implicitly canceled, depending on the format
driver (e.g., the PostGIS driver will cancel it, SQLite/GPKG will not). In
any case, in the event of an error, an explicit call to
rollbackTransaction()
should be done to keep things balanced.
Returns logical TRUE
if the transaction is created, or FALSE
on failure.
$commitTransaction()
Commits a transaction if supported by the vector data source.
Returns a logical value, TRUE
if the transaction is successfully committed.
Returns FALSE
if no transaction is active, or the rollback fails, or if the
data source does not support transactions.
Depending on the format driver, this may or may not abort layer sequential
reading that may be active.
$rollbackTransaction()
Rolls back a data source to its state before the start of the current
transaction, if transactions are supported by the data source.
Returns a logical value, TRUE
if the transaction is successfully rolled
back. Returns FALSE
if no transaction is active, or the rollback fails,
or if the data source does not support transactions.
$getMetadata()
Returns a character vector of all metadata NAME=VALUE
pairs for the
layer or empty string (""
) if there are no metadata items.
$setMetadata(metadata)
Sets metadata on the layer if the format supports it. The metadata
argument is given as a character vector of NAME=VALUE
pairs.
Returns logical TRUE
on success or FALSE
if metadata could
not be set.
$getMetadataItem(mdi_name)
Returns the value of a specific metadata item named mdi_name
, or empty
string (""
) if no matching item is found.
$close()
Closes the vector dataset (no return value, called for side effects).
Calling $close()
results in proper cleanup, and flushing of any
pending writes.
The GDALVector
object is still available after calling $close()
.
The layer can be re-opened on the existing dsn
with
$open(read_only = {TRUE|FALSE})
.
See also
ogr_define, ogr_manage, ogr2ogr()
, ogrinfo()
GDAL vector format descriptions:
https://gdal.org/drivers/vector/index.html
GDAL-supported SQL dialects:
https://gdal.org/user/ogr_sql_sqlite_dialect.html)
Examples
## MTBS fire perimeters in Yellowstone National Park 1984-2022
f <- system.file("extdata/ynp_fires_1984_2022.gpkg", package = "gdalraster")
## copy to a temporary file that is writeable
dsn <- file.path(tempdir(), basename(f))
file.copy(f, dsn)
#> [1] TRUE
lyr <- new(GDALVector, dsn, "mtbs_perims")
## object of class GDALVector
lyr
#> C++ object <0x55b38c5ca370> of class 'GDALVector' <0x55b389d251e0>
str(lyr)
#> Reference class 'Rcpp_GDALVector' [package "gdalraster"] with 8 fields
#> $ defaultGeomFldName: chr "geometry"
#> $ m_dialect : chr ""
#> $ m_is_sql : logi FALSE
#> $ m_layer_name : chr "mtbs_perims"
#> $ promoteToMulti : logi FALSE
#> $ quiet : logi FALSE
#> $ returnGeomAs : chr "WKB"
#> $ wkbByteOrder : chr "LSB"
#> and 66 methods, of which 52 are possibly relevant:
#> OGRFeatureFromList_dumpReadble, bbox, clearSpatialFilter, close,
#> commitTransaction, createFeature, deleteFeature, fetch, finalize,
#> getAttributeFilter, getDriverLongName, getDriverShortName, getDsn,
#> getFIDColumn, getFeature, getFeatureCount, getFieldNames, getFileList,
#> getGeomType, getGeometryColumn, getLastWriteFID, getLayerDefn, getMetadata,
#> getMetadataItem, getName, getNextFeature, getSpatialFilter, getSpatialRef,
#> initialize, isOpen, layerClip, layerErase, layerIdentity, layerIntersection,
#> layerSymDifference, layerUnion, layerUpdate, open, resetReading,
#> rollbackTransaction, setAttributeFilter, setFeature, setIgnoredFields,
#> setMetadata, setNextByIndex, setSelectedFields, setSpatialFilter,
#> setSpatialFilterRect, startTransaction, syncToDisk, testCapability,
#> upsertFeature
## dataset info
lyr$getDriverShortName()
#> [1] "GPKG"
lyr$getDriverLongName()
#> [1] "GeoPackage"
lyr$getFileList()
#> [1] "/tmp/Rtmp9tfQ6k/ynp_fires_1984_2022.gpkg"
## layer info
lyr$getName()
#> [1] "mtbs_perims"
lyr$getGeomType()
#> [1] "MULTIPOLYGON"
lyr$getGeometryColumn()
#> [1] "geom"
lyr$getFIDColumn()
#> [1] "fid"
lyr$getSpatialRef()
#> [1] "PROJCS[\"NAD83 / Montana\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"latitude_of_origin\",44.25],PARAMETER[\"central_meridian\",-109.5],PARAMETER[\"standard_parallel_1\",49],PARAMETER[\"standard_parallel_2\",45],PARAMETER[\"false_easting\",600000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"32100\"]]"
lyr$bbox()
#> [1] 469685.73 -12917.76 573531.72 96577.34
## layer capabilities
lyr$testCapability()
#> $RandomRead
#> [1] TRUE
#>
#> $SequentialWrite
#> [1] FALSE
#>
#> $RandomWrite
#> [1] FALSE
#>
#> $FastSpatialFilter
#> [1] TRUE
#>
#> $FastFeatureCount
#> [1] TRUE
#>
#> $FastGetExtent
#> [1] TRUE
#>
#> $FastSetNextByIndex
#> [1] FALSE
#>
#> $CreateField
#> [1] FALSE
#>
#> $CreateGeomField
#> [1] FALSE
#>
#> $DeleteField
#> [1] FALSE
#>
#> $ReorderFields
#> [1] FALSE
#>
#> $AlterFieldDefn
#> [1] FALSE
#>
#> $IgnoreFields
#> [1] TRUE
#>
#> $DeleteFeature
#> [1] FALSE
#>
#> $StringsAsUTF8
#> [1] TRUE
#>
#> $CurveGeometries
#> [1] TRUE
#>
## re-open with write access
lyr$open(read_only = FALSE)
lyr$testCapability()$SequentialWrite
#> [1] TRUE
lyr$testCapability()$RandomWrite
#> [1] TRUE
## feature class definition - a list of field names and their definitions
defn <- lyr$getLayerDefn()
names(defn)
#> [1] "event_id" "incid_name" "incid_type" "map_id" "burn_bnd_ac"
#> [6] "burn_bnd_lat" "burn_bnd_lon" "ig_date" "ig_year" "geom"
str(defn)
#> List of 10
#> $ event_id :List of 8
#> ..$ type : chr "OFTString"
#> ..$ subtype : chr "OFSTNone"
#> ..$ width : int 254
#> ..$ precision : int 0
#> ..$ is_nullable: logi TRUE
#> ..$ is_unique : logi FALSE
#> ..$ default : chr ""
#> ..$ is_geom : logi FALSE
#> $ incid_name :List of 8
#> ..$ type : chr "OFTString"
#> ..$ subtype : chr "OFSTNone"
#> ..$ width : int 254
#> ..$ precision : int 0
#> ..$ is_nullable: logi TRUE
#> ..$ is_unique : logi FALSE
#> ..$ default : chr ""
#> ..$ is_geom : logi FALSE
#> $ incid_type :List of 8
#> ..$ type : chr "OFTString"
#> ..$ subtype : chr "OFSTNone"
#> ..$ width : int 254
#> ..$ precision : int 0
#> ..$ is_nullable: logi TRUE
#> ..$ is_unique : logi FALSE
#> ..$ default : chr ""
#> ..$ is_geom : logi FALSE
#> $ map_id :List of 8
#> ..$ type : chr "OFTInteger64"
#> ..$ subtype : chr "OFSTNone"
#> ..$ width : int 0
#> ..$ precision : int 0
#> ..$ is_nullable: logi TRUE
#> ..$ is_unique : logi FALSE
#> ..$ default : chr ""
#> ..$ is_geom : logi FALSE
#> $ burn_bnd_ac :List of 8
#> ..$ type : chr "OFTInteger64"
#> ..$ subtype : chr "OFSTNone"
#> ..$ width : int 0
#> ..$ precision : int 0
#> ..$ is_nullable: logi TRUE
#> ..$ is_unique : logi FALSE
#> ..$ default : chr ""
#> ..$ is_geom : logi FALSE
#> $ burn_bnd_lat:List of 8
#> ..$ type : chr "OFTString"
#> ..$ subtype : chr "OFSTNone"
#> ..$ width : int 10
#> ..$ precision : int 0
#> ..$ is_nullable: logi TRUE
#> ..$ is_unique : logi FALSE
#> ..$ default : chr ""
#> ..$ is_geom : logi FALSE
#> $ burn_bnd_lon:List of 8
#> ..$ type : chr "OFTString"
#> ..$ subtype : chr "OFSTNone"
#> ..$ width : int 10
#> ..$ precision : int 0
#> ..$ is_nullable: logi TRUE
#> ..$ is_unique : logi FALSE
#> ..$ default : chr ""
#> ..$ is_geom : logi FALSE
#> $ ig_date :List of 8
#> ..$ type : chr "OFTDate"
#> ..$ subtype : chr "OFSTNone"
#> ..$ width : int 0
#> ..$ precision : int 0
#> ..$ is_nullable: logi TRUE
#> ..$ is_unique : logi FALSE
#> ..$ default : chr ""
#> ..$ is_geom : logi FALSE
#> $ ig_year :List of 8
#> ..$ type : chr "OFTInteger"
#> ..$ subtype : chr "OFSTNone"
#> ..$ width : int 0
#> ..$ precision : int 0
#> ..$ is_nullable: logi TRUE
#> ..$ is_unique : logi FALSE
#> ..$ default : chr ""
#> ..$ is_geom : logi FALSE
#> $ geom :List of 4
#> ..$ type : chr "MULTIPOLYGON"
#> ..$ srs : chr "PROJCS[\"NAD83 / Montana\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,2"| __truncated__
#> ..$ is_nullable: logi TRUE
#> ..$ is_geom : logi TRUE
## default value of the read/write field 'returnGeomAs'
lyr$returnGeomAs
#> [1] "WKB"
lyr$getFeatureCount()
#> [1] 61
## sequential read cursor
feat <- lyr$getNextFeature()
# a list of field names and their values, with class attribute `OGRFeature`
feat
#> OGR feature
#> $FID
#> integer64
#> [1] 1
#>
#> $event_id
#> [1] WY4413411069519870807
#>
#> $incid_name
#> [1] POLECAT
#>
#> $incid_type
#> [1] Wildfire
#>
#> $map_id
#> integer64
#> [1] 10015934
#>
#> $burn_bnd_ac
#> integer64
#> [1] 1093
#>
#> $burn_bnd_lat
#> [1] 44.132
#>
#> $burn_bnd_lon
#> [1] -110.696
#>
#> $ig_date
#> [1] 1987-08-07
#>
#> $ig_year
#> [1] 1987
#>
#> $geom
#> [1] WKB MULTIPOLYGON: raw 01 06 00 00 ...
#>
## set an attribute filter
lyr$setAttributeFilter("ig_year = 2020")
lyr$getFeatureCount()
#> [1] 1
feat <- lyr$getNextFeature()
plot(feat)
## NULL when no more features are available
lyr$getNextFeature()
#> NULL
## reset reading to the start
lyr$resetReading()
lyr$getNextFeature()
#> OGR feature
#> $FID
#> integer64
#> [1] 61
#>
#> $event_id
#> [1] WY4438911082120200822
#>
#> $incid_name
#> [1] LONE STAR
#>
#> $incid_type
#> [1] Wildfire
#>
#> $map_id
#> integer64
#> [1] 10020495
#>
#> $burn_bnd_ac
#> integer64
#> [1] 3348
#>
#> $burn_bnd_lat
#> [1] 44.4
#>
#> $burn_bnd_lon
#> [1] -110.782
#>
#> $ig_date
#> [1] 2020-08-22
#>
#> $ig_year
#> [1] 2020
#>
#> $geom
#> [1] WKB MULTIPOLYGON: raw 01 06 00 00 ...
#>
## clear the attribute filter
lyr$setAttributeFilter("")
lyr$getFeatureCount()
#> [1] 61
## set a spatial filter
## get the bounding box of the largest 1988 fire and use as spatial filter
## first set a temporary attribute filter to do the lookup
lyr$setAttributeFilter("ig_year = 1988 ORDER BY burn_bnd_ac DESC")
feat <- lyr$getNextFeature()
feat
#> OGR feature
#> $FID
#> integer64
#> [1] 7
#>
#> $event_id
#> [1] WY4470811082119880722
#>
#> $incid_name
#> [1] NORTH FORK
#>
#> $incid_type
#> [1] Wildfire
#>
#> $map_id
#> integer64
#> [1] 10014217
#>
#> $burn_bnd_ac
#> integer64
#> [1] 563527
#>
#> $burn_bnd_lat
#> [1] 44.678
#>
#> $burn_bnd_lon
#> [1] -110.716
#>
#> $ig_date
#> [1] 1988-07-22
#>
#> $ig_year
#> [1] 1988
#>
#> $geom
#> [1] WKB MULTIPOLYGON: raw 01 06 00 00 ...
#>
bbox <- g_wk2wk(feat$geom) |> bbox_from_wkt()
## set spatial filter on the full layer
lyr$setAttributeFilter("") # clears
lyr$setSpatialFilterRect(bbox)
lyr$getFeatureCount()
#> [1] 40
## fetch in chunks and return as data frame (class `OGRFeatureSet`)
feat_set <- lyr$fetch(20)
head(feat_set)
#> OGR feature set
#> FID event_id incid_name incid_type map_id
#> 1 38 MT4471311115120070627 MADISON ARM Wildfire 16113
#> 2 7 WY4470811082119880722 NORTH FORK Wildfire 10014217
#> 3 32 MT4491211108020030820 RATHBONE Wildfire 13014
#> 4 25 WY4433011103020000816 SPRUCE COMPLEX (PLATEAU) Wildfire 10014141
#> 5 6 WY4499211096519880625 FAN Wildland Fire Use 10014215
#> 6 40 MT4502711102920070720 OWL Wildfire 16428
#> burn_bnd_ac burn_bnd_lat burn_bnd_lon ig_date ig_year
#> 1 3564 44.713 -111.151 2007-06-27 2007
#> 2 563527 44.678 -110.716 1988-07-22 1988
#> 3 2701 44.912 -111.080 2003-08-20 2003
#> 4 2808 44.329 -111.027 2000-08-16 2000
#> 5 20422 44.994 -110.976 1988-06-25 1988
#> 6 2175 45.027 -111.029 2007-07-20 2007
#> geom
#> 1 WKB MULTIPOLYGON: raw 01 06 00 00 ...
#> 2 WKB MULTIPOLYGON: raw 01 06 00 00 ...
#> 3 WKB MULTIPOLYGON: raw 01 06 00 00 ...
#> 4 WKB MULTIPOLYGON: raw 01 06 00 00 ...
#> 5 WKB MULTIPOLYGON: raw 01 06 00 00 ...
#> 6 WKB MULTIPOLYGON: raw 01 06 00 00 ...
plot(feat_set)
## the next chunk
feat_set <- lyr$fetch(20)
nrow(feat_set)
#> [1] 20
## no features remaining
feat_set <- lyr$fetch(20)
nrow(feat_set)
#> [1] 0
str(feat_set) # 0-row data frame with columns typed
#> Classes ‘OGRFeatureSet’ and 'data.frame': 0 obs. of 11 variables:
#> $ FID :integer64
#> $ event_id : chr
#> $ incid_name : chr
#> $ incid_type : chr
#> $ map_id :integer64
#> $ burn_bnd_ac :integer64
#> $ burn_bnd_lat: chr
#> $ burn_bnd_lon: chr
#> $ ig_date : 'Date' num(0)
#> $ ig_year : int
#> $ geom : list()
#> - attr(*, "gis")=List of 5
#> ..$ type : chr "vector"
#> ..$ geom_column : chr "geom"
#> ..$ geom_col_type: chr "MULTIPOLYGON"
#> ..$ geom_col_srs : chr "PROJCS[\"NAD83 / Montana\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,2"| __truncated__
#> ..$ geom_format : chr "WKB"
## fetch all pending features
feat_set <- lyr$fetch(-1) # resets reading to the first feature
nrow(feat_set)
#> [1] 40
plot(feat_set)
lyr$clearSpatialFilter()
lyr$getFeatureCount()
#> [1] 61
lyr$close()
## simple example for feature write methods showing use of various data types
## create and write to a new layer in a GeoPackage data source
dsn2 <- tempfile(fileext = ".gpkg")
## define a feature class
defn <- ogr_def_layer("POINT", srs = epsg_to_wkt(4326))
## add field definitions
defn$unique_int <- ogr_def_field("OFTInteger", is_nullable = FALSE,
is_unique = TRUE)
defn$bool_data <- ogr_def_field("OFTInteger", fld_subtype = "OFSTBoolean")
defn$large_ints <- ogr_def_field("OFTInteger64")
defn$doubles <- ogr_def_field("OFTReal")
defn$strings <- ogr_def_field("OFTString", fld_width = 50)
defn$dates <- ogr_def_field("OFTDate")
defn$dt_modified <- ogr_def_field("OFTDateTime",
default_value = "CURRENT_TIMESTAMP")
defn$blobs <- ogr_def_field("OFTBinary")
ogr_ds_create("GPKG", dsn2, "test_layer", layer_defn = defn)
#> [1] TRUE
lyr <- new(GDALVector, dsn2, "test_layer", read_only = FALSE)
# lyr$getLayerDefn() |> str()
## define a feature to write
feat1 <- list()
## $FID is omitted since it is assigned when written (could also be NA)
## $dt_modified is omitted since the datasource sets a default timestamp
feat1$unique_int <- 1001
feat1$bool_data <- TRUE
## passing a string to as.integer64()
## this value is too large to be represented exactly as R numeric (double)
feat1$large_ints <- bit64::as.integer64("90071992547409910")
feat1$doubles <- 1.234
feat1$strings <- "A test string"
feat1$dates <- as.Date("2024-01-01")
feat1$blobs <- charToRaw("A binary object")
feat1$geom <- "POINT (1 1)" # can be a WKT string or raw vector of WKB
## create as a new feature in the layer
lyr$createFeature(feat1)
#> [1] TRUE
## the assigned FID
lyr$getLastWriteFID()
#> integer64
#> [1] 1
## this fails due to the unique constraint
lyr$createFeature(feat1)
#> [1] FALSE
feat2 <- list()
feat2$unique_int <- 1002
feat2$bool_data <- FALSE
feat2$large_ints <- bit64::as.integer64("90071992547409920")
feat2$doubles <- 2.345
feat2$strings <- "A test string 2"
feat2$dates <- as.Date("2024-01-02")
feat2$blobs <- charToRaw("A binary object 2")
feat2$geom <- "POINT (2 2)"
lyr$createFeature(feat2)
#> [1] TRUE
lyr$getLastWriteFID()
#> integer64
#> [1] 2
## close and re-open as a read-only layer
lyr$open(read_only = TRUE)
lyr$getFeatureCount()
#> [1] 2
feat_set <- lyr$fetch(-1) # -1 for all features reading from start
str(feat_set)
#> Classes ‘OGRFeatureSet’ and 'data.frame': 2 obs. of 10 variables:
#> $ FID :integer64 1 2
#> $ unique_int : int 1001 1002
#> $ bool_data : logi TRUE FALSE
#> $ large_ints :integer64 90071992547409910 90071992547409920
#> $ doubles : num 1.23 2.35
#> $ strings : chr "A test string" "A test string 2"
#> $ dates : Date, format: "2024-01-01" "2024-01-02"
#> $ dt_modified: POSIXct, format: "2024-12-07 02:04:27" "2024-12-07 02:04:27"
#> $ blobs :List of 2
#> ..$ : raw 41 20 62 69 ...
#> ..$ : raw 41 20 62 69 ...
#> $ geom :List of 2
#> ..$ : raw 01 01 00 00 ...
#> ..$ : raw 01 01 00 00 ...
#> - attr(*, "gis")=List of 5
#> ..$ type : chr "vector"
#> ..$ geom_column : chr "geom"
#> ..$ geom_col_type: chr "POINT"
#> ..$ geom_col_srs : chr "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AU"| __truncated__
#> ..$ geom_format : chr "WKB"
## edit an existing feature, e.g., feat <- lyr$getFeature(2)
## here we copy a row of the data frame returned by lyr$fetch() above
feat <- feat_set[2,]
str(feat)
#> Classes ‘OGRFeatureSet’ and 'data.frame': 1 obs. of 10 variables:
#> $ FID :integer64 2
#> $ unique_int : int 1002
#> $ bool_data : logi FALSE
#> $ large_ints :integer64 90071992547409920
#> $ doubles : num 2.35
#> $ strings : chr "A test string 2"
#> $ dates : Date, format: "2024-01-02"
#> $ dt_modified: POSIXct, format: "2024-12-07 02:04:27"
#> $ blobs :List of 1
#> ..$ : raw 41 20 62 69 ...
#> $ geom :List of 1
#> ..$ : raw 01 01 00 00 ...
#> - attr(*, "gis")=List of 5
#> ..$ type : chr "vector"
#> ..$ geom_column : chr "geom"
#> ..$ geom_col_type: chr "POINT"
#> ..$ geom_col_srs : chr "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AU"| __truncated__
#> ..$ geom_format : chr "WKB"
Sys.sleep(1) # only to ensure a timestamp difference
feat$bool_data <- TRUE
feat$strings <- paste(feat$strings, "- edited")
feat$dt_modified <- Sys.time()
feat$geom <- "POINT (2.001 2.001)"
lyr$open(read_only = FALSE)
## lyr$setFeature() re-writes the feature identified by the $FID element
## N.B., all fields are re-written:
## any fields omitted from the input feature, or set to NA, will be
## re-written as OGR NULL
lyr$setFeature(feat)
#> [1] TRUE
lyr$open(read_only = TRUE)
lyr$getFeatureCount()
#> [1] 2
lyr$returnGeomAs <- "WKT"
feat_set <- lyr$fetch(-1)
str(feat_set)
#> Classes ‘OGRFeatureSet’ and 'data.frame': 2 obs. of 10 variables:
#> $ FID :integer64 1 2
#> $ unique_int : int 1001 1002
#> $ bool_data : logi TRUE TRUE
#> $ large_ints :integer64 90071992547409910 90071992547409920
#> $ doubles : num 1.23 2.35
#> $ strings : chr "A test string" "A test string 2 - edited"
#> $ dates : Date, format: "2024-01-01" "2024-01-02"
#> $ dt_modified: POSIXct, format: "2024-12-07 02:04:27" "2024-12-07 02:04:28"
#> $ blobs :List of 2
#> ..$ : raw 41 20 62 69 ...
#> ..$ : raw 41 20 62 69 ...
#> $ geom : chr "POINT (1 1)" "POINT (2.001 2.001)"
#> - attr(*, "gis")=List of 5
#> ..$ type : chr "vector"
#> ..$ geom_column : chr "geom"
#> ..$ geom_col_type: chr "POINT"
#> ..$ geom_col_srs : chr "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AU"| __truncated__
#> ..$ geom_format : chr "WKT"
lyr$close()