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

news2024/9/22 3:45:45

 一、什么是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.coloradmin.cn/o/1421623.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql入门到精通003-基础篇-SQL

1、目录 2、SQL通用语法及分类 2.1 SQL通用语法 2.2 SQL分类 3、SQL DDL数据库操作 3.1 SQL DDL表操作-创建&查询 3.1.1 表操作-查询 3.1.2 表操作-创建 create table tb_user(id int comment 编号,name varchar(50) comment 用户名,age int comment 用户名,gender varch…

MySQL库表操作 作业

题目&#xff1a; 1. sql语句分为几类?2. 表的约束有哪些,分别是什么,设置的语法分别是什么?3. 做出班级表,学生表的E-R图,数据库模型图,以及核心的sql语句. 1. MySQL致力于支持全套ANSI/ISO SQL标准。在MySQL数据库中&#xff0c;SQL语句主要可以划分为以下几类: > DD…

搜索引擎评价指标及指标间的关系

目录 二分类模型的评价指标准确率(Accuracy,ACC)精确率(Precision,P)——预测为正的样本召回率(Recall,R)——正样本注意事项 P和R的关系——成反比F值F1值F值和F1值的关系 ROC&#xff08;Receiver Operating Characteristic&#xff09;——衡量分类器性能的工具AUC&#xff…

OpenCV 2 - 矩阵的掩膜操作

1知识点 1-1 CV_Assert(myImage.depth() == CV_8U); 确保输入图像是无符号字符类型,若该函数括号内的表达式为false,则会抛出一个错误。 1-2 Mat.ptr(int i = 0); 获取像素矩阵的指针,索引 i 表示第几行,从0开始计行数。 1-3 const uchar* current = mylmage.ptr(row); 获得…

Physically Based Area Lights

11.1 概括 本章介绍了由 Guerrilla Games 公司在 PS4 开发的基于物理的区域照明系统&#xff08;见图11.1&#xff09;。 我们提出了一种新颖、实时的区域照明分析模型&#xff0c;能够支持多种照明形状。每种形状都可以用平面上简单的三维或二维函数来表示。讨论的应用包括以下…

Apache Flink文件上传漏洞(CVE-2020-17518)漏洞代码分析

漏洞复现参考如下文章 Apache Flink文件上传漏洞&#xff08;CVE-2020-17518&#xff09;漏洞复现分析_文件上传漏洞复现cve-CSDN博客 分析代码的话&#xff0c;首先找到漏洞修复的邮件 漏洞详情&#xff0c;可以看到漏洞概要&#xff0c;影响的版本&#xff0c;漏洞描述以及…

Docker核心教程

1. 概述 官网&#xff1a;https://docs.docker.com/ Docker Hub 网站&#xff1a;https://hub.docker.com/ 容器较为官方的解释&#xff1a; 一句话概括容器&#xff1a;容器就是将软件打包成标准化单元&#xff0c;以用于开发、交付和部署。 容器镜像是轻量的、可执行的独立…

嵌入式学习第十四天!(结构体、共用体、枚举、位运算)

1. 结构体&#xff1a; 1. 结构体类型定义&#xff1a; 嵌入式学习第十三天&#xff01;&#xff08;const指针、函数指针和指针函数、构造数据类型&#xff09;-CSDN博客 2. 结构体变量的定义&#xff1a; 嵌入式学习第十三天&#xff01;&#xff08;const指针、函数指针和…

Meta开源Code Llama 70B,缩小与GPT-4之间的技术鸿沟

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【C++基础入门】一、C++初识

一、C初识 1.1 第一个C程序 编写一个C程序总共分为4个步骤 创建项目创建文件编写代码运行程序 1.1.1 创建项目 ​ Visual Studio是我们用来编写C程序的主要工具&#xff0c;我们先将它打开 1.1.2 创建文件 右键源文件&#xff0c;选择添加->新建项 给C文件起个名称&am…

vue3-hand-mobile

当我写完手势移动事件后&#xff0c;我又通过svg的方法添加了一段文字和polygon。当我在这个蓝色的polygon上滑动手势的时候&#xff0c;会报错。 可能这个bug只是我个人的代码导致的。但是我觉得vue3-hand-mobile插件的这一段代码写的有问题。 我通过circular-json库修复了这…

petalinux2022.2启动文件编译配置

安装必要运行库: sudo apt-get install iproute2 gawk python3 python sudo apt-get install build-essential gcc git make net-tools libncurses5-dev tftpd sudo apt-get install zlib1g-dev libssl-dev flex bison libselinux1 gnupg wget git-core diffstat sudo apt-ge…

IDEA Java常用快捷键

目录 main方法快捷键&#xff1a;psvm输出语句&#xff1a;sout复制行&#xff1a;ctrld删除行&#xff1a;ctrly单行注释或多行注释 &#xff1a; Ctrl / 或 Ctrl Shift /for循环 直接 &#xff1a;fori代码块包围&#xff1a;try-catch,if,while等 ctrlaltt缩进&#xff1…

CentOS 7 部署 ZeroTier Moon 节点

ZeroTier是一套使用UDP协议构建的SD-WAN网络软件&#xff0c;其主要有三部分组成&#xff1a;行星服务器Planet、月亮服务器Moon、客户端节点LEFA&#xff0c;行星服务器是ZeroTier的根节点&#xff0c;可以采用ZeroTier官方的服务器&#xff0c;也可以使用开源代码自行搭建 月…

linux平台 LED情报板网关项目总结

LED情报板目前已经基本稳定 主要存在两个版本LED1.5 和LED2 两个版本的主要差别是 &#xff1a; 1.1.5的配置文件存在本地 2.0的存在平台 需要通过接口从平台获取 2.1.5的下发消息的时候需要同步返回 2.0的是异步返回&#xff0c;所以1.5的要尽可能完成 不然会导致发 布平台…

Oracle 锁的概念以及分类

1.什么是锁 数据库是一个庞大的多用户数据管理系统&#xff0c; 同一时刻可能有多个用户同时操作。事务的分离性要求当前事务不能影响其他的事务&#xff0c;所以多个会话操作同一个资源时&#xff0c;数据库会利用锁确保他们像队列一样一次执行。利用来锁消除多个用户操作同一…

Jmeter分布式场景

Jmeter分布式 1. 为什么使用Jmter分布式测试 1.1 需求 对学院接口(查询学院-所有)进行1000用户并发访问&#xff0c;测试服务器处理批量请求能力1.2 现状 我们单台电脑由于配置(CPU、内存)问题&#xff0c;最模拟500用户时&#xff0c;就出现卡死现象按照一般的压力机配置&…

opencv学习 特征提取

内容来源于《opencv4应用开发入门、进阶与工程化实践》 图像金字塔 略 拉普拉斯金字塔 对输入图像进行reduce操作会生成不同分辨率的图像&#xff0c;对这些图像进行expand操作&#xff0c;然后使用reduce减去expand之后的结果&#xff0c;就会得到拉普拉斯金字塔图像。 …

6.2 静态内存分配模式

Bruce Powel Douglass大师介绍-CSDN博客https://blog.csdn.net/ChatCoding/article/details/134665868 嵌入式软件开发从小工到专家-CSDN博客https://blog.csdn.net/ChatCoding/article/details/135297955 C嵌入式编程设计模式源码-CSDN博客https://blog.csdn.net/ChatCoding…

STM32单片机基本原理与应用(四)

直流电机驱动控制原理 1、电机正反转控制 在STM32中&#xff0c;直流电机的正反转控制主要通过改变电机输入电源的极性来实现。当电机的电压极性发生变化时&#xff0c;电机的旋转方向也会相应改变。在硬件电路中&#xff0c;可以通过继电器或晶体管等电子开关来切换电机的电源…