Giter VIP home page Giter VIP logo

geojson-vt's Introduction

geojson-vt — GeoJSON Vector Tiles

Build Status

A highly efficient JavaScript library for slicing GeoJSON data into vector tiles on the fly, primarily designed to enable rendering and interacting with large geospatial datasets on the browser side (without a server).

Created to power GeoJSON in Mapbox GL JS, but can be useful in other visualization platforms like Leaflet, OpenLayers and d3, as well as Node.js server applications.

Resulting tiles conform to the JSON equivalent of the vector tile specification. To make data rendering and interaction fast, the tiles are simplified, retaining the minimum level of detail appropriate for each zoom level (simplifying shapes, filtering out tiny polygons and polylines).

Read more on how the library works on the Mapbox blog.

There's a C++11 port: geojson-vt-cpp

Demo

Here's geojson-vt action in Mapbox GL JS, dynamically loading a 100Mb US zip codes GeoJSON with 5.4 million points:

There's a convenient debug page to test out geojson-vt on different data. Just drag any GeoJSON on the page, watching the console.

Usage

// build an initial index of tiles
var tileIndex = geojsonvt(geoJSON);

// request a particular tile
var features = tileIndex.getTile(z, x, y).features;

// show an array of tile coordinates created so far
console.log(tileIndex.tileCoords); // [{z: 0, x: 0, y: 0}, ...]

Options

You can fine-tune the results with an options object, although the defaults are sensible and work well for most use cases.

var tileIndex = geojsonvt(data, {
	maxZoom: 14,  // max zoom to preserve detail on; can't be higher than 24
	tolerance: 3, // simplification tolerance (higher means simpler)
	extent: 4096, // tile extent (both width and height)
	buffer: 64,   // tile buffer on each side
	debug: 0,     // logging level (0 to disable, 1 or 2)
	lineMetrics: false, // whether to enable line metrics tracking for LineString/MultiLineString features
	promoteId: null,    // name of a feature property to promote to feature.id. Cannot be used with `generateId`
	generateId: false,  // whether to generate feature ids. Cannot be used with `promoteId`
	indexMaxZoom: 5,       // max zoom in the initial tile index
	indexMaxPoints: 100000 // max number of points per tile in the index
});

By default, tiles at zoom levels above indexMaxZoom are generated on the fly, but you can pre-generate all possible tiles for data by setting indexMaxZoom and maxZoom to the same value, setting indexMaxPoints to 0, and then accessing the resulting tile coordinates from the tileCoords property of tileIndex.

The promoteId and generateId options ignore existing id values on the feature objects.

GeoJSON-VT only operates on zoom levels up to 24.

Install

Install using NPM (npm install geojson-vt) or Yarn (yarn add geojson-vt), then:

// import as a ES module
import geojsonvt from 'geojson-vt';

// or require in Node / Browserify
const geojsonvt = require('geojson-vt');

Or use a browser build directly:

<script src="https://unpkg.com/[email protected]/geojson-vt.js"></script>

geojson-vt's People

Contributors

aaronlidman avatar anandthakker avatar andrewharvey avatar categulario avatar chrisloer avatar craiggleso avatar dependabot[bot] avatar district10 avatar fitnr avatar incanus avatar ivansanchez avatar jed avatar jfirebaugh avatar jjhembd avatar kkaefer avatar m0ose avatar mcwhittemore avatar mlptownsend avatar mourner avatar nazar-pc avatar skalt avatar tmcw avatar vicb avatar waldyrious avatar yhahn 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  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

geojson-vt's Issues

identifying geojson-vt features on leaflet

How can I associate click events with polygons from a polygon geojson which is rendered using geojson vt? I am trying to use leaflet to do that. Thanks for the help.

Progress callback / event

It would be nice to have a way to indicate progress of tile indexing, so that there's some feedback when you load 100M GeoJSON into the stuff.

API for tiling on demand

Need something like this:

tileFurther(tileIndex, zoom, tileX, tileY);

Takes existing tile index and tiles further to a specific tile. This means finding the closest existing parent tile and then tiling deeper from it to the specified one.

Mapbox GL

Hello,
Can you share an example with Mapbox GL js and geojson-vt ?
Thx

Support different tile sizes

If you create a canvas tile layer in Leaflet using a tile size other than 256 then the tile indexes within geojson-vt are no longer valid.

For example if you create a canvas tile layer in Leaflet using a tile size of 512:

var tiles = new geojsonvt(geoJsonFeatureCollection);

var canvasTile = L.tileLayer.canvas({
    tileSize: 512
});

canvasTile.drawTile = function(canvas, tilePoint, zoom) {
    ...
    var tile = tiles.getTile(zoom, tilePoint.x, tilePoint.y);
   ...
}

When the drawCanvasTile function is called the tilePoint x and y values are different based on the tile size, though the getTile function always expects it to be an x and y value that corresponds to a tile size of 256. The below table gives example values based on tile size of x and y

tilePoint 256 512 getTile expects
x 3500 1750 3500
y 3600 1800 3600

Tiles not always immediately available

Using the natural earth country boundaries from here.

The first time I request some tiles, I get null, but if I wait, they return values. For example:

var fs = require('fs'),
  gvt = require('geojson-vt');

var c = gvt(JSON.parse(fs.readFileSync('ne_50m_admin_0_countries.geojson', 'utf8')));

console.log(c.getTile(15, 9379, 12533));

setTimeout(function () {
  console.log(c.getTile(15, 9379, 12533));
}, 5000);

