001集—shapefile(.shp)格式详解——arcgis

 一、什么是shapefile

Shapefile 是一种用于存储地理要素的几何位置和属性信息的非拓扑简单格式。shapefile 中的地理要素可通过点、线或面(区域)来表示。包含 shapefile 的工作空间还可以包含 dBASE 表,它们用于存储可连接到 shapefile 的要素的附加属性。

下面是 shapefile 如何在 ArcCatalog 中显示的示例。还能看到 dBASE 文件(它可能与 shapefile 相关联)。

默认情况下,具有文件扩展名 .txt、.asc、.csv 或 .tab 的所有文件将以文本文件的形式显示在 ArcCatalog 中。但在选项 对话框中,您可以选择其中哪些文件类型应显示为文本文件以及哪些不能显示在目录树中。当文本文件包含逗号分隔和制表符分隔的值时,您能够在 ArcCatalog 表视图中看到它们的内容并可将其连接到地理要素。在 ArcCatalog 中,可将文本文件删除,但其内容为只读。

可以在图层“属性”对话框的连接和关联选项卡中,将 dBASE 表或文本文件中存储的属性连接到 shapefile 中的要素。如果表包含描述空间位置的信息(例如,x,y,z 坐标或街道地址),则可以使用 ArcCatalog 中提供的工具创建用以表示这些位置的 shapefile。

旧版本:

除 shapefile 和表之外,ArcView GIS 用户还可以处理项目文件、图例文件和 Avenue 脚本。虽然无法直接在 ArcGIS Desktop 中处理这些项目,但可以通过 ArcCatalog 对其进行管理。要在 ArcCatalog 中查看这些项目,必须将其文件扩展名添加到文件类型列表中。例如,要查看 ArcView GIS 项目,请将文件扩展名 .apr 添加到列表中。

Shapefile 是一种用于存储地理要素的几何位置和属性信息的非拓扑简单格式。Shapefile 是可以在 ArcGIS 中使用和编辑的其中一种空间数据格式。

shapefile 格式在应存储在同一项目工作空间且使用特定文件扩展名的三个或更多文件中定义地理配准要素的几何和属性。这些文件是:

  • .shp - 用于存储要素几何的主文件;必需文件。
  • .shx - 用于存储要素几何索引的索引文件;必需文件。
  • .dbf - 用于存储要素属性信息的 dBASE 表;必需文件。

    几何与属性是一对一关系,这种关系基于记录编号。dBASE 文件中的属性记录必须与主文件中的记录采用相同的顺序。

  • .sbn 和 .sbx - 用于存储要素空间索引的文件。
  • .fbn 和 .fbx - 用于存储只读 shapefile 的要素空间索引的文件。
  • .ain 和 .aih - 用于存储某个表中或专题属性表中活动字段属性索引的文件。
  • .atx - .atx 文件针对在 ArcCatalog 中创建的各个 Shapefile 或 dBASE 属性索引而创建。ArcGIS 不使用 shapefile 和 dBASE 文件的 ArcView GIS 3.x 属性索引。已为 shapefile 和 dBASE 文件开发出新的属性索引建立模型。
  • .ixs - 读/写 shapefile 的地理编码索引。
  • .mxs - 读/写 shapefile(ODB 格式)的地理编码索引。
  • .prj - 用于存储坐标系信息的文件;由 ArcGIS 使用。
  • .xml - ArcGIS 的元数据 - 用于存储 shapefile 的相关信息。
  • .cpg - 可选文件,指定用于标识要使用的字符集的代码页。

各文件必须具有相同的前缀,例如,roads.shp、roads.shx 和 roads.dbf。

在 ArcCatalog(或任何 ArcGIS 应用程序)中查看 Shapefile 时,将仅能看到一个代表 Shapefile 的文件;但可以使用 Windows 资源管理器查看与 Shapefile 相关联的所有文件。复制 Shapefile 时,建议在 ArcCatalog 中或者使用地理处理工具执行该操作。但如果在 ArcGIS 之外复制 shapefile,确保复制组成该 shapefile 的所有文件。

编辑 shapefile

可以在具有任意许可等级的 ArcGIS Desktop(ArcGIS Desktop Basic、ArcGIS Desktop Standard或 ArcGIS Desktop Advanced)中编辑 shapefile。但要想利用高级编辑功能(例如,拓扑),则需要将 shapefile 作为要素类导入到地理数据库中。

了解有关在 ArcGIS 中进行编辑的详细信息

将 shapefile 和 dBASE 表导入到地理数据库要素类和表

shapefile 中的所有要素类型都会在地理数据库中转换为几何类型。与 coverage 不同的是,shapefile 要素类型与地理数据库中存储的几何类型相类似,因此转换要更为简单。有关详细信息,请参阅导入时数据如何进行转换。

Shapefile 文件大小限制

组成 shapefile 的每个文件均被限制为 2 GB。因此,.dbf 文件不能超过 2 GB,.shp 文件也不能超过 2 GB(只有这两个文件的容量会很大)。所有组成文件的总大小可以超过 2 GB。

多年以来,Esri 研发了三种用于存储地理信息的主要数据格式:coverage、shapefile 以及地理数据库。其中,Shapefile 为存储地理及属性信息提供了一种简单的格式。正由于 shapefile 的简易性,使其成为一种非常流行的开放式数据转换格式。凭借其简易性,shapefile 似乎已成为人们的必然选择,然而,在它的使用中,仍然存在由地理数据库地址所决定的局限性。因此,使用 shapefile 时,应注意其局限性。概括如下:

  • 地理数据不仅包含 shapefile 可存储的简单要素和属性信息。例如:在地理数据库中,可支持注记、属性关系、拓扑关系、属性域和子类型、坐标精度和分辨率以及很多其他功能,但在 shapefile 中则不支持这些内容。
  • 由于 shapefile 是一种广泛用于数据转换的开放式格式,因此,许多非 Esri 软件包都可将数据输出为 shapefile 格式。(要了解 shapefile 格式规范,请参阅 http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf。) 遗憾的是,这些软件包并不总能创建格式正确的 shapefile。或许,您已遇到过从其他源接收到受损的 shapefile 的问题。
  • Shapefile 利用 dBASE 文件格式(.dbf 文件)来存储属性。而 dBASE 是一种非 Esri 格式,该格式是于 20 世纪 80 年代早期开发的,是当时最为流行的属性表存储格式。然而,它们的时代已悄然而逝,从那时起,数据制图表达方法方面的改进(如,Unicode 标准)不断涌现,以支持世界上大部分的书写系统。这就是 shapefile 无法使用非英语语言有效存储信息的原因之一。
  • 与地理数据库中的要素类不同,ArcGIS 不对形状长度和形状面积字段进行计算和维护。

正因为存在这些(或更多)问题,如果选用 shapefile 进行活动数据库管理将显得捉襟见肘 - 它们无法处理现今数据的创建、编辑、版本管理及归档的生命周期。

何时使用 shapefile?

  • 导出数据供非 Esri 软件应用程序使用时
  • 导出数据供 ArcView GIS 3 或 ArcInfo Workstation 使用时
  • 需要迅速写入简单要素和属性时。(但是,您必须注意下面所述的局限性。)

何时不能使用 shapefile?

除以下列出的一些特例外,可以使用 shapefile 来存储简单的要素几何。不过,shapefile 在属性存储上存在严重问题。例如,它们无法存储空值,无法向上舍入数字,对 Unicode 字符串的支持不足,字段名称最长只能为 10 个字符,且无法在日期字段中存储时间。这些只是其中的主要问题。此外,它们不支持在地理数据库中的某些功能,如:属性域和子类型。因此,除非是非常简单的属性且不需要使用地理数据库功能,否则请不要使用 shapefile。

Shapefile 组件与文件扩展名

Shapefile 存储在三个或更多个具有相同前缀的文件中,且位于同一系统文件夹(shapefile 工作空间)中。使用 Windows 资源管理器而非 ArcCatalog 查看该文件夹时,可以看到单个文件。

Shapefile 扩展名

扩展名

说明

必需的文件?

.shp

用于存储要素几何的主文件。此文件中未存储任何属性 - 仅有几何。

.shx

.shp 的配套文件,用于存储 .shp 文件中各个要素 ID 的位置。

.dbf

用于存储要素属性信息的 dBASE 表。

.sbn 和 .sbx

用于存储要素空间索引的文件。

.atx

为各 dBASE 属性索引(建立于 ArcCatalog 中)而创建。

.ixs 和 .mxs

读写 shapefile 的地理编码索引。

.prj

用于存储坐标系信息的文件。

.xml

ArcGIS 的元数据;用于存储 shapefile 的相关信息。

几何限制

  • 任何 shapefile 组件文件都有大小为 2 GB 的上限,可理解为可包含的点要素最多约为 7000 万个。shapefile 中可存储的线或面要素的实际数量取决于每个线或面中的折点数(一个折点相当于一个点)。
  • Shapefile 也不包含类似于地理数据库要素类具有的 x,y 容差的信息。两坐标系被视为同一坐标系之前,x、y 容差就是它们之间的最小距离。当评估相同要素类中各要素之间的关系或评估多个不同要素类之间的关系时,会使用此 x、y 容差。编辑要素时,也会经常使用它。若所要执行的任意类型的操作涉及元素之间的比较(例如,使用叠加工具、裁剪工具、按位置选择图层工具或任何将两个或多个要素类作为输入的工具),则应使用地理数据库要素类(包含 x,y 容差)而非 shapefile。
  • 由于形状压缩方法的不同,shapefile 所占用的空间可能为文件地理数据库或 SDE 的三到五倍。
  • Shapefile 支持多面体,但不支持以下多面体的高级功能:
    • 纹理坐标
    • 纹理及部分色带
    • 光线法向量
  • 与地理数据库要素类的空间索引相比,Shapefile 的空间索引效率较低。这就意味着,同地理数据库要素类相比,空间查询(如选择面内的要素)耗时更长。只有在处理大量要素时,这一项劣势才会明显。
  • shapefile 不支持通过参数定义的曲线 (也称为圆弧曲线)。如创建曲线中所述,参数曲线是通过编辑数据库要素类而创建的。圆弧曲线利用数学公式绘制曲线。若您将含圆弧曲线的地理数据库要素类导出到 shapefile 中,就可将弯曲要素变换为简单线要素,并使空间上靠近的折点捕捉到弯曲的形状。

