关键词搜索

源码搜索 ×
×

GIS矢量切片算法(转载)

发布2021-01-06浏览490次

详情内容

转自: https://www.giserdqy.com/database/postgresqlhttps://cdn.jxasp.com:9143/image/25838/

对于大范围矢量vb.net教程数据,由于类型众多范围广泛往往数据量极大,加载渲染会造成平台卡顿。因此对矢量数据进行四叉树索引切c#教程片可以高效加载当前区域矢量,提高效率。

image

常见的矢量数据为shapefile,可以通python基础教程过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);
            /https://cdn.jxasp.com:9143/image/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;
        }
    }
    
      12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128

    相关技术文章

    点击QQ咨询
    开通会员
    返回顶部
    ×
    微信扫码支付
    微信扫码支付
    确定支付下载
    请使用微信描二维码支付
    ×

    提示信息

    ×

    选择支付方式

    • 微信支付
    • 支付宝付款
    确定支付下载