001集—dwg扩展属性转shp(shapefile格式详解)——arcgis

 一、什么是shapefile

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

SHP格式优点

SHP格式的优点如下:

  1. 结构简单、易于存储:SHP文件采用二进制格式,结构简单,易于存储和传输。
  2. 读取速度快:SHP文件的读取速度较快,因为其采用了二进制格式,不需要进行复杂的文本转换。
  3. 通用性强:SHP文件是AutoCAD系列软件(如AutoCAD、ArcGIS等)的常用文件格式之一,可以在不同的GIS软件和平台之间进行转换和共享。
  4. 支持空间信息表达:SHP文件可以存储矢量数据,能够表达更为精细的空间信息。

下面是 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空间数据格式详细说明


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

一.主文件的组织

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

我们将一个二进制位称为1bit,8bit,也就是8个二进制位构成一个字节。我们看一下一个字节可以表达的十进制范围

00000000(二进制)→0(十进制)

11111111(二进制)→255(十进制)

可以看到,一个字节可以表达256个数字,c语言中的char变量就是占用1个字节。另外,我们需要了解常见变量类型所占字节数,例如

       C语言中:int整型变量占用4个字节,float类型占用4个字节,double占用8个字节。

        而VBA中:int整型变量占用两个字节;长整型 Long,占用4个字节;单精度浮点型 Single,占用4个字节;双精度浮点型 Double,占用8个字节。

实际上4个字节就可以表达很大的整数了,可以表达2^32个值,也就是4294967296个值,但通常整型加上正负号范围也就是:-2147483647~+2147483647,可以满足大部分需求,当然还有占用很多字节的长整型,可以占用8个字节(天文数字)。为了降低空间浪费,也有占用2个字节的短整型。

1.主文件头

  主文件头长度为 100 字节,一共有9个int型和8个double型数据。
注:表中最后4个加星号特别标示的四个数据只有当这个Shapefile文件包含Z方向坐标或者具有Measure值时才有值,否则为0.0。所谓Measure值,是用于存储需要的附加数据,可以用来记录各种数据,例如权值、道路长度等信息。

(注:带星号的标注的为:若无M值或Z值,则未使用,值为0.0)

坐标包含小数,

在VBA中,当你将一个Double类型的实数(8字节,64位)写入内存时,VBA会遵循IEEE 754标准来编码这个数值。IEEE 754标准定义了浮点数在计算机内存中的表示方式。

一个64位的Double类型数值在内存中的编码方式如下:

  1. 符号位(Sign Bit):最高位(第64位,从0开始计数)表示数的正负。0表示正数,1表示负数。

  2. 指数部分(Exponent):接下来的11位(第63位到第53位)表示指数。这个指数是一个有偏的二进制表示,实际的指数值需要减去一个固定的偏置值(对于Double类型,这个偏置值是1023)。

  3. 尾数部分(Mantissa):剩下的52位(第52位到第1位)表示尾数,也称为分数部分。它表示一个介于1和2之间的数(隐含的1.xxxxxx),这个数乘以2的指数次方就是原始的浮点数值。

在VBA中,当你将一个Double类型的值赋给一个变量时,VBA会自动按照上述规则将这个值编码成内存中的64位表示。这个编码过程对程序员通常是透明的,除非你直接操作内存(比如使用指针或者某些低级的内存操作函数)。

例如,假设你有一个Double类型的变量myVar,它的值为1.2。在内存中,myVar的编码将按照IEEE 754标准表示1.2的二进制形式。具体编码值取决于1.2在二进制下的表示,以及IEEE 754标准如何对这个值进行编码。

如果你想要查看Double类型变量在内存中的具体编码,通常需要使用一些专门的工具或者技术,比如指针操作、内存查看工具,或者编写特定的代码来提取这些位。但是,请注意,直接操作内存通常是不安全的,并且可能违反某些编程最佳实践。在大多数情况下,你应该避免直接操作内存,除非你有明确的需求和足够的知识来安全地进行这样的操作。

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 字节表示的文件的总长度(文件头的 100字节 加上记录个数的 4 倍)。

