不写一行代码在OSM上获取AOI数据

本文主要介绍如何在OpenStreetMap上获取AOI数据,点到为止 🤏 。原文可参考我的公众号文章《不写一行代码在OSM上获取地点的轮廓数据

有时候业务上需要在地图上展示AOI(兴趣面)数据,每一个AOI对应的是一个不规则的封闭区域,由一组坐标表示,比如小区轮廓。国内的百度和高德地图都没有提供相应方法来获取这类数据(谈业务合作的话是有的),普通开发者基本拿不到。不过没关系,国外有一个OSM网站,在那里可以查询到指定类型的轮廓数据。

OSM介绍

"OpenStreetMap 是一个由地图制作爱好者组成的社区。这些爱好者提供并维护世界各地关于道路、小道、咖啡馆、铁路车站等各种各样的数据。"

编辑地图数据

访问网站 openstreetmap 支持【点、线、面】的方式在卫星地图上编辑地图。

查看地图数据

还是openstreetmap网站,搜索某一个地点,如果存在,则会在地图上展示它的轮廓,比如这里搜索"世纪公园":

如图展示了该地点的详细数据,包括是哪个用户在时候编辑的。

获取地图数据

访问网站 overpass-turbo 使用Overpass查询语言(Overpass QL)构建查询想要的数据,如:获取"上海市所有的小区"

js 复制代码
// @name 上海市所有小区

/*
 This has been generated by the overpass-turbo wizard.
 The original search was:
 "residential=apartment in Shanghai"
*/
[out:json][timeout:25];
// fetch area "Shanghai" to search in
{{geocodeArea:Shanghai}}->.searchArea;
// gather results
nwr["landuse"="residential"](area.searchArea);
// print results
out geom;

查询语句可以交给ChatGPT。点击"运行"按钮

如果查询到数据,可以点击右上角的"地图"按钮,然后点击地图工具里的放大镜:"缩放到数据",就可以在地图上显示刚刚查询的结果了。

放大地图,展示小区的轮廓:

最后可以把数据导出,支持JSON、GPX、KML,以及图片格式。

另外,也可以直接请求接口查询:

js 复制代码
const axios = require('axios');

// 构建Overpass查询
const overpass_query = `
[out:json];
area[name="上海市"]->.a;
(node["shop"="mall"](area.a); way["shop"="mall"](area.a); relation["shop"="mall"](area.a););
out body;
>;
out skel qt;
`;

// Overpass API端点
const overpass_url = "https://overpass-api.de/api/interpreter";

// 发送Overpass查询请求
axios.post(overpass_url, overpass_query)
.then(response => {
    const data = response.data;
    console.log('data:', data);
})
.catch(error => {
    console.error('Error:', error);
});

需要注意的是,数据量太大会导致查询请求报错中止,这时候可以到网页上查询试试。

查询结果demo:

js 复制代码
{
  "version": 0.6,
  "generator": "Overpass API 0.7.61.5 4133829e",
  "osm3s": {
    "timestamp_osm_base": "2024-02-18T04:08:14Z",
    "timestamp_areas_base": "2024-02-18T00:39:44Z",
    "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."
  },
  "elements": [
    {
      "type": "way",
      "id": 48873443,
      "bounds": {
        "minlat": 31.3237333,
        "minlon": 121.5218845,
        "maxlat": 31.3267723,
        "maxlon": 121.5274975
      },
      "nodes": [
        620110214,
        620110215,
        620110216,
        620110217,
        620110218,
        620110219,
        620110220,
        640424170,
        1032444307,
        640424176,
        1032444233,
        1032444238,
        620110221,
        1493810686,
        1493810647,
        1878618593,
        1493810667,
        620110222,
        620110223,
        1177786393,
        620110224,
        2355402966,
        2355402952,
        620110214
      ],
      "geometry": [
        { "lat": 31.3252665, "lon": 121.5218845 },
        { "lat": 31.3252848, "lon": 121.5227213 },
        { "lat": 31.3253385, "lon": 121.5230239 },
        { "lat": 31.3254554, "lon": 121.5232328 },
        { "lat": 31.3257800, "lon": 121.5230624 },
        { "lat": 31.3260089, "lon": 121.5230218 },
        { "lat": 31.3267684, "lon": 121.5229826 },
        { "lat": 31.3267613, "lon": 121.5250161 },
        { "lat": 31.3267618, "lon": 121.5251091 },
        { "lat": 31.3267594, "lon": 121.5253529 },
        { "lat": 31.3267618, "lon": 121.5255422 },
        { "lat": 31.3267537, "lon": 121.5258913 },
        { "lat": 31.3267723, "lon": 121.5273240 },
        { "lat": 31.3267524, "lon": 121.5273902 },
        { "lat": 31.3267079, "lon": 121.5274506 },
        { "lat": 31.3266721, "lon": 121.5274793 },
        { "lat": 31.3266315, "lon": 121.5274975 },
        { "lat": 31.3256535, "lon": 121.5274785 },
        { "lat": 31.3256489, "lon": 121.5272586 },
        { "lat": 31.3249724, "lon": 121.5272586 },
        { "lat": 31.3237334, "lon": 121.5272586 },
        { "lat": 31.3237333, "lon": 121.5219434 },
        { "lat": 31.3243177, "lon": 121.5219173 },
        { "lat": 31.3252665, "lon": 121.5218845 }
      ],
      "tags": {
        "landuse": "residential",
        "name": "开鲁新村",
        "name:en": "Kailu Xincun"
      }
    },
    //...
]

可以看到,数据中包含AOI点位轮廓坐标数组和其它信息。

使用数据

在overpass网站上导出的数据的经纬度是gps84坐标系,如果要在高德地图里使用,需要转换成gcj02(火星)坐标系,如果要在百度地图种使用,需要转换成bd09坐标系。这里推荐一个坐标转换开源库 coordtransform

下面放一张在高德地图中,用不同颜色区块显示小区的demo:

由于OSM上的数据是全世界的用户自发编辑发布维护的,因此难免会存在数据不全、有误的情况。但是总体而言,这可能是普通开发者获取AOI最方便有效的途径了。

相关推荐
IT_陈寒2 分钟前
Java集合的这个坑,我调试了整整3小时才爬出来
前端·人工智能·后端
前端老石人42 分钟前
前端网站换肤功能的 3 种实现方案
开发语言·前端·css·html
冴羽yayujs43 分钟前
2026 年的 JavaScript 已经不是你认识的 JavaScript 了
前端·javascript
小灰灰搞电子44 分钟前
PyQt QWebChannel详解-C++与Web页面的无缝双向通信
前端·pyqt
M ? A1 小时前
你的 Vue v-for,VuReact 会编译成什么样的 React 代码?
前端·javascript·vue.js·经验分享·react.js·面试·vureact
午安~婉1 小时前
Electron桌面应用(续3)
前端·javascript·electron·重构通用模型·异步可迭代对象
W.A委员会1 小时前
伪类与伪元素
前端·javascript·css
午安~婉1 小时前
Electron桌面应用(续2)
前端·javascript·electron·路由守卫·优化llm返回的内容
eEKI DAND1 小时前
一个比 Nginx 还简单的 Web 服务器
服务器·前端·nginx
Highcharts.js8 小时前
Highcharts 云端渲染的真相:交互式图表与服务器端生成的边界
前端·信息可视化·服务器渲染·highcharts·图表渲染