Giter Site home page Giter Site logo

ngageoint / geopackage-js Goto Github PK

View Code? Open in Web Editor NEW
296.0 26.0 75.0 379.93 MB

GeoPackage JavaScript Library

Home Page: http://ngageoint.github.io/geopackage-js/

License: MIT License

JavaScript 26.23% HTML 0.02% TypeScript 73.76%
geopackage-libraries geopackage-js javascript-library nga geopackage nodejs javascript geopackage-viewer demo leaflet

geopackage-js's Introduction

GeoPackage JS

GeoPackage JS is an implementation of the OGC GeoPackage spec. This library works in both the browser and Node 12+.

GeoPackage Viewer

GeoPackage Viewer

Cloning this repository and opening the docs/index.html in your browser will run the demo locally.

Installation

Build Status NPM Coverage Status

$ npm install @ngageoint/geopackage

GeoPackage JS Library

The GeoPackage Libraries were developed at the National Geospatial-Intelligence Agency (NGA) in collaboration with BIT Systems. The government has "unlimited rights" and is releasing this software to increase the impact of government investments by providing developers with the opportunity to take things in new directions. The software use, modification, and distribution rights are stipulated within the MIT license.

Pull Requests

If you'd like to contribute to this project, please make a pull request. We'll review the pull request and discuss the changes. All pull request contributions to this project will be released under the MIT license.

Software source code previously released under an open source license and then modified by NGA staff is considered a "joint work" (see 17 USC § 101); it is partially copyrighted, partially public domain, and as a whole is protected by the copyrights of the non-government authors and must be released according to the terms of the original open source license.

About

GeoPackage JS is a GeoPackage Library JavaScript implementation of the Open Geospatial Consortium GeoPackage spec. It is listed as an OGC GeoPackage Implementation by the National Geospatial-Intelligence Agency.

The GeoPackage JavaScript library currently provides the ability to read GeoPackage files. This library works both in the browser and in Node. In the browser tiles are rendered using HTML5 Canvas and GeoPackages are read using sql.js. In Node tiles are rendered PureImage and GeoPackages are read using node-sqlite3.

Usage

View the latest docs.

Browser Usage

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Test</title>
  <script src="/path/to/geopackage.min.js"></script>
</head>
<body>
<input id="fileInput" type="file"/>
<script src="./index.js"></script>
</body>
</html>
// Specify folder containing the sql-wasm.wasm file.
// By default, geopackage loads from https://server/public/sql-wasm.wasm
const {
  GeoPackageManager,
  Canvas,
  TileUtils,
  GeoPackageTileRetriever,
  FeatureTiles,
  FeatureIndexManager,
  BoundingBox,
  setSqljsWasmLocateFile
} = window.GeoPackage

setSqljsWasmLocateFile(file => 'public/' + file);

// attach an event listener onto a file input
document.getElementById('fileInput').addEventListener('change',  function () {
  const file =this.files[0];
  const fileReader = new FileReader();
  fileReader.onload = function() {
    loadByteArray(new Uint8Array(fileReader.result));
  }
  fileReader.readAsArrayBuffer(file);
}, false);

function loadByteArray(array) {
  GeoPackageManager.open(array).then(async (geoPackage) => {
    // get the tile table names
    const tileTables = geoPackage.getTileTables();

    for (let i = 0; i < tileTables.length; i++) {
      const table = tileTables[i];
      // get tile dao
      const tileDao = geoPackage.getTileDao(table);

      // get table info
      const tableInfo = geoPackage.getInfoForTable(tileDao);

      // Get a GeoPackageTile and then draw it into a canvas.
      const canvas = Canvas.create(TileUtils.TILE_PIXELS_DEFAULT, TileUtils.TILE_PIXELS_DEFAULT);
      const context = canvas.getContext('2d');
      const gpr = new GeoPackageTileRetriever(tileDao);
      const x = 0;
      const y = 0;
      const zoom = 0;

      // Get the GeoPackageTile for a particular web mercator tile
      const geoPackageTile = await gpr.getTile(x, y, zoom)
      // get the tile data as a Buffer
      let tileData = geoPackageTile.getData();
      // Get the GeoPackageImage from the GeoPackageTile
      const geoPackageImage = await geoPackageTile.getGeoPackageImage()
      // draw the tile and use the canvas to get the Data URL
      context.drawImage(geoPackageImage.getImage(), 0, 0);
      const base64String = canvas.toDataURL('image/png');

      // In node.js, users must dispose of any GeoPackageImage and Canvas created to prevent memory leaks
      Canvas.disposeImage(geoPackageImage);
      Canvas.disposeCanvas(canvas);

      // Query tile table directly.
      const tileRow = tileDao.queryForTile(x, y, zoom);
      tileData = tileRow.getTileData();  // the raw bytes from the GeoPackage
    }

    // get the feature table names
    const featureTables = geoPackage.getFeatureTables();

    for (let i = 0; i < featureTables.length; i++) {
      const table = featureTables[i];
      // get the feature dao
      const featureDao = geoPackage.getFeatureDao(table);

      // get the info for the table
      const tableInfo = geoPackage.getInfoForTable(featureDao);

      // draw tiles using features
      const canvas = Canvas.create(TileUtils.TILE_PIXELS_DEFAULT, TileUtils.TILE_PIXELS_DEFAULT);
      const context = canvas.getContext('2d');
      const ft = new FeatureTiles(geoPackage, featureDao);
      var x = 0;
      var y = 0;
      var zoom = 0;
      const geoPackageImage = await ft.drawTile(x, y, zoom);
      context.drawImage(geoPackageImage.getImage(), 0, 0);
      const base64String = canvas.toDataURL('image/png');
      Canvas.disposeImage(geoPackageImage);
      Canvas.disposeCanvas(canvas);

      // iterate over indexed features that intersect the bounding box
      const featureIndexManager = new FeatureIndexManager(geoPackage, table);
      const resultSet = featureIndexManager.query();
      for (const featureRow of resultSet) {
        // ...
      }
      resultSet.close();

      // iterate over all features in a table in the geojson format
      const geoJSONResultSet = geoPackage.queryForGeoJSONFeatures(table);
      for (const feature of geoJSONResultSet) {
        // ...
      }
      geoJSONResultSet.close();
    }
  }).catch(function(error) {
    console.error(error);
  });
}

