postgis计算矢量切片

2024-04-20 19:32
文章标签 切片 计算 矢量 postgis

本文主要是介绍postgis计算矢量切片,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    没写错,是使用postgis计算出来矢量切片。在这之前先准备一个数据:一个GIS数据表(本例中数据为一百万的点数据,坐标:4326),并在表中添加x,y字段,方便后面的数据筛选。sql中用到了
ST_AsMVT和ST_AsMVTGeom。

    本文中创建矢量切片很简单,就是使用下方的一个sql,运行结果如下图。接着写一个矢量切片的http服务(参考go-vtile-example,这个例子中矢量切片压缩率更高),并且使用mapbox进行前端展示(小贴士:sql中‘points’的字符串与渲染中mapbox里的source-layer一致).代码见最下方

SELECT ST_AsMVT(tile,'points') tile  FROM(
SELECT ST_AsMVTGeom(geom,ST_MakeEnvelope(100,10,125,22, 4326),4096, 0, true)	AS geom FROM grid20180322 ) 
AS  tile where  tile.geom is not null

准备的数据

sql查询
前端展示
切片请求控制台截图

package mainimport 
(   _ "github.com/lib/pq""database/sql""time""log""math""errors""fmt""net/http""regexp""strconv""strings"
)func tilePathToXYZ(path string) (TileID, error) {xyzReg := regexp.MustCompile("(?P<z>[0-9]+)/(?P<x>[0-9]+)/(?P<y>[0-9]+)")matches := xyzReg.FindStringSubmatch(path)if len(matches) == 0 {return TileID{}, errors.New("Unable to parse path as tile")}x, err := strconv.ParseUint(matches[2], 10, 32)if err != nil {return TileID{}, err}y, err := strconv.ParseUint(matches[3], 10, 32)if err != nil {return TileID{}, err}z, err := strconv.ParseUint(matches[1], 10, 32)if err != nil {return TileID{}, err}return TileID{x: uint32(x), y: uint32(y), z: uint32(z)}, nil
}
type LngLat struct {lng float64lat float64
}
type TileID struct {x uint32y uint32z uint32
}func tile2lon( x int,  z int)(a float64) {return float64(x) /math.Pow(2, float64(z)) * 360.0 - 180;}func tile2lat( y int,  z int)(a float64) {n := math.Pi - (2.0 * math.Pi * float64(y)) / math.Pow(2, float64(z));return math.Atan(math.Sinh(n))*180/math.Pi;}func FloatToString(input_num float64) string {// to convert a float number to a stringreturn strconv.FormatFloat(input_num, 'f', 6, 64)
}func loadData(xyz TileID)(a []byte){ymax :=FloatToString(tile2lat(int(xyz.y), int(xyz.z)));ymin := FloatToString(tile2lat(int(xyz.y+1), int(xyz.z)));xmin := FloatToString(tile2lon(int(xyz.x), int(xyz.z)));xmax := FloatToString(tile2lon(int(xyz.x+1), int(xyz.z)));fmt.Println("ymax: ", ymax)fmt.Println("ymin: ",ymin)fmt.Println("xmin : ",xmin )fmt.Println("xmax : ",xmax )connStr := "dbname=xx user=xx password=xx host=localhost port=5433  sslmode=disable"db, err := sql.Open("postgres", connStr)if err != nil {panic(err)}defer db.Close()err = db.Ping()if err != nil {panic(err)}fmt.Println("Successfully connected!")var tile []bytes := []string{xmin,ymin,xmax,ymax}maxmin:=strings.Join(s, ",") s2 := []string{" where (x between", xmin,"and",xmax,") and ( y between",ymin,"and",ymax,")"}wmaxmin:=strings.Join(s2, " ") sql:="SELECT ST_AsMVT(tile,'points') tile  FROM(SELECT ST_AsMVTGeom(w.geom,ST_MakeEnvelope("+maxmin+", 4326),4096, 0, true)	 AS geom FROM (select geom from grid20180322"+wmaxmin+") w) AS  tile where  tile.geom is not null"rows1:= db.QueryRow(sql)err1 := rows1.Scan(&tile)if err1 != nil {log.Fatal(err1)}fmt.Println(sql)//defer rows1.Close()return tile}
func main(){//t1 := time.Now() mux := http.NewServeMux()tileBase := "/tiles/"mux.HandleFunc(tileBase, func(w http.ResponseWriter, r *http.Request) {t2 := time.Now() log.Printf("url: %s", r.URL.Path)tilePart := r.URL.Path[len(tileBase):]fmt.Println("tilePart: ", tilePart)xyz, err := tilePathToXYZ(tilePart)fmt.Println("xyz: ", xyz)if err != nil {http.Error(w, "Invalid tile url", 400)return}tile:=loadData(xyz)// All this APi to be requests from other domains.w.Header().Set("Content-Type", "application/x-protobuf")w.Header().Set("Access-Control-Allow-Origin", "*")w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")w.Write(tile)elapsed2 := time.Since(t2)fmt.Println("耗时: ", elapsed2)})log.Fatal(http.ListenAndServe(":8081", mux))
}
<!DOCTYPE html>
<html><head><meta charset='utf-8' /><title>Add a third party vector tile source</title><meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /><script src='mapbox-gl.js'></script><link href='mapbox-gl.css' rel='stylesheet' /><style>body {margin: 0;padding: 0;}#map {position: absolute;top: 0;bottom: 0;width: 100%;}</style>
</head><body><div id='map'></div><script>mapboxgl.accessToken = undenfined;var tileset = 'mapbox.streets';var map = new mapboxgl.Map({container: 'map',zoom: 12,center: [109.898625809072612, 19.106708155556731],style: 'mapbox://styles/mapbox/light-v9',hash: false});map.on('load', function loaded() {map.addSource('custom-go-vector-tile-source', {type: 'vector',tiles: ['http://localhost:8081/tiles/{z}/{x}/{y}']});map.addLayer({id: 'background',type: 'background',paint: {'background-color': 'white'}});map.addLayer({"id": "custom-go-vector-tile-layer","type": "circle","source": "custom-go-vector-tile-source","source-layer": "points",paint: {'circle-radius': {stops: [[8, 0.1],[11, 0.5],[15, 3],[20, 20]]},'circle-color': '#e74c3c','circle-opacity': 1}});});</script></body></html>

这篇关于postgis计算矢量切片的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/921132

相关文章

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

XTU 1237 计算几何

题面: Magic Triangle Problem Description: Huangriq is a respectful acmer in ACM team of XTU because he brought the best place in regional contest in history of XTU. Huangriq works in a big compa

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

GPU 计算 CMPS224 2021 学习笔记 02

并行类型 (1)任务并行 (2)数据并行 CPU & GPU CPU和GPU拥有相互独立的内存空间,需要在两者之间相互传输数据。 (1)分配GPU内存 (2)将CPU上的数据复制到GPU上 (3)在GPU上对数据进行计算操作 (4)将计算结果从GPU复制到CPU上 (5)释放GPU内存 CUDA内存管理API (1)分配内存 cudaErro

Java - BigDecimal 计算分位(百分位)

日常开发中,如果使用数据库来直接查询一组数据的分位数,就比较简单,直接使用对应的函数就可以了,例如:         PERCENT_RANK() OVER(PARTITION BY 分组列名 ORDER BY 目标列名) AS 目标列名_分位数         如果是需要在代码逻辑部分进行分位数的计算,就需要我们自己写一个工具类来支持计算了 import static ja

OpenStack离线Train版安装系列—2计算节点-环境准备

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

新一代车载(E/E)架构下的中央计算载体---HPC软件架构简介

老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节能减排。 无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事.而不是让内心的烦躁、焦虑、毁掉你本就不多的热情和定力。 时间不知不觉中,快要来到夏末秋初。一年又过去了一大半,成