Demo

Hi,
Can you share your demo with Nodejs Server, please ?
How to enable this feature with Mapbox GL.js ?
Thank you

Filter out points on lower zoom tiles

We could just filter out same-coord points, but that's probably not enough. We can apply more sophisticated filtering algorithms, but it's tough to make a generic point filtering algorithm that suites any kind of data.

Limit the size of the tile cache

this.tiles grows as you render tiles and this causes memory issues when rendering more than a couple hundred tiles on the server.

Having something like an LRU cache, maybe configureable in size?, would be ideal to get around this.

cc @mourner

Optimize localized data use case

Currently even if the data is localized (e.g. all features are in a particular city), geojson-vt still starts clipping from z0, unnecessarily looping through all features on every zoom up to the relevant one.

Instead what we could do is find the bounding tile and only start clipping from it downwards. We'll also have to change the algorithm to derive lower zoom tiles from that top tile.

This will also help fix #1 in a way that doesn't degrade performance.

Command-line interface

There should be an executable that, given a GeoJSON file, generates tiles as a folder with files.

Large features disappearing between zoom levels

I'm finding some quite noticeable features being cut below zoom level 12. See below for an example - the geojson file is made up of a series of polygons.

I've tried playing with the tolerance setting but even at 1 it is still cut.

problem

z0 tile may include duplicate features

Test case:

var geojsonvt = require('geojson-vt');
console.log(geojsonvt(
    {"type": "Point", "coordinates": [90, 0]},
    {buffer: 2048, extent: 8192}).getTile(0, 0, 0).features.length);

This prints 2 because the point is included twice: one because it's within the normal extent and once because it's within the buffer, which for z0 is wrapping into the opposite side of the tile. It seems to me the buffer should be ignored for z0, rather than generating duplicate features. (What does mapnik do in this case?)

cc @mourner @flippmoke

performance on mobile in leaflet stable with canvas layer

Any ideas in terms of tweaking the settings for better performance on mobile devices? I am using leaflet 0.7 with the canvas layer plugin. The tiles render fine on mobile, but when performing drastic zoom level changes or drastic panning, the tiles seem to hang/stop rendering. Example. This may be just a limit on the capabilities of mobile processors. I have tested on a samsung tab pro 8.4 and a one touch idol 3 both in chrome. If switching to leaflet-beta would help, I would need to figure out how to draw the tiles with the new grid layer. I don't really want to learn a new js library ie mapbox gl.

constrain latitude?

Should the point projection clamp the latitude to +/-85.05112878?

geojson-vt/src/convert.js

Lines 95 to 100 in bfab801

function projectPoint(p) {
var sin = Math.sin(p[1] * Math.PI / 180),
x = (p[0] / 360 + 0.5),
y = (0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI);
return [x, y, 0];
}

Otherwise points out of that range get invalid unit projection values.

Precalculate precision of every coordinate to determine min zoom to tile to

Run through all coordinates of all features; for each point, calculate and save the first zoom at which the margin of error for the point encoded into 4096 integers goes below some small threshold.

When considering a tile for cutting, we can determine whether to cut or not by looking at the maximum of calculated zooms for each point in the tile. This way we don't compromise precision while not doing unnecessary tiling.

Support holed polygons

Currently it only processes the first ring of every polygon. Tiling with proper hole support will be a bit tricky.

Updatable tiles

Would it be possible to add an API that adds data into the pyramid of tiles (and potentially removes it, but that might be tougher)? This would make live-data use cases very interesting.

Support multiple projections

It would be great if this could support multiple projections- especially 4326 (equirectangular), or allow for creating a custom CRS like we can in Leaflet.

Prerun simplification on all data

Don't simplify features for each tile; instead run Douglas-Peucker algorithm (fast O(n log n)) once for all features before tiling, saving the deviation of each coord instead of throwing out points; then for each zoom, simplification will be a matter of picking out points less then a particular threshold.

This will make simplification fast, indicate max zoom up to which simplification matters for each tile upfront, and enable easier simplification-based heuristics.

Better strategy for determining when to stop tiling depending on tile data

  • each coordinate keeps a switch indicating whether it's from original data or introduced through clipping
  • if a tile contains at least one original point, slice deeper (up to z14)
  • otherwise stop tiling

This solution should reduce the number of tiles significantly while keeping all the necessary precision, is dead simple to implement, and removes the need for any other heuristics (such as based on num. of features, coordinates, simplification etc.).

It assumes we only need precision for areas where we have actual data points — all lines and polygons going "through" tiles don't need as much precision. Does this sound like a good assumption?

100% test coverage

  • drilldown with getTile
  • stopping on clipped square
  • feature as a top-level object
  • single geometry as a top-level object
  • MultiPoint
  • GeometryCollection
  • throw if not GeoJSON
  • at least one run with debug: 2

A first pass metric to replace maxZoom

Currently you need to specify maxZoom for the first pass tiling run manually depending on the data. It's fine to have it z14 for smaller files like <=20M, but for something like 100M, you hit a JS wall if you specify something more than z4. Instead we need to go indexing and stop automatically if there is a sign that it takes too much memory and will slow down now.

Any sample?

Hi Vladimir, do you have any live sample or could you tell me how may I use your library in a Windows server? Thank you very much in advance

Cesare

geojson-vt does not support certain point-only data sets

The tiling process fails when attempting to process geojson's containing geometries of type == 'Point'.

Is there any plan to support tiling points in the future or is this intentionally not included in the feature set of geojson-vt?

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.