属性限制

  • 与其他格式不同,shapefile 以字符格式(而非二进制格式)存储数值型属性。对于实数(即,包含小数位的数字),这可能会导致舍入误差。因此,此限制不适用于形状坐标,而仅适用于属性。下表列出了各属性数据类型的字段宽度。
    dBASE 中的字段宽度

    地理数据库数据类型

    dBASE 字段类型

    dBASE 字段宽度(字符数)

    对象 ID

    数值

    9

    短整型

    数值

    4

    长整型

    数值

    9

    浮点型

    浮点型

    13

    双精度型

    浮点型

    13

    文本

    字符

    254

    日期

    日期

    8

  • dBASE 文件标准仅支持其字段名称及字段值中的 ANSI 字符。Esri 已针对 dBASE 文件新增了大量 Unicode 支持,以存储 Unicode 字段名称及字段值。但此附加支持仅适用于 ArcGIS,在非 Esri 应用程序中可能不提供这些支持。

    注:

    若您的字段名称或字段值需要支持 Unicode,则强烈建议您使用地理数据库,而非 shapefile。

  • 日期字段仅支持日期。它们不支持时间。

    警告:

    对于执行时态分析的所有工具(例如时空模式挖掘工具箱中的工具)而言,日期字段不支持时间是一个严重限制。请避免使用 shapefile 进行任何类型的时态分析或日期时间计算。

  • 字段名称的长度不能超过 10 个字符。
  • 属性的最大记录长度为 4000 字节。记录长度是用于定义全部字段的字节数,而非用于存储实际值的字节数。
  • 最大字段数为 255。若超出此上限,当转换为 shapefile 时只会转换前 255 个字段。
  • dBASE 文件必须至少包含一个字段。当您新建 shapefile 或 dBASE 表格时,默认会创建一个整数 ID 字段。
  • dBASE 文件不支持类型 blob、guid、全局 ID、坐标 ID 或栅格字段类型。
  • dBASE 文件除了 WHERE 语句以外,不支持 其它 SQL 命令。
  • 当您保存编辑时,属性索引会被删除,因此,必须重新创建属性索引。

空值表示

Shapefile 不支持空值。如果将含有空值的要素类转换为 shapefile 或将数据库表转换为 dBASE 文件,则将按下表所述更改空值。

警告:

当将 shapefile 或 dBASE (.dbf) 文件用作工具的输入时,ArcGIS 无法确定某一字段值表示空值还是合法值。

shapefile 和 dBASE (.dbf) 文件中的空值替换

包含空值的数据类型

空值替换

数字 - 当工具需要输出“空”、无穷大或 NaN()时

-1.7976931348623158e+308(最大负值的 IEEE 标准)

数字(所有其他地理处理工具)

0

文本

“ ”(空白 - 单空格)

日期

存储为零,但显示为 <空>

不支持的功能

Shapefile 在工作空间或要素类级别无扩展数据类型。因此,从地理数据库要素类或其他格式转换为 shapefile 时会导致下列数据丢失:

  • 子类型
  • 属性域
  • 几何网络
  • 拓扑
  • 注记

形状长度和形状面积

对于存储在地理数据库中的线或面要素类,ArcGIS 会计算并维护 shape_length 和 shape_area 字段;也就是说,编辑地理数据库要素类中的线形状或面形状时,系统会重新计算 shape_length 和 shape_area 字段中的值以反映对要素所做的编辑。但这不适用于 shapefile。即使 shapefile 具有 shape_area 或 shape_leng 字段,对 shapefile 进行编辑后,字段也不会更新。

Shapefile 和地理处理

任何能够输出要素类的地理处理工具,均可选择 shapefile 或地理数据库要素类作为输出格式。同样,任意输出结果为表的工具,均可选择 dBASE 文件 (.dbf) 或地理数据库表作为输出格式。需要始终了解所使用的格式,以及将地理数据库输入转换为 shapefile 输出所产生的后果。

地理处理工具可自动生成输出要素类或表。自动生成的输出基于使用当前及临时工作空间环境中所述的许多因素。若您的临时工作空间环境未设置为某个地理数据库,而是设置为了某个系统文件夹,则自动生成的输出要素类将为 shapefile 或 dBASE 文件,如下图所示。

建议您将临时工作空间设置为某个文件地理数据库,以便自动生成的输出不会被写入 shapefile 或 .dbf 表中,而是被写入文件地理数据库中。

了解有关地理处理环境的详细信息

由于 shapefile 写入速度快,通常将它作为模型的中间数据使用,从而可加快模型执行速度。不过,写入文件地理数据库与写入 shapefile 的速度几乎相同,所以除非对执行速度的要求较高,否则应始终使用文件地理数据库写入中间数据及输出数据。若您一定要使用 shapefile,请注意上述局限性,且仅将 shapefile 用于简单要素和属性。将 shapefile 用于中间数据的替代方法是将要素写入 in_memory 工作空间。

有关 shapefile 的坐标系的基础知识

通常,shapefile 并不包含任何用于确定已使用哪个坐标系来定义其要素的信息。在这种情况下,“形状”列的“空间参考”属性将为“未知”或“假定地理”。如果要素的边界坐标在 x 方向上介于 -180 到 180 范围内,在 y 方向上介于 -90 到 90 范围内,ArcGIS 会认为该数据为地理数据,其基准面为 NAD27。如果边界坐标不在该范围内,软件会认为空间参考为未知。

了解有关坐标系的详细信息

即使 shapefile 的坐标系未定义,也可以使用相应的 shapefile,但可能无法利用所有可用功能。例如,shapefile 可能不能与其他数据排列在一起,这样,其自动创建的元数据将是不完整的。

在 ArcCatalog 中可以多种方式定义 shapefile 的坐标系:

  • 选择 ArcCatalog 随附的其中一个预定义坐标系。
  • 导入由另一数据源使用的坐标系参数。
  • 定义新的自定义坐标系。

坐标系参数必须保存在 shapefile 所在文件夹的 .prj 文件中,并且 .prj 文件必须与 shapefile 具有相同的文件前缀。例如,如果您正在使用名为 wells.shp 的 shapefile,那么其坐标系参数必须存储在同一文件夹的 wells.prj 文件中。

定义坐标系后,可以修改各参数。例如,您可能想要修改坐标系中从另一数据源导入的一个参数或者对其中一个预定义坐标系进行自定义。创建自定义坐标系后,可以将其另存为单独的坐标系文件;您可能需要与您所在组织中的其他人共享该坐标系。

要在 ArcCatalog 中添加或修改 shapefile 的坐标系,请使用“投影”工具或“创建空间参考”工具。

shapefile(.shp)空间数据格式详细说明

shp空间数据格式详细说明
  • shapefile(.shp)空间数据格式详细说明
    • 写在前面
    • 一.主文件的组织
      • 1.主文件头
      • 2.主文件记录
        • (1)记录头
        • (2)主文件记录内容
          • 1)空 shape
          • 2)Point (点)
          • 3)MultiPoint (多点)
          • 4) Arc(弧段)
          • 5)Polygon(面)
    • 二.索引文件的组织
      • 1.索引文件文件头
      • 2.索引记录
    • 三.属性文件的组织
      • 1.属性文件的文件头
      • 2.属性文件的实体信息
      • 3.读取属性文件的示例:

写在前面

  本文只做记录,参考资料均来源于网络,版权归原作者所有。
  ESRI 的 shape 文件由一个主文件(.shp)、一个索引文件(.shx)和一个 dBASE 表(.dbf)构成。主文件(.shp)是一个可变记录长度的随机文件,文件中的每个记录描述一个包含多个顶点的 shape。在索引文件(.shx)中,每个记录内容包含着与主文件中记录相对应的从主文件开始处的偏移量。dBASE 表(.dbf)中包含着与每个要素相对应的一条要素属性记录。几何数据与属性的一一对应关系是基于记录号来对应的。dBASE 文件中属性记录的顺序必须与主文件中的记录顺序相同。

一.主文件的组织

  主文件(.shp)用于记录空间坐标信息,包含一个固定长度的文件头,在文件头的后面存储着可变长度的记录。每个可变长度记录由一个固定长度的记录头和跟随其后的可变长度记录内容组成。
在这里插入图片描述

1.主文件头

  主文件头长度为 100 字节,一共有9个int型和8个double型数据。
注:表中最后4个加星号特别标示的四个数据只有当这个Shapefile文件包含Z方向坐标或者具有Measure值时才有值,否则为0.0。所谓Measure值,是用于存储需要的附加数据,可以用来记录各种数据,例如权值、道路长度等信息。
在这里插入图片描述
Shapefile文件所支持的几何类型:
注:对于一个不是记录Null Shape 类型的Shapefile文件,它所记录的空间目标的几何类型必须一致,不能在一个Shapefile文件中同时记录两种不同类型的几何目标。
在这里插入图片描述
读取坐标文件(.shp)的文件头的代码如下:

void OnReadShp(CString ShpFileName)
{
       FILE*   m_ShpFile_fp;       //****Shp文件指针
//打开坐标文件
       if((m_ShpFile_fp=fopen(ShpFileName,"rb"))==NULL)
       {
              return;
       }
       //读取坐标文件头的内容 开始
       int FileCode;
       int Unused;
       int FileLength;
       int Version;
       int ShapeType;
       double Xmin;
       double Ymin;
       double Xmax;
       double Ymax;
       double Zmin;
       double Zmax;
       double Mmin;
       double Mmax;
       fread(&FileCode,     sizeof(int),   1,m_ShpFile_fp);
       FileCode  = OnChangeByteOrder (FileCode);
       for(i=0;i<5;i++)
              fread(&Unused,sizeof(int),   1,m_ShpFile_fp);
       fread(&FileLength,   sizeof(int),   1,m_ShpFile_fp);
       FileLength      = OnChangeByteOrder (FileLength);
       fread(&Version,          sizeof(int),   1,m_ShpFile_fp);
       fread(&ShapeType,    sizeof(int),   1,m_ShpFile_fp);
       fread(&Xmin,         sizeof(double),1,m_ShpFile_fp);
       fread(&Ymin,         sizeof(double),1,m_ShpFile_fp);
       fread(&Xmax,         sizeof(double),1,m_ShpFile_fp);
       fread(&Ymax,         sizeof(double),1,m_ShpFile_fp);
       fread(&Zmin,         sizeof(double),1,m_ShpFile_fp);
       fread(&Zmax,        sizeof(double),1,m_ShpFile_fp);
       fread(&Mmin,         sizeof(double),1,m_ShpFile_fp);
       fread(&Mmax,         sizeof(double),1,m_ShpFile_fp);
       //读取坐标文件头的内容 结束
       //根据几何类型读取实体信息
       ……
}
2.主文件记录

  每个记录段分为记录头和记录内容两部分。

(1)记录头

  每个记录的记录头都储存着记录号和记录内容的长度,记录头的长度是 8 个字节,记
录号从 1 开始。字节位置是相对于记录头算起的。记录头的内容包括记录号(Record Number)和坐标记录长度(Content Length) 两个记录项。它们的位序都是big。记录号(Record Number)和坐标记录长度(Content Length) 两个记录项都是int型,并且shapefile文件中的记录号都是从1开始的。

(2)主文件记录内容

  Shape 文件的记录内容由 shape 类型和其后面的 shape 的几何数据组成。记录内容的长度取决于 part 的数量和 shape 的顶点数目。对于每个 shape 类型,我们先给出它的描述,然后是它在磁盘上的记录内容。position 是从记录内容的开始算起的。记录内容包括目标的几何类型(ShapeType)和具体的坐标记录(X、Y) ,记录内容因要素几何类型的不同其具体的内容及格式都有所不同。
具体分为以下几种:

1)空 shape

  Shape 类型为 0 表示一个没有几何类据的空的(Null)shape。每个要素类型(point、line、polygon 等等)都支持“空状态”-在同一个 shape 文件中“有点”(have point)和“无点”(null point)都是合法的。空 shape 经常作为位置标志符来使用,在创建 shape 文件时使用它,稍后就会被填充为几何数据。
在这里插入图片描述

2)Point (点)

  一个 Point 由一对双精度坐标组成,存储顺序为 X,Y。
在这里插入图片描述