Web Worker Usage

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test</title>
    <script src="/path/to/geopackage.min.js"></script>
</head>
<body>
<input id="fileInput" type="file" onchange="openConnection(this.files)"/>
<canvas id="canvas" width="256px" height="256px"></canvas>
<br>
<input id="table" type="text">Table:</input>
<br>
<input id="column" type="number">X:</input>
<br>
<input id="row" type="number">Y:</input>
<br>
<input id="zoom" type="number">Zoom:</input>
<br>
<button onclick="drawFeatureTileInCanvas(document.getElementById('table').value, document.getElementById('column').value, document.getElementById('row').value, document.getElementById('zoom').value)">GetFeatureTile</button>
<br>
<button onclick="drawTileInCanvas(document.getElementById('table').value, document.getElementById('column').value, document.getElementById('row').value, document.getElementById('zoom').value)">DrawTileInCanvas</button>
<br>
<button onclick="getFeatureTableAsGeoJSON(document.getElementById('table').value)">GetFeatureTableAsGeoJSON</button>
<br>
<button onclick="closeConnection()">Close</button>
<br>
<script src="./index.js"></script>
</body>
</html>
index.js
// canvas for drawing, will need to be defined in html file.
var canvas = document.getElementById('canvas');

// setup worker
var geopackageWorker;
if (window.Worker) {
  geopackageWorker = new Worker("worker.js");

  // handle responses from the geopackage web worker
  geopackageWorker.onmessage = function(e) {
    // draw tile
    if (e.data.type === 'tile') {
      const ctx = canvas.getContext('2d');
      ctx.putImageData(e.data.tileImageData, 0, 0);
      // print geojson
    } else if (e.data.type === 'geojson') {
      console.log(e.data.geojson)
    }
  }
}

/**
 * Attach this method to a file input onchange event to open a geopackage connection
 * files[0] should be a valid .gpkg file
 * @param files - event.target.files
 */
openConnection = function(files) {
  var f = files[0];
  var r = new FileReader();
  r.onload = function() {
    var array = new Uint8Array(r.result);
    // create a connection to the geopackage
    geopackageWorker.postMessage({
      type: 'load',
      file: array
    });
  }
  r.readAsArrayBuffer(f);
}

/**
 * Closes the geopackage connection inside the worker
 */
closeConnection = function () {
  geopackageWorker.postMessage({
    type: 'close',
  });
}

/**
 * Will request the x,y,z feature tile to be drawn
 * @param table
 * @param x
 * @param y
 * @param z
 */
drawFeatureTileInCanvas = function (table, x, y, z) {
  console.log([table, x, y, z]);
  geopackageWorker.postMessage({
    type: 'get-feature-tile',
    table: table,
    x: x,
    y: y,
    z: z,
    width: canvas.width,
    height: canvas.height
  });
}

/**
 * Will request the x,y,z file to be drawn
 * @param table
 * @param x
 * @param y
 * @param z
 */
drawTileInCanvas = function (table, x, y, z) {
  geopackageWorker.postMessage({
    type: 'get-tile',
    table: table,
    x: x,
    y: y,
    z: z,
    width: canvas.width,
    height: canvas.height
  });
}

/**
 * Will request the features of a table in geojson format
 * @param table
 */
getFeatureTableAsGeoJSON = function (table) {
  geopackageWorker.postMessage({
    type: 'get-geojson',
    table: table
  });
}
worker.js
// import the geopackage browser library
self.importScripts('/path/to/geopackage.min.js');
const {
  GeoPackageManager,
  Canvas,
  TileUtils,
  GeoPackageTileRetriever,
  FeatureTiles,
  BoundingBox,
  setSqljsWasmLocateFile
} = GeoPackage;

