LuciadCPillar support for GeoPackage

LuciadCPillar offers basic support for the decoding of GeoPackage data.

The GeoPackageModelDecoder::discoverTablesGeoPackageModelDecoder::discoverTablesGeoPackageModelDecoder::discoverTables method provides a list of all tables that you can decode in a GeoPackage file. You can then individually decode those tables with a second method call. That call depends on the data type in the tables.

Decoding features

For feature decoding details, see the GeoPackageModelDecoder::decodeGeoPackageModelDecoder::decodeGeoPackageModelDecoder::decode method documentation.

Decoding tiles

You can open GeoPackage files that contain tiles in a tile matrix set representing a quad tree. See the method documentation of GeoPackageModelDecoder::decodeGeoPackageModelDecoder::decodeGeoPackageModelDecoder::decode for details.

Decoding example

Program: Decoding GeoPackage data
const std::string source = "test/resources/Data/GeoPackage/states10.gpkg";
luciad::expected<std::vector<GeoPackageTableMetadata>, ErrorInfo> tablesExpected = GeoPackageModelDecoder::discoverTables(source, false);
if (!tablesExpected.has_value()) {
  std::cout << "Failed to load GeoPackage file " << source << ": " << tablesExpected.error().getMessage() << std::endl;
  return;
}

const std::vector<GeoPackageTableMetadata>& tables = tablesExpected.value();
std::cout << "The GeoPackage file contains " << tables.size() << " table(s):" << std::endl;

for (const GeoPackageTableMetadata& table : tables) {
  std::cout << " * Table '" << table.getName() << "' ";
  if (table.getType() == GeoPackageTableMetadata::typeFeatures()) {
    std::shared_ptr<GeoPackageDataSource> datasource = GeoPackageDataSource::newBuilder().source(source).tableName(table.getName()).build();
    luciad::expected<std::shared_ptr<Model>, ErrorInfo> modelExpected = GeoPackageModelDecoder::decode(datasource);
    if (modelExpected.has_value()) {
      auto model = std::dynamic_pointer_cast<IFeatureModel>(*modelExpected);
      if (model != nullptr) {
        uint32_t count = 0;
        auto callback = IFeatureQueryCallback::create([&](const Feature& /*f*/) {
          count++;
          return true;
        });
        model->query(FeatureQuery::all(), *callback);
        std::cout << "contains " << count << " features.";
      }
    } else {
      ErrorInfo errorInfo = modelExpected.error();
      std::cout << "could not be decoded: " << errorInfo.getMessage();
    }
  } else {
    std::cout << "contains raster data.";
  }
  std::cout << std::endl;
}
string source = @"test\resources\Data\GeoPackage\cities.gpkg";
try
{
    var tables = GeoPackageModelDecoder.DiscoverTables(source, false);
    Console.WriteLine("The GeoPackage file contains " + tables.Count + " table(s):");

    foreach (var table in tables)
    {
        Console.WriteLine(" * Table '" + table.Name + "'");
        if (GeoPackageTableMetadata.TypeFeatures == table.Type)
        {
            var dataSource = GeoPackageDataSource.NewBuilder()
                .Source(source)
                .TableName(table.Name)
                .Build();
            try
            {
                Model model = GeoPackageModelDecoder.Decode(dataSource);
                IFeatureModel featureModel = model as IFeatureModel;
                QueryCallbackCounter callback = new QueryCallbackCounter();
                featureModel.Query(FeatureQuery.All(), callback);
                Console.WriteLine("contains " + callback.Count + " features.");
            }
            catch (IOException e)
            {
                Console.WriteLine("could not be decoded: " + e.Message);
            }
        }
        else
        {
            Console.WriteLine("contains raster data.");
        }
    }
}
catch (IOException e)
{
    Console.WriteLine("Failed to load GeoPackage file " + source + ": " + e.Message);
}
String source = "test/resources/Data/GeoPackage/states10.gpkg";
try {
  List<GeoPackageTableMetadata> tables = GeoPackageModelDecoder.discoverTables(source, false);
  Log.i("gpkg", "The GeoPackage file contains " + tables.size() + " table(s):");

  for (GeoPackageTableMetadata table : tables) {
    Log.i("gpkg", " * Table '" + table.getName() + "' ");
    if (GeoPackageTableMetadata.TypeFeatures.equals(table.getType())) {
      GeoPackageDataSource datasource = GeoPackageDataSource.newBuilder()
                                                            .source(source)
                                                            .tableName(table.getName())
                                                            .build();
      try {
        Model model = GeoPackageModelDecoder.decode(datasource);
        if (model instanceof IFeatureModel) {
          IFeatureModel featureModel = (IFeatureModel) model;
          AtomicLong count = new AtomicLong(0);
          IFeatureQueryCallback callback = feature -> {
            count.incrementAndGet();
            return true;
          };
          featureModel.query(FeatureQuery.all(), callback);
          Log.i("gpkg", "contains " + count + " features.");
        }
      } catch (Exception e) {
        Log.w("gpkg", "could not be decoded: " + e.getMessage());
      }
    } else {
      Log.i("gpkg", "contains raster data.");
    }
  }
} catch (Exception e) {
  Log.w("gpkg", "Failed to load GeoPackage file " + source + ": " + e.getMessage());
}