• ArcEngine+C# TIN相关三维功能模块介绍(四)


    ArcEngine+C#  TIN相关三维功能模块介绍(四)

    功能综合演示

     

    作者:刘志远

    PDF浏览  示例程序下载

                                                      

    1.简介

           本篇打算对TIN的介绍做个小结,把前面将的功能都集中到一个小程序中。除了前面将的功能外,本篇还添加了如下一些功能。只要有数据,这些功能都是可以单独使用的,方便读者根据具体的需要直接参考相应代码。

    Ø         由矢量点或线数据,通过核函数密度制图方法生成栅格数据(类DEM);

    Ø         按给定间距,从栅格数据(DEM)中提取矢量等高线数据;

    Ø         由栅格数据(DEM)生成TIN模型;

    Ø         动态变化DEMTIN的渲染样式;

    Ø         矢量图层叠加到TIN模型;

           本文主要对这几个功能进行简单的讲解,希望对接触TIN的朋友有所帮助。具体的实现,可以参看程序中相应的代码。同时,在压缩包中有个简短的“使用说明”,可以通过该程序尝试讲过的功能。

     

    2.核函数密度制度生成“类DEM

           通常情况下,我们通过对高程点数据进行插值操作(如反距离权插值、样条插值、克里金插值等)生成DEM(数字高程模型)栅格数据,生成的栅格数据的像元灰度值即代表对应的高程值。

           本文介绍的是密度制图,生成的栅格灰度值代表密度大小,所以这里成为“类DEM”。密度制图有核函数密度制图(Kernal)和简单密度制图(Simple)两种方法,本文用的是Kernal方法。对于二次开发来说,由矢量数据生成栅格数据,不论是DEM也好,还是密度制图,只是调用相应接口的某个方法而已,内部的具体操作都是封装好的,程序员只需根据实际需要进行选择即可。这也体现了面向对象的巨大优势。主要代码如下:

     

    代码
     1    /// <summary>
     2        /// 核函数密度制图
     3         /// </summary>
     4        /// <param name="pFeatureLayer">进行密度分析的矢量数据图层</param>
     5        /// <param name="cellSize">输出栅格格网大小</param>
     6        /// <param name="radius">制图搜索半径</param>
     7        /// <param name="path">栅格文件保存路径  可以为空,则作为临时数据处理</param>
     8        /// <returns></returns>

     9        public IRaster DensityAnalyst(IFeatureLayer pFeatureLayer, double cellSize, double radius, string path)
    10        {
    11            IFeatureClass pFClass01 = pFeatureLayer.FeatureClass;
    12            IDensityOp pDensityOp = new RasterDensityOpClass();
    13            IRasterAnalysisEnvironment pEnv = pDensityOp as IRasterAnalysisEnvironment;
    14
    15            Double double_cellSize = cellSize;
    16            object object_cellSize = (System.Object)double_cellSize;
    17            pEnv.SetCellSize(esriRasterEnvSettingEnum.esriRasterEnvValue, ref object_cellSize);
    18            IFeatureClassDescriptor pFDescr = new FeatureClassDescriptorClass();
    19            pFDescr.Create(pFClass01, null"NONE");
    20
    21            System.Double double_radio_dis = radius;
    22            object object_radio_dis = (System.Object)double_radio_dis;
    23            object Missing = Type.Missing;
    24            //调用核函数密度制图方法生成栅格数据
    25            IRaster pRasOut1 = pDensityOp.KernelDensity(pFDescr as IGeoDataset, ref object_radio_dis, ref Missing) as IRaster;
    26            
    27            //栅格值重计算,将栅格值缩放到合理范围(主要是纠正由于坐标系统不同而造成的数据夸张变大)
    28            //如数据的坐标系等没有问题则可以不用重计算
    29            IMapAlgebraOp pMapAlgebraOp = (IMapAlgebraOp)new RasterMapAlgebraOp();
    30            IRasterAnalysisEnvironment pRasAnaEnv = (IRasterAnalysisEnvironment)pMapAlgebraOp;
    31            pMapAlgebraOp.BindRaster(pRasOut1 as IGeoDataset, "R");
    32            string expresion = "[R] * 0.0000915"//坐标系统转换参数
    33            IRaster pRasOut = pMapAlgebraOp.Execute(expresion) as IRaster;
    34
    35            //输出栅格数据,否则存放为临时数据
    36            if (path != "")
    37            {
    38                string foldPath = System.IO.Path.GetDirectoryName(path);
    39                string rasterName = System.IO.Path.GetFileName(path);
    40                try
    41                {
    42                    IRasterBandCollection bandCollection = (IRasterBandCollection)pRasOut;
    43                    IRasterDataset dataset = bandCollection.Item(0).RasterDataset;
    44                    ITemporaryDataset temp = (ITemporaryDataset)dataset;
    45                    RasterWorkspaceFactory factory = new RasterWorkspaceFactory();
    46                    IWorkspace workSpace = factory.OpenFromFile(foldPath, 0);
    47                    temp.MakePermanentAs(rasterName, workSpace, "IMAGINE Image");
    48                }

    49                catch
    50                {
    51                    return pRasOut;
    52                }

    53            }

    54            return pRasOut;
    55        }

    56

     

     

    3.DEM提取等高线

           根据指定间隔,从DEM栅格数据中提取等高线数据。主要用了ISurfaceOp接口下的Contour()方法。主要代码如下:

     

    代码
    1    ISurfaceOp pSurfaceOP = new RasterSurfaceOpClass();
    2    IFeatureLayer pFL = new FeatureLayerClass(); 
    3    object Missing = Type.Missing;
    4    pFL.FeatureClass = pSurfaceOP.Contour(iRaster as IGeoDataset, interval, ref Missing) as IFeatureClass;
    5

     

     

    4.DEM生成TIN

     

    代码
      1               //***************生成TIN模型*********************************************
      2                IGeoDataset pGeoData = iRaster as IGeoDataset;
      3                IEnvelope pExtent = pGeoData.Extent;
      4                IRasterBandCollection pRasBC = iRaster as IRasterBandCollection;
      5                IRasterBand pRasBand = pRasBC.Item(0);
      6                IRawPixels pRawPixels = pRasBand as IRawPixels;
      7                IRasterProps pProps = pRawPixels as IRasterProps;
      8
      9                int iWid = pProps.Width;
     10                int iHei = pProps.Height;
     11
     12                double w = iWid / 1000.0f;
     13                double h = iHei / 1000.0f;
     14
     15                IPnt pBlockSize = new DblPntClass();
     16                bool IterationFlag;
     17
     18                if (w < 1 && h < 1//横纵都小于1000个像素
     19                {
     20                    pBlockSize.X = iWid;
     21                    pBlockSize.Y = iHei;
     22                    IterationFlag = false;
     23                }

     24                else
     25                {
     26                    pBlockSize.X = 1001.0f;
     27                    pBlockSize.Y = 1001.0f;
     28                    IterationFlag = true;
     29                }

     30
     31                double cellsize = 0.0f;     //栅格大小
     32                IPnt pPnt1 = pProps.MeanCellSize(); //栅格平均大小
     33                cellsize = pPnt1.X;
     34
     35                ITinEdit pTinEdit = new TinClass() as ITinEdit;
     36                pTinEdit.InitNew(pExtent);
     37
     38                ISpatialReference pSpatial = pGeoData.SpatialReference;
     39                pExtent.SpatialReference = pSpatial;
     40
     41                IPnt pOrigin = new DblPntClass();
     42                IPnt pPixelBlockOrigin = new DblPntClass();
     43
     44                //栅格左上角像素中心坐标
     45                double bX = pBlockSize.X;
     46                double bY = pBlockSize.Y;
     47
     48                pBlockSize.SetCoords(bX, bY);
     49                IPixelBlock pPixelBlock = pRawPixels.CreatePixelBlock(pBlockSize);
     50
     51                object nodata = pProps.NoDataValue;     //无值标记
     52                ITinAdvanced2 pTinNodeCount = pTinEdit as ITinAdvanced2;
     53                int nodeCount = pTinNodeCount.NodeCount;
     54
     55                object vtMissing = Type.Missing;
     56
     57                object vPixels = null;      //格子
     58                if (IterationFlag)   //当为一个处理单元格子时
     59                {
     60                    pPixelBlockOrigin.SetCoords(0.0f0.0f);
     61                    pRawPixels.Read(pPixelBlockOrigin, pPixelBlock);
     62
     63                    vPixels = pPixelBlock.get_SafeArray(0);
     64                    double xMin = pExtent.XMin;
     65                    double yMax = pExtent.YMax;
     66                    pOrigin.X = xMin + cellsize / 2;
     67                    pOrigin.Y = yMax - cellsize / 2;
     68                    bX = pOrigin.X;
     69                    bY = pOrigin.Y;
     70
     71                    pTinEdit.AddFromPixelBlock(bX, bY, cellsize, cellsize, nodata, vPixels, m_zTolerance, ref vtMissing, out vtMissing);
     72                }

     73                else  //当有多个处理单元格时,依次循环处理每个单元格
     74                {
     75                    int i = 0, j = 0, count = 0;
     76                    int FirstGoNodeCount = 0;
     77                    while (nodeCount != FirstGoNodeCount)
     78                    {
     79                        count++;
     80                        nodeCount = pTinNodeCount.NodeCount;
     81                        //依次循环处理
     82                        for (i = 0; i < h + 1; i++)
     83                        {
     84                            for (j = 0; j < w + 1; j++)
     85                            {
     86                                double bX1, bY1, xMin1, yMax1;
     87                                bX1 = pBlockSize.X;
     88                                bY1 = pBlockSize.Y;
     89
     90                                pPixelBlockOrigin.SetCoords(j * bX1, i * bY1);
     91                                pRawPixels.Read(pPixelBlockOrigin, pPixelBlock);
     92                                vPixels = pPixelBlock.get_SafeArray(0);
     93
     94                                xMin1 = pExtent.XMin;
     95                                yMax1 = pExtent.YMax;
     96
     97                                bX1 = pBlockSize.X;
     98                                bY1 = pBlockSize.Y;
     99
    100                                pOrigin.X = xMin1 + j * bX1 * cellsize + cellsize / 2.0f;
    101                                pOrigin.Y = yMax1 + i * bY1 * cellsize - cellsize / 2.0f;
    102
    103                                bX1 = pOrigin.X;
    104                                bY1 = pOrigin.Y;
    105
    106                                pTinEdit.AddFromPixelBlock(bX1, bY1, cellsize, cellsize, nodata, vPixels, m_zTolerance, ref vtMissing, out vtMissing);
    107
    108                                FirstGoNodeCount = pTinNodeCount.NodeCount;
    109                            }

    110                        }

    111                    }

    112                }

    113
    114                //保存TIN文件
    115                pTinEdit.SaveAs(tinFileName, ref vtMissing);
    116              pTinEdit.StopEditing(true);
    117

     

     

    5.动态变化DEMTIN的渲染样式

           动态变化DEMTIN的渲染样式其实是根据用户的设定重新生成对应的渲染样式而已,这里就不贴代码了,具体的可以参考程序。

     

    6.矢量图层叠加到TIN模型

           矢量图层叠加到TIN模型,其实是改变图层的属性,将图层中对应的ILayerExtensions接口变为I3DProperties接口,然后将I3DProperties. BaseSurface属性设为TIN图层表面数据。具体代码如下:

     

    代码
     1        /// <summary>
     2        /// 将矢量图层叠加到TIN模型上
     3        /// </summary>
     4        /// <param name="pLayer">要叠加的图层</param>
     5        /// <param name="pSceneControl">三维控件</param>

     6        public void setLayerToTIN(ILayer pLayer, AxSceneControl pSceneControl)
     7        {
     8            I3DProperties p3DProperties;
     9            p3DProperties = get3DProps(pLayer);
    10            p3DProperties.BaseOption = esriBaseOption.esriBaseSurface;
    11            ISurface pSurface = getTinlayer(pSceneControl).Dataset as ISurface;
    12            p3DProperties.BaseSurface = pSurface;
    13            p3DProperties.Apply3DProperties(pLayer);
    14        }

    15
    16        /// <summary>
    17        /// 恢复到平常样式
    18        /// </summary>
    19        /// <param name="pLayer"></param>
    20        /// <param name="pSceneControl"></param>

    21        public void setLayerOutTIN(ILayer pLayer, AxSceneControl pSceneControl)
    22        {
    23            I3DProperties p3DProperties;
    24            p3DProperties = get3DProps(pLayer);
    25            p3DProperties.BaseOption = esriBaseOption.esriBaseExpression;
    26            p3DProperties.Apply3DProperties(pLayer);
    27        }

    28
    29        /// <summary>
    30        /// 获得普通要素图层的3D属性
    31        /// </summary>
    32        /// <param name="pLayer">普通矢量图层</param>
    33        /// <returns></returns>

    34        public I3DProperties get3DProps(ILayer pLayer)
    35        {
    36            ILayerExtensions pLayerExts = pLayer as ILayerExtensions;
    37            if (pLayerExts != null)
    38            {
    39                for (int i = 0; i < pLayerExts.ExtensionCount; i++)
    40                {
    41                    I3DProperties p3DProps = pLayerExts.get_Extension(i) as I3DProperties;
    42                    if (p3DProps != null)
    43                        return p3DProps;
    44                }

    45            }

    46            return null;
    47        }

    48
    49       /// <summary>
    50        /// 返回TIN数据图层
    51        /// </summary>
    52        /// <param name="pSceneControl">三维控件</param>
    53        /// <returns></returns>

    54        public ITinLayer getTinlayer(AxSceneControl pSceneControl)
    55        {
    56            ITinLayer pTinlayer = null;
    57            IScene map = pSceneControl.Scene;
    58            if (map == null)
    59                return null;
    60            for (int i = 0; i < map.LayerCount; i++)
    61            {
    62                ILayer lyr = map.get_Layer(i);
    63                if (lyr is ITinLayer)
    64                {
    65                    pTinlayer = lyr as ITinLayer;
    66                    break;
    67                }

    68            }

    69            return pTinlayer;
    70        }

    71

     

     

    7.总结

           至此,关于TIN的一些介绍就到这告一段落,文中没有阐述清楚的部分可以参看程序中的代码。当然,其中不足之处还请各位留言批评指正。

  • 相关阅读:
    mysql基础语句
    .opt,frm,.MYD,.MYI文件如何转为.sql文件?
    如何使用phpstudy本地搭建多站点(每个站点对应不同的端口)
    吐槽下微软的vs code编辑器
    补码的两个重要问题
    注意力不集中是因为你没有紧迫感
    弧度与角度的转换公式推导
    ps图层面板上的【透明度】与【填充】的区别
    【ctrl+A】与【ctrl+单击图层缩略图】有什么区别?
    DRF-认证 权限 频率组件
  • 原文地址:https://www.cnblogs.com/liuzhiyuan/p/1613118.html
Copyright © 2020-2023  润新知