// specify the location of the sql.wasm file
setSqljsWasmLocateFile(file => 'public/' + file);

// message listener
onmessage = function(e) {
  // open geopackage connection to fileData provided in message
  if (e.data.type === 'load') {
    GeoPackageManager.open(e.data.file).then(gp => {
      self.gp = gp;
    });
    // close the geopackage connection
  } else if (e.data.type === 'close') {
    self.gp.close();
    // request a tile from a feature table
  } else if (e.data.type === 'get-feature-tile') {
    const table = e.data.table;
    const x = parseInt(e.data.x);
    const y = parseInt(e.data.y);
    const z = parseInt(e.data.z);
    const width = parseInt(e.data.width);
    const height = parseInt(e.data.height);
    const featureDao = self.gp.getFeatureDao(table);
    const ft = new FeatureTiles(self.gp, featureDao, width, height);
    ft.drawTile(x, y, z).then(tile => {
      postMessage({
        type: 'tile',
        tileImageData: tile.getImageData()
      });
    });
    // request a tile from a tile table
  } else if (e.data.type === 'get-tile') {
    const table = e.data.table;
    const x = parseInt(e.data.x);
    const y = parseInt(e.data.y);
    const z = parseInt(e.data.z);
    const width = parseInt(e.data.width);
    const height = parseInt(e.data.height);
    self.gp.xyzTile(table, x, y, z, width, height).then(gpTile => {
      gpTile.getGeoPackageImage().then(gpImage => {
        postMessage({
          type: 'tile',
          tileImageData: gpImage.getImageData()
        });
      })
    })
    // request the features from a feature table in geojson format
  } else if (e.data.type === 'get-geojson') {
    const table = e.data.table;
    const features = [];
    const featureResultSet = self.gp.queryForGeoJSONFeatures(table);
    for(const feature of featureResultSet) {
      features.push(feature);
    }
    featureResultSet.close();
    const featureCollection = {
      type: 'FeatureCollection',
      features: features
    }
    postMessage({
      type: 'geojson',
      geojson: featureCollection
    });
  }
}

NodeJS Usage

const {
  setCanvasKitWasmLocateFile,
  GeoPackageManager,
  GeoPackageTileRetriever,
  FeatureTiles,
  Canvas,
  FeatureIndexManager,
  BoundingBox,
  TileUtils
} = require('@ngageoint/geopackage');
const { Projections } = require('@ngageoint/projections-js')
const { GeometryType } = require('@ngageoint/simple-features-js')

// specify the CanvasKit WebAssembly module's location.
setCanvasKitWasmLocateFile(file => '/path/to/node_modules/@ngageoint/geopackage/dist/canvaskit/' + file);

// open the .gpkg file
GeoPackageManager.open('/path/to/file.gpkg').then(async (geoPackage) => {
  // get the tile table names
  const tileTables = geoPackage.getTileTables();

  for (let i = 0; i < tileTables.length; i++) {
    const table = tileTables[i];
    // get tile dao
    const tileDao = geoPackage.getTileDao(table);

    // get table info
    const tableInfo = geoPackage.getInfoForTable(tileDao);

    // Get a GeoPackageTile and then draw it into a canvas.
    const canvas = Canvas.create(TileUtils.TILE_PIXELS_DEFAULT, TileUtils.TILE_PIXELS_DEFAULT);
    const context = canvas.getContext('2d');
    const gpr = new GeoPackageTileRetriever(tileDao);
    const x = 0;
    const y = 0;
    const zoom = 0;

    // Get the GeoPackageTile for a particular web mercator tile
    const geoPackageTile = await gpr.getTile(x, y, zoom)
    // get the tile data as a Buffer
    let tileData = geoPackageTile.getData();
    // Get the GeoPackageImage from the GeoPackageTile
    const geoPackageImage = await geoPackageTile.getGeoPackageImage()
    // draw the tile and use the canvas to get the Data URL
    context.drawImage(geoPackageImage.getImage(), 0, 0);
    const base64String = canvas.toDataURL('image/png');

    // In node.js, users must dispose of any GeoPackageImage and Canvas created to prevent memory leaks
    Canvas.disposeImage(geoPackageImage);
    Canvas.disposeCanvas(canvas);

    // Query tile table directly.
    const tileRow = tileDao.queryForTile(x, y, zoom);
    tileData = tileRow.getTileData();  // the raw bytes from the GeoPackage
  }

  // get the feature table names
  const featureTables = geoPackage.getFeatureTables();

  for (let i = 0; i < featureTables.length; i++) {
    const table = featureTables[i];
    // get the feature dao
    const featureDao = geoPackage.getFeatureDao(table);

    // get the info for the table
    const tableInfo = geoPackage.getInfoForTable(featureDao);

    // draw tiles using features
    const canvas = Canvas.create(TileUtils.TILE_PIXELS_DEFAULT, TileUtils.TILE_PIXELS_DEFAULT);
    const context = canvas.getContext('2d');
    const ft = new FeatureTiles(geoPackage, featureDao);
    var x = 0;
    var y = 0;
    var zoom = 0;
    const geoPackageImage = await ft.drawTile(x, y, zoom);
    context.drawImage(geoPackageImage.getImage(), 0, 0);
    // canvas.toDataURL('image/png'));
    Canvas.disposeImage(geoPackageImage);
    Canvas.disposeCanvas(canvas);

    // iterate over indexed features that intersect the bounding box
    const featureIndexManager = new FeatureIndexManager(geoPackage, table);
    const resultSet = featureIndexManager.queryWithBoundingBoxAndProjection(new BoundingBox(0, -90, 180, 90), Projections.getWGS84Projection());
    for (const featureRow of resultSet) {
      // ...
    }
    resultSet.close();

    // iterate over all features in a table in the geojson format
    const geoJSONResultSet = geoPackage.queryForGeoJSONFeatures(table);
    for (const feature of geoJSONResultSet) {
      // ...
    }
    geoJSONResultSet.close();
  }
});