Point
{
Double X // X coordinate
Double Y // Y coordinate
}

下面是读取点状目标的记录内容的代码:


OnReadPointShp(CString ShpFileName)
{
       //打开坐标文件
       ……
       //读取坐标文件头的内容 开始
       ……
       //读取点状目标的实体信息
       int RecordNumber;
       int ContentLength;
       int num   =0;
       while((fread(&RecordNumber,    sizeof(int),   1,ShpFile_fp)!=0))
       {
              num++;
              fread(&ContentLength,sizeof(int),   1,ShpFile_fp);
              RecordNumber      = OnChangeByteOrder (RecordNumber);
              ContentLength       = OnChangeByteOrder (ContentLength);
              int shapeType;
              double x;
double y;
              fread(&shapeType, sizeof(int),   1,ShpFile_fp);
              fread(&x, sizeof(double),   1,ShpFile_fp);
              fread(&y, sizeof(double),   1,ShpFile_fp);
}
}

3)MultiPoint (多点)

一个 MultiPoint 描述一组点, 具体如下:
在这里插入图片描述

MultiPoint
{
Double[4] Box // Bounding Box
Integer NumPoints // Number of Points
Point[NumPoints] Points // The Points in the set
}

Bounding box 的存储顺是 Xmin, Ymin, Xmax, Ymax.

4) Arc(弧段)

  一条弧段是一个按次序排列的顶点序列,包含一个或几个 part,一个 part 是由两个或两个以上的点连接而成的序列,Part 之间互相连接或不连接均可,Part 之间可以交叉也可以不交叉。Shapefile允许出现多个坐标完全相同的连续点,当读取文件时一定要注意这种情况,但是不允许出现某个退化的、长度为0的子线段出现。
在这里插入图片描述

Arc
{
Double[4] Box // Bounding Box
Integer NumParts // Number of Parts
Integer NumPoints // Total Number of Points
Integer[NumParts] Parts // Index to first Point in Part
Point[NumPoints] Points // Points for all parts
}

各个字段描述如下:
  Box: Arc 的 Bounding box,按照 Xmin, Ymin, Xmax, Ymax 的顺序存储。
  NumParts: Arc 中 Part 的数目。
  NumPoints: 所有 Part 的总点数。
  Parts: 长度为 NumParts 的数组,存储着每个 part(注:原文中是 polyline)的起始点在 points 数组中的索引,索引从 0 开始。
  Points: 长度为 NumPoints 的数组,按顺序存储构成 Arc 的所有 Part 的点。组成序号为 2 的 Part 的点紧接着序号为 1 的,依此类推。数组 Parts 中存储着每个 Part 起点的数组索引。在 points 数组中,各 Part 之间没有分隔符。

下面是读取线状目标的记录内容的代码:

OnReadLineShp(CString ShpFileName)
{
       //打开坐标文件
       ……
       //读取坐标文件头的内容 开始
       ……
       //读取线状目标的实体信息
       int RecordNumber;
       int ContentLength;
       int num   =0;
       while((fread(&RecordNumber,    sizeof(int),   1,ShpFile_fp)!=0))
       {
              fread(&ContentLength,sizeof(int),   1,ShpFile_fp);
              RecordNumber      = OnChangeByteOrder (RecordNumber);
              ContentLength       = OnChangeByteOrder (ContentLength);
              int shapeType;
              double Box[4];
              int NumParts;
              int NumPoints;
              int *Parts;
              fread(&shapeType,    sizeof(int),   1,ShpFile_fp);
              //读Box
              for(i=0;i<4;i++)
                     fread(Box+i,     sizeof(double),1,ShpFile_fp);
              //读NumParts和NumPoints
              fread(&NumParts,     sizeof(int),   1,ShpFile_fp);
              fread(&NumPoints,    sizeof(int),   1,ShpFile_fp);
              //读Parts和Points
              Parts       =new int[NumParts];
              for(i=0;i<NumParts;i++)
                     fread(Parts+i,   sizeof(int),   1,ShpFile_fp);
              int pointNum;
              for(i=0;i<NumParts;i++)
              {
                     if(i!=NumParts-1)
                            pointNum       =Parts[i+1]-Parts[i];
                     else
                            pointNum       =NumPoints-Parts[i];
                     double *PointsX;
                     double *PointsY;
                     
                     PointsX =new double[pointNum];
                     PointsY =new double[pointNum];
                     
                     for(j=0;j<pointNum;j++)
                     {
                            fread(PointsX+j, sizeof(double),1,ShpFile_fp);
                            fread(PointsY+j, sizeof(double),1,ShpFile_fp);
                     }
                     delete[] PointsX;
                     delete[] PointsY;
              }
              delete[] Parts;
       }
}

5)Polygon(面)

  Polygon 由一个或多个环组成。环是一个由 4 个或 4 个以上的顺序连接的点构成的闭
合的、非自相交的回路。Polygon 可以包含多个外部环。顶点的顺序或方向表明环的哪一
侧是处于 Polygon 内部的。沿着一个环的顶点顺序前进,前进方向的右侧就是这个环所在
的 Polygon。在 Polygon 中由顶点组成的洞是逆时针方向的。单一且闭合的 Polygon 的结
点顺序总是顺时针方向的。组成 Polygon 的 ring 就是 Polygon 的 Part。
在这里插入图片描述

Polygon
{
Double[4] Box // Bounding Box
Integer NumParts // Number of Parts
Integer NumPoints // Total Number of Points
Integer[NumParts] Parts // Index to First Point in Part
Point[NumPoints] Points // Points for All Parts
}

Polygon 中各个字段的描述如下:
  Box: Polygon 的封装边界,存储顺序为:Xmin, Ymin, Xmax, Ymax。
  NumParts: Polygon 中环的个数。
  NumPoints: 构成所有环的点的数目。
  Parts: 长度为 NumParts 的数组,存储着每个环的首点在 Points 数组中的索引,数
组索引从 0 开始。
  Points: 长度为 NumPoints 的数组。构成 Polygon 的每个环的点,按照首尾相连的顺序存储的。组成序号为 2 的环的点紧接着序号为 1 的环,依此类推。数组Parts 中存储着每个环的起点的数组索引。组成不同环的点之间没有分隔符。

对于一个shapefile中的多边形,它必须满足下面三个条件:
  (1)构成多边形的每个子环都必须是闭合的,即每个子环的第一个顶点跟最后一个顶点是同一个点;
  (2)每个子环在Points数组中的排列顺序并不重要,但每个子环的顶点必须按照一定的顺序连续排列;
  (3)存储在shapefile 中的多边形必须是干净的。所谓一个干净的多边形,它必须满足两点:
    1)没有自相交现象。这就要求任何一个子环不能跟其它的子环相交,共线的现 象也将被当作相交。但是允许两个子环的顶点重合;
    2) 对于一个不含岛的多边形或者是含岛的多边形的外环,它们的顶点排列顺序必须是顺时针方向;而对于内环,它的排列顺序必须是逆时针方向。所谓的“脏多边形”就是指顶点排列顺序为顺时针的内环。

典型多边形示例:
  下图中这个多边形包括一个岛,所有顶点的个数为8。NumParts等于2,NumPoints等于10。请注意内环(岛)的顶点的排列顺序是逆时针的。
在这里插入图片描述

在这里插入图片描述
下面是读取Polygon(面)的记录内容的代码:

void OnReadAreaShp(CString ShpFileName)
{
       //打开坐标文件
       ……
       //读取坐标文件头的内容 开始
       ……
       //读取面状目标的实体信息
       int RecordNumber;
       int ContentLength;
       while((fread(&RecordNumber,    sizeof(int),   1,m_ShpFile_fp)!=0))
       {
              fread(&ContentLength,sizeof(int),   1,m_ShpFile_fp);
              RecordNumber      = OnChangeByteOrder (RecordNumber);
              ContentLength       = OnChangeByteOrder (ContentLength);
              int shapeType;
              double Box[4];
              int NumParts;
              int NumPoints;
              int *Parts;
              fread(&shapeType,    sizeof(int),   1,m_ShpFile_fp);
              //读Box
              for(i=0;i<4;i++)
                     fread(Box+i,     sizeof(double),1,m_ShpFile_fp);
              //读NumParts和NumPoints
              fread(&NumParts,     sizeof(int),   1,m_ShpFile_fp);
              fread(&NumPoints,    sizeof(int),   1,m_ShpFile_fp);
              //读Parts和Points
              Parts       =new int[NumParts];
              for(i=0;i<NumParts;i++)
                     fread(Parts+i,   sizeof(int),   1,m_ShpFile_fp);
              int pointNum;
              int xx;
              int yy;
              for(i=0;i<NumParts;i++)
              {
                     if(i!=NumParts-1)
                            pointNum       =Parts[i+1]-Parts[i];
                     else
                            pointNum       =NumPoints-Parts[i];
                     
                     double *PointsX;
                     double *PointsY;
                     
                     PointsX =new double[pointNum];
                     PointsY =new double[pointNum];
                     
                     for(j=0;j<pointNum;j++)
                     {
                            fread(PointsX+j, sizeof(double),1,m_ShpFile_fp);
                            fread(PointsY+j, sizeof(double),1,m_ShpFile_fp);
                     }
                     delete[] PointsX;
                     delete[] PointsY;
              }
              delete[] Parts;
       }
}

二.索引文件的组织

  索引文件(.shx)由一个长度为 100 字节的文件头引导,后面是一系列长度为 8 字节的记录。
在这里插入图片描述

1.索引文件文件头

  索引文件文件头的组织形式与上面的主文件文件头的描述是一样的。文件头中存储的文件长度是以 16 字节表示的文件的总长度(文件头的 50 个 16 字节 加上记录个数的 4 倍)。

2.索引记录

  索引文件中的第 I 个记录存储着第 I 个记录在主文件中的偏移量和内容长度。表中显示了文件头中的各个字段以及它们的位置、值、类型、字节顺序。表中的位置是从索引文件记录的开始算起的。
在这里插入图片描述

  一个记录在主文件中的偏移量是用 16 字节表示的,它表示从主文件开始至这个记录记录头第一个字节的 word 个数。因此,主文件中的第一个记录的偏移量是 50。索引记录中存储的内容长度与主文件中记录头中存储的数值相同。

下面是一段读取索引文件的代码:

void OnReadShx(CString ShxFileName)
{
       FILE*   m_ShxFile_fp;       //****Shx文件指针
       //打开索引文件
       if((m_ShxFile_fp=fopen(ShxFileName,"rb"))==NULL)
       {
              return;
       }
       //读取索引文件头的内容 开始
       int FileCode;
       int Unused;
       int FileLength;
       int Version;
       int ShapeType;
       double Xmin;
       double Ymin;
       double Xmax;
       double Ymax;
       double Zmin;
       double Zmax;
       double Mmin;
       double Mmax;
       fread(&FileCode,     sizeof(int),   1,m_ShxFile_fp);
       FileCode  = OnChangeByteOrder (FileCode);
       for(i=0;i<5;i++)
              fread(&Unused,sizeof(int),   1,m_ShxFile_fp);
       fread(&FileLength,   sizeof(int),   1,m_ShxFile_fp);
       FileLength      = OnChangeByteOrder (FileLength);
       fread(&Version,          sizeof(int),   1,m_ShxFile_fp);
       fread(&ShapeType,    sizeof(int),   1,m_ShxFile_fp);
       fread(&Xmin,         sizeof(double),1,m_ShxFile_fp);
       fread(&Ymin,         sizeof(double),1,m_ShxFile_fp);
       fread(&Xmax,         sizeof(double),1,m_ShxFile_fp);
       fread(&Ymax,         sizeof(double),1,m_ShxFile_fp);
       fread(&Zmin,         sizeof(double),1,m_ShxFile_fp);
       fread(&Zmax,        sizeof(double),1,m_ShxFile_fp);
       fread(&Mmin,         sizeof(double),1,m_ShxFile_fp);
       fread(&Mmax,         sizeof(double),1,m_ShxFile_fp);
       //读取索引文件头的内容 结束
       
              int Offset, ContentLength;
       //读取实体信息
       while((fread(&Offset,    sizeof(int),   1, m_ShxFile_fp)!=0))
       {
              fread(&ContentLength,sizeof(int),   1, m_ShxFile_fp);
              Offset            = OnChangeByteOrder (Offset);
              ContentLength       = OnChangeByteOrder (ContentLength); 
       }
}

三.属性文件的组织

  dBASE 文件(.dbf)中包含任何需要的要素属性或可供其它表连接的属性关键字。它是标准的 DBF 格式文件,广泛应用于诸多的 Windows 和 DOS 平台上基于表格的应用程序。各类字段都可被引入到表中。
在这里插入图片描述

1.属性文件的文件头

  其中文件头部分的长度是不定长的,它主要对DBF文件作了一些总体说明,其中最主要的是对这个DBF文件的记录项的信息进行了详细地描述,比如对每个记录项的名称、数据类型、长度等信息都有具体的说明。

2.属性文件的实体信息

  实体信息部分就是一条条属性记录,每条记录都是由若干个记录项构成,因此只要依次循环读取每条记录就可以了。

3.读取属性文件的示例:

假设要读取一个名为soil的dbf文件(存储了土地利用信息),它含有8个记录项。

下面是读取这个dbf文件的代码:

