OSM API Way Nodes заказаны неправильно

Итак, моя цель — получить заданный путь из OSM для отображения на карте Leaflet. Однако, когда я пытаюсь вытащить данный Путь, кажется, что Узлы не упорядочены в ответе правильно.

import axios from 'axios'
import xml2js from 'xml2js'

let parser = new xml2js.Parser()

export default {
  async getStpPolygon () {
    let xml = await axios.get('https://www.openstreetmap.org/api/0.6/way/39394541/full')

    return parseNodes(xml)
  },

  async getMplsPolygon () {
    let xml = await axios.get('https://www.openstreetmap.org/api/0.6/way/93481561/full')

    return parseNodes(xml)
  }
}

async function parseNodes (xml) {
  return new Promise((resolve, reject) => {
    parser.parseString(xml.data, (err, data) => {
      if (err) reject(err)

      let output = data.osm.node.map((node) => {
        return [
          parseFloat(node.$.lat),
          parseFloat(node.$.lon)
        ]
      })

      resolve(output)
    })
  })
}

Вот пример пути, отображаемого на официальной карте OSM... OSM API Way Nodes заказаны неправильно

и вот Путь отображается на моей карте Листовки. OSM API Way Nodes заказаны неправильно

Заранее благодарю за любую помощь!

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
396
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот как выглядит XML:

<?xml version = "1.0" encoding = "UTF-8"?>
<osm version = "0.6" generator = "CGImap 0.6.1 (18903 thorn-01.openstreetmap.org)" copyright = "OpenStreetMap and contributors" attribution = "http://www.openstreetmap.org/copyright" license = "http://opendatacommons.org/licenses/odbl/1-0/">
 <node id = "1083701880" visible = "true" version = "1" changeset = "6873749" timestamp = "2011-01-05T16:51:40Z" user = "neuhausr" uid = "16591" lat = "44.9751170" lon = "-93.2758411"/>
 <node id = "1083701882" visible = "true" version = "1" changeset = "6873749" timestamp = "2011-01-05T16:51:40Z" user = "neuhausr" uid = "16591" lat = "44.9746502" lon = "-93.2772842"/>
 <node id = "1083701938" visible = "true" version = "1" changeset = "6873749" timestamp = "2011-01-05T16:51:41Z" user = "neuhausr" uid = "16591" lat = "44.9727679" lon = "-93.2778367"/>
 <node id = "1083701987" visible = "true" version = "1" changeset = "6873749" timestamp = "2011-01-05T16:51:42Z" user = "neuhausr" uid = "16591" lat = "44.9730222" lon = "-93.2787594"/>
 <node id = "1083701993" visible = "true" version = "1" changeset = "6873749" timestamp = "2011-01-05T16:51:42Z" user = "neuhausr" uid = "16591" lat = "44.9737736" lon = "-93.2793709"/>
 <node id = "1083702026" visible = "true" version = "1" changeset = "6873749" timestamp = "2011-01-05T16:51:43Z" user = "neuhausr" uid = "16591" lat = "44.9754130" lon = "-93.2765707"/>
 <way id = "93481561" visible = "true" version = "1" changeset = "6873749" timestamp = "2011-01-05T16:51:43Z" user = "neuhausr" uid = "16591">
  <nd ref = "1083701993"/>
  <nd ref = "1083701987"/>
  <nd ref = "1083701938"/>
  <nd ref = "1083701880"/>
  <nd ref = "1083702026"/>
  <nd ref = "1083701882"/>
  <nd ref = "1083701993"/>
  <tag k = "amenity" v = "university"/>
  <tag k = "name" v = "University of St. Thomas"/>
 </way>
</osm>

Обратите внимание, что в XML-формат OSM описаны два типа информации:

A node is one of the core elements in the OpenStreetMap data model. It consists of a single point in space defined by its latitude, longitude and node id.

  • прочь предоставляет упорядоченный список тегов nd, ссылающихся на узлы.

A way is an ordered list of nodes [...]

Итак, чтобы получить координаты в правильном порядке, вам нужно будет изменить свою функцию синтаксического анализа на что-то вроде:

async function parseNodes (xml) {
    return new Promise((resolve, reject) => {
        parser.parseString(xml.data, (err, data) => {
            if (err) reject(err)

            //map node ids to their coordinates
            const refs = {};
            data.osm.node.forEach((node) => {
                const attrs = node.$;
                refs[attrs.id] = [+attrs.lat, +attrs.lon];
            });

            // return the coordinates in the correct order
            const output = data.osm.way.nd.map((nd) => {
                const id = nd.$.ref;
                return refs[id];
            });

            resolve(output)
        })
    })
}

И демо

async function  getStpPolygon () {
    const resp = await axios.get('https://www.openstreetmap.org/api/0.6/way/93481561/full')

    const json = xml2js(resp.data, {compact: true});
    const refs = {};
    json.osm.node.forEach((node) => {
        const attrs = node._attributes;
        refs[attrs.id] = [+attrs.lat, +attrs.lon];
    });
    
    return json.osm.way.nd.map((nd) => {
        const id = nd._attributes.ref;
        return refs[id];
    });
};


var map = L.map('map').setView([44.97386, -93.27569], 15);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href = "https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);


getStpPolygon().then((points) => {
    L.polyline(points).addTo(map);
});
#map { width: 100%; height:200px }
<link rel = "stylesheet" href = "https://unpkg.com/[email protected]/dist/leaflet.css"/>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<script src = "https://cdn.jsdelivr.net/npm/[email protected]/dist/xml-js.min.js"></script>
<script src = "https://unpkg.com/[email protected]/dist/leaflet.js"></script>

<div id = "map"></div>

Доступная рабочий пример: https://jsfiddle.net/mnf9eL3o/

Ах, так OSM обеспечивает порядок внутри Пути и позволяет пользователю сопоставлять Узлы со ссылками внутри Пути. Большое спасибо за помощь, исправление сработало отлично!

Chase Ingebritson 08.03.2019 19:09

Да, потому что несколько способов могут использовать одни и те же узлы. Порядок <node> элементов в файле не имеет значения. Порядок <nd> предметов имеет значение.

scai 11.03.2019 14:52

Другие вопросы по теме