geopackage-js's People

Contributors

bjornreppen avatar bosborn avatar btuttle avatar caldwellc avatar danielbarela avatar diff-by-default avatar dylrich avatar jaredlincenberg avatar juancromero-cotesa avatar mrkhan avatar nanonid avatar newmanw avatar nstarke avatar restjohn avatar taviroquai avatar tyburg avatar wallw-teal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

geopackage-js's Issues

Tests

Need to write automated tests.

Failure on reproj that isn't 4326->3857

var maxLatitude;
var minLatitude;
if (projectionTo.toUpperCase() === 'EPSG:3857' && projectionFrom.toUpperCase() === 'EPSG:4326') {
maxLatitude = tilePieceBoundingBox.maxLatitude > 85.0511 ? 85.0511 : tilePieceBoundingBox.maxLatitude;
minLatitude = tilePieceBoundingBox.minLatitude < -85.0511 ? -85.0511 : tilePieceBoundingBox.minLatitude;
minLongitude = tilePieceBoundingBox.minLongitude - pixelXSize < -180.0 ? -180.0 : tilePieceBoundingBox.minLongitude - pixelXSize;
maxLongitude = tilePieceBoundingBox.maxLongitude + pixelXSize > 180.0 ? 180.0 : tilePieceBoundingBox.maxLongitude + pixelXSize;
}
var pieceBoundingBoxInTileProjectionSW = conversion.inverse([minLongitude, minLatitude]);

min/max lat/long are never defined if the conversion is anything but 4326->3395

featureDao.create() doesn't update nga_geometry_index

Hi guys,

I insert feature into geopackage with addGeoJSONFeatureToGeoPackage() method that calls featureDao.create(featureRow, callback). The problem is that create() insert row but doesn't update nga_geometry_index.

Because I use featureDao.queryIndexedFeaturesWithWebMercatorBoundingBox() to render features whatever was created is not visible on the map.

From my point, nga_geometry_index table might become a pain in the neck, as you have to keep it in sync with all tables and update it on every feature CRUD operation. And if someone does changes via sqlbrowser app table will be also out of sync.

Thanks Alex

Do not require primary key on tiles table

Hi,

Would be possible to set default primary key column as id in GeoPackage?
We are creating GPKG tiles as view, and there is not possible to set primary key index.

Now I receive this backtrace:

Uncaught Error: No primary key column was found for table 'package_tiles'
    at TileTable.UserTable (gp.js:48931)
    at new TileTable (gp.js:48364)
    at TileTableReader.createTableWithNameAndColumns (gp.js:48485)
    at TileTableReader.<anonymous> (gp.js:49096)
    at gp.js:38813
    at gp.js:38840
    at gp.js:50009
    at gp.js:49387
    at gp.js:38811
    at gp.js:38835

This GPKG can't be opened in your JS.

I have tried to change it in commit in the fork, but now I receive this error backtrace:

Uncaught TypeError: Cannot read property 'name' of undefined
    at TileDao.UserDao (gp.js:48597)
    at new TileDao (gp.js:47819)
    at GeoPackage.<anonymous> (gp.js:40721)
    at TileTableReader.<anonymous> (gp.js:49129)
    at gp.js:38841
    at gp.js:38868
    at gp.js:50041
    at gp.js:49419
    at gp.js:38839
    at gp.js:38863

Broken links in repo README

demo/browserify/index.html does not exist in the repository. Instructions for opening a demo locally should be updated.

Additionally, first line in Usage section contains two broken links - those also point to the above demo directory.

Geopackage made from .dwg in QGis error No GEOMETRY column was found for table 'lines'

