简体   繁体   English

OSM API方式节点排序错误

[英]OSM API Way Nodes Ordered Incorrectly

So my goal is to be able to pull a given Way from OSM to display on a Leaflet map. 因此,我的目标是能够从OSM中提取给定的Way,以显示在Leaflet地图上。 However, when I attempt to pull a given Way, the Nodes don't seem to be ordered correctly in the response. 但是,当我尝试拉出给定的Way时,响应中的Node似乎没有正确排序。

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

Here is an example of the way being displayed on the official OSM map... 这是在官方OSM地图上显示方式的示例 ... 官方地图

and here is the Way being displayed on my Leaflet map. 这是在我的传单地图上显示的方式。 我的地图

Thanks in advance for any help! 在此先感谢您的帮助!

Here's what the XML looks like: 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>

Note that there are two types of information described in the OSM XML format : 请注意, OSM XML格式描述了两种信息:

A node is one of the core elements in the OpenStreetMap data model. 节点是OpenStreetMap数据模型的核心元素之一。 It consists of a single point in space defined by its latitude, longitude and node id. 它由空间中的一个点组成,该点由其纬度,经度和节点ID定义。

  • a way exposing an ordered list of nd tags referencing the nodes. 一种公开引用节点的nd标签的有序列表的方法

A way is an ordered list of nodes [...] 一种方法是节点的有序列表[...]

So, to get the coordinates in the correct order, you would have to modify your parsing function to something like: 因此,为了以正确的顺序获取坐标,您必须将解析函数修改为以下形式:

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

And a demo 和演示

 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/leaflet@1.4.0/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/xml-js@1.6.11/dist/xml-js.min.js"></script> <script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script> <div id="map"></div> 

Fiddle available: https://jsfiddle.net/mnf9eL3o/ 提琴可用: https : //jsfiddle.net/mnf9eL3o/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2025 STACKOOM.COM