C#+AE 栅格表面分析

一、栅格表面分析

栅格表面分析,虽然从名字上来看是针对栅格表面来进行分析,但是在AE中这里的栅格表面一般是指“数字地形曲面”(DEM或者DTM),所以在AE中也可以把栅格表面分析理解为“数字地形分析”。按照这种思维再来理解AE中的很多概念就容易很多了,对于“数字地形分析”而言,其实质上只有两个目的:地形属性计算和地形特征提取,而我们经常会遇到的地形因子本就很多,例如:坡度、坡向、曲率等等,除此之外就是针对地形要素的特征进行提取,这类的地形要素也有很多,例如山脊线、山谷线、流域、可视性等等。

总的来说呢,了解这些地形因子和要素概念有助于我们接下来学习AE的栅格表面分析这部分内容,而且我一直认为在把书上的程序实现的同时,再去真正的理解了程序之外的这些知识点会使我们真正的掌握程序内的东西*~*,下面就是我认为有必要了解的几个地形因子。

1.1坡度

地形表面任一点的坡度是指过该点的切平面与水平面的夹角。其表现了地形表面在该点的倾斜程度,在数值上等于过该点的地表微分单元的法向量n与z轴的夹角。如下图所示:

从上图可以看出坡度值越低,说明该点(像元)所处的地势越平坦,反之,则表明地势较为陡峭。

1.2坡向

坡向的定义则是地形表面上一点的切平面的法向量在水平面的投影与该点的正北方向的夹角。在上图中,因为是地理坐标系的关系,所以x轴的正半轴所指的方向是正北方向,除此之外特别要说一下的是,坡向表征的是该点高程值改变量的最大变化方向。

我记得我有一段时间一直以为坡向是该点切平面法向量所指的方向,之后仔细看了定义之后才知道自己搞错了啊*^*。其实现在想想也能理解一二,像我们现实生活中经常使用东南西北、1点钟方向等等,这些都还停留在二维平面上,而坡向仍然是沿用了这种二维表述,大概是感觉这样描述更能让人理解事物的大致方位。

1.3曲率

曲率是对地形表面上的一点扭曲变化程度的定量化度量因子,地面曲率在垂直和水平两个方向上的分量则被称为平面曲率和剖面曲率。其中剖面曲率是对地面坡度沿最大坡降方向地面高程变化率的度量,而平面曲率描述的是地表曲面沿水平方向的弯曲、变化情况,也就是该点所在的地面等高线(等值线)的弯曲程度。

因为自己实在是没有绘图的天赋,所以就截取了书上的图来说明了一下这部分内容*~*。

二、方法实现

原始数据图像:
在这里插入图片描述

2.1坡度计算

