Bekerja dengan GeoJSON di Node.js: pengantar praktis

GeoJSON adalah format standar untuk mewakili struktur data geografis berdasarkan JSON. Ada banyak alat hebat untuk memvisualisasikan data GeoJSON. Apalagi format ini bagus bukan hanya dalam penyimpanan koordinat titik-titik tertentu. Selain poin, Anda dapat mendeskripsikan objek lain: garis, poligon, koleksi objek.



Poin - Objek titik


Titik GeoJSON terlihat seperti ini:

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

Titik ini mewakili taman di Miami Beach, Florida, AS. Anda dapat dengan mudah memvisualisasikan titik ini di peta menggunakan proyek geojson.io .


Arahkan pada peta

Penting untuk dicatat bahwa koordinat dalam properticoordinatesditulis dalam format[lng, lat]. Bujur di GeoJSON hadir sebelum garis lintang . Ini karena garis bujur mewakili arah timur-barat (sumbuxpada peta tipikal), dan garis lintang mewakili arah utara-selatan (sumbuypada peta tipikal). Penulis GeoJSON berusaha untuk menjaga ketertiban koordinatx, y.

Contoh khas menggunakan poin GeoJSON adalah geocoding - menerjemahkan alamat seperti "429 Lenox Ave, Miami Beach, FL" ke dalam koordinat yang dinyatakan dalam bujur dan lintang. Misalnya, kami menggunakan APIGeocoding Mapbox. Untuk mengakses API ini, permintaan HTTP harus dilakukan ke titik akhir berikut:

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

Sebagai tanggapan, kode berikut akan datang:

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

Jika Anda mencermati jawabannya, ternyata features[0].geometrydalam kode JSON itu adalah poin GeoJSON:

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


Visualisasi dari koordinat peta statis

API Mapbox adalah alat yang hebat untuk menampilkan titik pada peta. Di bawah ini adalah skrip yang menerjemahkan string yang diteruskan ke sana dan mengembalikan URL ke gambar yang menunjukkan hasil pencarian pertama.

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


Contoh memvisualisasikan titik pada peta

Lines - Objek LineString


Dalam garis GeoJSON, objek LineStringmewakili array koordinat yang menggambarkan garis pada peta. Berikut ini adalah objek GeoJSON yang LineStringmewakili perkiraan perbatasan antara negara bagian California dan Oregon di AS:

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


Rendering LineString pada

Garis Peta , menggunakan API navigasi seperti Mapbox , digunakan untuk membuat jalur langkah-demi-langkah antara dua titik. Salah satu cara untuk mewakili jalan dari titik[-80.139145,25.77409](kantor WeWork Miami Beach) ke titik[-80.2752743,25.7938434](Bandara Internasional Miami) adalah dengan menggunakan objek 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]
  ]
}

Objek LineStringyang merupakan beberapa rute bisa sangat kompleks. Objek di atas, misalnya, menggambarkan perjalanan singkat 15 menit. Ini adalah tampilannya di peta.


Jalur dari satu titik ke titik lainnya

Berikut ini adalah skrip sederhana yang mengembalikanLineStringrepresentasi jalur antara 2 titik menggunakandirectionsMapboxAPI.

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

Poligon - Objek Poligon


GeoJSON poligon, objek Polygon, digunakan untuk menggambarkan area tertutup pada peta. Ini bisa berupa area dalam bentuk segitiga, persegi, dodecagon , atau bentuk lain dengan jumlah sisi yang tetap. Sebagai contoh, objek GeoJSON berikut secara kasar menggambarkan perbatasan negara bagian Colorado di AS:

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


Visualisasi poligon pada peta

GeoJSON poligon dapat digunakan untuk menggambarkan bentuk yang sangat kompleks. Misalnya, untuk beberapa waktu Uber menggunakan satu-satunya tempat pelatihan GeoJSON, yang mencakup semua 3 bandara utama di wilayah Teluk San Francisco.


Poligon Kompleks GeoJSON

Benar, harus dicatat bahwa poligon GeoJSON tidak dapat mewakili lingkaran dan elips.

Untuk apa poligon digunakan? Biasanya - untuk menggambarkan geofences . Misalnya, bayangkan Anda bekerja di Uber atau di Lyft. Anda perlu menunjukkan kepada pengguna yang memesan perjalanan dari bandara dengan layar khusus. Untuk melakukan ini, Anda harus mencari tahu apakah titik dari mana perjalanan dipesan berada dalam kisaran yang menggambarkan bandara (atau beberapa bandara seperti pada gambar sebelumnya).

Salah satu cara untuk memverifikasi bahwa titik GeoJSON berada dalam poligon adalah dengan menggunakan modul Turpm npm. Modul ini @turf/boolean-point-in-polygon memungkinkan Anda untuk mengetahui apakah suatu titik berada dalam poligon.

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

Paket Turf memungkinkan Anda untuk mengetahui apakah suatu titik berada dalam poligon menggunakan Node.js. Tetapi bagaimana jika kita tertarik untuk memperoleh informasi yang sama dengan mengeksekusi query ke database? Dalam hal ini, Anda harus menyadari bahwa pernyataan MongoDB $geoIntersectsbawaan mendukung GeoJSON. Karena itu, misalnya, Anda dapat menulis kueri yang memungkinkan Anda untuk mengetahui negara bagian AS mana yang sesuai dengan titik tertentu di peta:

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
}

Ringkasan


GeoJSON bukan hanya penyimpanan koordinat titik. Anda dapat menyimpan jalur dalam format ini. Dengan menggunakan data GeoJSON, Anda dapat mengetahui kapan seorang pengguna memasukkan geofence. Dan jika perlu, maka GeoJSON bahkan memungkinkan Anda untuk membuat isochrones . Di sekitar format GeoJSON, seperangkat alat hebat telah terbentuk. Jadi, sumber daya geojson.io memungkinkan Anda untuk melakukan visualisasi koordinat sederhana pada peta. Proyek Mapbox menyediakan akses ke API geografis lanjutan. Paket Turf memungkinkan Anda untuk melakukan komputasi geospasial di browser dan di Node.js.

MongoDB mendukung kueri yang terkait dengan data geografis. Dan jika Anda menyimpan koordinat geografis titik sebagai pasangan nilai, tanpa menggunakan format GeoJSON, ini berarti Anda kehilangan peluang untuk menggunakan beberapa alat pengembangan yang hebat.

Pembaca yang budiman! Apakah Anda menggunakan format GeoJSON?


All Articles