如何访问下载的 OSM 数据

问题描述 投票:0回答:1

我正在使用 js/node。按照 You requested too many nodes (limit is 50000) 处的说明进行操作。要么请求更小的区域,要么使用 planet.osm 我已经下载了一个 670MB 的文件,代表一个地理区域中的节点。当我在 vim 中打开它时,它看起来像 xml。

我有兴趣在这个区域内寻找高速公路节点/道路网络。我如何查询这个大文件以获取适当的节点/LineString?

javascript node.js xml gis openstreetmap
1个回答
0
投票

好吧,所以我做了一些假设:

  1. 整个数据集基本上看起来就像你的屏幕转储。
  2. 在我的虚拟数据集中,我每 6:th node 一个高速公路节点,里面有 3 个标签(traffic_signals 等)。
  3. 我还假设(仅在生成 JSON 时对我来说很重要)lat 和 long 总是以相同的顺序出现。

我采取了两种平行的方法:

  1. 生成一个新的 XML 文件,所有信息都完好无损,但只保留内部带有“高速公路”的节点。
  2. 为每条高速公路生成一个只有“long”和“lat”的最小 JSON 结构,处理标签/traffic_signals 甚至 id。因此,我们在 JSON 数据文件中只剩下高速公路的坐标...

我不知道这些方法中的任何一种是否是您想要的,但我认为您可以使用代码作为起点!

我创建了一个比你说的稍微大一点的虚拟数据文件,713MB。

这是我写的解析器(在 Node.js 中运行),解析这些数据的技巧是逐行(或以小块)读写,而不是试图将所有数据保存在内存中。 ..

const fs = require('fs');
const readline = require('readline');

parse('./data.xml', './highways.xml', './compact.json');

async function parse(inFile, outFile, jsonFile) {
  let startTime = Date.now();
  const inStream = fs.createReadStream(inFile);
  const outStream = fs.createWriteStream(outFile);
  const jsonStream = fs.createWriteStream(jsonFile);
  const rl = readline.createInterface({
    input: inStream,
    crlfDelay: Infinity // consider \r\n to be a single line break
  });
  // Parse line by line
  let inNode = false, nodeMem, firstJsonObj = true;
  jsonStream.write('[\n');
  for await (const line of rl) {
    // look for node spanning several lines
    if (line.trim().indexOf('<node ') === 0 && line.trim().slice(-2) !== '/>') {
      nodeMem = [];
      inNode = true;
    }
    inNode && nodeMem.push(line);
    if (line.trim().indexOf('</node>') === 0) {
      inNode = false;
      nodeMem = nodeMem.join('\n');
      if (nodeMem.includes('k="highway"')) {
        outStream.write(nodeMem + '\n');
        let j = nodeMem.split('\n')[0];
        j = j.slice(j.indexOf('lat'));
        j = '{' + j.replaceAll('"', '')
          .replaceAll('=', ':').replaceAll('>', '}')
          .replace(/(lat|lon)/g, '"$1"')
          .replaceAll('"lon":', ', "lon":');
        !firstJsonObj && (j = ',\n' + j);
        jsonStream.write('  ' + j);
        firstJsonObj = false;
      }
    }
  }
  // close out streams
  outStream.end();
  jsonStream.write('\n]');
  jsonStream.end();
  console.log('Found all those highways and wrote ' +
    'a verbose XML file and a compact JSON file.');
  console.log(`Time taken ${Date.now() - startTime} ms...`);
}

在我的 Macbook Pro 2021(14" 基本版)上,读取、解析和写入花费了 7151 毫秒。

创建的新的、冗长的 XML 文件,只保留了高速公路节点,大小为 295 MB。

简洁的 JSON 文件大小为 63 MB。

小到足以让我们能够在 Node.js 中将整个 JSON 文件读取到内存中。我用以下代码测试了它:

let startTime = Date.now();
let highways = require('./compact.json');
console.log("Read the json in ", Date.now() - startTime, 'ms');

将所有 JSON 读入内存(作为数据结构)花费了 338 毫秒。

现在你可以用所有这些坐标做任何你想做的事;)进一步过滤它们以进行不同的搜索——通过 REST api 返回它们的一部分。或者也许先将它们写入数据库......

干杯!

© www.soinside.com 2019 - 2024. All rights reserved.