65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 MapWinGIS 和 C# 构建桌面 GIS 应用程序 - 第四部分

starIconstarIconstarIconstarIconstarIcon

5.00/5 (31投票s)

2010 年 5 月 19 日

CPOL

8分钟阅读

viewsIcon

141873

downloadIcon

10616

GIS 数据创建的隐藏秘诀。

前言

本课程是系列课程的第 4 部分,旨在展示使用 C# 开发基于 Windows 的桌面 GIS 独立应用程序的 MapWinGIS.ocx 的功能。如果您是第一次了解 MapWinGIS.ocx,我强烈建议您先阅读之前的三个教程。这些教程可以在这里找到:第 1 部分第 2 部分第 3 部分

引言

许多 GIS 专家认为数据创建是最重要的 GIS 活动之一。GIS 数据可以通过多种方式创建,可以直接绘制,也可以从辅助源导入。在本文中,我将讨论如何使用 MapWinGIS.ocx 和 C# 管理数据创建。我使用的是 .NET Framework 3.5 和 Microsoft Visual Studio 2008 Professional Edition。实际上,您也可以毫无问题地使用 Visual Studio Express Edition。此外,您还必须在您的计算机上安装 MapWinGIS.ocx。最后,本文中使用的数据已作为压缩文件提供。

目标

以下程序的目的是使用存储在逗号分隔值(*.csv)文本格式中的辅助数据创建点 shape 文件。CSV 文件是一种特殊格式的纯文本文件,以非常简单的格式存储表格式信息,每行一个记录,并且每条记录中的字段都用逗号分隔。在本教程中,一系列位置存储在一个名为 road.csv 的 CSV 文件中。每个位置都使用三个参数进行描述。第一个参数是 ID,它是整数索引。第二个和第三个参数是以通用横轴墨卡托(UTM)米制坐标格式表示的坐标。下图显示了在 Notepad++ 软件中显示的 road.csv 文件的内容。

01.JPG

我必须在这里提到,许多数据采集设备,如 GPS 和声纳,都可以导出采集到的数据。例如,从 GPS 设备下载的 NMEA 0183 文件就是一种 CSV 文件格式。

方法论

程序员在进行 CSV 到 shape 文件转换软件时,应考虑三个主要问题。这些问题是如何创建一个新的 shape 文件,如何正确读取 CSV 文件内容并进行解析,最后是如何创建 shape 并将其添加到 shape 文件中。下图展示了将 CSV 文件转换为 shape 文件的详细方法。

Drawing1.jpg

第一步是使用 MapWinGIS API 创建一个新的 shape 文件实例。第二步是为新的 shape 文件表添加一个新字段。建议在创建阶段至少为 shape 文件添加一个字段。在此示例中,索引字段将是整数数据类型。这些步骤代表了开发人员需要考虑的第一个任务,即 shape 文件创建任务。完成此任务后,我们将得到一个空的 shape 文件。如果我们在此点终止程序,我们将丢失 shape 文件,因为它为空。Shape 文件应包含一些 shape 才能成为真正的 shape 文件,并在存储介质上有位置和大小。在为 shape 文件添加 shape 之前,我们必须使用 CSV 文件提供的数据创建这些 shape。因此,下一个任务是打开 CSV 文件并读取其内容。第三步是打开 CSV 文件。这是一个非常简单的步骤,因为该文件是一个文本文件。逐行读取 CSV 文件内容并分析该行以提取 ID、x 和 y 数据是第四步。使用辅助子例程进行 CSV 行的分析。这些子例程引入了第四步。第五步是使用 MapWinGIS API 创建 shape。创建 shape 后,应将 shape 添加到 shape 文件中,这是第六步。当 CSV 文件仍有待读取的行时,将重复步骤四到六。最后一步是保存 shape 文件。

是时候写代码了

我认为我们已经制定了完整的路线图来开发一个简单的软件,将 CSV 文件转换为 ESRI Shape 文件。那么,让我们写一些有趣的 C# 代码吧。在本教程中,我们将使用控制台应用程序模板。启动您的 Visual Studio 并创建一个新的控制台应用程序项目。我们需要添加 MapWinGIS 的引用。您可以在本系列的第一篇教程中找到有关如何为项目添加此引用的详细说明。在编写我们的核心代码——CSV 到 shape 文件转换代码——之前,我们必须开发一个简单的代码来解析 CSV 文件内容。下面的代码框显示了三个静态方法:GetIndexGetXGetY,每个方法接收一个 CSV 行并返回该行中的特定组件(Index、X、Y 字段值)。

private static double GetY(string sentence)
{
    string strY = sentence.Substring(sentence.LastIndexOf(";") + 1);
    double result = Convert.ToDouble(strY);
    return result;
}

private static double GetX(string sentence)
{
    string strNewSentense = sentence.Substring(sentence.IndexOf(";")+1);
    string strX = strNewSentense.Substring(0, strNewSentense.IndexOf(";"));
    double result = Convert.ToDouble(strX);
    return result;
}

private static Int16 GetIndex(string sentence)
{
    string strId = sentence.Substring(0, sentence.IndexOf(";"));
    Int16 result = Convert.ToInt16(strId);
    return result;
}

