{"id":28956808,"url":"https://github.com/developmentseed/vt-grid","last_synced_at":"2025-09-10T23:42:25.165Z","repository":{"id":35639765,"uuid":"39914114","full_name":"developmentseed/vt-grid","owner":"developmentseed","description":"Build up a pyramid of mapbox vector tiles by aggregating quantitative data into grids at lower zooms.","archived":false,"fork":false,"pushed_at":"2016-06-12T20:59:41.000Z","size":3630,"stargazers_count":26,"open_issues_count":5,"forks_count":6,"subscribers_count":51,"default_branch":"master","last_synced_at":"2025-08-16T01:37:24.030Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/developmentseed.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-29T20:15:58.000Z","updated_at":"2023-09-01T15:41:14.000Z","dependencies_parsed_at":"2022-09-05T06:31:46.341Z","dependency_job_id":null,"html_url":"https://github.com/developmentseed/vt-grid","commit_stats":null,"previous_names":["anandthakker/vt-grid"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/developmentseed/vt-grid","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/developmentseed%2Fvt-grid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/developmentseed%2Fvt-grid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/developmentseed%2Fvt-grid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/developmentseed%2Fvt-grid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/developmentseed","download_url":"https://codeload.github.com/developmentseed/vt-grid/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/developmentseed%2Fvt-grid/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274549290,"owners_count":25306358,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-10T02:00:12.551Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-23T21:40:55.161Z","updated_at":"2025-09-10T23:42:25.133Z","avatar_url":"https://github.com/developmentseed.png","language":"JavaScript","readme":"# vt-grid\n\nBuild up a pyramid of [Mapbox vector\ntiles](https://github.com/mapbox/vector-tile-spec) by aggregating quantitative\ndata into grids at lower zooms.\n\n## Motivation\n\nSay you have a dataset of polygons that have some kind of density data\n(population, vegetation, ...), and you want to build an interactive map with\nit.  Vector tiles are great for this--especially with\n[mapbox-gl](https://github.com/mapbox/mapbox-gl-js) steadily maturing.\n\nBut if your data is at a fine resolution and you don't want to be limited to\nvery high zoom levels, you're stuck using standard simplification techniques.\n(Or, much better, the rather badass and blazingly fast simplification and point\ndropping techniques offered by\n[tippecanoe](https://github.com/mapbox/tippecanoe)). For many cases, this works\ngreat, but it's not ideal here: for instance, in simplification many small,\nhigh-density polygons get dropped, even though these are often important\nfeatures.\n\nThis tool is an alternative to simplification: using a grid whose resolution\nvaries with zoom level, aggregate the quantitative features of interest, so\nthat you can visualize the spatial distribution of your data at any scale.\n\n## Installation\n\nInstall [tippecanoe](https://github.com/mapbox/tippecanoe), and then:\n\n```sh\nnpm install -g vt-grid\n```\n\n## Usage\n\nTo start, you'll need an `mbtiles` file containing the original feature data at\nsome (high) zoom level.  If you've got the data in, say, a shapefile or\nPostGIS, you can use Mapbox Studio to create a source and then export to\nMBTiles -- just set the min and max zoom to something high enough.\n\n### CLI\n\nLet's say you've got the data in `data.mbtiles`, at zoom 12 in a layer called\n`'foo'`, and each polygon in this layer has a field called `density`. Then, you\ncan build the grid pyramid above this base layer with:\n\n```sh\nvt-grid input.mbtiles -o output.mbtiles --basezoom 12 --minzoom 1 --gridsize 16 \\\n --aggregations 'foo:areaWeightedMean(density)'\n```\n\nStarting at zoom 11 and going down to zoom 1, this will build a 16x16 grid in\neach tile, aggregating the data from the zoom level above.  The aggregations\nare defined by the `--aggregations` parameters.  Each one is of the form:\n`layer:aggregationFunction(field)`, where `aggregationFunction` can\nbe any of the built-in aggregations available in\n[`geojson-polygon-aggregate`](https://github.com/anandthakker/geojson-polygon-aggregate).\nSo, in this case, we'll end up with a grid where each box has a `density`\nproperty, which is the (correctly weighted) mean of the densities of the\npolygons from the previous (higher) zoom level that fall within that box.\n\nWith other aggregations, other stats.  For instance, we could have done:\n\n```sh\n# first use count() to find out the number of polygons from the original\n# dataset being aggregated into each grid box at z11\nvt-grid input.mbtiles output.mbtiles --basezoom 12 --minzoom 11 --gridsize 16 \\\n  --aggregations 'foo:areaWeightedMean(density)' 'foo:count(numzones)'\n\n# now, for z10 and below, sum the counts\nvt-grid input.mbtiles output.mbtiles --basezoom 12 --minzoom 11 --gridsize 16 \\\n  --aggregations 'foo:areaWeightedMean(density)' 'foo:sum(numzones)'\n```\n\n### Node\n\nYou can have a little more flexibility with aggregations (and post-aggregation\nfunctions) by using vt-grid programmatically:\n\n```javascript\nvar path = require('path')\nvar vtGrid = require('vt-grid')\nvar reducers = require('geojson-polygon-aggregate/reducers')\n\nif (require.main === module) {\n  vtGrid('/path/to/output.mbtiles', 'path/to/input.mbtiles', {\n    minzoom: 1,\n    basezoom: 10,\n    aggregations: __filename, // this can be any file that exports an `aggregations` object like the one below\n    postAggregations: __filename // same for this\n  }, function (err) {\n    if (err) { throw err }\n    console.log('Finished!')\n  })\n}\n\nmodule.exports = {\n  aggregations: {\n    footprints: {\n      FID: reducers.union('FID'),\n      someField: function myCustomAggregator (memo, feature) {\n        var newMemo = -1\n        // do stuff, works like an Array.reduce() function\n        return newMemo\n      }\n    }\n  },\n  postAggregations: {\n    footprints: {\n      // called on each grid square feature after all aggregations are run, with\n      // the result added to its properties under the given key (unique_count)\n      unique_count: function (feature) {\n        return feature.properties.FID ? JSON.parse(feature.properties.FID).length : 0\n      }\n    }\n  }\n}\n```\n\nThis yields features that look like:\n\n```json\n{\n  \"type\": \"Feature\",\n  \"geometry\": {\n    \"type\": \"Polygon\",\n    \"coordinates\": [\n      [\n        [\n          -111.09375,\n          40.97989806962016\n        ],\n        [\n          -111.09375,\n          40.9964840143779\n        ],\n        [\n          -111.07177734375,\n          40.9964840143779\n        ],\n        [\n          -111.07177734375,\n          40.97989806962016\n        ],\n        [\n          -111.09375,\n          40.97989806962016\n        ]\n      ]\n    ]\n  },\n  \"properties\": {\n    \"FID\": \"[59, 707, 1002]\",\n    \"unique_count\": 3,\n    \"someField\": -1\n  }\n}\n```\n\n## API\n\n### vtGrid\n\nBuild a pyramid of aggregated square-grid features.\n\n**Parameters**\n\n-   `output` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Path to output aggregated mbtiles data\n-   `input` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Path to the input mbtiles data\n-   `opts` **([Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)\\|[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array))** Options OR an array of options objects to allow different aggregations/settings for different zoom levels\n    -   `opts.basezoom` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** The zoom level at which to find the initial data\n    -   `opts.inputTiles` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)=** An array of [z, x, y] tile coordinates to start with\n    -   `opts.gridsize` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of grid squares per tile\n    -   `opts.aggregations` **([Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)\\|[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** If an object, then it maps layer names to aggregation objects, which themselves map field names to geojson-polygon-aggregate aggregation function names. Each worker will construct the actual aggregation function from geojson-polygon-aggregate by passing it the field name as an argument.  If a string, then it's the path of a module that exports a layer to aggregation object map (see `#grid` for details).\n    -   `opts.postAggregations` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)=** Path to a module mapping layer names to postAggregations objects.  See `#grid` for details.\n    -   `opts.jobs` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** The number of jobs to run in parallel.\n-   `done` **[function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** called with (err) when done\n\n## Built With\n\n-   [Turf.js](http://turfjs.org),\n    [geojson-vt](https://github.org/mapbox/geojson-vt), and several other super\n    fly modules by [Mapbox](https://github.com/mapbox)\n-   Also, several conversations with @morganherlocker (the author of many of the\n    aforementioned modules, including Turf.)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevelopmentseed%2Fvt-grid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevelopmentseed%2Fvt-grid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevelopmentseed%2Fvt-grid/lists"}