代码如下:
RasterSurfaceAnalysis.cs:

 	public partial class RasterSurfaceAnalysis : DevExpress.XtraEditors.XtraForm
    {
        public RasterSurfaceAnalysis()
        {
            InitializeComponent();
        }

        public AxMapControl axMapControl { get; set; }
        IMap pMap;

        private ISurfaceOp2 surfaceOp;       //表面分析操作对象
        private IGeoDataset inputDataset;   //输入数据集
        private IGeoDataset outputDataset;   //输出数据集
        private object Missing = Type.Missing;

        private esriGeoAnalysisSlopeEnum slopeEnum;     //输出单位的形式

        //窗体生成事件
        private void RasterSurfaceAnalysis_Load(object sender, EventArgs e)
        {
            surfaceOp = new RasterSurfaceOpClass();
            pMap = axMapControl.Map;
            if (pMap == null)
                return;
            for (int i = 0; i < pMap.LayerCount; i++)
            {
                comboBox_InputDataset.Properties.Items.Add(pMap.Layer[i].Name);
            }
        }

        //设置输入的数据集
        private void comboBox_InputDataset_SelectedIndexChanged(object sender, EventArgs e)
        {
            ILayer pLayer = GetLayerByName(pMap, comboBox_InputDataset.Text);
            IRasterLayer rasLayer = pLayer as IRasterLayer;
            IRaster raster = rasLayer.Raster;
            inputDataset = raster as IGeoDataset;
        }

        /// <summary>
        /// 坡度计算
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void simpleButton_Slope_Click(object sender, EventArgs e)
        {
            outputDataset = surfaceOp.Slope(inputDataset, slopeEnum, ref Missing);
            SaveAndShowRasterDataset(textEdit_Output.Text);
        }
        //设置输出单位的形式
        private void comboBoxEdit_SlopeUnit_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = comboBoxEdit_SlopeUnit.SelectedIndex;
            switch (index)
            {
                case 0:
                    slopeEnum = esriGeoAnalysisSlopeEnum.esriGeoAnalysisSlopeDegrees;
                    break;
                case 1:
                    slopeEnum = esriGeoAnalysisSlopeEnum.esriGeoAnalysisSlopePercentrise;
                    break;
            }
        }

        //保存并显示栅格数据集
        private void SaveAndShowRasterDataset(string filePath)
        {
            string directoryPath = System.IO.Path.GetDirectoryName(filePath);
            string fileName = System.IO.Path.GetFileName(filePath);

            IWorkspaceFactory wf = new RasterWorkspaceFactoryClass();
            IWorkspace ws = wf.OpenFromFile(directoryPath, 0) as IWorkspace;
            IConversionOp converop = new RasterConversionOpClass();
            converop.ToRasterDataset(outputDataset, "TIFF", ws, fileName);

            IRasterLayer rlayer = new RasterLayerClass();
            IRaster raster = new Raster();
            raster = outputDataset as IRaster;
            rlayer.CreateFromRaster(raster);       //使用raster对象创建一个rasterLayer对象
            rlayer.Name = fileName;    //设置图层名字
            axMapControl.AddLayer(rlayer);
            axMapControl.Refresh();
        }

        //通过图层名获取图层
        private ILayer GetLayerByName(IMap pMap, string layerName)
        {
            ILayer pLayer = null;
            ILayer tempLayer = null;
            for (int i = 0; i < pMap.LayerCount; i++)
            {
                tempLayer = pMap.Layer[i];
                if (tempLayer.Name.ToUpper() == layerName.ToUpper())
                {
                    pLayer = tempLayer;
                    break;
                }
            }
            return pLayer;
        }

        //保存路径
         private void simpleButton_Output_Click(object sender, EventArgs e)
        {
            SaveFileDialog flg = new SaveFileDialog();
            flg.Title = "保存路径";
            flg.Filter = "TIFF(.tif)|*.tif|ShpFile(.shp)|*.shp";
            flg.ShowDialog();

            textEdit_Output.Text = flg.FileName;
        }
    }

MainForm.cs:

	   //栅格表面分析
       private void barButtonItem_RasterSurfacceAnalysis_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
       {
           RasterSurfaceAnalysis surfaceAnalysis = new RasterSurfaceAnalysis();
           surfaceAnalysis.axMapControl = axMapControl_MapView;
           surfaceAnalysis.ShowDialog();
       }

注:输出单位的形式如下:
在这里插入图片描述

实现效果:
在这里插入图片描述
在这里插入图片描述

2.2坡向计算

代码如下:

 		//坡向计算
        private void simpleButton_Aspect_Click(object sender, EventArgs e)
        {
            outputDataset= surfaceOp.Aspect(inputDataset);
            SaveAndShowRasterDataset(textEdit_Output.Text);
        }

实现效果:
在这里插入图片描述
在这里插入图片描述

2.3等值线计算

在AE中,等值线应理解为“等高线”更为合适,也就是指将栅格表面上相邻且等高程的点相连接而形成的线。

代码如下:

 		//等值线计算
        private void simpleButton_Contour_Click(object sender, EventArgs e)
        {
            double interval = Convert.ToDouble(textEdit_Interval.Text.Trim());
            outputDataset = surfaceOp.Contour(inputDataset, interval,ref Missing);
            SaveAndShowFeatureDataset(textEdit_Output.Text);
        }

        //保存并显示矢量数据集
        private void SaveAndShowFeatureDataset(string filePath)
        {
            string directoryPath = System.IO.Path.GetDirectoryName(filePath);
            string[] fileName = System.IO.Path.GetFileName(filePath).Split('.');

            IWorkspaceFactory wf = new ShapefileWorkspaceFactoryClass();		//要注意一下这里,因为是要保存矢量文件,所以应该创建矢量工作空间工厂对象
            IWorkspace ws = wf.OpenFromFile(directoryPath, 0) as IWorkspace;
            IConversionOp converop = new RasterConversionOpClass();
            converop.ToFeatureData(outputDataset, ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline,
                ws, fileName[0]);

            IFeatureClass featureClass = outputDataset as IFeatureClass;
            IFeatureLayer featLayer = new FeatureLayerClass();
            featLayer.FeatureClass = featureClass;
            featLayer.Name = fileName[0];          //设置图层名字
            axMapControl.AddLayer(featLayer);
            axMapControl.Refresh();
        }