Hello,
I have created a .gpkg file from a .dwg file with QGis. Unfortunately I cannot show you the data itself.

When trying to load my file this error message appears in the console.

No GEOMETRY column was found for table 'lines'

So it seems rather obvious that it is missing a geometry column.
I have also exported the data with QGis via a MySql plugin, I tried to make a pastebin of the dump but it is too large.
The database does appear to have a reference to a "geom" column in a table called geometry_columns and the tables blocks and lines have geom columns filled with data of type geometry. The points table is empty.

I am basically trying to find out here whether the data we have acquired from our customer is wrong or that I am maybe doing something wrong. I don't really have any further experience with GeoPackages...

promise api?

a promise based api would be pretty nice now that async await is available in most browers and node, any thoughts on switching to something like that in a newer version ?

Raster tiles not displayed

Viewer at http://ngageoint.github.io/geopackage-js (is it the version in master?) stopped displaying raster tiles from GeoPackages, not even rivers.gpkg.
I remember just a few weeks ago it worked fine.

Error message in browser console:

TypeError: GeoPackageAPI.drawXYZTileInCanvas is not a function
in createTile http://ngageoint.github.io/geopackage-js/common.js:498

featureDao.queryIndexedFeaturesWithWebMercatorBoundingBox method returns only geom value

Hello,

I found that featureDao.queryIndexedFeaturesWithWebMercatorBoundingBox(bbox, callback, done) function is returning rows with geom column only, skiping any other props.

I did some debugging and found that geopackage js is executing below query:

select rivers.geom 
from 'nga_geometry_index' inner join rivers on rivers.id = nga_geometry_index.geom_id 
where nga_geometry_index.table_name = 'rivers' and 
		nga_geometry_index.min_x <= -12863648.645994272 and 
		nga_geometry_index.max_x >=  -12865751.85860068  and 
		nga_geometry_index.min_y <=  6655573.571054254 and 
		nga_geometry_index.max_y >= 6651886.678768059
		

when it should be select *.

If you check FeatureTableIndex.js it says
' this.geometryIndexDao.queryJoinWhereWithArgs(join, where, whereArgs, [this.tableName + '.' + this.featureDao.getGeometryColumnName()], rowCallback, doneCallback);'

i.e. columns = this.tableName + '.' + this.featureDao.getGeometryColumnName() => rivers.geom

If i'm not wrong, fix should be something like this
' this.geometryIndexDao.queryJoinWhereWithArgs(join, where, whereArgs, '*', rowCallback, doneCallback);'

Thanks Alex

Add tutorial for openlayers intergration

I was hoping to be able to present geopackage on my website using openlayers.
Looking at the documentation and using google search did not allow me to find how to use this library with openlayers.
Is it possible to add a tutorial to the documentation to show what needs to be done in order to make openlayers present geopackage tiles?

"zoom to" on a layer extends to whole world

I have a layer with four points, all in Europe. Selecting "zoom to" extends to whole world (plus some).

Probably using the declared layer extent rather than actual extent, but the effect is surprising.

Features Spatial Reference System
SRS Name: WGS 84 geodetic
SRS ID: 4326
Organization: EPSG
Coordsys ID: 4326
Definition: GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]
Description: longitude/latitude coordinates in decimal degrees on the WGS 84 spheroid
Contents
Table Name: cats_feature
Data Type: features
Identifier: cats_feature
Description:
Last Change: 2017-12-24T23:58:46.092Z
Min X: -180
MinY: -90
Max X: 180
Max Y: 90
Contents Spatial Reference System
SRS Name: WGS 84 geodetic
SRS ID: 4326
Organization: EPSG
Coordsys ID: 4326
Definition: GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]
Description: longitude/latitude coordinates in decimal degrees on the WGS 84 spheroid
Geometry Columns
Table Name: cats_feature
Column Name:
Geometry Type Name: POINT
Z: 0
M: 0
cats_feature columns:
Index: 0
Name: id
Data Type: INTEGER
Max:
Not Null: false
Default Value:
Primary Key: true
Index: 1
Name: geometry
Data Type:
Max:
Not Null: false
Default Value:
Primary Key: false
Index: 2
Name: text_attribute
Data Type: TEXT
Max:
Not Null: false
Default Value:
Primary Key: false
Index: 3
Name: real_attribute
Data Type: REAL
Max:
Not Null: false
Default Value:
Primary Key: false
Index: 4
Name: relation
Data Type: TEXT
Max:
Not Null: false
Default Value:
Primary Key: false

rivers.gpkg issue

I believe the rivers.gpkg file in test/fixtures has a problem. For the tile pyramid, the srs_id is 4326 in gpkg_contents but 3857 in gpkg_tile_matrix_set, whereas the OGC spec says they must be the same value and it looks like that would be 3857.

Unable to execute the sample NodeJS code

Hi,

I was trying to use the NodeJS Usage code mentioned in README.md but got an error

TypeError: Cannot read property 'open' of undefined
at Object. (\app.js:10:18)

