使用 PostGIS 生成矢量图块

使用 PostGIS 生成矢量图块

您喜欢视听学习吗?观看视频指南!

或者直接跳到代码

Overture Maps Foundation是由亚马逊、Meta、微软和 tomtom 发起的联合开发基金会项目,旨在创建可靠、易于使用、可互操作的开放地图数据。

Overture Maps 允许我们以GeoJSON格式下载开放地图数据(例如名胜古迹),我们可以将其转换为 SQL 并导入 Supabase 上的 Postgres 数据库。

使用 PostGIS,我们可以以编程方式生成矢量图块,并使用 supabase-js 将它们提供给我们的 MapLibre GL 客户端。

矢量图块是地理数据包,被打包成预定义的大致正方形的“图块”,以便在网络上传输。客户端请求的地图数据是一组“图块”,对应于预定义大小和位置的方形土地区域。

特别是对于大型数据集,这样做的好处是数据传输大大减少,因为只需要传输当前视口内和当前缩放级别的数据。

在本教程中,您将学习

  • 使用 Overture Maps 以 GeoJSON 格式下载开放地图地点数据。
  • 使用 GDAL ogr2ogr 将 GeoJSON 转换为 SQL 语句。
  • 使用 psql 将位置数据和 JSON 元数据导入您的 Supabase Postgres 数据库。
  • 使用 PostGISST_AsMVT将与图块层对应的一组行聚合为二进制矢量图块表示。
  • addProtocol通过使用 supabase-js 进行远程过程调用,使用 MapLibre可视化大型 PostGIS 表。
  • 使用 supabase-js 按需获取其他 JSON 元数据

使用 Overture Maps 下载开放地图数据

Overture Maps 提供了一个Python 命令行工具来下载感兴趣区域内的数据并将其转换为几种常见的地理空间文件格式。

我们可以使用以下命令将新加坡的地点下载到 GeoJSON 文件中:

overturemaps download --bbox=103.570233,1.125077,104.115855,1.490957 -f geojson --type=place -o places.geojson

根据边界框的大小,这可能需要相当长的时间!

将 GeoJSON 转换为SQL

下一步,我们可以使用GDAL ogr2ogr将 GeoJSON 文件转换为 PostGIS 兼容的 SQL 文件。

您可以GDAL通过安装homebrew brew install gdal或按照下载说明进行操作。

PG_USE_COPY=true ogr2ogr -f pgdump places.sql places.geojson

将位置数据导入 Supabase

在专用的单独架构上启用 Supabase 数据库上的 PostGIS 扩展gis。为此,您可以导航到SQL 编辑器并运行以下 SQL,或者您可以从数据库扩展设置中启用扩展。(也可使用国内版supabase)

由于 PostGIS 的计算量可能很大,我们建议在专用的单独模式上启用它,例如名为gis

CREATE SCHEMA IF NOT EXISTS "gis";
CREATE EXTENSION IF NOT EXISTS "postgis" WITH SCHEMA "gis";

将打开的地图数据导入到placesSupabase中的表中:

psql -h aws-0-us-west-1.pooler.supabase.com -p 5432 -d postgres -U postgres.project-ref < places.sql

您可以在Supabase 仪表板的数据库设置中找到凭据。

启用 RLS 并创建公共读取策略

我们希望地点数据可以公开获取,因此我们可以创建一个允许公开读取的行级安全策略。

在您的 Supabase 仪表板中,导航到SQL 编辑器并运行以下命令:

ALTER TABLE "public"."places" ENABLE ROW LEVEL SECURITY;CREATE POLICY "Enable read access for all users" ON "public"."places" FOR SELECT USING (true);

使用PostGIS生成矢量图块

为了在客户端请求时以编程方式生成矢量图块,我们需要创建一个 Postgres 函数,可以通过远程过程调用来调用它。在 SQL 编辑器中,运行:

CREATE OR REPLACE FUNCTION mvt(z integer, x integer, y integer)
RETURNS text
LANGUAGE plpgsql
AS $$
DECLAREmvt_output text;
BEGINWITH-- Define the bounds of the tile using the provided Z, X, Y coordinatesbounds AS (SELECT ST_TileEnvelope(z, x, y) AS geom),-- Transform the geometries from EPSG:4326 to EPSG:3857 and clip them to the tile boundsmvtgeom AS (SELECT-- include the name and id only at zoom 13 to make low-zoom tiles smallerCASEWHEN z > 13 THEN idELSE NULLEND AS id,CASEWHEN z > 13 THEN names::json->>'primary'ELSE NULLEND AS primary_name,categories::json->>'main' as main_category,ST_AsMVTGeom(ST_Transform(wkb_geometry, 3857), -- Transform the geometry to Web Mercatorbounds.geom,4096, -- The extent of the tile in pixels (commonly 256 or 4096)0,    -- Buffer around the tile in pixelstrue  -- Clip geometries to the tile extent) AS geomFROMplaces, boundsWHEREST_Intersects(ST_Transform(wkb_geometry, 3857), bounds.geom))-- Generate the MVT from the clipped geometriesSELECT INTO mvt_output encode(ST_AsMVT(mvtgeom, 'places', 4096, 'geom'),'base64')FROM mvtgeom;RETURN mvt_output;
END;
$$;

为了限制通过网络发送的数据量,我们限制了矢量图块中包含的元数据量。例如,我们为缩放级别添加了一个条件,并且只有当用户放大到 13 级以上时才返回地名。

使用 supabase-js 从 MapLibre GL 客户端获取矢量瓦片

index.html您可以在GitHub上找到完整的代码。在这里,我们将重点介绍如何向 MapLibreGL 添加新协议,以通过 supabase-js 获取 bas64 编码的二进制矢量瓦片数据,以便 MapLibre GL 可以在用户与地图交互时获取和呈现数据:

index.html

const client = supabase.createClient('your-supabase-api-url', 'your-supabase-anon-key')function base64ToArrayBuffer(base64) {var binaryString = atob(base64)var bytes = new Uint8Array(binaryString.length)for (var i = 0; i < binaryString.length; i++) {bytes[i] = binaryString.charCodeAt(i)}return bytes
}maplibregl.addProtocol('supabase', async (params, abortController) => {const re = new RegExp(/supabase:\/\/(.+)\/(\d+)\/(\d+)\/(\d+)/)const result = params.url.match(re)const { data, error } = await client.rpc('mvt', {z: result[2],x: result[3],y: result[4],})const encoded = base64ToArrayBuffer(data)if (!error) {return { data: encoded }} else {throw new Error(`Tile fetch error:`)}
})

注册 supabase 协议后,我们现在可以将其添加到 MapLibre GL 源中,并放置在底图(如Protomaps)之上,例如:

index.html

// ...
const map = new maplibregl.Map({hash: true,container: 'map',style: {version: 8,glyphs: 'https://cdn.protomaps.com/fonts/pbf/{fontstack}/{range}.pbf',sources: {supabase: {type: 'vector',tiles: ['supabase://boston/{z}/{x}/{y}'],attribution: '© <a href="https://overturemaps.org">Overture Maps Foundation</a>',},protomaps: {type: 'vector',url: 'https://api.protomaps.com/tiles/v3.json?key=your-protomaps-api-key',attribution: 'Basemap © <a href="https://openstreetmap.org">OpenStreetMap</a>',},},},
})
// ...

按需获取额外的 JSON 元数据

为了限制通过网络发送的数据量,我们不会对矢量图块本身中的所有元数据进行编码,而是设置一个 onclick 处理程序以在 MapLibre GL 弹出窗口中按需获取其他元数据:

index.html