实现效果:
在这里插入图片描述
在这里插入图片描述

2.4填挖方

填挖操作是一个通过添加或移除表面物质来修改地表高程的过程。通过给定两个不同的表面,填挖函数会生成一个栅格数据,显示地面物质增加、减少或者不变的区域。负的体积值表明该区域已被填充,正的体积值表明该区域已发生移除。

实现代码如下:

 		//填挖计算变量
        private IGeoDataset inputAfterDataset;
         /// <summary>
        /// 填挖计算
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void simpleButton_CutFill_Click(object sender, EventArgs e)
        {
            ILayer pLayer = GetLayerByName(pMap, comboBoxEdit_InputAfterDataset.Text);
            IRasterLayer rasLayer = pLayer as IRasterLayer;
            IRaster raster = rasLayer.Raster;
            inputAfterDataset = raster as IGeoDataset;

            outputDataset=surfaceOp.CutFill(inputDataset, inputAfterDataset, ref Missing);
            SaveAndShowRasterDataset(textEdit_Output.Text);
        }

实现效果:
在这里插入图片描述
在这里插入图片描述
注:在这里使用IConvensionOp接口保存栅格数据时,发生了异常,说是保存的格式有问题,在将原来的.tif格式更换为.img格式之后,程序正常运行。

2.5山体阴影

山体阴影操作是指通过考虑照明源的角度和阴影,然后再根据表面栅格来晕染地形地貌的过程。

代码如下:

		/// <summary>
        /// 山体阴影
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void simpleButton_HillShade_Click(object sender, EventArgs e)
        {
            double azimuth = Convert.ToDouble(textEdit_Azimuth.Text.Trim());
            double altitude = Convert.ToDouble(textEdit_Altitude.Text.Trim());
            outputDataset = surfaceOp.HillShade(inputDataset, azimuth, altitude, true, ref Missing);
            SaveAndShowRasterDataset(textEdit_Output.Text);
        }

实现效果:
在这里插入图片描述
在这里插入图片描述

2.6曲率计算

曲率是表面的二阶导数,或者可称为坡度的坡度。

实现代码:

  		/// <summary>
        /// 曲率计算
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void simpleButton_Curvature_Click(object sender, EventArgs e)
        {
            outputDataset = surfaceOp.Curvature(inputDataset, true, true, ref Missing);
            SaveAndShowRasterDataset(textEdit_Output.Text);
        }

实现效果:
在这里插入图片描述
在这里插入图片描述

2.7可见性分析

实现代码:

 		//可视性分析
        private IGeoDataset observeDataset;
        private esriGeoAnalysisVisibilityEnum visibilityEnum;
		/// <summary>
        /// 可视性分析
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void simpleButton_Visibility_Click(object sender, EventArgs e)
        {
            outputDataset = surfaceOp.Visibility(inputDataset, observeDataset, visibilityEnum);
            SaveAndShowRasterDataset(textEdit_Output.Text);
        }

        //设置观测点数据
        private void comboBoxEdit_ObservePoint_SelectedIndexChanged(object sender, EventArgs e)
        {
            ILayer layer = GetLayerByName(pMap,comboBoxEdit_ObservePoint.Text);
            IFeatureLayer featLayer = layer as IFeatureLayer;
            observeDataset = featLayer.FeatureClass as IGeoDataset;
        }

        //分析类型
        private void comboBoxEdit_VisibilityType_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = comboBoxEdit_SlopeUnit.SelectedIndex;
            switch (index)
            {
                case 0:
                    visibilityEnum = esriGeoAnalysisVisibilityEnum.esriGeoAnalysisVisibilityFrequency;
                    break;
                case 1:
                    visibilityEnum = esriGeoAnalysisVisibilityEnum.esriGeoAnalysisVisibilityObservers;
                    break;
            }
        }

