不写一行代码在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最方便有效的途径了。

相关推荐
前端之虎陈随易6 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·vue.js·人工智能·typescript·node.js
一路向北he6 小时前
字节钢铁军团--“提供情境,而非控制”
java·开发语言·前端
kyriewen7 小时前
豆包和千问同时关了智能体,我用它们搭的 3 个自动化全废了——迁移方案整理
前端·javascript·ai编程
前端一小卒7 小时前
我用 TypeScript 从零手写了一个 Claude Code,然后发现它的核心只有 30 行
前端·agent
大圣编程8 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang8 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆9 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜10 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞11 小时前
异步HttpModule的实现方式
java·服务器·前端
用户8524950718412 小时前
从零构建 MCP 文件服务:50 行代码让 AI 读懂你的文件
程序员