2.索引记录

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

  一个记录在主文件中的偏移量是字符的偏移量(字节数除以2)的,它表示从主文件开始至这个记录记录头第一个字节的字符个数。本博使用vba7,对应的是unicode编码,因此,1个字符=2个字节,主文件中的文件头位100个字节,因此第一个记录的偏移量是 100/2=50。索引记录中存储的内容长度与主文件中记录头中存储的数值相同,即记录长度=字节长度/2。

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

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); 
       }
}

三.dbf属性文件的组织

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

1.属性文件的文件头

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

2.属性文件的实体信息

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

文件名必须与形状文件和索引文件具有相同的前缀。其后缀必须是.dbf。(
表中必须包含每个形状要素的一条记录。
记录顺序必须与主(*.shp)文件中的形状要素顺序相同。
dBASE标头中的年份值必须是1900年之后的年份。
有关dBASE文件格式的更多信息,请访问INPRISE Corp.网站:www.inprise.com.

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文件记录  结束
}

1.DBF文件的整体结构

文件头:包含①基本信息(含32字节的数据) ②字段格式说明(每项32个字节)

0D值的间隔符

记录1

记录2

记录3

记录n

1A结束符号"1A的16进制转10进制为26"

2.DBF文件头的详细格式:

①基本信息

在文件中的位置

内容

说明

0

1个字节

表示当前的版本信息

1-3

3个字节

表示最近的更新日期,按照YYMMDD格式。

4-7

1个32位数

文件中的记录条数。

8-9

1个16位数

文件头中的字节数。

10-11

1个16位数

一条记录中的字节长度。值应该是一条记录中所有字段的长度之和再加上1个字节,这额外一个字节是控制位,表示该记录是否被删除。

12-13

2个字节

保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。

14

1个字节

表示未完成的操作。

15

1个字节

dBASE IV编密码标记。

16-27

12个字节

保留字节,用于多用户处理时使用。

28

1个字节

DBF文件的MDX标识。在创建一个DBF 表时 ,如果使用了MDX 格式的索引文件,那么 DBF 表的表头中的这个字节就自动被设置了一个标志,当你下次试图重新打开这个DBF表的时候,数据引擎会自动识别这个标志,如果此标志为真,则数据引擎将试图打开相应的MDX 文件。

29

1个字节

Language driver ID.

30-31

2个字节

保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。

②DBF文件头中记录项(字段)的详细格式:

位置

内容

说明

0-10

11个字节

记录项名称,是ASCII码值。

11

1个字节

记录项的数据类型,是ASCII码值。(B、C、D、G、L、M和N,具体的解释见表2.9)。

12-15

4个字节

保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。

16

1个字节

记录项长度,二进制型。

17

1个字节

记录项的精度,二进制型。

18-19

2个字节

保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。

20

1个字节

工作区ID。

21-30

10个字节

保留字节,用于以后添加新的说明性信息时使用,这里用0来填写。

31

1个字节

MDX标识。如果存在一个MDX 格式的索引文件,那么这个记录项为真,否则为空。

如一表有n个字段,该格式就有n项,共占空间32*n个字节。

③  DBF文件中的数据类型:

代码

数据类型

允许输入的数据

B

二进制型

各种字符。

C

字符型

各种字符。

D

日期型

用于区分年、月、日的数字和一个字符,内部存储按照YYYYMMDD格式。

G

(General

or OLE)

各种字符。

N

数值型(Numeric)

. 0 1 2 3 4 5 6 7 8 9

L

逻辑型(Logical)

? Y y N n T t F f (? 表示没有初始化)。

M

(Memo)

各种字符。

④记录数据

序号

控制位

内容

1

20

字段1内容字段2内容…字段n内容

2

20

3

20

20

n

20

每个记录第一个字节是控制位,表示该记录是否被删除,0x20表示没有被删除,0x2A表示删除。

 记录是以ASCII的形式存放的,没有分隔符

 见下图dbf文件的底层代码:

本博发现,数据内容字节中,整形数据放入字节位为靠右对齐,字符串为靠左对齐。(上图31 37 为整型id字段的ascii码在6个字节位中靠右对齐,空余部分“20”填充。jdh字段内容“41010”的ascii码在50个字节位中靠左对齐,空余部分“20”填充,为方便写代码,本博字段全部定义为字符串类型)

举例说明:

假如文件中有10条记录,每个记录有4个字段,4个字段的长度分别为:12、14、16、18,那么文件的详细格式如下:

文件头占32+32*4+1个字节:

前32个字节是文件头中的基本信息,32*4个字节是记录项(即字段的定义信息),最后一个字节分别是16进制的0D,0D是文件头终止标识。

数据信息占(1+12+14+16+18)*10+1个字节:

1+12+14+16+18个字节,其中1是控制位占的,其他是每个数据项占的,共10条记录。最后一个字节是数据的终止表示通常是16进制表示的1A。

补充说明:

由于上述文件格式的定义,决定了字段名称不能超过11个字节(或者5个中文字符),字符类型的字段,数据最大不能超过255个字节。在从文本、Excel、大型数据库导出数据到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字节(双精度浮点数)有符号浮点数字段。(arcgis10.7版本)

其中:

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

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 转为十六进制4E14 倒序144E0000 用十进制来表示 340656128

1000 转为十六进制 3E8(1F4) 倒序e8030000 用十进制来表示3892510720

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

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

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

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

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

第二行CAD选择集过滤器为:8  JZD  (图层名位JZD);

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

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

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

第六行是字段的总长度;

第八行开始是字段清单。

其中:

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

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

arcgis中帮助文件: 

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

第三列是字段长度;

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

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

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

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

黙认值:第七列中的数据

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

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

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

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

