win2008做的网站打不开,网易企业邮箱收费标准,网站seo查询工具,wordpress屏蔽f12目录
前言
二、实现步骤
1.将数据写入postgis数据库 2.将矢量瓦片数据写入缓存库
3.瓦片接口实现
4.瓦片局部更新接口实现
总结 前言 矢量瓦片作为webgis目前最优秀的数据格式#xff0c;其主要特点就是解决了大批量数据在前端渲染时出现加载缓慢、卡顿的问题#xff0…目录
前言
二、实现步骤
1.将数据写入postgis数据库 2.将矢量瓦片数据写入缓存库
3.瓦片接口实现
4.瓦片局部更新接口实现
总结 前言 矢量瓦片作为webgis目前最优秀的数据格式其主要特点就是解决了大批量数据在前端渲染时出现加载缓慢、卡顿的问题能够环境前端设备的计算压力。动态矢量瓦片技术解决了矢量存储在数据库中的实时动态更新不再需要使用离线工具对矢量进行本地切片发布的问题。但是动态矢量瓦片技术的缺陷也很大就是因为其运行逻辑是通过对数据库矢量实时切片那么当用户访问并发数过多的时候pg库就会超负荷运行会出现访问超时的情况。为解决这一问题搭建矢量瓦片缓存库就非常重要。 一、缓存库的意义 为解决多用户访问时pg库切片压力过大的问题首先对数据库所有数据进行切片然后将X,Y,Z和瓦片信息储存在缓存库中。当用户访问矢量瓦片接口时优先判断缓存库内有无对应的瓦片数据如果没有则调用pg函数实时切片切片完成后再缓存库插入数据如果缓存库有数据则直接返回缓存库储存的瓦片数据。如果需要对数据库的矢量进行增删改查操作则计算更改矢量对应的瓦片范围对缓存库做对应的局部更新即可。
二、实现步骤
1.将数据写入postgis数据库
对各大空间数据库读写最强工具非FME莫属直接写模块即可需要注意一点就是如果。pg的表是MultiPolygon那么我们需要加入aggregator把要素变为聚合体格式写入还有就是坐标系要和表一致。 2.将矢量瓦片数据写入缓存库 将矢量数据写入一个临时的postgis数据表然后用fme生成对应层级的瓦片范围最后用python调用postgis函数对数据进行切片最后过滤一下空白瓦片最后将数据写入缓存库。 获得了各类层级的二进制矢量瓦片数据
3.瓦片接口实现
后端框架采用python的geodjango首先造一个x,y,z转换为wg84坐标范围的函数
import math
def xyz2lonlat(x,y,z):n math.pow(2, z)lon_deg (x / n) * 360.0 - 180.0lat_rad math.atan(math.sinh(math.pi * (1 - (2 * y) / n)));lat_deg (180 * lat_rad) / math.pireturn [lon_deg, lat_deg]
同时造一个mvt生成器并实现空间库和缓存库信息判定有则直接调用缓存库数据不调用pg函数切片无则调用pg函数切片切片完成后更新缓存库并同时返回瓦片数据。
def make_mvt(model,temp_model,x,y,z):temp_model为矢量瓦片缓存库模型类model为pg矢量库模型要素x,y,z为前端请求参数temp_mvt temp_model.objects.filter(xx,yy,zz)if len(temp_mvt) 1:return HttpResponse(temp_mvt[0].byte, content_typeapplication/x-protobuf)if len(temp_mvt) 1:for i in range(0, len(temp_mvt) - 1):temp_mvt[i].delete()return HttpResponse(temp_mvt[len(temp_mvt) - 1].byte, content_typeapplication/x-protobuf)tablename model._meta.db_tableboundbox_min xyz2lonlat(x, y, z)boundbox_max xyz2lonlat(x 1, y 1, z)sql SELECTST_AsMVT ( P,polygon, 4096, geom ) AS mvt FROM (SELECT ST_AsMVTGeom (ST_Transform (st_simplify(geom,0.0), 3857 ), ST_Transform (ST_MakeEnvelope( %s,%s, %s,%s, 4326 ),3857),4096, 64,TRUE ) geom FROM %s ) AS P % (boundbox_min[0], boundbox_min[1], boundbox_max[0], boundbox_max[1], tablename)cursor connection.cursor()cursor.execute(sql)tile bytes(cursor.fetchone()[0])temp_model.objects.create(xx,yy,zz,bytetile,)if not len(tile):return Falseelse:return tile
视图类
#视图类
class ZJGG_mvt_ViewSet(APIView):def get(self,request,z, x, y):tilemake_mvt(ZJGG,mvt_temp,x,y,z)if tile:return HttpResponse(tile, content_typeapplication/x-protobuf)else:return Response(statusstatus.HTTP_404_NOT_FOUND)
然后用postman调试一下接口瓦片请求成功 4.瓦片局部更新接口实现 这一步的主要内容是为了前端需要对矢量数据增删改查的时候同时删除缓存库的对应瓦片用户在下一次访问的时候通过上一步的mvt生成器完成新瓦片数据的更新。
首先造一个4326到3857坐标系的转换工具
import mathdef lonlat2mercator(lon, lat):semimajor_axis 6378137.0x semimajor_axis * math.radians(lon)y semimajor_axis * math.log(math.tan((math.pi / 4) (math.radians(lat) / 2)))return x, ydef mercator2lonlat(x, y):semimajor_axis 6378137.0lon math.degrees(x / semimajor_axis)lat math.degrees(2 * math.atan(math.exp(y / semimajor_axis)) - math.pi / 2)return lon, latdef epsg4326_to_epsg3857(lon, lat):x, y lonlat2mercator(lon, lat)r_major 6378137.0x r_major * math.radians(lon)scale x / lony 180.0 / math.pi * math.log(math.tan(math.pi / 4.0 lat * (math.pi / 180.0) / 2.0)) * scalereturn x, ydef epsg3857_to_epsg4326(x, y):r_major 6378137.0lon x / r_major * 180.0 / math.pilat math.atan(math.exp(y / r_major)) * 360.0 / math.pi - 90.0return lon, lat
造一个瓦片计算器传入geojson的extend返回瓦片的x,y,z信息。
import mathHEMI_MAP_WIDTH math.pi * float(6378137)
PRECISION 6def generate(zoomLevel, tileSize, rows, cbeg, cend):# Calculate x-direction tile originscols [(c, round(c * tileSize - HEMI_MAP_WIDTH, PRECISION)) for c in range(cbeg, cend 1)]cols [(cols[i][0], cols[i][1], cols[i 1][1]) for i in range(len(cols) - 1)]tile_json[]# Generate and output tile features.for row, ymin, ymax in rows:for column, xmin, xmax in cols:tile_json.append({Z: zoomLevel,X: column,Y: row,})return tile_jsondef TileGenerate(xmin,ymin,xmax,ymax):west float(xmin)east float(xmax)south float(ymin)north float(ymax)tile[]for i in range(6, 17):zoomLevel iif zoomLevel 0:zoomLevel 0numColumns int(math.pow(2, zoomLevel))tileSize 2.0 * HEMI_MAP_WIDTH / numColumnsrbeg int(math.floor((HEMI_MAP_WIDTH - north) / tileSize))rend int(math.ceil((HEMI_MAP_WIDTH - south) / tileSize))rows [(r, round(HEMI_MAP_WIDTH - r * tileSize, PRECISION)) for r in range(rbeg, rend 1)]rows [(rows[i][0], rows[i 1][1], rows[i][1]) for i in range(len(rows) - 1)]cbeg int(math.floor((HEMI_MAP_WIDTH west) / tileSize))cend int(math.ceil((HEMI_MAP_WIDTH east) / tileSize))if cbeg cend:tile_jsongenerate(zoomLevel, tileSize, rows, cbeg, cend)else:tile_jsongenerate(zoomLevel, tileSize, rows, cbeg, numColumns)tile_json1generate(zoomLevel, tileSize, rows, 0, cend)tile_json.extend(tile_json1)tile.extend(tile_json)return tilemvt局部更新函数
def del_mvt(model,temp_model,sm):model为空间数据存储模型类temp_model为缓存库模型类sm为空间数据库查询结果实现缓存库和空间库数据的局部删除data make_geojson(model, sm)data json.loads(data)xmin, ymin, xmax, ymax bound(data)xmin, ymin epsg4326_to_epsg3857(xmin, ymin)xmax, ymax epsg4326_to_epsg3857(xmax, ymax)tilelist TileGenerate(xmin, ymin, xmax, ymax)for i in tilelist:DEL temp_model.objects.filter(xi[X], yi[Y], zi[Z])DEL.delete()sm.delete()
视图函数
class ZJGG_mvt_del_ViewSet(APIView):def post(self,request):id request.data.get(id)smZJGG.objects.filter(pkid)del_mvt(ZJGG,mvt_temp,sm)return Response(statusstatus.HTTP_200_OK)最后用postman测试接口传入一个id测试空间信息表和缓存表的对应内容是否都删除。
提交前 提交后 可以看到对应的空间库id为338的数据已经删除同时缓存库中的对应的4条瓦片信息也被删。 总结 这项技术的前景是非常可观的现阶段各类webgis平台对大批量地理空间数据的展现方式几乎都为静态矢量瓦片和geojson配合的方式实现。但是这种方式在面对较大体量需要全局展示且需要动态更新的数据的时候就显得捉襟见肘。