GeoPackage-高级

介绍

创建和读取GeoPackage有几种不同的方法。大多数实现软件产品都有自己独特的方式来支持GeoPackage的处理。在本章中,我们将展示如何使用免费的开源GeoPackage Java库来读取GeoPackage here .

为了便于参考,我们复制了下面的GeoPackag 模式概述。

../../_images/geopackage-overview.png

这个 gpkg_spatial_ref_sys 表包含坐标参考系定义,这些定义用于将用户表中的矢量和平铺数据引用到地球上的位置。

这个 gpkg_contents 表提供了GeoPackage中所有地理空间内容的列表,以允许应用程序识别和描述可供访问和/或更新的地理空间数据。

这个 gpkg_geometry_columns 表指定包含要素的用户数据表支持的几何图形类型。

这个 gpkg_tile_matrix_set 表提供了标识GeoPackage中包含的每个平铺金字塔用户数据表的记录。

这个 gpkg_tile_matrix 表记录了每个平铺表中每个缩放级别的平铺矩阵的结构。

这个 gpkg_extensions GeoPackage中的表或可更新视图用于指示特定扩展应用于GeoPackage、GeoPackage中的表或GeoPackage中表的列。

这个 gpkg_data_columns table存储了feature和tile matrix数据表模式的最小描述,这些数据表补充了SQLite SQLite_master table和pragma table_info(table_name)SQL函数提供的数据。

这个 gpkg_data_column_constraints 表包含用于指定对基本数据类型列值的限制的数据。

这个 gpkg_metadata 表允许在GeoPackage中存储元数据。

这个 gpkg_metadata_reference 表将存储在gpkg_元数据中的元数据记录与存储在GeoPackage中的要素和分片数据相关联。

为什么GeoPackage有这些表?