`var geopackage = require('@ngageoint/geopackage')
, GeoPackageManager = geopackage.GeoPackageManager
, GeoPackageConnection = geopackage.GeoPackageConnection
, GeoPackageTileRetriever = geopackage.GeoPackageTileRetriever;

var filename = "./rivers.gpkg";

GeoPackageManager.open(filename, function(err, geoPackage) {`

it seems that GeoPackageManager is undefined.
is there any prerequisite before using geopackage-js ?

Regards,
M. Rizwan Khan

Web Workers

We should investigate using web workers to draw the tiles into the canvases. This should improve performance.

Update README

Update README to reflect the new way to use the library.

Difficulty loading raster tiles from generated GPKG

I am creating new geopackages in Python from Numpy arrays, using Rasterio to create subdatasets.

I can open the geopackage in QGIS and view the rasters, but they do not show at all in Leaflet, although the console shows Draw tile messages as if the tiles are being rendered.

I am not all too familiar with geopackage creation, so perhaps it is my fault and I am not correctly initializing something.

cannot use geopackage-js in react-native

Hi

I'm thinking of using geopackage-js in react-native.
However, the installation of the module by NPM has caused many errors and has not been able to run it.

For example, I get the following error
Unable to resolve "../build/better_sqlite3.node" from "node_modules\better-sqlite3\lib\database.js"

Unable to resolve "../build/integer.node" from "node_modules\integer\lib\index.js"

The package at "node_modules\@ngageoint\geopackage\node_modules\image-size\dist\index.js" attempted to import the Node standard library module "fs". It failed because React Native does not include the Node standard library.

ffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
⇒Added the max-old-space-size=4096 option, but it didn't finish the process. (Is there a loop going on?)

etc..

Incidentally, I use rn-nodeify appropriately to install the necessary packages.

Is it better not to think about using it in react-native?
Do you have any plans to support react-native?
If you have a sample that uses react-native, can you tell me about it?

thankyou

Slow point loading from gpkg in Leaflet

Hi!

Thanks for making this library, I really like the idea of working with geopackage in Leaflet! I tried loading a point set with about 72k points and have run into load performance issues. It takes several minutes to display all the points. And it seems that points are loaded in random order and not within the current bound. I guess Im doing something wrong.

For example in Qgis the geopackage file loads and displays instantly. Any ideas on how to load the point features quicker?

I attached a working example (zip) file here for anyone to look at and debug. The geopackage are generated with a spatial index. The gpkg file in the example is generaed from Qgis 3 but I also tried with the same dataset using gdal but with the same results.

Thanks!
geop.zip

Problem on Checking Column Max in GeoPackage.js

I am trying to run the demo locally and using the .js contained in the static folder.

image

It looks like the function validateMax is checking on the numeric dataType and not the type name so should be implemented as:

