Travailler avec GeoJSON dans Node.js: une introduction pratique

GeoJSON est un format normalisé pour représenter les structures de données géographiques basé sur JSON. Il existe de nombreux excellents outils pour visualiser les données GeoJSON. De plus, ce format est bon non seulement dans le stockage des coordonnées de certains points. Il, en plus des points, vous permet de décrire d'autres objets: lignes, polygones, collections d'objets.



Points - Objets ponctuels


Le point GeoJSON ressemble à ceci:

{
  "type": "Point",
  "coordinates": [-80.1347334, 25.7663562]
}

Ce point représente un parc à Miami Beach, Floride, USA. Vous pouvez facilement visualiser ce point sur la carte à l'aide du projet geojson.io .


Point sur la carte

Il est important de noter que les coordonnées dans la propriété sontcoordinatesécrites au format[lng, lat]. La longitude dans GeoJSON précède la latitude . En effet, la longitude représente la direction est-ouest (axexsur une carte typique) et la latitude représente la direction nord-sud (axeysur une carte typique). Les auteurs de GeoJSON ont cherché à maintenir l' ordre des coordonnéesx, y.

Un exemple typique d'utilisation de points GeoJSON est le géocodage - traduction d'adresses comme "429 Lenox Ave, Miami Beach, FL" en coordonnées exprimées en longitude et latitude. Par exemple, nous utilisons l' APIMapbox de géocodage. Pour accéder à cette API, une demande HTTP doit être envoyée au point de terminaison suivant:

https://api.mapbox.com/geocoding/v5/mapbox.places/429%20lenox%20ave%20miami.json?access_token=pk.eyJ1IjoibWF0dGZpY2tlIiwiYSI6ImNqNnM2YmFoNzAwcTMzM214NTB1NHdwbnoifQ.Or19S7KmYPHW8YjRz82v6g&cachebuster=1581993735895&autocomplete=true

En réponse, le code suivant viendra:

