Giter VIP home page Giter VIP logo

vtquery's Introduction

vtquery

Build Status codecov node-cpp-skel

npm install @mapbox/vtquery

Get the closest features from a longitude/latitude in a set of vector tile buffers. Made possible with node-cpp-skel, vtzero, geometry.hpp, spatial-algorithms, and cheap-ruler-cpp.

The two major use cases for this library are:

  1. To get a list of the features closest to a query point
  2. Point in polygon checks (radius=0)

API

Table of Contents

vtquery

Parameters

  • tiles Array<Object> an array of tile objects with buffer, z, x, and y values
  • LngLat Array<Number> a query point of longitude and latitude to query, [lng, lat]
  • options Object?
    • options.radius Number the radius to query for features. If your radius is larger than the extent of an individual tile, include multiple nearby buffers to collect a realistic list of features (optional, default 0)
    • options.limit Number limit the number of results/features returned from the query. Minimum is 1, maximum is 1000 (to avoid pre allocating large amounts of memory) (optional, default 5)
    • options.layers Array<String>? an array of layer string names to query from. Default is all layers.
    • options.geometry String? only return features of a particular geometry type. Can be point, linestring, or polygon. Defaults to all geometry types.
    • options.dedup String perform deduplication of features based on shared layers, geometry, IDs and matching properties. (optional, default true)

Examples

const vtquery = require('@mapbox/vtquery');
const fs = require('fs');

const tiles = [
  { buffer: fs.readFileSync('./path/to/tile.mvt'), z: 15, x: 5238, y: 12666 }
];

const options = {
  radius: 0,
  limit: 5,
  geometry: 'polygon',
  layers: ['building', 'parks'],
  dedupe: true
};

vtquery(tiles, [-122.4477, 37.7665], options, function(err, result) {
  if (err) throw err;
  console.log(result); // geojson FeatureCollection
});

Response object

The response object is a GeoJSON FeatureCollection with Point features containing the following in formation:

  • Geometry - always a Point. This library does not return full geometries of features. It only returns the closest point (longitude/latitude) of a feature. If the original feature is a point, the result is the actual location of that point. If the original feature is a linestring or polygon, the result is the interpolated closest latitude/longitude point of that feature. This could be along a line of a polygon and not an actual node of a polygon. If the query point is within a polygon, the result will be the query point location.
  • Properties of the feature
  • Extra properties including:
    • tilequery.geometry_type - either "Point", "Linestring", or "Polygon"
    • tilequery.distance in meters - if distance is 0.0, the query point is within the geometry (point in polygon)
    • tilequery.layer which layer the feature was a part of in the vector tile buffer
  • An id if it existed in the vector tile feature

Here's an example response

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -122.42901,
          37.80633
        ]
      },
      "properties": {
        "property_one": "hello",
        "property_two": 15,
        "tilequery": {
          "distance": 11.3,
          "geometry": "Point",
          "layer": "parks"
        }
      }
    },
    { ... },
    { ... },
  ]
}

Point in polygon queries

To perform a "point in polygon" query, set your radius value to 0. This will only return polygons that your query point is within.

GOTCHA 1: Be aware of the number of results you are returning - there may be overlapping polygons in a tile, especially if you are querying multiple layers. If a query point exists within multiple polygons there is no way to sort them so they come back in the order they were queried. If there are more results than your numResults value specifies, they will just be cut off once the query hits the maximum number of results.

GOTCHA 2: Any query point that exists directly along an edge of a polygon will not return.

Deduplicating results

When querying across multiple tiles (or even within a single tile) it's likely source geometries have been split by the tile boundaries into multiple, seemingly unique geometries. This can result in duplicate results in a response for edges of tile boundaries, rather than actual edges of source data. Vtquery assumes features are duplicates if the following all of the following are true:

  • The features are from the same layer
  • The features are the same geometry type
  • The features have the same id AND same properties
  • The features' properties are the same (if no ids are present)

Develop

git clone [email protected]:mapbox/vtquery.git
cd vtquery

# Build binaries. This looks to see if there were changes in the C++ code. This does not reinstall deps.
make

# Run tests
make test

# Cleans your current builds and removes potential cache
make clean

# Cleans everything, including the things you download from the network in order to compile (ex: npm packages).
# This is useful if you want to nuke everything and start from scratch.
# For example, it's super useful for making sure everything works for Travis, production, someone else's machine, etc
make distclean

# Generate API docs from index.js
# Requires documentation.js to be installed globally
npm install -g documentation
npm run docs

To install and test on a linux instance, you can use the Dockerfile provided.

# build the image
docker build -t vtquery .

# run it - this will put you inside the image
docker run -it vtquery

# run tests
make test

# edit files - helpful for debugging
vim src/vtquery.cpp

Benchmarks

Benchmarks can be run with the bench/vtquery.bench.js script to test vtquery against common real-world fixtures (provided by mvt-fixtures). When making changes in a pull request, please provide the benchmarks from the master branch and the HEAD of your current branch. You can control the concurrency and iterations of the benchmarks with the following command:

node bench/vtquery.bench.js --iterations 1000 --concurrency 5

And the output will show how many times the library was able to execute per second, per fixture:

1: pip: many building polygons ... 954 runs/s (1048ms)
2: pip: many building polygons, single layer ... 1012 runs/s (988ms)
3: query: many building polygons, single layer ... 773 runs/s (1294ms)
4: query: linestrings, mapbox streets roads ... 1664 runs/s (601ms)
5: query: polygons, mapbox streets buildings ... 745 runs/s (1343ms)
6: query: all things - dense single tile ... 400 runs/s (2497ms)
7: query: all things - dense nine tiles ... 51 runs/s (19544ms)
8: elevation: terrain tile nepal ... 801 runs/s (1249ms)
9: geometry: 2000 points in a single tile, no properties ... 2083 runs/s (480ms)
10: geometry: 2000 points in a single tile, with properties ... 1047 runs/s (955ms)
11: geometry: 2000 linestrings in a single tile, no properties ... 978 runs/s (1022ms)
12: geometry: 2000 linestrings in a single tile, with properties ... 689 runs/s (1452ms)
13: geometry: 2000 polygons in a single tile, no properties ... 661 runs/s (1513ms)
14: geometry: 2000 polygons in a single tile, with properties ... 485 runs/s (2062ms)

Viz

The viz/ directory contains a small node application that is helpful for visual QA of vtquery results. It requests Mapbox Streets tiles and adds results as points to the map. In order to request tiles, you'll need a MapboxAccessToken environment variable.

cd viz
npm install
MapboxAccessToken={token} node app.js
# localhost:5000

vtquery's People

Watchers

 avatar

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.