-
GIS矢量切片算法(转载)
转自: https://www.giserdqy.com/database/postgresql/25838/
对于大范围矢量数据,由于类型众多范围广泛往往数据量极大,加载渲染会造成平台卡顿。因此对矢量数据进行四叉树索引切片可以高效加载当前区域矢量,提高效率。
常见的矢量数据为shapefile,可以通过GDAL读取shp范围进行四叉树划分,构建某一层级瓦块。
以下为C#调用GDAL进行矢量四叉树切片算法:
struct TileStructure { public int level; public int x; public int y; public OSGeo.OGR.Geometry extentPolygon; public string path; public OSGeo.OGR.DataSource ds; public OSGeo.OGR.Layer layer; }
public class VectorTileTool { List<TileStructure> tiles; public VectorTileTool() { } public bool SeprateShpLayer(string sourcePath, string resultFolder, int level) { OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", ""); OSGeo.OGR.Ogr.RegisterAll(); OSGeo.OGR.Driver dr = OSGeo.OGR.Ogr.GetDriverByName("ESRI shapefile"); if (dr == null) { return false; } OSGeo.OGR.DataSource ds = dr.Open(sourcePath, 0); int layerCount = ds.GetLayerCount(); OSGeo.OGR.Layer layer = ds.GetLayerByIndex(0); //投影信息 OSGeo.OSR.SpatialReference coord = layer.GetSpatialRef(); string coordString; coord.ExportToWkt(out coordString); //地理范围 Envelope layerEx = new Envelope(); layer.GetExtent(layerEx, 0); ////如果瓦块数据存在,全部删除 //if (Directory.Exists(resultFolder)) //{ // Directory.Delete(resultFolder,true); //} //创建文件夹 Directory.CreateDirectory(resultFolder + "\\JSON\\"); //针对本项目,划分第16级,根据地理范围求出瓦片 int y0 = Convert.ToInt32((90 - layerEx.MaxY) * Math.Pow(2, level)/180.0); int x0 = Convert.ToInt32((180 + layerEx.MinX) * Math.Pow(2, level)/180.0); int y1 = Convert.ToInt32((90 - layerEx.MinY) * Math.Pow(2, level) / 180.0); int x1 = Convert.ToInt32((180 + layerEx.MaxX) * Math.Pow(2, level) / 180.0); //20160621 ZXQ 创建层行列配置文件 string filePath = resultFolder + "\\JSON\\" + "\\tile.txt"; FileStream fs = new FileStream(filePath, FileMode.CreateNew); StreamWriter sw = new StreamWriter(fs); //写入层行列 sw.Write(level.ToString()); sw.Write(","); sw.Write(x0.ToString()); sw.Write(","); sw.Write(x1.ToString()); sw.Write(","); sw.Write(y0.ToString()); sw.Write(","); sw.Write(y1.ToString()); sw.Write(","); sw.Write("json"); sw.Flush(); sw.Close(); fs.Close(); tiles = new List<TileStructure>(); for (int x =x0;x<=x1;x++) { for (int y=y0;y<=y1;y++) { TileStructure tile; tile.level = level; tile.x = x; tile.y = y; double lonMin = -180 + 180 / (Math.Pow(2, level)) * x; double lonMax = -180 + 180 / (Math.Pow(2, level)) * (x + 1); double latMax = 90 - 180 / (Math.Pow(2, level)) * y; double latMin = 90 - 180 / (Math.Pow(2, level)) * (y + 1); tile.extentPolygon = new OSGeo.OGR.Geometry(OSGeo.OGR.wkbGeometryType.wkbPolygon); OSGeo.OGR.Geometry geo = new OSGeo.OGR.Geometry(OSGeo.OGR.wkbGeometryType.wkbLinearRing); geo.AddPoint(lonMin,latMax,0); geo.AddPoint(lonMax, latMax, 0); geo.AddPoint(lonMin, latMin, 0); geo.AddPoint(lonMax, latMin, 0); tile.extentPolygon.AddGeometryDirectly(geo); tile.extentPolygon.CloseRings(); //创建空shp文件 string tileFolder = resultFolder + "\\SHP\\" + level.ToString() + "\\" + x.ToString(); string fileName = y.ToString() + ".shp"; string tilePath = tileFolder + "\\" + fileName; if (!Directory.Exists(tileFolder)) { Directory.CreateDirectory(tileFolder); } tile.path = tilePath; tile.ds = dr.CreateDataSource(tilePath, null); tile.layer = tile.ds.CreateLayer("house", coord, OSGeo.OGR.wkbGeometryType.wkbPolygon, null); FieldDefn fd = new FieldDefn("HEIGHT", FieldType.OFTReal); tile.layer.CreateField(fd,1); tiles.Add(tile); Console.WriteLine("创建第{0}层第{1}行第{2}列瓦块空shapefile数据", level, x, y); } } OSGeo.OGR.Feature feat; //读取shp文件 while ((feat = layer.GetNextFeature()) != null) { int id = feat.GetFID(); OSGeo.OGR.Geometry geometry = feat.GetGeometryRef(); OSGeo.OGR.wkbGeometryType goetype = geometry.GetGeometryType(); if (goetype != wkbGeometryType.wkbPolygon) { continue; } geometry.CloseRings(); //随机楼层3-15层 Random random = new Random(); double height = random.Next(3,15)*3;// feat.GetFieldAsDouble("房屋层数") * 3; for (int i = 0; i < tiles.Count;i++ ) { TileStructure tile = tiles[i]; //如果瓦片与要素相交,则将要素放入该瓦片 if (tile.extentPolygon.Intersect(geometry)) { OSGeo.OGR.Feature poFeature = new Feature(tile.layer.GetLayerDefn()); poFeature.SetField(0, height.ToString()); poFeature.SetGeometry(geometry); tile.layer.CreateFeature(poFeature); Console.WriteLine("写入第{0}个要素入shp", id); } } } return true; } }
最新更新
王炸!!IDEA 2021.1 推出语音、视频功能,
并发编程之ThreadLocal
为什么 DNS 协议使用 UDP?只使用了 UDP 吗
死磕Spring之AOP篇 - Spring AOP注解驱动与XM
学习笔记:Java中的数据结构——数组
Mybatis的日志工厂
rabbitmq五种模式详解(含实现代码)
rabbitmq五种模式详解(含实现代码)
ArryaList源码浅析
jasypt在springboot项目中遇到异常:Error cr
JAVA oa 办公系统模块 设计方案
MongoDB vs MySQL,哪个效率更高?
NoSql非关系型数据库之MongoDB应用(三):M
10分钟系列:NetCore3.1+EFCore三步快速完成数
NoSql非关系型数据库之MongoDB应用(一):安
NoSql非关系型数据库之MongoDB应用(二):安
【干货】SqlServer 总结几种存储过程分页的
SQLServer存储过程自制数据字典
MYSQL事务篇(高级篇)
mysql常用语句 3
Taro 3.4 beta 发布: 支持 Preact 为应用开辟
前端---梳理 http 知识体系 2
Java入门到架构师全新课程之JavaScript数据
构造函数与实例化之间的关系和原型的引
Vue库的使用
IIS安装和ASP.NET Web应用程序开发期间部署
ASP.NET MVC IOC依赖注入之Autofac系列开篇
ASP.NET中WebService的创建和部署以及通过反
ASP.NET Core Web 应用程序开发期间部署到I
ASP.NET Core Web 应用程序系列(一)- 使用