postgis 矢量切片

文章主要来自于该篇文章,对博客中的内容进行了注释及部分修改,帮助理解。

https://www.jianshu.com/p/24f7363c05b9

#BBOX函数,该函数要先在数据库中运行才不会报错,将文中的注释去掉
CREATE OR REPLACE FUNCTION BBox(x integer, y integer, zoom integer)
    RETURNS geometry AS
$BODY$
DECLARE
    max numeric := 6378137 * pi();#墨卡托投影的最大范围
    res numeric := max * 2 / 2^zoom;#墨卡托投影下一个瓦片代表的实际距离
    bbox geometry;
BEGIN
    根据传入的行列号计算出该瓦片对应的墨卡托投影范围并转换到84坐标系下,
    返回的范围是84坐标系下的范围--经纬度
    return st_transform(ST_MakeEnvelope(
        -max + (x * res),
        max - (y * res),
        -max + (x * res) + res,
        max - (y * res) - res,
        3857),4326);
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE;

python执行代码

import psycopg2
#配置数据库字典
dbConfig={
    "database":"postgis_25_sample",
    "user":"postgres",
    "password":"123456",
    "host":"localhost",
    "port":"5432"
}

#该函数的作用就是根据表名,动态生成sql语句,在已知表结构的情况下,完全不需要这个函数。
def createSql(table_name,x,y,z):
    geoColumn = "(select f_geometry_column from geometry_columns where f_table_name= '" + table_name + "' )"
    #由于pg_attribute中没有与表名直接对应的字段,先从pg_class中选出c表,得到其c.oid。再用a.attrelid判断,即可得到c表
    #实际上第一句sql做的事情就是将空间字段列和属性字段列分开存储f_geometry_column,和name列中
    condition=" pg_class as c,pg_attribute as a  where c.relname = '" + table_name + "' and a.attrelid = c.oid and a.attnum>0"
    sql1 = "SELECT "+geoColumn+",replace(replace(string_agg(a.attname,','),"+geoColumn+"||',',''),"+geoColumn+"||'','') as name FROM" +condition

    print(sql1)
    conn = psycopg2.connect(database=dbConfig["database"], user=dbConfig["user"], password=dbConfig["password"], host=dbConfig["host"], port=dbConfig["port"])
    cur = conn.cursor()
    cur.execute(sql1)
    keyData = cur.fetchall()
    geom_column=keyData[0][0]
    other_fields=keyData[0][1]
    cur.close()
    conn.close()
    #select 前面就是正常的切片,from 后面的select在选择空间属性与普通属性列,where条件则是先判断是否相交,如果相交则返回交集
    sql2="SELECT ST_AsMVT(q, '"+table_name+"', 4096, 'geometry') from (SELECT "+other_fields+"ST_AsMvtGeom("+geom_column+",BBox("+str(x)+", "+str(y)+" ,"+str(z)+") , 4096,256, true) as geometry  FROM "+table_name+" WHERE "+geom_column+" && BBox("+str(x)+", "+str(y)+" ,"+str(z)+")  AND ST_Intersects("+geom_column+", BBox("+str(x)+", "+str(y)+" ,"+str(z)+") )) q;"
    return sql2;
#运行sql,获得mvt的16进制文件
def getPbfFile(table_name,x,y,z):
    sql=createSql(table_name,x,y,z)
    conn = psycopg2.connect(database=dbConfig["database"], user=dbConfig["user"], password=dbConfig["password"], host=dbConfig["host"], port=dbConfig["port"])
    cur = conn.cursor()
    cur.execute(sql)
    print(sql)
    keyData = cur.fetchall()
    cur.close()
    conn.close()
    with open(str(z)+"_"+str(x)+"_"+str(y)+'.pbf', 'wb') as f:
        f.write(keyData[0][0])
    return keyData[0][0]
#x,y,z对应的是矢量切片的行号,列号,级别
tile=getPbfFile("cs",54605,26956,16)
print(tile)
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值