if(this.max && this.dataType !== 9...
instead of
if(this.max && this.dataType !== 'TEXT'...

The type is passed in to FeatureTableReader.prototype.createColumnWithResults where it is converted to a numeric dataType so validateMax will never receive it.

UserColumn.call is used in two places: for FeatureColumn and TileColumn, the second call also passes on the numeric datatype so the check in validateMax definitely looks wrong.

getTile for different projections

Hi guys,

I'm trying to display tiles from some geopackage, which has srs EPSG:31467 and it doesn't work.
I use your code example from the project description to get tiles. It works perfectly for rivers.gpkg from the example and also for other geopackages, which have srs EPSG:4326 or EPSG:3857.
What should I do to get another projections work? Could you please help me?

queryForGeoJSONFeaturesInTable throws an error for some geopackage files

Version: 2.1.0

First of all, thanks for this comprehensive geopackage library!

I recently ran into a problem with some geopackage files. Calling queryForGeoJSONFeaturesInTable results in the following error:

Uncaught (in promise) TypeError: Cannot read property 'x' of null
    at geocentricToGeodetic (geopackage.js:58208)
    at datum_transform (geopackage.js:58393)
    at transform (geopackage.js:58506)
    at transformer (geopackage.js:58545)
    at proj4$1 (geopackage.js:58584)
    at BoundingBox.projectBoundingBox (geopackage.js:1264)
    at FeatureTableIndex.queryWithBoundingBox (geopackage.js:5724)
    at FeatureDao.queryForGeoJSONIndexedFeaturesWithBoundingBox (geopackage.js:13493)
    at module.exports.GeoPackage.queryForGeoJSONFeaturesInTable (geopackage.js:14250)
    at resolver (GeoPackageLoader.js:94)

The issue is, that point ends up being null in geocentricToGeodetic.
image

The point becomes null during datum_transform after calling geodeticToGeocentric.
image

And the reason is because the latitude is not in polar coordinates:
image

This is the location in my code where the error occurs:
https://github.com/potree/potree/blob/72748db38fd46a98c4d0800a70b1fe2570365152/src/loader/GeoPackageLoader.js#L92

Note that this looks a bit different than the official examples and the GeoPackage Viewer, because the version: 2.1.0 release seems to have a different API (no getFeatureRow() function, for example). What I'd like to accomplish is to load 3D data of all stored features, so that I can create 3D models out of them.

Here is an example that works:
3D Scene: http://mschuetz.potree.org/geopackage/examples/geopackage.html
Geopackage file: http://mschuetz.potree.org/geopackage/examples/morro_bay_shp/gpkg/geopackage.gpkg

And this is the geopackage that causes an error when loading with geopackage-js:
3D Scene: http://mschuetz.potree.org/geopackage/not_working/gpgp.html
Geopackage file: http://mschuetz.potree.org/geopackage/not_working/test2d_potree17_epsg2056.gpkg

Help on how to fix this issue or on how to correctly load 3D geometry data for features would be highly appreciated. Thanks!

Looking for a bit of help getting package installed

Hello,

I know this is probably a simple question but I am going to ask anyway.

Do I need to use NPM to build the package?(As might not be able to install on work computer)

I am trying to setup a simple webpage (Just a map for now) and display my GIS info (gpkg's). I have the basemap displaying but when I try to load layers nothing shows up.

Any help to point me the right direct would be great.

Current code encase you want to see it.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Leaflet Map with a Basemap</title>
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
  
  <!-- lets load Leaflet's .js and .css from CDN-->
  <link rel="stylesheet" href="../leaflet/leaflet.css" />
  <script src="../leaflet/leaflet.js"></script>

  <!-- Load Esri Leaflet from CDN.  it has no .css stylesheet of its own, only .js -->
  <script src="../esri-leaflet-v2.1.1/dist/esri-leaflet.js"></script>
  
  <script src="../GeoPack/leaflet/package.json"></script>
  <script src="../GeoPack/leaflet/leaflet-geopackage.js"></script>
  
  
  <style>
    html,
    body,
    #map {
      height: 90%;
      width: 90%;
      margin: auto;
      padding: 10px;
    }
  </style>
</head>
<body>
    <div id="map" class="map"></div>
	
	<script src="../GeoPack/leaflet/leaflet-geopackage.js"></script>
	<script>
	
		var map = L.map('map', {
			center: [44.66, -63.61],
			zoom: 15
		});
		var esriStreets = L.esri.basemapLayer('Streets').addTo(map);
		
		// Load the Rivers GeoPackage and display the tile layer
			L.geoPackageTileLayer({
			geoPackageUrl: '../GeoPack/leaflet/rivers.gpkg',
			layerName: 'rivers_tiles'
		}).addTo(map);
		
		// Load the Rivers GeoPackage and display the feature layer
		L.geoPackageFeatureLayer([], {
			geoPackageUrl: "../GeoPack/leaflet/rivers.gpkg",
			layerName: 'rivers'
		}).addTo(map);
		
	</script>
</body>
</html>

Query Builder

Hello,

I'm using GeoPackage now and found that it uses it's own query builder...

Is it too much trouble to use a well stablished query builder like http://knexjs.org ?

It would leave this package to focus on GeoPackage format and leave all the SQL API to KnexJS.

BTW, there is also TurfJS which can deal with geospatial operations.

Don't get me wrong, I'm just trying to figure out the best way to deal with GeoPackage format in Javascript.

Thanks!

NGA NSG PROFILE

Has geopackage-js and leaflet plugin been updated to support NGA NSG TILING SCHEMA/profile?

mbtiles

It would be great to also preview mbtiles
don't need to make mbtiles but load an mbtiles with tile_data with PNG or JPG tiles

separately, it would also be great to preview vector tiles mbtiles with PBF in tile_data

browser-test target fails

The first problem is that the browserify-istanbul dev dependency is missing. Fairly easy fix.

However, once getting past that, this is a bit more confusing:

bradh@ubuntu1710:~/geopackage-js$ yarn browser-test
yarn run v1.6.0
$ browserify -t browserify-istanbul ./test/test.js --standalone tests --exclude sqlite3 --exclude inquirer -o bundle/test.bundle.js -d
$ ./test/cli
events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: spawn node_modules/.bin/mocha-phantomjs ENOENT
    at _errnoException (util.js:1022:11)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:190:19)
    at onErrorNT (internal/child_process.js:372:16)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
    at Function.Module.runMain (module.js:695:11)
    at startup (bootstrap_node.js:188:16)
    at bootstrap_node.js:609:3
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Possibly it doesn't like my VM environment, but its hard to see.

Cannot find @ngageoint/geojson-to-geopackage on npmjs.com

Hello,

Thanks a lot for the tool!
I discovered a reference to a GeoJSON to GPKG tool in the converters/geojson folder. But I cannot find any reference to a package named @ngageoint/geojson-to-geopackage on npm.

Is that intentional?

proj.Proj4 is not a function in converters

No matter how I import the provided converter modules into my project (building with webpack), I get an error from the .addLayer method of the shapefile converter that proj4.Proj is not a function. I've tried explicitly importng proj4 with no luck. I am developing on Fedora Linux, if that makes any difference. The GeoPackageAPI works fine for me, but none of the converters work. Any hints or instructions on grabbing more useful information from my end would be most appreciated.

mbtiles converter dependency 'sqlite3' not available

When I yarn install the node modules for ./converter/mbtiles/ I get the following error:

node-pre-gyp info it worked if it ends with ok
node-pre-gyp info using [email protected]
node-pre-gyp info using [email protected] | darwin | x64
node-pre-gyp info check checked for "/Users/dujohnson/tmp/geopackage-js/converters/mbtiles/node_modules/sqlite3/lib/binding/node-v64-darwin-x64/node_sqlite3.node" (not found)
node-pre-gyp http GET https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v3.1.13/node-v64-darwin-x64.tar.gz
node-pre-gyp http 403 https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v3.1.13/node-v64-darwin-x64.tar.gz
node-pre-gyp ERR! Tried to download(403): https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v3.1.13/node-v64-darwin-x64.tar.gz
node-pre-gyp ERR! Pre-built binaries not found for [email protected] and [email protected] (node-v64 ABI) (falling back to source compile with node-gyp)
node-pre-gyp http 403 status code downloading tarball https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v3.1.13/node-v64-darwin-x64.tar.gz
node-pre-gyp ERR! Tried to download(undefined): https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v3.1.13/node-v64-darwin-x64.tar.gz
node-pre-gyp ERR! Pre-built binaries not found for [email protected] and [email protected] (node-v64 ABI) (falling back to source compile with node-gyp)
node-pre-gyp http Connection closed while downloading tarball file

And indeed, when I visit https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v3.1.13/node-v64-darwin-x64.tar.gz I get the following error:

<Error>
  <Code>AccessDenied</Code>
  <Message>Access Denied</Message>
  <RequestId>F2735A74E4249542</RequestId>
  <HostId>nROeg5Ex5GGEQuNYvefpuGITA3fV4ambpNX8gSD0bBPj3ZY46kn+pUlf07lgdto8n2ky6M9hQcQ=</HostId>
</Error>

Is it possible to write a geopackage file?

I am trying to generate a geopackage file based on multiple drawn features in a layer using OpenLayers 5 Draw class. Could you provide me any example or interesting class methods for such a task?

Thanks in advance

proj4 is not a function in TileDao.js

Hi guys,

I've recently got an issue probably connected in some way to this one #103. In the file TileDao.js in the function TileDao.prototype.initialize occurs the following error:
proj4 is not a function

The code line from the fix of the issue #103
proj4 = 'default' in proj4 ? proj4['default'] : proj4;
solves the problem.
Would it be possible/right solution to provide this hack in the package?

queryForGeoJSONFeaturesInTable should not assume the bounding box is 4326

The queryForGeoJSONFeaturesInTable should not assume that the projection is in 4326 especially if the FeatureDao projection is different. The projection should be optionally passed in. The projection could also potentially be included in the BoundingBox class which is returned from the FeatureDao.

geoPackage error: "proj4.defs is not a function"

Hi guys,

the following problem occurs using geoPackage and proj4 ^2.4.3:
since this commit (the file lib/defs.js line 55) has been published by Proj4-team the geoPackage fails by initialization on following line. It seams, that now the correct way of calling proj4.defs at this point is proj4.default.defs(name, defs[name]); otherwise it throws the error "proj4.defs is not a function".

Could this issue be fixed or any workaround be suggested?
Thank you for help!

leaflet-geopackage build problems

Hi!

Thanks for your work on leaflet-geopackage; it's great to see this integration between leaflet and geopackage-js working.

I thought I should report two problems with your current package.json that I found when trying to compile leaflet-geopackage:

  1. the webworkify package is missing (I got the error "Error: Cannot find module 'webworkify' from '/home/user/geopackage/leaflet/node_modules/geopackage/lib/tiles/creator'")
  2. the default uglify-js installed does not support es6, so gives the error "uglifyjs failed: SyntaxError: Unexpected token: operator (>)".

A fix to the missing webworkify package is straight-forward.

And I found a fix for the uglify-js problem here: ionic-team/ionic-framework#8817 , which says you need to reference the "harmony" branch of uglify-js.

The revised package.json file that includes these two fixes is attached.

Documentation

Should create documentation using documentation.js

geopackage.addGeoJSONFeatureToGeoPackage() is using hardcoded SRS

Hello,

I'm trying to create a feature and store into 'rivers' geopackage file which is in 3857 projection. It looks like addGeoJSONFeatureToGeoPackage() method has hardcoded SRS -> geometryData.setSrsId(4326);

Is it possible to patch it with something like this:

featureDao.getSrs(srs, function() {
    geometryData.setSrsId(srs.srs_id);
    ...
})

Thanks Alex

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.