GeoPackage标准实现了OGC OpenGIS®简单要素接口标准(SFS),该标准为应用程序在关系数据库或对象关系数据库中存储和访问要素数据提供了一种通用方法。在这方面起关键作用的特定表是 gpkg_geometry_columnsgpkg_spatial_ref_sysgpkg_contents 以及包含要素属性的用户命名表。通过GeoPackage使用SFS,可以实现GeoPackage标准,从而利用寄存器(如 EPSG Geodetic Parameter Registry。通过GeoPackage使用SFS还可以使GeoPackage与使用SFS的其他格式(例如OGC地理标记语言(GML))进行互操作。这意味着数据可以在GeoPackage和其他基于SFS的格式之间交换,而信息丢失最小或没有损失,因为数据模型基于一个共同的特征模型。

GeoPackage标准采用基于瓷砖的金字塔结构,以多种分辨率存储图像和栅格地图。下图显示了这种结构。在这些数据的存储中起关键作用的特定表包括 gpkg_tile_matrix_setgpkg_tile_matrixgpkg_contents 以及一个用户命名的表,其中包含实际的二进制编码分片。这种基于平铺的金字塔结构在处理小型或受限设备(如移动电话、平板电脑或笔记本电脑)上的GeoPackage时特别有用,因为可以根据缩放级别和设备屏幕大小选择适当的分辨率。

../../_images/pyramid.png

使用NGA GeoPackage Java库

开源NGA GeoPackage Java库的设计目的是紧密地抽象GeoPackage的表。该库为在GeoPackage中找到的每个核心表提供一个数据访问对象(DAO)。

可以从DAO实例访问特性和分片,并对其进行查询以提取元数据或特性属性。下面的代码块显示了一个程序的注释示例,该程序读取两个独立的GeoPackage,一个包含矢量特征,另一个包含图像块。源代码改编自 GeoPackage Java library website。注意,该示例使用states10.gpkg和蓝大理石.gpkg示例文件。这两个文件都可以从 here

package org.opengeospatial.GeoPackageDemo;

import java.io.File;
import java.util.List;
import mil.nga.geopackage.GeoPackage;
import mil.nga.geopackage.core.contents.ContentsDao;
import mil.nga.geopackage.core.srs.SpatialReferenceSystemDao;
import mil.nga.geopackage.extension.ExtensionsDao;
import mil.nga.geopackage.features.columns.GeometryColumnsDao;
import mil.nga.geopackage.features.user.FeatureDao;
import mil.nga.geopackage.features.user.FeatureResultSet;
import mil.nga.geopackage.features.user.FeatureRow;
import mil.nga.geopackage.geom.GeoPackageGeometryData;
import mil.nga.geopackage.io.GeoPackageTextOutput;
import mil.nga.geopackage.manager.GeoPackageManager;
import mil.nga.geopackage.metadata.MetadataDao;
import mil.nga.geopackage.metadata.reference.MetadataReferenceDao;
import mil.nga.geopackage.schema.columns.DataColumnsDao;
import mil.nga.geopackage.schema.constraints.DataColumnConstraintsDao;
import mil.nga.geopackage.tiles.matrix.TileMatrixDao;
import mil.nga.geopackage.tiles.matrixset.TileMatrixSetDao;
import mil.nga.geopackage.tiles.user.TileDao;
import mil.nga.geopackage.tiles.user.TileResultSet;
import mil.nga.geopackage.tiles.user.TileRow;
import mil.nga.wkb.geom.Geometry;

/**
 * GeoPackage demonstration
 *
 */
public class App {

  /**
  * This method reads a GeoPackage file and prints out the contents to the console
  */
  public void read(File geopackageFile) {

          // Open a GeoPackage and create an handle to it
          GeoPackage geoPackage = GeoPackageManager.open(geopackageFile);

          // Create DAO instances of GeoPackage tables
          SpatialReferenceSystemDao srsDao = geoPackage.getSpatialReferenceSystemDao(); //accesses gpkg_spatial_ref_sys
          ContentsDao contentsDao = geoPackage.getContentsDao();   //accesses gpkg_contents
          GeometryColumnsDao geomColumnsDao = geoPackage.getGeometryColumnsDao();  //accesses gpkg_geometry_columns
          TileMatrixSetDao tileMatrixSetDao = geoPackage.getTileMatrixSetDao();  //accesses gpkg_tile_matrix_set
          TileMatrixDao tileMatrixDao = geoPackage.getTileMatrixDao();   //accesses gpkg_tile_matrix
          DataColumnsDao dataColumnsDao = geoPackage.getDataColumnsDao();  //accesses gpkg_data_columns
          DataColumnConstraintsDao dataColumnConstraintsDao = geoPackage.getDataColumnConstraintsDao(); //accesses gpkg_data_columns_constraints
          MetadataDao metadataDao = geoPackage.getMetadataDao(); //accesses gpkg_metadata
          MetadataReferenceDao metadataReferenceDao = geoPackage.getMetadataReferenceDao();  //accesses gpkg_metadata_reference
          ExtensionsDao extensionsDao = geoPackage.getExtensionsDao(); //accesses gpkg_extensions

          // Feature and tile tables
          List<String> features = geoPackage.getFeatureTables();
          List<String> tiles = geoPackage.getTileTables();

          // If there are any features print their properties (as represented by column names and values)
          if (features.size() > 0) {
                  FeatureDao featureDao = geoPackage.getFeatureDao(features.get(0));
                  FeatureResultSet featureResultSet = featureDao.queryForAll();
                  try {
                          while (featureResultSet.moveToNext()) {
                                  FeatureRow featureRow = featureResultSet.getRow();
                                  String[] columnNames = featureRow.getColumnNames();
                                  for(String columnName: columnNames)
                                  {
                                          if(featureRow.getColumn(columnName).isGeometry())
                                                  System.out.println(featureRow.getGeometry().toString());
                                          else
                                                  System.out.println(featureRow.getColumn(columnName).getName()+"="+featureRow.getValue(columnName));
                                  }


                          }
                  } finally {
                          featureResultSet.close();
                  }

          }

          // If there are any tiles in the GeoPackage, then print out information about the tile tables
          if (tiles.size() > 0) {

                  TileDao tileDao = geoPackage.getTileDao(tiles.get(0));
                  TileResultSet tileResultSet = tileDao.queryForAll();

                  //Now print out descriptions of the tiles
                  StringBuilder output = new StringBuilder();
                  GeoPackageTextOutput textOutput = new GeoPackageTextOutput(
                                  geoPackage);
                  output.append("\n\n");
                  output.append(textOutput.header());
                  output.append("\n\n");
                  output.append(textOutput.tileTable(geoPackage.getTileTables().get(0)));
                  System.out.println(output);
          }

          // Close the database when done
    System.out.println("Done!");
          geoPackage.close();

  }

  /*
   * This is the main method. It creates an array of two GeoPackage files, one consisting of vector feature data and another consisting of imagery tile data.
   */
  public static void main(String[] args) {

          //Create an array of two GeoPackage files.
          File[] existingGeoPackages = new File[2];
          existingGeoPackages[0] = new File("/Users/Shared/states10.gpkg");
          existingGeoPackages[1] = new File("/Users/Shared/bluemarble.gpkg");

          //Pass each of the files in the array to the read() method for reading
          App app = new App();
          for(File existingGeoPackage: existingGeoPackages){
                  app.read(existingGeoPackage);
          }

  }

}

当程序运行时,它打印出特征和分片数据集,包括特征属性和分片矩阵描述。

要运行此程序,请创建一个Maven项目并将以下依赖项添加到Maven项目的配置文件中。这将允许从Maven中央存储库中提取库依赖项。可以找到创建Maven项目的快速入门指南 here

<dependency>
    <groupId>mil.nga.geopackage</groupId>
    <artifactId>geopackage</artifactId>
    <version>1.3.1</version>
</dependency>

使用GDAL/OGR库

访问GeoPackage还有其他方法,包括使用其他prorging语言和库。提供这种功能的软件库之一是免费的开源地理空间数据抽象层(GDAL)及其向量工具包OGR。GDAL提供了C、C++和Python绑定,允许它被导入各种应用程序。

要在Windows、Linux或macosx上构建和安装GDAL,可以从 here

为了快速入门,在安装QGIS的过程中还安装了GDAL1.11。

下面是一个使用gdal1.11读取GeoPackage的Python脚本示例。源代码改编自 here。当程序运行时,它会打印出特征属性的值。

import sys
import ogr
# First open a handle on the GeoPackage.
ds = ogr.Open( "/home/ogckm/Downloads/states10.gpkg" )
# If the file handle is null then exit
if ds is None:
    print "Open failed.\n"
    sys.exit( 1 )
# Select the dataset to retrieve from the GeoPackage and assign it to an layer instance called lyr.
# The names of available datasets can be found in the gpkg_contents table.
lyr = ds.GetLayerByName( "statesQGIS" )
# Refresh the reader
lyr.ResetReading()
# for each feature in the layer, print the feature properties
for feat in lyr:

    feat_defn = lyr.GetLayerDefn()
    # for each non-geometry feature property, print its value
    for i in range(feat_defn.GetFieldCount()):
        field_defn = feat_defn.GetFieldDefn(i)

        if field_defn.GetType() == ogr.OFTInteger:
            print "%d" % feat.GetFieldAsInteger(i)
        elif field_defn.GetType() == ogr.OFTReal:
            print "%.3f" % feat.GetFieldAsDouble(i)
        elif field_defn.GetType() == ogr.OFTString:
            print "%s" % feat.GetFieldAsString(i)
        else:
            print "%s" % feat.GetFieldAsString(i)
    # Confirm whether there is a geometry property
    geom = feat.GetGeometryRef()
    if geom is not None and geom.GetGeometryType() == ogr.wkbMultiPolygon:
        print "has a geometry property"
    print "\n"

ds = None

注意,gdal2.0使用一组不同的类来访问向量数据。我们在本例中使用了gdal1.11,因为它目前默认包含在Linux存储库中,而且还捆绑在QGIS中。