GeoPackage Support
Introduction
This document explains GeoTools' implementation of the GeoPackage standard, an open, standards-based, platform-independent, portable, self-contained data format for geospatial information. GeoPackage is an SQLite container that allows you to store both vector features and raster data tiles, making it a versatile format for geospatial applications.
GeoTools provides comprehensive support for reading from and writing to GeoPackage files, including handling of features (vector data), tiles (raster data), metadata, and various GeoPackage extensions.
- modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPackage.java
- modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPkgDialect.java
GeoPackage Architecture in GeoTools
GeoPackage support in GeoTools is implemented primarily through the geopkg module, which extends the JDBC framework with GeoPackage-specific handling.
Architecture Overview
Key Components
- GeoPkgDataStoreFactory: Creates instances of GeoPackage data stores
- GeoPackage: Main class for interacting directly with GeoPackage files
- GeoPkgDialect: Handles SQL translation, geometry encoding/decoding, and other SQLite-specific operations
- FeatureEntry/TileEntry: Metadata for feature and tile datasets
- Extensions: Support for standard GeoPackage extensions
- modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPkgDataStoreFactory.java
- modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPackage.java
- modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPkgDialect.java
GeoPackage Data Model
Standard Tables
The GeoPackage format defines several standard tables:
| Table | Purpose |
|---|---|
gpkg_contents | Lists all feature and tile datasets in the GeoPackage |
gpkg_spatial_ref_sys | Defines spatial reference systems |
gpkg_geometry_columns | Describes geometry columns in feature tables |
gpkg_tile_matrix_set | Defines the tile matrix set extent |
gpkg_tile_matrix | Defines parameters for each zoom level |
gpkg_extensions | Registers extensions used in the GeoPackage |
User Data Tables
Feature Tables: Store vector features with attributes and geometries
Tile Tables: Store tiled raster data with zoom levels, rows, and columns
modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPackage.java107-129
modules/plugin/geopkg/src/test/java/org/geotools/geopkg/GeoPackageTest.java143-148
Feature Support
Feature Reading and Writing
Feature Data Types
GeoTools provides specific handling for various data types in GeoPackage:
- Geometries: Full support for all OGC geometry types including 3D geometries
- Basic Types: Integer, Double, String, Boolean, etc.
- Date/Time: Support for Date, Time, and Timestamp data types
- Enumerations: Support for storing and retrieving enumerated values
- Arrays: Support for array types stored as JSON strings
Spatial Indexing
GeoTools implements the GeoPackage R-Tree spatial indexing extension for improved spatial query performance:
Creates an R-Tree virtual table in SQLite
Sets up triggers to maintain the index when data changes
Uses the index for spatial queries like bbox and intersections
modules/library/jdbc/src/main/java/org/geotools/jdbc/JDBCFeatureReader.java
modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPkgDialect.java
modules/plugin/geopkg/src/main/resources/org/geotools/geopkg/gpkg_spatial_index.sql
Tile Support
GeoTools supports reading and writing tiled raster data in GeoPackage through the GeoPackageReader and associated classes.
Tile Reading Pipeline
Zoom Levels and Resolution
GeoPackage organizes tiles in zoom levels with different resolutions. GeoTools provides methods to:
Select the appropriate zoom level based on requested resolution
Handle multiple zoom levels as internal overviews
Support different tile formats (PNG, JPEG) within the same dataset
modules/plugin/geopkg/src/main/java/org/geotools/geopkg/mosaic/GeoPackageReader.java
modules/plugin/geopkg/src/main/java/org/geotools/geopkg/TileMatrix.java
modules/plugin/geopkg/src/test/java/org/geotools/geopkg/mosaic/GeoPackageReaderTest.java
Extensions Support
GeoTools supports several GeoPackage extensions:
Spatial Index Extension
Implements the R-Tree spatial index extension for faster spatial queries on feature data. Spatial indexes are created using:
geoPackage.createSpatialIndex(featureEntry);Schema Extension
The schema extension provides additional metadata about columns and constraints, implemented through the GeoPkgSchemaExtension class:
- Column Descriptions: Add titles, descriptions, and MIME types to columns
- Constraints: Define enum values, ranges, or patterns for columns
- Enumeration Support: Map between stored codes and human-readable values
DataColumn dc = new DataColumn();
dc.setColumnName("enumProperty");
dc.setConstraint(new DataColumnConstraint.Enum("constraint_name", enumValues));
geopkg.getExtension(GeoPkgSchemaExtension.class).addDataColumn(tableName, dc, connection);- modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPkgSchemaExtension.java
- modules/plugin/geopkg/src/test/java/org/geotools/geopkg/GeoPkgEnumTest.java
Special Data Type Handling
Date and Time
GeoPackage stores date and time values as text strings in ISO-8601 format. GeoTools provides special handling for:
java.sql.Datefor DATE columnsjava.sql.Timestampfor DATETIME columnsjava.sql.Timefor TIME columns
The GeoPkgDialect ensures proper timezone handling when converting between SQLite strings and Java date objects.
Enumerations
GeoTools supports enumerated values through:
- Feature type options:
builder.options("one", "two", "three") - Explicit enumeration constraint via the schema extension
- Automatic conversion between stored codes and human-readable values
Arrays
GeoPackage doesn't natively support array types, but GeoTools implements array support by:
- Storing arrays as JSON strings in the database
- Setting MIME type to "application/json" in the schema extension
- Automatically converting between JSON and Java arrays
- modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPkgDialect.java663-721
- modules/plugin/geopkg/src/test/java/org/geotools/geopkg/GeoPkgDatetimeTest.java
- modules/plugin/geopkg/src/test/java/org/geotools/geopkg/GeoPkgEnumTest.java
- modules/plugin/geopkg/src/main/java/org/geotools/geopkg/JSONArrayIO.java
Filtering and Querying
GeoPackage supports standard GeoTools filtering capabilities through the GeoPkgFilterToSQL class, which translates Filter objects to SQL:
Spatial Filters
Spatial filters like BBOX and Intersects are optimized to use:
- Spatial indices when available
- Spatial functions (ST_MinX, ST_MaxX, etc.) as fallbacks
Attribute Filters
Full support for:
- Comparison filters (=, <, >, BETWEEN, LIKE)
- Logical filters (AND, OR, NOT)
- Special handling for date/time comparisons
Query Performance
GeoTools implements several optimizations for GeoPackage queries:
Spatial index utilization
Prepared statements
Connection pooling
Query limits and offsets
modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPkgFilterToSQL.java
modules/plugin/geopkg/src/main/java/org/geotools/geopkg/GeoPkgDialect.java796-854
Usage Examples
Reading Features from a GeoPackage
// Open a GeoPackage file
File file = new File("example.gpkg");
Map<String, Object> params = new HashMap<>();
params.put(GeoPkgDataStoreFactory.DBTYPE.key, "geopkg");
params.put(GeoPkgDataStoreFactory.DATABASE.key, file);
// Create the data store
DataStore dataStore = DataStoreFinder.getDataStore(params);
// Get feature source
String typeName = dataStore.getTypeNames()[0];
SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
// Read features
SimpleFeatureCollection features = featureSource.getFeatures();Writing Features to a GeoPackage
// Create a new GeoPackage file
File file = new File("new.gpkg");
GeoPackage geopkg = new GeoPackage(file);
geopkg.init();
// Create a feature entry
FeatureEntry entry = new FeatureEntry();
entry.setTableName("features");
entry.setSrid(4326);
entry.setBounds(new ReferencedEnvelope(-180, 180, -90, 90, CRS.decode("EPSG:4326")));
// Add features to the GeoPackage
geopkg.add(entry, featureCollection);
// Create a spatial index
geopkg.createSpatialIndex(entry);
geopkg.close();Reading Tiles
// Open a GeoPackage with tiles
GeoPackageReader reader = new GeoPackageReader(file, null);
// Set up parameters for reading
GridGeometry2D gg = new GridGeometry2D(
new GridEnvelope2D(new Rectangle(1000, 500)),
new ReferencedEnvelope(-180, 180, -90, 90, CRS.decode("EPSG:4326"))
);
ParameterValue<GridGeometry2D> param = AbstractGridFormat.READ_GRIDGEOMETRY2D.createValue();
param.setValue(gg);
// Read the tiles as a GridCoverage2D
GridCoverage2D coverage = reader.read("tile_layer", new GeneralParameterValue[] { param });- modules/plugin/geopkg/src/test/java/org/geotools/geopkg/GeoPackageTest.java
- modules/plugin/geopkg/src/test/java/org/geotools/geopkg/mosaic/GeoPackageReaderTest.java
Limitations and Considerations
- Version Compatibility: GeoTools implements the GeoPackage 1.2 specification
- Performance: For very large datasets, consider using spatial indexes
- Memory Usage: Tile reading can be memory-intensive for large areas
- SQLite Limitations: Remember SQLite's concurrent access limitations