实现效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、小结

整个过程虽然相对简单,但是我也学到了下面两点:

1、怎样使用IConversionOp接口去保存栅格数据或者是矢量数据。
2、在AE中的Raster对象和FeatureClass对象才是真正的栅格数据或矢量数据的内存对象,这两个对象会直接控制对栅格数据(或矢量数据)的读取,而他们相应的Dataset对象则是对栅格数据(或矢量数据)的抽象,主要是指磁盘上的数据。

参考资料:《地理信息系统-汤国安》《ArcgisEngine地理信息系统开发教程》

  • 8
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
栅格计算器是一种常见的计算机应用程序,它允许用户在一个矩形的网格中输入数值,然后对这些数值进行各种计算。在本文中,我们将使用C#AE(Adobe After Effects)来实现一个简单的栅格计算器功能。 首先,在AE中创建一个新的合成(Composition),并添加一个文本层(Text Layer)。将文本层的内容设置为“栅格计算器”,并将其放置在合成的顶部。 接下来,我们需要创建一个矩形网格,以便用户可以输入数值。我们可以使用AE中的形状层(Shape Layer)来创建一个矩形。在AE中,选择“Layer”->“New”->“Shape Layer”来创建一个新的形状层。选择“Rectangle Tool”(矩形工具),并在画布上绘制一个矩形。然后,选择矩形图层,打开“Add”->“Fill”属性,选择一种颜色填充矩形。 现在,我们需要将矩形网格分成若干个小格子,以便用户可以在其中输入数值。我们可以使用C#编写一个简单的脚本来完成这个任务。在Visual Studio中创建一个新的C#控制台应用程序,并将其命名为“GridCalculator”。 在GridCalculator项目中,我们需要添加一个引用,以便我们可以访问AE中的COM(Component Object Model)对象。选择“Project”->“Add Reference”,然后在“COM”选项卡中找到“Adobe After Effects XX.X Type Library”(其中XX.X表示你的AE版本号),并添加它。 接下来,我们需要编写一个C#脚本来创建网格。以下是一个示例脚本: ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using AE_COM; namespace GridCalculator { class Program { static void Main(string[] args) { // Create a new AE project var ae = new Application(); var proj = ae.NewProject(); // Create a new composition var comp = proj.Items.AddComp("Grid Calculator", 1920, 1080, 1.0, 10.0, 30); // Add a new shape layer var shapeLayer = comp.Layers.AddShape(); shapeLayer.Name = "Grid"; // Create a new rectangle shape var rect = new Shape(); var rectGroup = new ShapeGroup(); rectGroup.AddShape(rect); shapeLayer.Property("Contents").AddProperty("ADBE Vector Group").SetValue(rectGroup); // Set the rectangle size rect.Size = new PointF(400, 400); // Create the grid var rows = 10; var cols = 10; var cellSize = new PointF(rect.Size.X / cols, rect.Size.Y / rows); for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { // Create a new rectangle shape for each cell var cell = new Shape(); var cellGroup = new ShapeGroup(); cellGroup.AddShape(cell); shapeLayer.Property("Contents").AddProperty("ADBE Vector Group").SetValue(cellGroup); // Set the cell position and size var pos = new PointF(col * cellSize.X, row * cellSize.Y); cell.Position = pos; cell.Size = cellSize; } } // Save the project proj.Save(@"C:\GridCalculator.aep"); // Quit AE ae.Quit(); } } } ``` 在上面的脚本中,我们首先创建了一个新的AE项目和一个新的合成。然后,我们添加了一个新的形状层,并在其中创建了一个矩形。接下来,我们使用嵌套循环创建了一个网格,其中每个单元格都是一个独立的矩形。 最后,我们保存了AE项目,并退出AE应用程序。 现在,我们可以在AE中打开“GridCalculator.aep”文件,并将生成的网格图层拖放到我们之前创建的合成中。用户现在可以在每个单元格中输入数值,并使用AE中的表达式(Expressions)功能对这些数值进行计算。 总的来说,使用C#AE来创建栅格计算器功能是非常简单的。通过利用AE的COM对象和C#的编程能力,我们可以轻松地创建一个自定义的栅格计算器工具,以满足我们的具体需求。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大鱼BIGFISH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值