'114度带cgcs2000坐标系为例
PROJCS["CGCS2000_3_Degree_GK_CM_114E",GEOGCS["GCS_China_Geodetic_Coordinate_System_2000",DATUM["D_China_2000",SPHEROID["CGCS2000",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Gauss_Kruger"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",114.0],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]


CGCS2000_3_Degree_GK_CM_114E
WKID: 4547 权限: EPSG

Projection: Gauss_Kruger
False_Easting: 500000.0
False_Northing: 0.0
Central_Meridian: 114.0
Scale_Factor: 1.0
Latitude_Of_Origin: 0.0
Linear Unit: Meter (1.0)

Geographic Coordinate System: GCS_China_Geodetic_Coordinate_System_2000
Angular Unit: Degree (0.0174532925199433)
Prime Meridian: Greenwich (0.0)
Datum: D_China_2000
  Spheroid: CGCS2000
    Semimajor Axis: 6378137.0
    Semiminor Axis: 6356752.314140356
    Inverse Flattening: 298.257222101

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西安坐标系"

 

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

调试代码结果如下(shp文件创建及字段录入已完成,图形及属性录入有待完善):

Public 图层名 As String
Public 字段总长度     As Integer
Public 文件头长度     As Integer
Public 记录条数       As Long
Public 记录长度       As Long
Public 范围框(0 To 3) As Double
Public 图形框(0 To 3) As Double
Public 记录编号
Dim KZW1A As Byte
Public FUZU As String
Public kzw20 As Byte ''20控制位,只有定义byte型才能只占一个字节
Public asciibyte As Byte
Public JJ As Integer
Public kk As Long
Public onechar() As String
Public ShpName As String, ShpFile As Integer, Shp指针 As Long  'Shp文件名、文件号、指针
Public ShxName As String, ShxFile As Integer, Shx指针 As Long
Public DbfName As String, DbfFile As Integer, Dbf指针 As Long, Dbf指针2 As Long, Dbf指针3 As Long 'Dbf文件名、文件号、指针
Public mm As String
Public N As Long, i As Integer, r As Integer
Public fType(1) As Integer, fData(1)           '选择集过滤条件
Public SelectA  As AcadSelectionSet            '选择集
Public Entry As AcadEntity                     'CAD实体
Public XDType As Variant, xData As Variant     '查询扩展属性
Public longN As Long
Public version As Byte
Public dateF(2) As Byte
'Dim 表名 As String
Public 发包方编码 As String

Public 坐标系 As String, 加带号 As Boolean, 中央子午线 As Double, 投影带宽 As Integer

Public 表名  As String, 字段数 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
Public pField()        As 字段属性  '字段组

'整理多段线的节点坐标
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

'''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''
                                      ' '''''

''''      完整代码联系本博qq443440204  '''''''
      
                                      '''''''

'''''''''''''''''''''''''''''''''''''''''''''''

'''''''''''''''''''''''''''''''''''''''''''''''
    Dbf指针2 = Dbf指针 '这句话一定要放在for外面
    Put #DbfFile, Dbf指针2, FUZU 'Asc(Mid(FUZU, kk, 1))
'            For kk = 1 To Len(FUZU)
'                'Put #DbfFile, r + N, Asc(Mid(pField(i).Name, N, 1))''mid
''                asciibyte = Asc(Mid(FUZU, kk, 1)) 'asc()函数返回的上一个四字节整数,内存中占4字节,因此需要放入byte中截取一个字节
'
'                Put #DbfFile, Dbf指针2, Asc(Mid(FUZU, kk, 1)) ''Dbf指针2 + kk - 1,这句话返回一个整型数,而不是字节位置。midb函数返回字符串中的字节,而不是字符。此处有待完善代码,应为每个字符的ascii码
'                'MsgBox Asc(Mid(FUZU, kk, 1)) Put #DbfFile, r + N, Asc(Mid(pField(i).Name, N, 1))
'                Dbf指针2 = Dbf指针2 + 1
'            Next
'            '' Put #DbfFile, Dbf指针, pField(N).Name ''此处有待完善代码,应为数据内容
            Dbf指针 = Dbf指针 + pField(N).Length
            'Stop
Next

End Sub

 
 
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 creatsel(ByVal selname As String) As AcadSelectionSet
On Error Resume Next
Dim sel As AcadSelectionSet
  For i = 0 To ThisDrawing.SelectionSets.Count - 1
     Set sel = ThisDrawing.SelectionSets.Item(i)
     If StrComp(sel.Name, selname, 1) = 0 Then
        sel.Delete
        Exit For
     End If
  Next i
Set creatsel = ThisDrawing.SelectionSets.Add(selname)
End Function

Sub dwg动态属性转Shapefile()

''Set sel = creatsel("mysel")
''sel.Select acSelectionSetAll
'MsgBox sel.Count

''本博vba采用的ansi编码模式,需生成一个内容为"ANSI"的.cpg文件,否则arcgis10.7默认采用utf-8编码读取文件会出现乱码

图层名 = "JZD"  '改为待转数据的图层名称
On Error Resume Next
   ' Start Excel
    Set excel = GetObject(, "Excel.Application")
  
    If Err <> 0 Then
        Err.Clear
        Set excel = CreateObject("Excel.Application")
            
        If Err <> 0 Then
            MsgBox "Could not load Excel.", vbExclamation
            End
        End If
    End If
    
    On Error GoTo 0
    On Error Resume Next
    excel.Visible = True
Dim 工作目录 As String
ShpName = 表名 & ".shp"
工作目录 = ThisDrawing.Path & "\"    'ThisDrawing.Path + "\NEWShape\"
If InStr(工作目录, "C:\Program Files (x86)\AutoCAD 2008") > 0 Then Exit Sub

 
'创建空间参考文件
'定义空间参考.show     '自定义选择参数 坐标系、加带号、中央子午线、投影带宽
坐标系 = "2000国家大地坐标系"
中央子午线 = 114
加带号 = False
投影带宽 = 3
Dim PrjName As String
PrjName = ThisDrawing.Path & "\ZD.prj"
Dim m(0 To 12) As String
常数 = 中央子午线 / 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") & "]"
                  
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]]"                      '长度单位
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
发包方编码 = Left(ThisDrawing.Name, 12)
Dim 转换标准 As String       'Shape转换标准样本.xlsx
转换标准 = ThisDrawing.Path & "\ZD.xlsx"

excel.Workbooks.Open filename:=转换标准        '打开文件
'Dim MySheet As excel.worksheet     'Excel工作表
'For Each MySheet In excel.ActiveWorkbook.Sheets   '历遍Excel的工作表
'    If excel.activesheet.Name = "JZX" Or MySheet.Name = "说明" Then Exit For     '目前不转界址线
    Dim MySheet As Object
'    Set MySheet = excel.worksheets(1)
        Set MySheet = excel.activesheet
    表名 = 工作目录 & 发包方编码 & MySheet.Name
    文件名 = 表名 + ".prj"
    FileCopy PrjName, 文件名     '复制预先创建好的空间参考文件
    ShpName = 表名 & ".shp": ShpFile = 1
    ShxName = 表名 & ".shx": ShxFile = 2
    DbfName = 表名 & ".dbf": DbfFile = 3
    CPGName = 表名 & ".CPG": CPGFile = 4
    '如果文件已存在,删除文件
    If Dir(ShpName) <> "" Then Kill ShpName
    If Dir(ShxName) <> "" Then Kill ShxName
    If Dir(DbfName) <> "" Then Kill DbfName
    If Dir(CPGName) <> "" Then Kill DbfName
    '创建打开Shape文件,输出头文件内容
    Open CPGName For Binary As #CPGFile     '打开文件
    Put #CPGFile, 1, "ANSI"
    Close
    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    'pdf的文件头32字节和字段描述,每个字段32字节
            On Error Resume Next
            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
        
        文件头长度 = 字段数 * 32 + 32 + 1
        Put #DbfFile, 9, 文件头长度       '文件头长度 文件头32+每个字段32+控制位0D一个字节
        Put #DbfFile, 11, 字段总长度 + 1    '一条记录的字节长度
 
        version = 3
        Put #DbfFile, 1, version          'dbf版本信息
        dateF(0) = 2024 - 1900: dateF(1) = 2: dateF(2) = 26
        Put #DbfFile, 2, dateF            '最近的更新日期,年数是1900到今年的年数
        Dim myb As Byte
        myb = &HD
        Put #DbfFile, 文件头长度, myb     '0d控制位,vba中&h为十六进制数,c++中是0X
    
        longN = 170328064 '' 9994转16进制270A倒序0A270000转十进制170328064
        Put #ShpFile, 1, longN    '1 File Code,文件号9994
        Put #ShxFile, 1, longN
        longN = 1000 '小端序,系统默认一样不需要转
        Put #ShpFile, 29, longN    '1 版本号
        Put #ShxFile, 29, longN
        longN = MySheet.Cells(4, 2) '点线面135类型,此代码为面转换代码
        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
        SelectA.Highlight (True)
        For Each Entry In SelectA
            Entry.GetXData "", XDType, xData
'            MsgBox Entry.ObjectName
'          ThisDrawing.Regen acActiveViewport
            记录条数 = 记录条数 + 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
    
    KZW1A = &H1A '控制位1A
    Put #DbfFile, Dbf指针, KZW1A
    Offset = LOF(ShpFile) / 2 '这里的长度是字节数/2
    longN = 转为大端序(Offset)
    Put #ShpFile, 25, longN   'Shp文件长度
    longN = 转为大端序((Shx指针 - 1) / 2)
    Put #ShxFile, 25, longN   'Shx文件长度字节数/2

    Put #ShpFile, 37, 图形框
    Put #ShxFile, 37, 图形框
'    Put #ShpFile, 37, 范围框
'    Put #ShxFile, 37, 范围框
    Close

'excel.ActiveWorkbook.Close SaveChanges:=True
MsgBox "已完成", , "QQ443440204"

End Sub

 转换前的cad和vba代码:

 转换后的shp:

  • 41
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: DWG属性SHP插件是一种用于将DWG文件换为SHP文件并保留属性信息的工具。DWG是AutoCAD绘图文件的格式,而SHPShapefile文件的格式,常用于GIS(地理信息系统)软件中。该插件的作用是将DWG中的几何信息及其对应的属性信息换为SHP文件,使其在GIS软件中可以进行进一步的空间分析和数据管理。 使用DWG属性SHP插件非常简单。首先,将需要换的DWG文件加载到AutoCAD软件中。然后,打开插件并选择将要换的图层。插件会自动提取DWG文件中的几何信息以及相应的属性信息,生成对应的SHP文件。换完成后,我们可以在GIS软件中导入SHP文件,查看并分析其中的空间数据。 除了换功能,该插件还提供其他一些辅助功能。例如,我们可以通过插件调整SHP文件中的图层属性,使其更符合我们的需求。同时,插件还支持批量换,可以同时处理多个DWG文件,提高工作效率。 总的来说,DWG属性SHP插件为我们在GIS软件中使用DWG文件提供了便利。它能够将DWG文件中的几何信息和属性信息换为SHP文件,使其在GIS软件中更容易进行空间分析和数据管理。该插件简单易用,功能强大,是GIS领域中不可或缺的工具之一。 ### 回答2: DWG属性SHP插件是一种常用的CAD软件辅助工具。DWG是AutoCAD的标准文件格式,而SHP则是ArcGIS软件使用的矢量地理信息文件格式。通过DWG属性SHP插件,用户可以将CAD中的图形数据和属性信息换为GIS中的矢量数据,并保留图形对象的属性信息。 该插件的安装和使用相对简单。首先,用户需要安装对应版本的CAD软件,并确保具备访问DWG文件的权限。其次,下载并安装DWG属性SHP插件,根据安装向导完成插件的安装。 一旦插件安装完成,用户可以通过以下步骤进行换操作: 1. 启动CAD软件,打开需要换的DWG文件。 2. 找到插件工具栏或菜单项,点击“DWG属性SHP”选项。 3. 在换设置中,用户可以选择要换的DWG图层、属性字段以及输出文件的保存路径和格式。 4. 单击“换”按钮,开始进行DWG属性SHP的过程。 5. 换完成后,插件会将DWG中的图层和属性信息按照用户设定的输出格式保存为SHP文件。 使用DWG属性SHP插件可以提高CAD与GIS之间的数据交互性和共享性。通过该插件,用户能够快速将DWG文件中的图形数据换为SHP格式,方便在ArcGIS等GIS软件中进行空间分析、地图制图等工作。同时,插件支持属性字段的换,保留了CAD中对象的相关信息,使得换后的SHP数据更具可读性和可操作性。 需要注意的是,插件的换结果可能受到DWG文件的复杂程度和属性字段的多样性影响。用户在操作时应根据实际情况灵活选择换设置,以获得最佳的换效果。 ### 回答3: DWG属性SHP插件是一种用于将AutoCAD中的DWG文件(包含属性数据)换为SHP文件的工具。DWG文件是AutoCAD软件使用的原生数据格式,而SHP文件是一种用于存储地理空间数据的常用格式。 使用DWG属性SHP插件可以提供以下优点: 1. 数据换:该插件可以将DWG文件中的几何要素和相应的属性数据换为SHP文件,便于在GIS软件中使用和处理。 2. 属性保留:插件能够保留DWG文件中的属性数据,并将其换为SHP文件的属性表。这意味着换后的SHP文件会包含与DWG文件中相对应的属性信息,便于进一步的地理空间分析和可视化。 3. 批量换:插件通常支持批量换,可以一次性换多个DWG文件为SHP文件。这样可以节省时间和劳动力,提高工作效率。 4. 定制选项:一些插件提供了一些定制选项,允许用户根据自己的需要进行设置。例如,可以选择换的DWG图层、换为SHP的几何要素类型等。 5. 操作简便:这类插件通常拥有用户友好的界面和简单的操作步骤,即使是对于没有专门的GIS技能的用户,也可以轻松上手。 总而言之,DWG属性SHP插件是一种方便快捷的工具,可以帮助用户将AutoCAD中的DWG文件换为SHP文件,并保留其属性数据。通过使用这种插件,用户可以更好地在GIS软件中分析和处理DWG数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值