void OnReadDbf(CString DbfFileName)
{
       FILE*   m_DbfFile_fp;       //****Dbf文件指针
       //打开dbf文件
       if((m_DbfFile_fp=fopen(DbfFileName,"rb"))==NULL)
       {
              return;
       }
       int i,j;
       //****读取dbf文件的文件头  开始
       BYTE version;
       fread(&version,     1,   1,m_DbfFile_fp);
       
       BYTE date[3];
       for(i=0;i<3;i++)
       {
              fread(date+i,     1,   1,m_DbfFile_fp);
       }
       
       int RecordNum;            //******
       fread(&RecordNum,         sizeof(int),   1,m_DbfFile_fp);
       short HeaderByteNum;
       fread(&HeaderByteNum,  sizeof(short), 1,m_DbfFile_fp);
       short RecordByteNum
       fread(&RecordByteNum,  sizeof(short), 1,m_DbfFile_fp);
       short Reserved1;           
       fread(&Reserved1,    sizeof(short), 1,m_DbfFile_fp);
       
       BYTE Flag4s;
       fread(&Flag4s,                 sizeof(BYTE),  1,m_DbfFile_fp);
       BYTE EncrypteFlag;
       fread(&EncrypteFlag,            sizeof(BYTE),  1,m_DbfFile_fp);
       
       for(i=0;i<3;i++)
       {
              fread(&Unused,        sizeof(int),   1,m_DbfFile_fp);
       }
       BYTE MDXFlag;
       fread(&MDXFlag,     sizeof(BYTE),  1,m_DbfFile_fp);
       
       BYTE LDriID;
       fread(&LDriID,                sizeof(BYTE),  1,m_DbfFile_fp);
       short Reserved2;
       fread(&Reserved2,    sizeof(short), 1,m_DbfFile_fp);
       BYTE name[11];
       BYTE fieldType;
       int Reserved3;
       BYTE fieldLength;
       BYTE decimalCount;
       short Reserved4;
       BYTE workID;
       short Reserved5[5];
       BYTE mDXFlag1;
       int fieldscount;
       fieldscount = (HeaderByteNum - 32) / 32;
       //读取记录项信息-共有8个记录项
       for(i=0;i< HeaderByteNum;i++)
       {
              //FieldName----11   bytes
              fread(name,    11, 1,m_DbfFile_fp);
              //FieldType----1     bytes
              fread(&fieldType,   sizeof(BYTE), 1,m_DbfFile_fp);
              //Reserved3----4     bytes
              Reserved3      =0;
              fread(&Reserved3, sizeof(int),  1,m_DbfFile_fp);
              //FieldLength--1     bytes
              fread(&fieldLength,sizeof(BYTE), 1,m_DbfFile_fp);
              //DecimalCount-1   bytes
              fread(&decimalCount,sizeof(BYTE), 1,m_DbfFile_fp);
              //Reserved4----2     bytes
              Reserved4      =0;
              fread(&Reserved4, sizeof(short),  1,m_DbfFile_fp);
              //WorkID-------1    bytes
              fread(&workID,            sizeof(BYTE), 1,m_DbfFile_fp);
              //Reserved5----10   bytes
              for(j=0;j<5;j++)
              {
                     fread(Reserved5+j,sizeof(short),  1,m_DbfFile_fp);
              }
              //MDXFlag1-----1  bytes
              fread(&mDXFlag1,       sizeof(BYTE), 1,m_DbfFile_fp);
       }
       BYTE terminator;
       fread(&terminator,        sizeof(BYTE), 1,m_DbfFile_fp);
       //读取dbf文件头结束
       double Area,Perimeter,Centroid_y,Centroid_x;
       int Soils_,Soils_id;
       CString Soil_code,suit;
       BYTE   deleteFlag;
       char media[31];
       //读取dbf文件记录  开始
       for(i=0;i<RecordNum;i++)
       {
              fread(&deleteFlag,  sizeof(BYTE), 1,m_DbfFile_fp);
              //读取 Area double
              for(j=0;j<31;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Area =atof(media);
              //读取 Perimeter double
              for(j=0;j<31;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Perimeter =atof(media);
              //读取 soils_  int
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<11;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Soils_      =atoi(media);
              //读取 Soils_id  int
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<11;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Soils_id   =atoi(media);
              //读取 soil_code string
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<3;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Soil_code       =media;
              //读取 suit string
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<1;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              suit =media;
              //读取 Centroid_y double
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<31;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Centroid_y      =atof(media);
              //读取 Centroid_x double
              for(j=0;j<31;j++)
                     strcpy(media+j,"");
              for(j=0;j<31;j++)
                     fread(media+j, sizeof(char), 1,m_DbfFile_fp);
              Centroid_x      =atof(media);
       }
       //读取dbf文件记录  结束
}

ArcGIS使用shapefile文件保存几何图形的位置及相关属性,Shapefile文件是一种按特定规列存储的二进制文件,实际上该种文件格式包含多个文件。Shapefile中".shp"、 ".shx"、 ".dbf"和”.prj”文件必不可少,例如,一个以“ZD”(宗地)为命名的Shapefile中就必须有ZD.shp、ZD.shx、ZD.dbf、ZD.prj四个文件。

Shapefile图形格式 (.shp)
Shapefile格式的主文件包含了地理参照数据。该文件由一个定长的文件头和一个或若干个变长的记录数据组成。每一条变长数据记录包含一个记录头和一些记录内容。

1.1文件头
主文件头包含17个字段,共100个字节,其中包含九个4字节(32位有符号整数,Integer)整数字段,紧接着是八个8字节(双精度浮点数)有符号浮点数字段。

其中:

文件的字节数需在所有图形输出完成后补写,头文件中的所有内容均可在最后补写。

Shapefile中所有图形的外接矩形,可以在所有图形输出完成后补写。

文件的更新信息:ArcGIS10.1以前的版本就9994,以后的版本是19988。

1.2图形数据
图形数据包含记录头和记录内容二部分,长度根据记录类型和形状确定。

1.2.1点要素的输出内容
设:已有图形数据的总长度=i

1.2.2线要素的输出内容
设:已有图形数据的总长度=i;线数=xi,点数=N

其中大多数情况:线数=1、点序=0

记录长度=4(记录类型)+32(图形边界合)+4(线数)+4(总点数)+xi*4(点序)+N*16(坐标X、Y)

1.2.3面要素的输出内容
设:已有图形数据的总长度=i;环数=qi,点数=N

其中:

1.封闭多段线表示的面  环数=1、环序=0;

2.填充图案表示的面(弧岛)外环的坐标应是顺时针,还必须回到第一点;

3.内环的坐标应是逆时针,也必须回到第一点。

记录长度=4(记录类型)+32(图形边界合)+4(环数)+4(总点数)+qi*4(点序)+N*16(坐标X、Y)

1.2.4记录长度和开始位置

每一个要素输出后,文件的字节数=LOF(ShpFile);

第一个要素的开始位置=101(100为头文件);

以后每一个要素的开始位置= LOF(ShpFile)+1。

1.3字节序
小端序是正常的数。

大端序是把数字由十进制转十六进制,把十六进制数每二位为一节进行倒序后再用十进制来表示。如:

19988 转为十六进制 270A 倒序 0A270000 用十进制来表示 170328064

1000 转为十六进制 1F4 倒序 F4010000 用十进制来表示 -201261056

Shapefile索引文件(.shx)
索引文件(.Shx)前100个字节是文件头,内容和数据文件(.shp)一样,可以在输出数据文件时同时输出。

索引文件的图形信息只有二项:开始位置、记录长度

3. Shapefile属性文件(. dbf)
对于CAD输出Shape文件来说,数据文件(.shp)的结构虽然复杂,但输出方法是不变的,一次把代码写好,可以适用于任何项目的转换。属性是变化的,每一个项目都不同,以往的解决方法是给CAD图形赋上与转出结构一样的扩展属性,这样CAD图形的数据量增加,不便于查看和编辑,本文介绍一种动状处理属性文件中属性项的办法。

对需要转换Shape文件的项目编制一个配置文件,文件是一个Excel文件,每一张表代表一个转出图层,其中规定了CAD图形的选择集过滤器、Shape文件类型、字段数、字段总长度以及创建字段的清单。如下图:

第一行是转出Shape文件的文件名=ZD;

第二行CAD选择集过滤器为:8  地块  (表示 图层=地块);

第三行CAD选择集过滤器为:0  *Polyline,Region,Hatch (类型=多段线,面域,填充图案)

第四行是文件的要素类型;

第五行是字段数量(不包括Shp自动生成的Shape字段和ID字段 ;

第六行是字段的总长度;

第八行开始是字段清单。

其中:

第一列是字段名,字段名不支持中文,并且最多只能有11个字符。

第二列是字段类型,这理是字段类型代码的ASCLL值,Shape中规定字段类型应输入这个值。几种常用类型的取值见下表:  

***ArcGIS10.2不支持逻辑型字段

第三列是字段长度;

第四列是字段精度(小数的位数,只有双精度类型的字段需要)

第六列是取值方法,有:编号、扩展属性、黙认值、X坐标、Y坐标、Z坐标六个选项。

编号:按输出顺序自动编号获取

扩展属性:提取输出图形扩展属性第i项的值,i= 第七列中的数字

黙认值:第七列中的数据

X坐标:点要素的插入点坐标、面要素的中心点坐标的X值

Y坐标:点要素的插入点坐标、面要素的中心点坐标的Y值

Z坐标:点要素的插入点坐标、面要素的中心点坐标的Y值

4. Shapefile空间参考(.prj)
空间参考文件是shp 的地图投影信息,可以复制同类项目的投影文件,也可以根据4个参数(坐标系统、中央子午线、投影带宽、横坐标是否加带号)来编辑组成,内容如下:

PROJCS["Xian_1980_3_Degree_GK_CM_117E",

GEOGCS["GCS_Xian_1980",

DATUM["D_Xian_1980",

SPHEROID["Xian_1980",6378140.0,298.257]],

PRIMEM["Greenwich",0.0],

UNIT["Degree",0.0174532925199433]],

PROJECTION["Gauss_Kruger"],

PARAMETER["False_Easting",500000.0],

PARAMETER["False_Northing",0.0],

PARAMETER["Central_Meridian",117],

PARAMETER["Scale_Factor",1.0],

PARAMETER["Latitude_Of_Origin",0.0],

UNIT["Meter",1.0]]

核心源代码
3.1代码:输出模块

 

Public 坐标系 As String, 加带号 As Boolean, 中央子午线 As Double, 投影带宽 As Integer
Public Type 字段属性
        Name   As String    '字段名
        Type   As Byte      '字段类型
        Length As Byte      '字段长度
        pScale As Byte      '字段精度
        Method As String    '取值方法
        Number As Integer   '属性项序号
        Value  As Variant   '黙认值
End Type
Dim pField()       As 字段属性  '字段组
Dim 字段数         As Integer
Dim 字段总长度     As Integer
Dim 文件头长度     As Integer
Dim 记录条数       As Long
Dim 记录长度       As Long
Dim 范围框(0 To 3) As Double
Dim 图形框(0 To 3) As Double
 
Dim ShpName As String, ShpFile As Integer, Shp指针 As Long  'Shp文件名、文件号、指针
Dim ShxName As String, ShxFile As Integer, Shx指针 As Long  'Shx文件名、文件号、指针
Dim DbfName As String, DbfFile As Integer, Dbf指针 As Long  'Dbf文件名、文件号、指针
Sub 创建空间参考文件()
    创建空间参考.show
End Sub
Sub 动态属性转Shape()
Dim mm As String
Dim N As Long, i As Integer, r As Integer
Dim fType(1) As Integer, fData(1)           '选择集过滤条件
Dim SelectA  As AcadSelectionSet            '选择集
Dim Entry As AcadEntity                     'CAD实体
Dim XDType As Variant, xData As Variant     '查询扩展属性
Dim longN As Long
Dim version As Byte
Dim dateF(2) As Byte
Dim 表名 As String, 发包方编码 As String
On Error Resume Next
Dim 工作目录 As String
工作目录 = "E:\ArcGIS\NEWShape\"    'ThisDrawing.Path + "\NEWShape\"
If InStr(工作目录, "C:\Program Files (x86)\AutoCAD 2008") > 0 Then Exit Sub
Call 创建目录(工作目录)
 
'创建空间参考文件
'定义空间参考.show     '自定义选择参数 坐标系、加带号、中央子午线、投影带宽
坐标系 = "1980西安坐标系"
中央子午线 = 118.5
加带号 = False
投影带宽 = 3
Dim PrjName As String
PrjName = 投影文件(坐标系, 加带号, 中央子午线, 投影带宽)
发包方编码 = Left(ThisDrawing.Name, 12)
Dim 转换标准 As String       'Shape转换标准样本.xlsx
转换标准 = VBApath & "Shape转换标准样本.xlsx"
Workbooks.Open FileName:=转换标准        '打开文件
Dim MySheet As Worksheet     'Excel工作表
For Each MySheet In ActiveWorkbook.Sheets   '历遍Excel的工作表
    If MySheet.Name = "JZX" Or MySheet.Name = "说明" Then Exit For     '目前不转界址线
    表名 = 工作目录 & 发包方编码 & MySheet.Name
    文件名 = 表名 + ".prj"
    FileCopy PrjName, 文件名     '复制预先创建好的空间参考文件
    ShpName = 表名 & ".shp": ShpFile = 1
    ShxName = 表名 & ".shx": ShxFile = 2
    DbfName = 表名 & ".dbf": DbfFile = 3
    '如果文件已存在,删除文件
    If Dir(ShpName) <> "" Then Kill ShpName
    If Dir(ShxName) <> "" Then Kill ShxName
    If Dir(DbfName) <> "" Then Kill DbfName
    
    '创建打开Shape文件,输出头文件内容
    Open ShpName For Binary As #ShpFile     '打开文件
    Open ShxName For Binary As #ShxFile     '打开文件
    Open DbfName For Binary As #DbfFile     '打开文件
        字段数 = MySheet.Cells(5, 2)
        字段总长度 = MySheet.Cells(6, 2)
        ReDim pField(字段数 - 1)
        For i = 0 To 字段数 - 1
            pField(i).Name = MySheet.Cells(i + 8, 1)
            pField(i).Type = MySheet.Cells(i + 8, 2)
            pField(i).Length = MySheet.Cells(i + 8, 3)
            pField(i).pScale = MySheet.Cells(i + 8, 4)
            pField(i).Method = MySheet.Cells(i + 8, 6)
            Select Case pField(i).Method    '取值方法
                   Case "扩展属性"
                        pField(i).Number = MySheet.Cells(i + 8, 7)
                   Case "黙认值"
                        pField(i).Value = MySheet.Cells(i + 8, 7)
            End Select
            
            r = 32 + i * 32
            For N = 1 To 11      '只有11个字节  记录字段名,是ASCII码值,如果字段名超过11个字符会被舍去。
                Put #DbfFile, r + N, Asc(Mid(pField(i).Name, N, 1))
            Next
            Put #DbfFile, r + 12, pField(i).Type
            Put #DbfFile, r + 17, pField(i).Length
            Put #DbfFile, r + 18, pField(i).pScale
        Next
        字段总长度 = 字段总长度 + 1
        文件头长度 = 字段数 * 32 + 32 + 1
        Put #DbfFile, 9, 文件头长度       '文件头长度
        Put #DbfFile, 11, 字段总长度      '一条记录的字节长度
 
        version = 3
        Put #DbfFile, 1, version          '版本信息
        dateF(0) = 19: dateF(1) = 2: dateF(2) = 15
        Put #DbfFile, 2, dateF            '最近的更新日期
        Put #DbfFile, 文件头长度, 13      '结束标志
    
        longN = 170328064
        Put #ShpFile, 1, longN    '1 File Code
        Put #ShxFile, 1, longN
        longN = 1000
        Put #ShpFile, 29, longN    '1 版本号
        Put #ShxFile, 29, longN
        longN = MySheet.Cells(4, 2)
        Put #ShpFile, 33, longN    '33 几何类型
        Put #ShxFile, 33, longN
        
        '以下输出图形信息
        范围框(0) = 100000000: 范围框(1) = 100000000
        范围框(2) = 0: 范围框(3) = 0
        Shp指针 = 101: 记录长度 = 101
        Shx指针 = 101
        记录条数 = 0
        Dbf指针 = 文件头长度 + 1
        r = LOF(DbfFile)
        ThisDrawing.SelectionSets.Item("窗选").Delete
        Err.Clear
        Set SelectA = ThisDrawing.SelectionSets.Add("窗选")
            fType(0) = MySheet.Cells(2, 1): fData(0) = MySheet.Cells(2, 3)
            fType(1) = MySheet.Cells(3, 1): fData(1) = MySheet.Cells(3, 3)
        SelectA.Select acSelectionSetAll, , , fType, fData
        For Each Entry In SelectA
            Entry.GetXData "", XDType, xData
            记录条数 = 记录条数 + 2
            For i = 0 To 字段数 - 1
                Select Case pField(i).Method    '取值方法
                       Case "扩展属性"
                            pField(i).Name = xData(pField(i).Number)
                       Case "黙认值"
                            pField(i).Name = pField(i).Value
                       Case "编号"
                            pField(i).Name = 记录条数 / 2
                       Case Else
                            pField(i).Name = ""
                End Select
            Next
            Select Case MySheet.Cells(4, 2)    'Shape类型
                   Case 5    '面
                        Call Shape面记录内容(Entry)
                   Case 3    '线
                        Call Shape线记录内容(Entry)
                   Case 1    '点
                        Call Shape点记录内容(Entry)
            End Select
        Next
        SelectA.Delete
        
    '关闭Shape文件
    Dim Offset As Long
    N = 记录条数 / 2
    Put #DbfFile, 5, N
    Offset = LOF(ShpFile)
    longN = 转为大端序(Offset)
    Put #ShpFile, 25, longN    'Shp文件长度
    longN = 转为大端序(Shx指针 - 1)
    Put #ShxFile, 25, longN    'Shx文件长度
    Put #ShpFile, 37, 范围框
    Put #ShxFile, 37, 范围框
    Close
Next
Workbooks("Shape转换标准样本").Close
End Sub
'整理多段线的坐标数组,调整节点的方向:外环为顺时针、内环为逆时针;取4位小数(ArcMap中只接收4位小数)
Public Function 面Points(Plobj As AcadEntity, 环序 As Long, R点数 As Long) As Double()
Dim Mxy As Variant
Dim 方向 As Integer, 坐标序 As Integer
Dim ShpPoints() As Double
On Error Resume Next
 
方向 = Sgn(Shp多边形面积(Plobj))   '负号函数
坐标序 = IIf(环序 = 1, 方向, -1 * 方向)
Dim i As Integer, J As Integer, r As Integer, N As Integer
r = IIf(Plobj.ObjectName = "AcDbPolyline", 2, 3)
Mxy = Plobj.Coordinates
N = Int(UBound(Mxy) / r)   '原编号从0开始的点数
R点数 = N + 2              '编号从1开始,回到第一点的点数
ReDim ShpPoints(N * 2 + 3) '编号从0开始,回到第一点的坐标个数
If 坐标序 = 1 Then         '正向
    J = 0
    For i = 0 To N
        ShpPoints(J) = Format(Mxy(i * r), "0.0000")
        ShpPoints(J + 1) = Format(Mxy(i * r + 1), "0.0000")
        J = J + 2
    Next
    ShpPoints(J) = Format(Mxy(0), "0.0000")
    ShpPoints(J + 1) = Format(Mxy(1), "0.0000")
Else                       '反向
    ShpPoints(0) = Format(Mxy(0), "0.0000")
    ShpPoints(1) = Format(Mxy(1), "0.0000")
    J = 2
    For i = N To 0 Step -1
        ShpPoints(J) = Format(Mxy(i * r), "0.0000")
        ShpPoints(J + 1) = Format(Mxy(i * r + 1), "0.0000")
        J = J + 2
    Next
End If
面Points = ShpPoints
End Function
 
Sub Shape面记录内容(Entry As AcadEntity)
Dim longP As Long
Dim Obj小 As Variant, Obj大 As Variant
Dim 环指针 As Long, 环数 As Long, 环序 As Long
Dim 点数 As Long, 点序 As Long
Dim 记录指针 As Long
Dim Offset As Long, longN As Long
Dim loopObj As AcadEntity
Dim N As Integer
Dim ShpPoints() As Double
On Error Resume Next
Entry.GetBoundingBox Obj小, Obj大
图形框(0) = Format(Obj小(0), "0.000")
图形框(1) = Format(Obj小(1), "0.000")
图形框(2) = Format(Obj大(0), "0.000")
图形框(3) = Format(Obj大(1), "0.000")
范围框(0) = IIf(图形框(0) < 范围框(0), 图形框(0), 范围框(0))
范围框(1) = IIf(图形框(1) < 范围框(1), 图形框(1), 范围框(1))
范围框(2) = IIf(图形框(2) > 范围框(2), 图形框(2), 范围框(2))
范围框(3) = IIf(图形框(3) > 范围框(3), 图形框(3), 范围框(3))
'记录头 大端序《记录条数,记录长度》
Put #ShpFile, Shp指针, 转为大端序(记录条数)       '记录编号
记录指针 = Shp指针 + 4                            '图形输出结束后补输出记录长度
Shp指针 = Shp指针 + 8
'记录内容
Put #ShpFile, Shp指针, 5      '记录类型
Shp指针 = Shp指针 + 4
Put #ShpFile, Shp指针, 图形框: Shp指针 = Shp指针 + 32    '图形边界合:x小、y小、大、y大
Select Case Entry.ObjectName
       Case "AcDbHatch"
            Dim MyHatch As New Collection
            Set MyHatch = 填充图案的环PR(Entry)
            环数 = MyHatch.Count
            Put #ShpFile, Shp指针, 环数                         '环数
                                                               '总点数在后面补写
            环指针 = Shp指针 + 4
            Shp指针 = Shp指针 + 环数 * 4 + 8
            点数 = 0: 点序 = 0: 环序 = 1   '总点数、各环的起点编号
            For Each loopObj In MyHatch
                Put #ShpFile, 环指针 + 4 * 环序, 点序          '点序
                ShpPoints = 面Points(loopObj, 环序, 点数)      '获取多段线的坐标数组
                点序 = 点序 + 点数
                环序 = 环序 + 1
                Put #ShpFile, Shp指针, ShpPoints: Shp指针 = Shp指针 + 点数 * 16
            Next
            Put #ShpFile, 环指针, 点序                           '补写总点数
            
       Case "AcDb2dPolyline", "AcDbPolyline", "AcDbWlPolyline", "AcDb3dPolyline"
            ShpPoints = 面Points(Entry, 1, 点数)                 '获取多段线的坐标数组
            Put #ShpFile, Shp指针, 1: Shp指针 = Shp指针 + 4      '环数=1
            Put #ShpFile, Shp指针, 点数: Shp指针 = Shp指针 + 4   '总点数
            Put #ShpFile, Shp指针, 0: Shp指针 = Shp指针 + 4      '环序=0
            Put #ShpFile, Shp指针, ShpPoints: Shp指针 = Shp指针 + 点数 * 16
End Select
记录长度 = Shp指针 - 记录长度 - 8
Put #ShpFile, 记录指针, 转为大端序(记录长度)       '当前记录要素的记录长度
Offset = 记录指针 - 5
longN = 转为大端序(Offset)
Put #ShxFile, Shx指针, longN: Shx指针 = Shx指针 + 4
longN = 转为大端序(记录长度)
Put #ShxFile, Shx指针, longN: Shx指针 = Shx指针 + 4
   
记录长度 = Shp指针
Put #DbfFile, Dbf指针, 32
Dbf指针 = Dbf指针 + 1
For N = 0 To 字段数 - 1
    Put #DbfFile, Dbf指针, pField(N).Name
    Dbf指针 = Dbf指针 + pField(N).Length
Next
End Sub
Public Function Shp多边形面积(Plobj As AcadEntity) As Double   '当面积为正值,多边形为顺时针;当面积为负值,多边形为逆时针。
Dim N As Long, i As Long, J As Long, r As Integer
Dim 面积 As Double
On Error Resume Next
xy = Plobj.Coordinates
r = IIf(Plobj.ObjectName = "AcDbPolyline", 2, 3)
N = Int(UBound(xy) / r)
For i = 0 To N
    J = IIf(i = N, 0, i + 1)
    面积 = 面积 + xy(i * r) * xy(J * r + 1) - xy(i * r + 1) * xy(J * r)
Next i
Shp多边形面积 = -1 * 面积 / 2
End Function
 
 
Sub Shape点记录内容(PointObj As AcadEntity)
Dim longP As Long, N As Integer
Dim Offset As Long, longN As Long
Dim xy As Variant
Dim ShpPoints(0 To 1) As Double
Select Case PointObj.ObjectName
       Case "AcDbText"
            xy = PointObj.InsertionPoint
       Case "AcDbBlockReference"
            xy = PointObj.InsertionPoint
       Case "AcDbPoint"
            xy = PointObj.Coordinates
       Case "AcDbCircle"
            xy = PointObj.Center
End Select
ShpPoints(0) = xy(0)
ShpPoints(1) = xy(1)
范围框(0) = IIf(ShpPoints(0) < 范围框(0), ShpPoints(0), 范围框(0))
范围框(1) = IIf(ShpPoints(1) < 范围框(1), ShpPoints(1), 范围框(1))
范围框(2) = IIf(ShpPoints(0) > 范围框(2), ShpPoints(0), 范围框(2))
范围框(3) = IIf(ShpPoints(1) > 范围框(3), ShpPoints(1), 范围框(3))
'记录头 大端序《记录条数,记录长度》
Offset = Shp指针 - 1
Put #ShpFile, Shp指针, 转为大端序(记录条数): Shp指针 = Shp指针 + 4   '记录条数
Put #ShpFile, Shp指针, 转为大端序(20): Shp指针 = Shp指针 + 4      '记录长度:点的记录长度固定=20
'记录内容
Put #ShpFile, Shp指针, 1: Shp指针 = Shp指针 + 4       '记录类型
Put #ShpFile, Shp指针, ShpPoints: Shp指针 = Shp指针 + 16
longN = 转为大端序(Offset)
Put #ShxFile, Shx指针, longN: Shx指针 = Shx指针 + 4
longN = 转为大端序(20)
Put #ShxFile, Shx指针, longN: Shx指针 = Shx指针 + 4
Put #DbfFile, Dbf指针, 32
Dbf指针 = Dbf指针 + 1
For N = 0 To 字段数 - 1
    Put #DbfFile, Dbf指针, pField(N).Name
    Dbf指针 = Dbf指针 + pField(N).Length
Next
End Sub
Sub Shape线记录内容(Plobj As AcadEntity)
Dim longP As Long, N As Integer
Dim Offset As Long, longN As Long
Dim 点数 As Long, 线数 As Long
Dim X As Double
Dim ShpPoints() As Double
Dim Obj小 As Variant, Obj大 As Variant
ShpPoints = 线Points(Plobj)    '获取多段线的节点坐标
线数 = 1
点数 = (UBound(ShpPoints) + 1) / 2
记录长度 = 44 + 线数 * 4 + 点数 * 16
 
Plobj.GetBoundingBox Obj小, Obj大
图形框(0) = Format(Obj小(0), "0.000")
图形框(1) = Format(Obj小(1), "0.000")
图形框(2) = Format(Obj大(0), "0.000")
图形框(3) = Format(Obj大(1), "0.000")
范围框(0) = IIf(图形框(0) < 范围框(0), 图形框(0), 范围框(0))
范围框(1) = IIf(图形框(1) < 范围框(1), 图形框(1), 范围框(1))
范围框(2) = IIf(图形框(2) > 范围框(2), 图形框(2), 范围框(2))
范围框(3) = IIf(图形框(3) > 范围框(3), 图形框(3), 范围框(3))
'记录头 大端序《记录条数,记录长度》
Offset = Shp指针 - 1
Put #ShpFile, Shp指针, 转为大端序(记录条数): Shp指针 = Shp指针 + 4     '记录条数
Put #ShpFile, Shp指针, 转为大端序(记录长度): Shp指针 = Shp指针 + 4     '记录长度:线点的记录长度=52 + 线数 * 4 + 点数 * 16
'记录内容
Put #ShpFile, Shp指针, 3: Shp指针 = Shp指针 + 4       '记录类型
Put #ShpFile, Shp指针, 图形框: Shp指针 = Shp指针 + 32 '坐标范围(Box)
Put #ShpFile, Shp指针, 线数: Shp指针 = Shp指针 + 4    '线段的个数
Put #ShpFile, Shp指针, 点数: Shp指针 = Shp指针 + 4    '顶点个数
Put #ShpFile, Shp指针, 0: Shp指针 = Shp指针 + 4       '坐标点在Points的位置
Put #ShpFile, Shp指针, ShpPoints: Shp指针 = Shp指针 + 点数 * 16
longN = 转为大端序(Offset)
Put #ShxFile, Shx指针, longN: Shx指针 = Shx指针 + 4
longN = 转为大端序(记录长度)
Put #ShxFile, Shx指针, longN: Shx指针 = Shx指针 + 4
Put #DbfFile, Dbf指针, 32
Dbf指针 = Dbf指针 + 1
For N = 0 To 字段数 - 1
    Put #DbfFile, Dbf指针, pField(N).Name
    Dbf指针 = Dbf指针 + pField(N).Length
Next
End Sub
'整理多段线的节点坐标
Public Function 线Points(Plobj As AcadEntity) As Double()
Dim xy As Variant
Dim i As Integer, J As Integer, r As Integer
Dim ShpPoints() As Double
Select Case Plobj.ObjectName
       Case "AcDbPolyline"
            xy = Plobj.Coordinates
            r = 2
       Case "AcDb2dPolyline"
            xy = Plobj.Coordinates
            r = 3
       Case "AcDbLine"
            ReDim ShpPoints(3)
            xy = Plobj.StartPoint
            ShpPoints(0) = xy(0)
            ShpPoints(1) = xy(1)
            xy = Plobj.EndPoint
            ShpPoints(2) = xy(0)
            ShpPoints(3) = xy(1)
            GoTo 20
End Select
 
J = Int(UBound(xy) / r)
ReDim ShpPoints(J * 2 + 1)
For i = 0 To J
    ShpPoints(i * 2) = Format(xy(i * r), "0.0000")
    ShpPoints(i * 2 + 1) = Format(xy(i * r + 1), "0.0000")
Next
20: 线Points = ShpPoints
End Function

3.2代码:空间参考模块

Function 投影文件(坐标系 As String, 加带号 As Boolean, 中央子午线 As Double, 投影带宽 As Integer) As String
Dim str1 As String, str2 As String
Dim 投影项目   As String    'PROJCS["CGCS2000_3_Degree_GK_Zone_39",
Dim 地理标志   As String    'GEOGCS["GCS_China_Geodetic_Coordinate_System_2000",
Dim 基准       As String    'DATUM["D_China_2000",
Dim 球体       As String    'SPHEROID["CGCS2000",6378137.0,298.257222101]],
Dim 加常数     As String    'PARAMETER["False_Easting",39500000.0],   '加常数
Dim 中央径线   As String    'PARAMETER["Central_Meridian",117.0],     '中央子午线
Dim 常数       As Long
 
中央径线 = "PARAMETER[" & Chr(34) & "Central_Meridian" & Chr(34) & Chr(44) & Format(中央子午线, "0.0") + "]" & Chr(44)
 
Select Case 坐标系
       Case "2000国家大地坐标系"
            str1 = "PROJCS[" & Chr(34) & "CGCS2000_"
            地理标志 = "GEOGCS[" & Chr(34) & "GCS_China_Geodetic_Coordinate_System_2000" & Chr(34) & Chr(44)
            基准 = "DATUM[" & Chr(34) & "D_China_2000" & Chr(34) & Chr(44)
            球体 = "SPHEROID[" & Chr(34) & "CGCS2000" & Chr(34) & ",6378137.0,298.257222101]],"
            '"2000 国家大地坐标系", "CGCS2000", 6378137, 6356752.31414   '1/298.257222101
 
       Case "1980西安坐标系"
            str1 = "PROJCS[" & Chr(34) & "Xian_1980_"
            地理标志 = "GEOGCS[" & Chr(34) & "GCS_Xian_1980" & Chr(34) & Chr(44)
            基准 = "DATUM[" & Chr(34) & "D_Xian_1980" & Chr(34) & Chr(44)
            球体 = "SPHEROID[" & Chr(34) & "Xian_1980" & Chr(34) & ",6378140.0,298.257]],"
            '"1975年椭球", "XA1980",6378140, 6356755.2882   '298.257
            
       Case "1954年北京坐标系"
            str1 = "PROJCS[" & Chr(34) & "Beijing_1954_"
            地理标志 = "GEOGCS[" & Chr(34) & "GCS_Beijing_1954" & Chr(34) & Chr(44)
            基准 = "DATUM[" & Chr(34) & "D_Beijing_1954" & Chr(34) & Chr(44)
            球体 = "SPHEROID[" & Chr(34) & "Beijing_1954" & Chr(34) & ",6378245.0,298.3]],"
            '"克拉索夫斯基椭球", "BJ1954", 6378245, 6356863.0188   '298.3
 
       Case "WGS_1984坐标系"
            str1 = "PROJCS[" & Chr(34) & "WGS_1984_"
            地理标志 = "GEOGCS[" & Chr(34) & "GCS_WGS_1984" & Chr(34) & Chr(44)
            基准 = "DATUM[" & Chr(34) & "D_WGS_1984" & Chr(34) & Chr(44)
            球体 = "SPHEROID[" & Chr(34) & "WGS_1984" & Chr(34) & ",6378137.0,298.257223563]],"
            '"WGS84椭球", "WGS84", 6378137, 6356752.3142   '298.257223563
End Select
 
Select Case 投影带宽
       Case 3
            Select Case 加带号
                   Case True
                        常数 = 中央子午线 / 3
                        投影项目 = str1 + "3_Degree_GK_Zone_" + Trim(常数) & Chr(34) & Chr(44)     '"Beijing_1954_3_Degree_GK_Zone_39"   "Xian_1980_3_Degree_GK_Zone_39"
                        加常数 = "PARAMETER[" & Chr(34) & "False_Easting" & Chr(34) & Chr(44) & Format(常数 * 1000000 + 500000, "0.0") & "],"
                   Case False
                        投影项目 = str1 + "3_Degree_GK_CM_" + Trim(中央子午线) + "E" & Chr(34) & Chr(44)          '"Beijing_1954_3_Degree_GK_CM_117E"  "Xian_1980_3_Degree_GK_CM_117E"
                        加常数 = "PARAMETER[" & Chr(34) & "False_Easting" & Chr(34) & Chr(44) & "500000.0],"
            End Select
       Case 6
            Select Case 加带号
                   Case True
                        常数 = 中央子午线 / 6
                        投影项目 = str1 + "GK_Zone_" + Trim(常数) & Chr(34) & Chr(44)      '"Beijing_1954_GK_Zone_20"   "CGCS2000_GK_Zone_20"   "Xian_1980_GK_Zone_20"
                        加常数 = "PARAMETER[" & Chr(34) & "False_Easting" & Chr(34) & Chr(44) & Format(常数 * 1000000 + 500000, "0.0") & "],"
                   Case False
                        投影项目 = str1 + "GK_CM_" + Trim(中央子午线) + "E" & Chr(34) & Chr(44)              '"CGCS2000_GK_CM_117E"   "Xian_1980_GK_CM_117E"
                        加常数 = "PARAMETER[" & Chr(34) & "False_Easting" & Chr(34) & Chr(44) & "500000.0],"
            End Select
End Select
Dim m(0 To 12) As String
m(0) = 投影项目
m(1) = 地理标志
m(2) = 基准
m(3) = 球体
m(4) = "PRIMEM[" & Chr(34) & "Greenwich" & Chr(34) & ",0.0],"                 '径线起点  格林威治"
m(5) = "UNIT[" & Chr(34) & "Degree" & Chr(34) & ",0.0174532925199433]],"      '弧度单位
m(6) = "PROJECTION[" & Chr(34) & "Gauss_Kruger" & Chr(34) & "],"              '投影
m(7) = 加常数
m(8) = "PARAMETER[" & Chr(34) & "False_Northing" & Chr(34) & ",0.0],"         '北纬
m(9) = 中央径线
m(10) = "PARAMETER[" & Chr(34) & "Scale_Factor" & Chr(34) & ",1.0],"          '长度比例
m(11) = "PARAMETER[" & Chr(34) & "Latitude_Of_Origin" & Chr(34) & ",0.0],"    '纬度起点
m(12) = "UNIT[" & Chr(34) & "Meter" & Chr(34) & ",1.0]]"                      '长度单位(米)
Dim PrjName As String
PrjName = VBApath + "空间参考.prj"
Open PrjName For Output As #1
     Print #1, m(0) + m(1) + m(2) + m(3) + m(4) + m(5) + m(6) + m(7) + m(8) + m(9) + m(10) + m(11) + m(12)
Close
投影文件 = PrjName
End Function


Function 投影文件(坐标系 As String, 加带号 As Boolean, 中央子午线 As Double, 投影带宽 As Integer) As String
Dim str1 As String, str2 As String
Dim 投影项目   As String    'PROJCS["CGCS2000_3_Degree_GK_Zone_39",
Dim 地理标志   As String    'GEOGCS["GCS_China_Geodetic_Coordinate_System_2000",
Dim 基准       As String    'DATUM["D_China_2000",
Dim 球体       As String    'SPHEROID["CGCS2000",6378137.0,298.257222101]],
Dim 加常数     As String    'PARAMETER["False_Easting",39500000.0],   '加常数
Dim 中央径线   As String    'PARAMETER["Central_Meridian",117.0],     '中央子午线
Dim 常数       As Long
 
中央径线 = "PARAMETER[" & Chr(34) & "Central_Meridian" & Chr(34) & Chr(44) & Format(中央子午线, "0.0") + "]" & Chr(44)
 
Select Case 坐标系
       Case "2000国家大地坐标系"
            str1 = "PROJCS[" & Chr(34) & "CGCS2000_"
            地理标志 = "GEOGCS[" & Chr(34) & "GCS_China_Geodetic_Coordinate_System_2000" & Chr(34) & Chr(44)
            基准 = "DATUM[" & Chr(34) & "D_China_2000" & Chr(34) & Chr(44)
            球体 = "SPHEROID[" & Chr(34) & "CGCS2000" & Chr(34) & ",6378137.0,298.257222101]],"
            '"2000 国家大地坐标系", "CGCS2000", 6378137, 6356752.31414   '1/298.257222101
 
       Case "1980西安坐标系"
            str1 = "PROJCS[" & Chr(34) & "Xian_1980_"
            地理标志 = "GEOGCS[" & Chr(34) & "GCS_Xian_1980" & Chr(34) & Chr(44)
            基准 = "DATUM[" & Chr(34) & "D_Xian_1980" & Chr(34) & Chr(44)
            球体 = "SPHEROID[" & Chr(34) & "Xian_1980" & Chr(34) & ",6378140.0,298.257]],"
            '"1975年椭球", "XA1980",6378140, 6356755.2882   '298.257
            
       Case "1954年北京坐标系"
            str1 = "PROJCS[" & Chr(34) & "Beijing_1954_"
            地理标志 = "GEOGCS[" & Chr(34) & "GCS_Beijing_1954" & Chr(34) & Chr(44)
            基准 = "DATUM[" & Chr(34) & "D_Beijing_1954" & Chr(34) & Chr(44)
            球体 = "SPHEROID[" & Chr(34) & "Beijing_1954" & Chr(34) & ",6378245.0,298.3]],"
            '"克拉索夫斯基椭球", "BJ1954", 6378245, 6356863.0188   '298.3
 
       Case "WGS_1984坐标系"
            str1 = "PROJCS[" & Chr(34) & "WGS_1984_"
            地理标志 = "GEOGCS[" & Chr(34) & "GCS_WGS_1984" & Chr(34) & Chr(44)
            基准 = "DATUM[" & Chr(34) & "D_WGS_1984" & Chr(34) & Chr(44)
            球体 = "SPHEROID[" & Chr(34) & "WGS_1984" & Chr(34) & ",6378137.0,298.257223563]],"
            '"WGS84椭球", "WGS84", 6378137, 6356752.3142   '298.257223563
End Select
 
Select Case 投影带宽
       Case 3
            Select Case 加带号
                   Case True
                        常数 = 中央子午线 / 3
                        投影项目 = str1 + "3_Degree_GK_Zone_" + Trim(常数) & Chr(34) & Chr(44)     '"Beijing_1954_3_Degree_GK_Zone_39"   "Xian_1980_3_Degree_GK_Zone_39"
                        加常数 = "PARAMETER[" & Chr(34) & "False_Easting" & Chr(34) & Chr(44) & Format(常数 * 1000000 + 500000, "0.0") & "],"
                   Case False
                        投影项目 = str1 + "3_Degree_GK_CM_" + Trim(中央子午线) + "E" & Chr(34) & Chr(44)          '"Beijing_1954_3_Degree_GK_CM_117E"  "Xian_1980_3_Degree_GK_CM_117E"
                        加常数 = "PARAMETER[" & Chr(34) & "False_Easting" & Chr(34) & Chr(44) & "500000.0],"
            End Select
       Case 6
            Select Case 加带号
                   Case True
                        常数 = 中央子午线 / 6
                        投影项目 = str1 + "GK_Zone_" + Trim(常数) & Chr(34) & Chr(44)      '"Beijing_1954_GK_Zone_20"   "CGCS2000_GK_Zone_20"   "Xian_1980_GK_Zone_20"
                        加常数 = "PARAMETER[" & Chr(34) & "False_Easting" & Chr(34) & Chr(44) & Format(常数 * 1000000 + 500000, "0.0") & "],"
                   Case False
                        投影项目 = str1 + "GK_CM_" + Trim(中央子午线) + "E" & Chr(34) & Chr(44)              '"CGCS2000_GK_CM_117E"   "Xian_1980_GK_CM_117E"
                        加常数 = "PARAMETER[" & Chr(34) & "False_Easting" & Chr(34) & Chr(44) & "500000.0],"
            End Select
End Select
Dim m(0 To 12) As String
m(0) = 投影项目
m(1) = 地理标志
m(2) = 基准
m(3) = 球体
m(4) = "PRIMEM[" & Chr(34) & "Greenwich" & Chr(34) & ",0.0],"                 '径线起点  格林威治"
m(5) = "UNIT[" & Chr(34) & "Degree" & Chr(34) & ",0.0174532925199433]],"      '弧度单位
m(6) = "PROJECTION[" & Chr(34) & "Gauss_Kruger" & Chr(34) & "],"              '投影
m(7) = 加常数
m(8) = "PARAMETER[" & Chr(34) & "False_Northing" & Chr(34) & ",0.0],"         '北纬
m(9) = 中央径线
m(10) = "PARAMETER[" & Chr(34) & "Scale_Factor" & Chr(34) & ",1.0],"          '长度比例
m(11) = "PARAMETER[" & Chr(34) & "Latitude_Of_Origin" & Chr(34) & ",0.0],"    '纬度起点
m(12) = "UNIT[" & Chr(34) & "Meter" & Chr(34) & ",1.0]]"                      '长度单位(米)
Dim PrjName As String
PrjName = VBApath + "空间参考.prj"
Open PrjName For Output As #1
     Print #1, m(0) + m(1) + m(2) + m(3) + m(4) + m(5) + m(6) + m(7) + m(8) + m(9) + m(10) + m(11) + m(12)
Close
投影文件 = PrjName
End Function

5.3窗体


Private Sub CommandButton1_Click()
坐标系 = ComboBox1.Text
中央子午线 = TextBox1.Value
加带号 = CheckBox1.Value
Unload Me
End Sub
 
Private Sub OptionButton1_Click()
投影带宽 = 3
End Sub
 
Private Sub OptionButton2_Click()
投影带宽 = 6
End Sub
 
 
Private Sub UserForm_Initialize()
ComboBox1.AddItem "2000国家大地坐标系"
ComboBox1.AddItem "1980西安坐标系"
ComboBox1.AddItem "1954年北京坐标系"
ComboBox1.AddItem "WGS_1984坐标系"
ComboBox1.ListIndex = 0
 
投影带宽 = 3
加带号 = True
End Sub
 
'其中:CGCS2000_3_Degree_GK_Zone_38 4526     '横坐标前加带号
      'CGCS2000_3_Degree_GK_Zone_39 4527     '横坐标前加带号
      'CGCS2000_3_Degree_GK_Zone_40 4528     '横坐标前加带号
      'CGCS2000_GK_CM_117E 4509              '横坐标前不加带号
      'CGCS2000_GK_CM_123E 4510              '横坐标前不加带号

3.3 userform用户窗体及控件

 

Private Sub CommandButton1_Click()
坐标系 = ComboBox1.Text
中央子午线 = TextBox1.Value
加带号 = CheckBox1.Value
Unload Me
End Sub
 
Private Sub OptionButton1_Click()
投影带宽 = 3
End Sub
 
Private Sub OptionButton2_Click()
投影带宽 = 6
End Sub
 
 
Private Sub UserForm_Initialize()
ComboBox1.AddItem "2000国家大地坐标系"
ComboBox1.AddItem "1980西安坐标系"
ComboBox1.AddItem "1954年北京坐标系"
ComboBox1.AddItem "WGS_1984坐标系"
ComboBox1.ListIndex = 0
 
投影带宽 = 3
加带号 = True
End Sub
 
'其中:CGCS2000_3_Degree_GK_Zone_38 4526     '横坐标前加带号
      'CGCS2000_3_Degree_GK_Zone_39 4527     '横坐标前加带号
      'CGCS2000_3_Degree_GK_Zone_40 4528     '横坐标前加带号
      'CGCS2000_GK_CM_117E 4509              '横坐标前不加带号
      'CGCS2000_GK_CM_123E 4510              '横坐标前不加带号

以上资料搜集自网络,版权归原作者。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/360030.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Adobe Camera Raw forMac/win:掌控原始之美的秘密武器

Adobe Camera Raw&#xff0c;这款由Adobe开发的插件&#xff0c;已经成为摄影师和设计师们的必备工具。对于那些追求完美、渴望探索更多创意可能性的专业人士来说&#xff0c;它不仅仅是一个插件&#xff0c;更是一个能够释放无尽创造力的平台。 在数字摄影时代&#xff0c;R…

【Ubuntu 22.04.3 LTS】apt-get下载安装有关问题可能原因及解决方法

ubuntu 22.04.3 LTS unaccountably error 装啥啥没依赖 可能是用了不合适的源&#xff0c;换个就好了 Now, let’s take a look at the lsb_release output, with a special focus on the Codename, which could be a crucial piece of information. The lsb_release comm…

普通spring项目配置加密

概述 本文主要介绍普通spring项目(非springboot)怎么进行配置加密。 出于安全考虑&#xff0c;生产配置不能明文出现在配置文件中。对于SpringBoot可以使用jasypt-spring-boot这个组件来为配置属性提供加密。 普通的spring项目暂时就没有找到合适的加密工具。这时候那就只能…

Banana Pi BPI-R4开源路由器开发板快速上手用户手册,采用联发科MT7988芯片设计

介绍 Banana Pi BPI-R4 路由器板采用 MediaTek MT7988A (Filogic 880) 四核 ARM Corex-A73 设计&#xff0c;4GB DDR4 RAM&#xff0c;8GB eMMC&#xff0c;板载 128MB SPI-NAND 闪存&#xff0c;还有 2x 10Gbe SFP、4x Gbe 网络端口&#xff0c;带 USB3 .2端口&#xff0c;M.2…

basic CNN

文章目录 回顾卷积神经网络卷积卷积核卷积过程卷积后图像尺寸计算公式&#xff1a;代码 padding代码 Stride代码 MaxPooling代码 一个简单的卷积神经网络用卷积神经网络来对MINIST数据集进行分类如何使用GPU代码 练习 回顾 下面这种由线形层构成的网络是全连接网络。 对于图像…

Codesys与威纶通触摸屏标签通信步骤

codesys软件&#xff0c;添加对象结构体。 添加对象全局变量列表。设置变量列表属性。 添加对象符号配置&#xff0c;编译。 勾选变量&#xff0c;编译。 文件夹出现xml文件。 打开威纶通软件&#xff0c;添加设备&#xff0c;导入标签&#xff0c;选择上图的文件。

RX-4571LC/NB/SA实时时钟模块

RX-4571LC实时时钟模块是EPSON推出的一求款额定频率32.768KHz&#xff0c;接口为SPI(3-wire)&#xff0c;月偏差为60 s的实时时钟模块&#xff0c;12脚贴片&#xff0c;具有小尺寸&#xff0c;高稳定性。该款实时时钟模块&#xff0c;可以在-40~85 C的温度内稳定工作,频率公差为…

解决Could not transfer artifact org.springframework.boot的问题

进行maven更新的时候&#xff0c;发现报错了 Could not transfer artifact org.springframework.boot&#xff0c;提示网络错误&#xff0c;搜了一下&#xff0c;应该是要忽略https 在maven设置中添加如下语句 -Dmaven.wagon.http.ssl.insecuretrue -Dmaven.wagon.http.ssl.a…

Redis(十)SpringBoot集成Redis

文章目录 连接单机mvnYMLController.javaRedisConfig.java 连接集群YML问题复现 RedisTemplate方式 连接单机 mvn <!--Redis--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</art…

[C++]类和对象(上)

目录 一:面向过程与面向对象的区别 二:类的定义 三:类的访问限定符和封装 3.1访问限定符 3.2 封装 四:类的实例化 五:类对象模型 如何计算类的大小 类对象的存储方式 六:this指针 this指针的引出 this指针的特性 一:面向过程与面向对象的区别 面向过程 C语言是面…

C#: 软件任务栏托盘图标添加关闭软件菜单等

说明&#xff1a;在软件在任务栏右下角的系统托盘的图标添加个右键弹出菜单功能&#xff0c;案例实现右键弹窗菜单关闭软件功能。 1.添加系统托盘图标控件 NotifyIcon 2.右键打开控件属性菜单添加鼠标点击事件函数 3.事件函数添加代码 //右键点击任务栏图标弹出关闭菜单 priv…

LeetCode Hot100 回顾(二)

子串 560.和为K的子数组 使用前缀和预处理一下题目给的数组, 然后用二重循环遍历一遍就可以了。 239.滑动窗口最大值 看题面比较容易想到的是用优先级队列来解决, 但是STL中的priority_queue不支持随机删除, 如果要用优先级队列来解决这道题的话比较复杂。这道题的一种正确…

leetcode刷题(剑指offer) 82.删除排序链表中的重复元素Ⅱ

82.删除排序链表中的重复元素Ⅱ 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,3,4,4,5] 输出&#xff1a;[1,2,5]示例 2&#xff1a…

数据监测的频次应如何设定

品牌在做控价时&#xff0c;需要先对线上数据进行监测&#xff0c;监测就要考虑监测的时间点&#xff0c;是白天监测还是夜晚监测&#xff0c;或者一天要监测几轮&#xff0c;这些问题都需要提前考虑好&#xff0c;因为待监测结果出来还要做破价治理&#xff0c;所以时间结点必…

PyCharm安装教程(超详细),零基础小白也能看懂

一、简介 PyCharm是一款Python IDE&#xff0c;其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具&#xff0c;比如&#xff0c; 调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制等等。此外&#xff0c;该IDE提供了一些高级功…

DAIL-SQL:LLM在Text-to-SQL任务中的详细评估

导语 本文聚焦于利用LLMs进行Text-to-SQL任务&#xff0c;并指出缺乏系统性基准测试限制了有效、高效和经济的LLM-based Text-to-SQL解决方案的发展。研究者首先系统地比较了现有的提示工程方法&#xff0c;并分析了它们的优缺点。基于这些发现&#xff0c;提出了一个新的综合…

高等数学基础【1】极限与连续

第一节 函数 一、基本概念 ①函数 设变量x的取值范围为D,若对任意的x∈D,按照某种对应关系总有唯一确定的值y与x对应,称y为x的函数,记为yf(z),其中D称为函数yf(x)的定义域 ②复合函数 设uφ(x)(x∈D1),yf(u)(u∈D,),且对任意的x∈D1有φ(x)∈D2,称y为x的复合函数,记为yf[φ…

iText操作pdf

最近有个任务是动态的创建pdf根据获取到的内容&#xff0c;百度到的知识点都比较零散&#xff0c;官方文档想必大家也不容易看懂。下文是我做出的汇总 public class CreatePdfUtils {public static void create(){//准备File file new File("C:\\code\\base-project-back…

pytorch学习笔记(十二)

以下代码是以CIFAR10这个10分类的图片数据集训练过程的完整的代码。 训练部分 train.py主要包含以下几个部件&#xff1a; 准备训练、测试数据集用DateLoader加载两个数据集&#xff0c;要设置好batchsize创建网络模型&#xff08;具体模型在model.py中&#xff09;设置损失函…

【大数据】Flink SQL 语法篇(三):窗口聚合(TUMBLE、HOP、SESSION、CUMULATE)

Flink SQL 语法篇&#xff08;三&#xff09;&#xff1a;窗口聚合 1.滚动窗口&#xff08;TUMBLE&#xff09;1.1 Group Window Aggregation 方案&#xff08;支持 Batch / Streaming 任务&#xff09;1.2 Windowing TVF 方案&#xff08;1.13 只支持 Streaming 任务&#xff…
最新文章