OSM的道路圖

Table of contents

背景

overpass-turbo

切割站台

#網址規則
https://overpass-turbo.eu/?Q=
/* This has been generated by the overpass-turbo wizard. The original search was: 
“type=route & route=bus” */ 
/[out:json][timeout:25]; 
// gather results 
( 
  // query part for: “type=route and route=bus” 
  way[highway](); 
); 
// print results 
out body; 
  >; 
  out skel qt; 
&C=51.18533;3.56321;16
url="https://overpass-api.de/api/interpreter?data=%2F%2F%20%40name%20songshanAirport%0A%0A%2F*%0AThis%20has%20been%20generated%20by%20the%20overpass-turbo%20wizard.%0AThe%20original%20search%20was%3A%0A%E2%80%9Ctype%3Droute%20%26%20route%3Dbus%E2%80%9D%0A*%2F%0A%5Bout%3Ajson%5D%5Btimeout%3A25%5D%3B%0A%2F%2F%20gather%20results%0A%28%0A%20%20%2F%2F%20query%20part%20for%3A%20%E2%80%9Ctype%3Droute%20and%20route%3Dbus%E2%80%9D%0A%20%20way%5Bhighway%5D%2825.06289035627052%2C121.54017305374147%2C25.07091380670631%2C121.56654024124147%29%3B%0A%29%3B%0A%2F%2F%20print%20results%0Aout%20body%3B%0A%3E%3B%0Aout%20skel%20qt%3B"

source

  • source code
  • main author:
    • Martin Raifer(tyr_asd)
    • HeiGIT: Heidelberg, DE

json format

OSM JSON

import json
import xml.etree.ElementTree as ET

# 載入 Overpass API 的 JSON 數據
with open('overpass_output.json') as f:
    data = json.load(f)

# 創建 OSM 根元素
osm = ET.Element('osm', version='0.6')

# 將 JSON 數據轉換為 OSM XML
for element in data['elements']:
    if element['type'] == 'node':
        node = ET.SubElement(osm, 'node', id=str(element['id']), lat=str(element['lat']), lon=str(element['lon']))
    elif element['type'] == 'way':
        way = ET.SubElement(osm, 'way', id=str(element['id']))
        for nd in element['nodes']:
            ET.SubElement(way, 'nd', ref=str(nd))
    elif element['type'] == 'relation':
        relation = ET.SubElement(osm, 'relation', id=str(element['id']))
        for member in element['members']:
            ET.SubElement(relation, 'member', type=member['type'], ref=str(member['ref']), role=member.get('role', ''))

# 將 OSM XML 寫入檔案
tree = ET.ElementTree(osm)
tree.write('output.osm', encoding='utf-8', xml_declaration=True)
  • Overpass API切割結果似乎沒有relations
In [14]: set([ element['type'] for element in data['elements']])
Out[14]: {'node', 'way'}

Geofabrik

description

下載台灣地區的 OpenStreetMap 資料

此伺服器上提供的 OpenStreetMap 資料檔案不包含OSM 物件的使用者名稱、使用者 ID 和變更集 ID,因為這些欄位被假定包含有關 OpenStreetMap 貢獻者的個人信息,因此受歐盟資料保護法規的約束。 包含完整元資料的摘錄僅供 OpenStreetMap 貢獻者使用。

常用格式

  • taiwan-latest.osm.pbf,適用於 Osmium、Osmosis、imposm、osm2pgsql、mkgmap 等。文件的最後修改時間為 1 天前,包含截至 該時間 的所有 OSM 資料。檔案大小:275 MB; MD5 總和:17bf64369467e02da9a4753fe6335414。
  • taiwan-latest-free.shp.zip,解壓縮後會產生許多與 ESRI 相容的形狀檔。(格式說明PDF)該文件最後修改時間為23小時前。檔案大小:203 MB; MD5 總和:723227f0761ef8b02e950e055798a007。

其他格式和輔助文件

  • taiwan-latest.osm.bz2,解壓縮後產生OSM XML;用於無法處理 .pbf 格式的程式。已棄用。該文件的最後修改時間是 100 天前。檔案大小:351 MB; MD5 總和:f511eee6b138a9a45f88d4ddd55e28cb。
  • taiwan-internal.osh.pbf 歷史文件包含個人數據,僅在內部伺服器上可用。請參閱上面的通知以了解更多資訊。
  • 描述該區域範圍的.poly 檔案
  • 符合Shortbread 架構的實驗性向量切片包,可與 MapLibre 和其他支援 MVT 的軟體一起使用
  • .osc.gz 檔案包含該區域中的所有更改,適用於 Osmosis 更新等
  • 該地區的 Taginfo 統計信息
  • 原始目錄索引可讓您查看和下載舊文件

