Arbeiten mit GeoJSON in Node.js: eine praktische Einführung

GeoJSON ist ein standardisiertes Format zur Darstellung von geografischen Datenstrukturen basierend auf JSON. Es gibt viele großartige Tools zur Visualisierung von GeoJSON-Daten. Darüber hinaus eignet sich dieses Format nicht nur für die Speicherung von Koordinaten bestimmter Punkte. Neben Punkten können Sie auch andere Objekte beschreiben: Linien, Polygone, Sammlungen von Objekten.



Punkte - Punktobjekte


Der GeoJSON-Punkt sieht folgendermaßen aus:

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

Dieser Punkt repräsentiert einen Park in Miami Beach, Florida, USA. Sie können diesen Punkt auf der Karte einfach mit dem Projekt geojson.io visualisieren .


Punkt auf der Karte

Es ist wichtig zu beachten, dass die Koordinate in der Eigenschaftcoordinatesim Format geschrieben ist[lng, lat]. Der Längengrad in GeoJSON kommt vor dem Breitengrad . Dies liegt daran, dass der Längengrad die Ost-West-Richtung (Achsexauf einer typischen Karte) und der Breitengrad die Nord-Süd-Richtung (Achseyauf einer typischen Karte) darstellt. GeoJSON-Autoren versuchten, die Koordinatenreihenfolge aufrechtzuerhaltenx, y .

Ein typisches Beispiel für die Verwendung von GeoJSON-Punkten ist die Geokodierung - Adressumsetzung wie "429 Lenox Ave, Miami Beach, FL" in Koordinaten in Längen- und Breitengrad. Zum Beispiel verwenden wir die APIGeocodierung Mapbox. Um auf diese API zugreifen zu können, muss eine HTTP-Anforderung an den folgenden Endpunkt gesendet werden:

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

Als Antwort wird der folgende Code kommen:

{"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]}, ...}

Wenn Sie sich die Antwort genau ansehen, stellt sich heraus, dass es sich features[0].geometryim JSON-Code um einen GeoJSON-Punkt handelt:

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


Visualisierung der Koordinaten der statischen

API- Karten Mapbox ist ein großartiges Werkzeug zum Anzeigen von Punkten auf Karten. Unten finden Sie ein Skript, das die übergebene Zeichenfolge dekodiert und die URL zu dem Bild zurückgibt, das das erste Suchergebnis zeigt.

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));


Ein Beispiel für die Visualisierung eines Punkts auf einer Karte

Linien - LineString-Objekte


In GeoJSON-Linien stellen Objekte LineStringKoordinatenfelder dar, die eine Linie auf einer Karte beschreiben. Das folgende Objekt ist ein GeoJSON-Objekt, LineStringdas die ungefähre Grenze zwischen den Bundesstaaten Kalifornien und Oregon in den USA darstellt:

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


Das Rendern eines LineStrings auf einer Map

Lines mithilfe einer Navigations-API wie Mapbox wird verwendet, um einen schrittweisen Pfad zwischen zwei Punkten zu rendern. Eine Möglichkeit, eine Straße von einem Punkt[-80.139145,25.77409](WeWork Miami Beach Office) zu einem Punkt[-80.2752743,25.7938434](Miami International Airport)darzustellen,besteht darin, ein GeoJSON-Objekt zu verwendenLineString:

{
  "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]
  ]
}

Objekte LineString, bei denen es sich um Routen handelt, können sehr komplex sein. Das obige Objekt beschreibt beispielsweise eine kurze 15-minütige Fahrt. So sieht alles auf der Karte aus.


Pfad von einem Punkt zum anderen

Hier ist ein einfaches Skript,LineStringdas mithilfe derdirectionsMapbox-APIeineDarstellung des Pfads zwischen zwei Punktenzurückgibt.

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);
});

Polygone - Polygonobjekte


GeoJSON-Polygone, Objekte Polygon, werden verwendet, um geschlossene Bereiche auf Karten zu beschreiben. Dies können Bereiche in Form eines Dreiecks, Quadrats, Zwölfecks oder einer anderen Form mit einer festen Anzahl von Seiten sein. Das folgende GeoJSON-Objekt beschreibt beispielsweise grob die Grenzen des Bundesstaates Colorado in den USA:

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


Visualisierung eines Polygons auf einer Karte Mit

GeoJSON-Polygonen können sehr komplexe Formen beschrieben werden. Zum Beispiel nutzte Uber für einige Zeit das einzige GeoJSON-Trainingsgelände, das alle drei großen Flughäfen in der San Francisco Bay umfasst.


Komplexes GeoJSON-Polygon

Richtig, es sollte beachtet werden, dass GeoJSON-Polygone keine Kreise und Ellipsen darstellen können.

Wofür werden Polygone verwendet? Normalerweise - um Geofences zu beschreiben. Stellen Sie sich zum Beispiel vor, Sie arbeiten in Uber oder in Lyft. Sie müssen Benutzern, die Reisen vom Flughafen aus buchen, einen speziellen Bildschirm anzeigen. Dazu müssen Sie herausfinden, ob sich der Punkt, von dem aus die Reise bestellt wird, innerhalb des Polygons befindet, das den Flughafen beschreibt (oder mehrere Flughäfen wie in der vorherigen Abbildung).

Eine Möglichkeit, um zu überprüfen, ob sich ein GeoJSON-Punkt innerhalb des Polygons befindet, ist die Verwendung des Turpm npm-Moduls. Mit dem Modul @turf/boolean-point-in-polygon können Sie herausfinden, ob sich ein Punkt innerhalb des Polygons befindet.

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));

Mit dem Turf-Paket können Sie mithilfe von Node.js herausfinden, ob sich ein Punkt innerhalb des Polygons befindet. Was aber, wenn wir daran interessiert sind, dieselben Informationen durch Ausführen von Abfragen an die Datenbank zu erhalten? In diesem Fall sollten Sie sich bewusst sein, dass die integrierte MongoDB- Anweisung$geoIntersects GeoJSON unterstützt. Daher können Sie beispielsweise eine Abfrage schreiben, mit der Sie herausfinden können, welcher US-Bundesstaat einem bestimmten Punkt auf der Karte entspricht:

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
}

Zusammenfassung


GeoJSON ist nicht nur die Speicherung von Punktkoordinaten. Sie können Pfade in diesem Format speichern. Mithilfe von GeoJSON-Daten können Sie herausfinden, wann ein Benutzer den Geofence betreten hat. Bei Bedarf können Sie mit GeoJSON sogar Isochronen erstellen . Um das GeoJSON-Format herum hat sich eine Reihe großartiger Werkzeuge gebildet. Mit der Ressource geojson.io können Sie also die Koordinaten auf der Karte einfach visualisieren. Das Mapbox- Projekt bietet Zugriff auf erweiterte geografische APIs. Mit dem Turf- Paket können Sie Geospatial Computing in Browsern und in Node.js durchführen.

MongoDB unterstützt Abfragen zu geografischen Daten. Wenn Sie die geografischen Koordinaten von Punkten in Form von Wertepaaren speichern, ohne das GeoJSON-Format zu verwenden, verpassen Sie die Gelegenheit, einige wunderbare Entwicklungswerkzeuge zu verwenden.

Liebe Leser! Verwenden Sie das GeoJSON-Format?


All Articles