{"type":"FeatureCollection","query":["429","lenox","ave","miami"],"features":[{"id":"address.8052276751051244","type":"Feature","place_type":["address"],"relevance":1,"properties":{"accuracy":"rooftop"},"text":"Lenox Avenue","place_name":"429 Lenox Avenue, Miami Beach, Florida 33139, United States","center":[-80.139145,25.77409],"geometry":{"type":"Point","coordinates":[-80.139145,25.77409]}, ...}

Si vous regardez attentivement la réponse, il s'avère que features[0].geometrydans le code JSON, il s'agit d'un point GeoJSON:

{"type":"Point","coordinates":[-80.139145,25.77409]}


Visualisation des coordonnées des cartes statiques

API Mapbox est un excellent outil pour afficher des points sur les cartes. Vous trouverez ci-dessous un script qui décode la chaîne qui lui est transmise et renvoie l'URL de l'image qui montre le premier résultat de la recherche.

const axios = require('axios');

async function search(str) {
  const geocoderUrl = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' +
    encodeURIComponent(str) +
    '.json?access_token=' +
    'pk.eyJ1IjoibWF0dGZpY2tlIiwiYSI6ImNqNnM2YmFoNzAwcTMzM214NTB1NHdwbnoifQ.Or19S7KmYPHW8YjRz82v6g';

  const res = await axios.get(geocoderUrl).then(res => res.data);
  const point = res.features[0].geometry;

  return 'https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/' +
    'pin-l-1+333(' + point.coordinates[0] + ',' + point.coordinates[1] + ')/' +
    point.coordinates[0] + ',' + point.coordinates[1] +
    ',14.25,0,0/600x600/' +
    '?access_token=pk.eyJ1IjoibWF0dGZpY2tlIiwiYSI6ImNqNnM2YmFoNzAwcTMzM214NTB1NHdwbnoifQ.Or19S7KmYPHW8YjRz82v6g';
}

search('429 Lenox Ave, Miami Beach').then(res => console.log(res));


Un exemple de visualisation d'un point sur une carte

Lines - Objets LineString


Dans les lignes GeoJSON, les objets LineStringreprésentent des tableaux de coordonnées qui décrivent une ligne sur une carte. Ce qui suit est un objet GeoJSON LineStringreprésentant la frontière approximative entre les États de Californie et de l'Oregon aux États-Unis:

{
  "type": "LineString",
  "coordinates": [[-124.2, 42], [-120, 42]]
}


Rendu d'un LineString sur une carte Les

lignes, à l'aide d'une API de navigation comme Mapbox , sont utilisées pour rendre un chemin pas à pas entre deux points. Une façon de représenter une route d'un point[-80.139145,25.77409](bureau WeWork à Miami Beach) à un point[-80.2752743,25.7938434](aéroport international de Miami) est d'utiliser un objet GeoJSONLineString:

{
  "type": "LineString",
  "coordinates": [
    [-80.139153, 25.774281],
    [-80.13829, 25.774307],
    [-80.142029, 25.774479],
    [-80.148438, 25.772148],
    [-80.151237, 25.772232],
    [-80.172043, 25.78116],
    [-80.177322, 25.787195],
    [-80.185326, 25.787212],
    [-80.189804, 25.785891],
    [-80.19268, 25.785954],
    [-80.202301, 25.789175],
    [-80.207954, 25.788721],
    [-80.223, 25.782646],
    [-80.231026, 25.78261],
    [-80.238007, 25.784889],
    [-80.246025, 25.784403],
    [-80.249611, 25.785175],
    [-80.253166, 25.786049],
    [-80.259262, 25.786324],
    [-80.264038, 25.786186],
    [-80.264221, 25.787256],
    [-80.264214, 25.791618],
    [-80.264221, 25.792633],
    [-80.264069, 25.795443],
    [-80.263397, 25.795652],
    [-80.263786, 25.794928],
    [-80.267723, 25.794926],
    [-80.271141, 25.794859],
    [-80.273163, 25.795704],
    [-80.275009, 25.796482],
    [-80.277481, 25.796461],
    [-80.278435, 25.795622],
    [-80.278061, 25.794088],
    [-80.275276, 25.793804]
  ]
}

Les objets LineStringqui sont des routes peuvent être très complexes. L'objet ci-dessus, par exemple, décrit un court trajet de 15 minutes. Voici à quoi tout cela ressemble sur la carte.


Chemin d'un point à un autre

Voici un script simple qui renvoie uneLineStringreprésentation du chemin entre 2 points à l'aide de l'APIdirectionsMapbox.

const axios = require('axios');

async function directions(fromPt, toPt) {
  const fromCoords = fromPt.coordinates.join(',');
  const toCoords = toPt.coordinates.join(',');
  const directionsUrl = 'https://api.mapbox.com/directions/v5/mapbox/driving/' +
    fromCoords + ';' + toCoords + '?' +
    'geometries=geojson&' +
    'access_token=pk.eyJ1IjoibWF0dGZpY2tlIiwiYSI6ImNqNnM2YmFoNzAwcTMzM214NTB1NHdwbnoifQ.Or19S7KmYPHW8YjRz82v6g';

  const res = await axios.get(directionsUrl).then(res => res.data);
  return res.routes[0].geometry;
}

const wework = { type: 'Point', coordinates: [-80.139145,25.77409] };
const airport = { type: 'Point', coordinates: [-80.2752743,25.7938434] };

directions(wework, airport).then(res => {
  console.log(res);
});

Polygones - Objets polygonaux


Les polygones GeoJSON, objets Polygon, sont utilisés pour décrire des zones fermées sur des cartes. Il peut s'agir de zones sous la forme d'un triangle, d'un carré, d'un dodécagone ou de toute autre figure avec un nombre fixe de côtés. Par exemple, l'objet GeoJSON suivant décrit approximativement les frontières de l'État du Colorado aux États-Unis:

{
  "type": "Polygon",
  "coordinates": [[
    [-109, 41],
    [-102, 41],
    [-102, 37],
    [-109, 37],
    [-109, 41]
  ]]
}


Visualisation d'un polygone sur une carte Les

polygones GeoJSON peuvent être utilisés pour décrire des formes très complexes. Par exemple, pendant un certain temps, Uber a utilisé le seul terrain d'entraînement GeoJSON, qui comprend les 3 principaux aéroports de la baie de San Francisco.


Polygone GeoJSON complexe

Il est vrai que les polygones GeoJSON ne peuvent pas représenter des cercles et des ellipses.

À quoi servent les polygones? Habituellement - pour décrire les geofences . Par exemple, imaginez que vous travaillez à Uber ou à Lyft. Vous devez montrer aux utilisateurs qui réservent des voyages depuis l'aéroport un écran spécial. Pour ce faire, vous devrez savoir si le point à partir duquel le voyage est réservé est dans la plage décrivant l'aéroport (ou plusieurs aéroports comme dans la figure précédente).

Une façon de vérifier qu'un point GeoJSON se trouve dans le polygone est d' utiliser le module Turpm npm. Le module @turf/boolean-point-in-polygon vous permet de savoir si un point se trouve dans le polygone.

const pointInPolygon = require('@turf/boolean-point-in-polygon').default;

const colorado = {
  "type": "Polygon",
  "coordinates": [[
    [-109, 41],
    [-102, 41],
    [-102, 37],
    [-109, 37],
    [-109, 41]
  ]]
};

const denver = {
  "type": "Point",
  "coordinates": [-104.9951943, 39.7645187]
};

const sanFrancisco = {
  "type": "Point",
  "coordinates": [-122.4726194, 37.7577627]
};

// true
console.log(pointInPolygon(denver, colorado));

// false
console.log(pointInPolygon(sanFrancisco, colorado));

Le package Turf vous permet de savoir si un point se trouve dans le polygone à l'aide de Node.js. Mais que se passe-t-il si nous souhaitons obtenir les mêmes informations en exécutant des requêtes dans la base de données? Dans ce cas, vous devez savoir que l' instruction MongoDB intégrée prend en $geoIntersectscharge GeoJSON. Par conséquent, par exemple, vous pouvez écrire une requête qui vous permet de savoir quel état américain correspond à un certain point sur la carte:

const mongoose = require('mongoose');

run().catch(err => console.log(err));

async function run() {
  await mongoose.connect('mongodb://localhost:27017/geotest', {
    useNewUrlParser: true,
    useUnifiedTopology: true
  });
  await mongoose.connection.dropDatabase();

  const State = mongoose.model('State', mongoose.Schema({
    name: String,
    location: mongoose.Schema({
      type: String,
      coordinates: [[[Number]]]
    })
  }));

  const colorado = await State.create({
    name: 'Colorado',
    location: {
      "type": "Polygon",
      "coordinates": [[
        [-109, 41],
        [-102, 41],
        [-102, 37],
        [-109, 37],
        [-109, 41]
      ]]
    }
  });

    const denver = {
    "type": "Point",
    "coordinates": [-104.9951943, 39.7645187]
  };

  const sanFrancisco = {
    "type": "Point",
    "coordinates": [-122.4726194, 37.7577627]
  };

  //     ?
  let res = await State.findOne({
    location: {
      $geoIntersects: { $geometry: denver }
    }
  });
  res.name; // 

  //     -?
  res = await State.findOne({
    location: {
      $geoIntersects: { $geometry: sanFrancisco }
    }
  });
  res; // null
}

Sommaire


GeoJSON n'est pas seulement un stockage de coordonnées de points. Vous pouvez stocker des chemins dans ce format. En utilisant les données GeoJSON, vous pouvez savoir quand un utilisateur est entré dans la zone géographique. Et si nécessaire, GeoJSON vous permet même de créer des isochrones . Autour du format GeoJSON, un ensemble d'excellents outils s'est formé. Ainsi, la ressource geojson.io vous permet d'effectuer une visualisation simple des coordonnées sur la carte. Le projet Mapbox donne accès à des API géographiques avancées. Le package Turf vous permet d'effectuer des calculs géospatiaux dans les navigateurs et dans Node.js.

MongoDB prend en charge les requêtes liées aux données géographiques. Et si vous stockez les coordonnées géographiques des points sous forme de paires de valeurs, sans utiliser le format GeoJSON, cela signifie que vous manquez la possibilité d'utiliser d'excellents outils de développement.

Chers lecteurs! Utilisez-vous le format GeoJSON?


All Articles