次區域

沒有為此區域定義子區域。

file_stats

(py39) 21:15@kuang:~/MyPrograms/CADN-A 
$ python osm_file_stats.py taiwan-latest.osm 
Nodes: 21,366,772
Ways: 1,533,433
Relations: 37,756

Cutter

serial

parallel

  (py39) 20:12@kuang:~/MyPrograms/CADN-A 
  $ cat cut_osmMult2.py 
  import osmium
  import multiprocessing

  class BoundingBoxHandler(osmium.SimpleHandler):
      def __init__(self, min_lat, min_lon, max_lat, max_lon, output_file):
          super().__init__()
          self.min_lat = min_lat
          self.min_lon = min_lon
          self.max_lat = max_lat
          self.max_lon = max_lon
          self.writer = osmium.SimpleWriter(output_file)

      def node(self, n):  
          if self.min_lat <= n.location.lat <= self.max_lat and self.min_lon <= n.location.lon <= self.max_lon:
              self.writer.add_node(n)

      def way(self, w):
          if any(self.min_lat <= n.lat <= self.max_lat and self.min_lon <= n.lon <= self.max_lon for n in w.nodes):
              self.writer.add_way(w)

      def relation(self, r):
          if any(self.min_lat <= n.lat <= self.max_lat and self.min_lon <= n.lon <= self.max_lon for n in r.nodes):
              self.writer.add_relation(r)

      def close(self):
          self.writer.close()

  def process_bbox(min_lat, min_lon, max_lat, max_lon, input_file, output_file):
      handler = BoundingBoxHandler(min_lat, min_lon, max_lat, max_lon, output_file)
      handler.apply_file(input_file)
      handler.close()

  def divide_bbox(min_lat, min_lon, max_lat, max_lon, num_parts):
      lat_step = (max_lat - min_lat) / num_parts
      lon_step = (max_lon - min_lon) / num_parts
      bboxes = []
      for i in range(num_parts):
          for j in range(num_parts):
              bboxes.append((min_lat + i * lat_step, min_lon + j * lon_step,
                            min_lat + (i + 1) * lat_step, min_lon + (j + 1) * lon_step))
      return bboxes

  if __name__ == '__main__':
      # 設定經緯度範圍
      min_lat = 25.0562234
      min_lon = 121.5332504
      max_lat = 25.0792724
      max_lon = 121.5712818

      # 分割經緯度範圍
      num_parts = 3  # 這裡設置為3x3的區塊
      bboxes = divide_bbox(min_lat, min_lon, max_lat, max_lon, num_parts)

      # 使用多進程處理每個區塊
      processes = []
      for i, bbox in enumerate(bboxes):
          p = multiprocessing.Process(target=process_bbox, args=(bbox[0], bbox[1], bbox[2], bbox[3], 'input.osm', f'output_{i}.osm'))
          processes.append(p)
          p.start()

      for p in processes:
          p.join()

使用 osmconvert

  • install:sudo apt install osmctools
  • first cut

    ln -s taiwan-latest.osm input.osm
    left=121.5332504
    right=121.5712818
    top=25.0792724
    bottom=25.0562234
    osmconvert input.osm -b=${left},${bottom},${right},${top} --complete-ways -o=output.osm
    
  • further cutting

    mv output.osm output48.osm
    ln -sf output48.osm input.osm
    echo ${left},${bottom},${right},${top}
    left=121.5432504
    right=121.5612818
    top=25.07
    bottom=25.0662234
    osmconvert input.osm -b=${left},${bottom},${right},${top} --complete-ways -o=output.osm
    
  • view by aspose

convert to KML and view

  • fail using ogr2ogr

    ogr2ogr -f "KML" output.kml input.osm
    
  • try python
  • s

BBBike

Onlne Viewers

aspose.app

  • upload and save as png
  • limitations
    • size: 32MB
    • time interval between uploadings: 2min
  • output_0.osm(3X3的西南角)

MyGeodata.Cloud