// ..
const popup = new maplibregl.Popup({closeButton: true,closeOnClick: false,maxWidth: 'none',
})function loadDetails(element, id) {element.innerHTML = 'loading...'client.from('places').select(`websites,socials,phones,addresses,source:  sources->0->dataset`).eq('id', id).single().then(({ data, error }) => {if (error) return console.error(error)element.parentElement.innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>`})
}map.on('click', 'overture-pois-text', async (e) => {if (e.features.length > 0) {const feature = e.features[0]console.log(feature)popup.setHTML(`<table style="font-size:12px"><tr><td>id:</td><td>${feature.properties.id}</td></tr><tr><td>name:</td><td>${feature.properties.primary_name}</td></tr><tr><td>main_category:</td><td>${feature.properties.main_category}</td></tr><tr><td>details:</td><td><span οnclick="loadDetails(this, '${feature.properties.id}')">load details</span></td></tr></table>`)popup.setLngLat(e.lngLat)popup.addTo(map)}
})
// ...

结论

PostGIS 功能强大,可让您以编程方式从存储在 Postgres 中的表行生成矢量图块。与 Supabase 自动生成的 REST API 和 supabase-js 客户端库配合使用,您可以轻松构建交互式地理空间应用程序!

更多 Supabase

  • 观看视频指南
  • 国内版suapbase
  • 查找代码
  • 使用 Protomaps 在 Supabase 存储上自托管地图
  • PostGIS 入门
  • PostGIS 文档指南

原文章:https://supabase.com/blog/postgis-generate-vector-tiles

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/39141.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【面试系列】产品经理高频面试题及详细解答

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&#xff1a;详细讲解AIGC的概念、核心技术、…

工业读码器与商用扫码器的区别

条码二维码在数字信息化应用越来越广泛&#xff0c;扫码器成为了数据收集和处理的重要工具&#xff0c;无论是工厂生产和物流包裹朔源追踪&#xff0c;还是商场超市扫码收银和餐饮娱乐等场景&#xff0c;均能看到扫码器的辅助&#xff0c;市场上的扫码器种类繁多&#xff0c;在…

【力扣】赎金信

&#x1f525;博客主页&#xff1a; 我要成为C领域大神&#x1f3a5;系列专栏&#xff1a;【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 ​ 给你两个字符串…

研发都认为DBA很Low?我反手一个嘴巴子

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…

antd(5.x) Popover 的content有个modal,关不掉了

问题描述&#xff1a; 如上图所示&#xff0c;我的提示modal 关不掉了&#xff0c;思考问题症结在handleVisibleChange const content (<div className{styles.box}>别的样式</div>{/* 链接 */}<div className{styles.linkBox}><Modaltitle{提示}open{…

武汉星起航:跨境电商流量红利爆发,2023年出海企业迎突破增长

在数字时代的浪潮中&#xff0c;中国跨境电商以惊人的爆发力崭露头角&#xff0c;成为全球贸易的璀璨新星。2023年数据显示&#xff0c;跨境电商出口额高达1.83万亿元&#xff0c;同比增长19.6%&#xff0c;这一显著增速不仅刷新纪录&#xff0c;更为众多出海企业带来了前所未有…

Kimi 上下文缓存功能开启公测!降低使用费用,加快模型相应速度

7月2日&#xff0c;系统之家发布消息&#xff0c;月之暗面科技有限公司旗下的Kimi开放平台正式推出上下文缓存功能&#xff0c;并已开放公测。这项功能专为处理频繁请求和大量重复引用初始上下文的场景设计&#xff0c;能有效降低使用长文本模型的成本&#xff0c;并显著提升处…

基于java+springboot+vue实现的旅游管理系统(文末源码+Lw)227

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本旅游管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助使用者在短时间内处理完毕庞大的数据信息&a…

本地文本向量模型的部署提供兼容openai的接口

前言 之前部署了fastgpt官方文档的一个,提供的一个m3e-large的向量模型打包的docker镜像,虽然使用起来整体效果还可以,但是有些文本向量相似度匹配的结果还是不太满意的,目前,网络上层出不穷的带推理文本向量,想体验一下,于是我基于modelscope库封装了一个兼容open ai的…

探索视觉世界:深入了解目标检测算法的奥秘

目标检测算法 一、介绍目标检测算法的背景和意义1.1 目标检测的定义和应用场景1.2 目标检测算法的发展历程 二、目标检测算法分类2.1 传统目标检测算法2.1.1 基于分类器的目标检测算法2.1.2 基于模板匹配的目标检测算法 2.2 深度学习目标检测算法2.2.1 两阶段目标检测算法2.2.2…

2024年广东省食品安全管理员考试精选练习题库

76.已具有主体资格的企业申请食品流通可&#xff0c;该企业的&#xff08;&#xff09;为可申请人。 A.投资者 B.经营负责人 C.本身 答案&#xff1a;C 77.食用亚硝酸盐的销售只面向&#xff08;&#xff09;。 A.食品生产加工行业 B.餐饮业 C.食品流通单位 答案&…

微软账户和本地账户有什么区别?如何切换登录账户?

Windows 操作系统是目前世界上比较流行的操作系统之一&#xff0c;在使用 Windows 系统的时候都需要我们进行登录&#xff0c;其中我们可以使用微软账户或者本地账户进行登录&#xff0c;那本地账户和微软账户有什么区别&#xff1f;下面就带大家了解一下微软账户和本地账户。 …

基于机器学习的零售商品销售数据预测系统

1 项目介绍 1.1 研究目的和意义 在电子商务日益繁荣的今天&#xff0c;精准预测商品销售数据成为商家提升运营效率、优化库存管理以及制定营销策略的关键。为此&#xff0c;开发了一个基于深度学习的商品销售数据预测系统&#xff0c;该系统利用Python编程语言与Django框架&a…

惠海 H6900B 2.7V3.7V4.2V5V9V升12V24V48VLED升压恒流芯片IC

惠海H6900B LED升压恒流芯片IC是一款功能丰富的LED驱动解决方案&#xff0c;为高亮度LED灯串设计。以下是针对该产品的进一步分析和解释&#xff1a; 产品特点 高效率&#xff1a;高达95%以上的效率意味着在驱动LED时&#xff0c;只有很少的能量转化为热量&#xff0c;从而提…

hadoop集群部署【二】YARN MapReduce 的部署

提前注意&#xff1a;请注意路径是否和我的相同&#xff0c;放置的位置不同&#xff0c;请修改标红处 HDFS部署 HDFS介绍及部署http://t.csdnimg.cn/Q3H3Y 部署说明 Hadoop HDFS分布式文件系统&#xff0c;我们会启动&#xff1a; NameNode进程作为管理节点 DataNode进程…

欢太主题商店 官方资源提取与应用第三方资源方法一览

前言叠甲&#xff1a;支持正版&#xff0c;尊重他人劳动成果&#xff0c;反对盗版提取&#xff0c;不要传播提取版&#xff0c;我本人也在支持正版&#xff0c;但是最近懒得用主题&#xff0c;用一段时间的默认吧&#xff0c;如有主题开发者不满&#xff0c;请联系删除 &#x…

机器人入门路线及参考资料(机器人操作方向)

机器人&#xff08;操作方向&#xff09;入门路线及参考资料 前言1 数理基础和编程2 机器人学理论3 计算机视觉4 机器人实操5 专攻方向总结Reference: 前言 随着机器人和具身智能时代的到来&#xff0c;机器人越来越受到大家的重视&#xff0c;本文就介绍了机器人&#xff08;…

基于SpringBoot民宿管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

13-4 GPT-5:博士级AI,人工智能的新时代

图片来源&#xff1a;AI Disruptive 人工智能世界正在迅速发展&#xff0c;新的创新和突破层出不穷。在本文中&#xff0c;我们将深入探讨最新的进展&#xff0c;从即将推出的 GPT-5 模型到 Apple 和 Meta 之间可能的合作。 GPT-5&#xff1a;博士级别的人工智能 虽然尚未正…

为何交易价格可能超出预期?

当你尝试执行订单时&#xff0c;如果收到“报价超出”的提示&#xff0c;这通常意味着交易无法按你的预期价格成交。对于某些交易者来说&#xff0c;这可能会带来一些困扰&#xff0c;但在外汇等流动性极高的市场中&#xff0c;这种情况是相当常见的。 外汇市场之所以吸引众多…