回到控制台项目的 `Main` 方法,我们将在此处编写核心代码。在第一行,添加创建 `Shapefile` 类新实例(myShapefile)所需的代码。在第二行,使用 `CreateNew` 方法通过指定其完整路径和几何类型来创建新的物理 shape 文件。Shape 文件的几何类型由 `ShapefileType` 枚举器定义。此枚举器可以定义 14 种几何类型。此枚举器提供的最常见的几何类型是用于点、折线和多边形几何类型的 `SHP_POINT`、`SHP_POLYLINE` 和 `SHP_POLYGON`。强烈建议在创建新 shape 文件时为 shape 文件表添加一个新字段,无论您是否为该字段单元格添加值。

第三行显示了如何为 `MapWinGIS.Filed` 类创建新实例(myField)。接下来的三行显示了如何设置字段属性。有许多可用的字段属性,但常见的属性是这三个。第一个属性是 `Name`,它是一个字符串,被指定为新字段的名称。您需要注意:Shape 文件格式使用旧的 *.dbf 格式存储属性;您必须在工作中考虑文件命名所有限制。这意味着,名称字符串应少于 12 个字母,且不包含特殊字符或空格。第二个属性是 `Type`,它定义了可以存储在此新字段中的数据类型。MapWinGIS 提供了一个枚举器(FieldType),其中包含 `Field` 类可能接受的所有可用数据类型。此枚举器为双精度、整数和字符串数据分别提供了 `DOUBLE_FIELD`、`INTEGER_FIELD` 和 `STRING_FIELD`。第三个属性是 `Width`。此属性定义了字段的宽度(多少字母或数字)。仅将整数值设置为此属性。最后,我们必须将此新字段添加到表中。`myShapefile` 实例的 `EditInsertField` 方法用于将新字段添加到表中。您需要注意这一点:使用此方法需要将表对象 `EditTable` 属性的值设置为 true。幸运的是,当我们使用 `CreateNew` 方法时,`EditTable` 和 `EditShape` 属性都会自动设置为 true

//Create new shapefile
Shapefile myShapefile = new Shapefile();
//Define the path of the new shapefile and geometry type
myShapefile.CreateNew(@"D:\GISLesson04\road.shp", ShpfileType.SHP_POINT);
//Create new field
MapWinGIS.Field myField = new Field();
//Set the field properties
myField.Name = "ID";
myField.Type = FieldType.INTEGER_FIELD;
myField.Width = 10;
//Add the filed for the shapefile table
int intFieldIndex = 0;
myShapefile.EditInsertField(myField, ref intFieldIndex, null);

现在我们有了一个具有单个字段表的新 shape 文件,可以随时使用。如果我们在这种情况下完成应用程序,MapWinGIS 将物理删除该 shape 文件,因为一个没有 shape 的 shape 文件没有意义。您必须至少添加一个 shape 文件才能被 MapWinGIS 接受并保存这个新的 shape 文件。但是,我们有一个包含绘制所需数据的 CSV 文件,这正是我们将在下一节中做的。要读取 CSV 文件内容——请记住,CSV 文件是文本文件——我们使用 `StreamReader` 实例(myFile),然后我们可以使用它作为流读取器实例,通过 while 循环逐行读取 CSV 文件内容。当到达 CSV 文件末尾时,此循环将停止。在 while 块内,每次循环,我们将创建一个 `Shape` 类的新实例(myShape)。`Shape` 类定义了 shape 文件中的 shape。每个 `Shape` 包含一个或多个点。应该使用 `myShape` 实例的 `Create` 方法来创建此新实例。此方法需要一个参数来定义 shape 的几何。此几何由之前提到的 `ShapefileType` 枚举器提供。创建 `Shape` 实例 myShape 后,我们必须使用 CSV 文件中的点数据来绘制它——或者说空间定义它。为此,我们必须创建一个名为 myPoint 的 `Point` 类的新实例。此实例有两个属性(x、y),用于定义点的位置。现在是时候利用之前设计的解析方法了。我们将使用 `GetX` 和 `GetY` 方法从 CSV 行获取 x 和 y 值,并将这些值设置为 myPoint 的(x, y)属性。创建点后,我们将使用 `InsertPoint` 方法将其添加到 `Shape` 实例(myShape)中。然后,我们将使用 `EditInsertShape` 方法将此 shape 添加到 shape 文件实例(myShapefile)中。

System.IO.StreamReader myFile =
   new System.IO.StreamReader(@"D:\GISLesson04\road.csv");
// Using while loop to read csv file line by line
while ((myLine = myFile.ReadLine()) != null)
{
    if (myCounter > 0)
    {
        MapWinGIS.Shape myShape = new Shape();
        myShape.Create(ShpfileType.SHP_POINT);
        MapWinGIS.Point myPoint = new Point();
        myPoint.x = GetX(myLine);
        myPoint.y = GetY(myLine);
        int myPointIndex = 0;
        myShape.InsertPoint(myPoint, ref myPointIndex);
        myShapefile.EditInsertShape(myShape, ref myShapeIndex);
        myShapeIndex++;
    }
    
    myCounter++;
}

while 循环到达 CSV 文件末尾时,CSV 文件中的每一行都将对应 shape 文件中的一个点。最后一步是停止编辑 shape 文件。为此,我们必须使用 myShapefile 实例的 `StopEditingShapes` 方法。现在,您可以使用任何 GIS 软件显示您的新 shape 文件。您可以像我们在早期课程中所做的那样,使用 MapWinGIS 应用程序来显示它。对我来说,我将在 MapWindows GIS 中显示 shape 文件,MapWindows GIS 是一个完全基于 MapWinGIS 构建的 Microsoft Windows 开源桌面 GIS 应用程序。

display.JPG

© . All rights reserved.