Итак, моя цель — получить заданный путь из 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...

и вот Путь отображается на моей карте Листовки.

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



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вот как выглядит 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: '© <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/
Да, потому что несколько способов могут использовать одни и те же узлы. Порядок <node> элементов в файле не имеет значения. Порядок <nd> предметов имеет значение.
Ах, так OSM обеспечивает порядок внутри Пути и позволяет пользователю сопоставлять Узлы со ссылками внутри Пути. Большое спасибо за помощь, исправление сработало отлично!