Unity读取并解析Shapefile地图文件

文章目录

      • 参考
      • 一、文件介绍
        • 1.shapefile组成
        • 2.Main File(.shx)的文件结构
        • 3.Index File(.shx)的文件结构
        • 4.dBASE(.dbf)的文件结构
      • 二、读取shp文件

参考

Github库:ShpLoader

有需要的同学请移步上面这位大佬的github库。我只是对内容做一个小小的总结。

一、文件介绍

1.shapefile组成

ESRI shapefile由一个主文件,一个索引文件组成。和一个dBASE表。主文件是一个直接访问、可变记录长度的文件,其中每条记录都用它的顶点列表来描述一个形状。在索引文件中。每条记录包含对应的主文件记录从主文件开始的偏移量。dBASE表包含每个特性一条记录的特性属性。几何图形和属性之间的一对一关系是基于记录号的。dBASE文件中的属性记录必须与主文件中的记录的顺序相同。

命名规范
所有的文件名都遵循8.3命名约定。的主要文件。索引文件。和dBASE文件具有相同的前缀。前缀必须以字母数字字符(a-Z)开头。0 - 9)。后跟0个或最多7个字符(a-Z)。0 - 9)。主文件的后缀是.shp。索引文件的后缀是.shx。dBASE表的后缀是.dbf。在具有区分大小写的文件名的操作系统上,文件名中的所有字母都是小写的。
在这里插入图片描述
数值类型
shapefile存储整数和双精度数。本文件的其余部分将引用以下类型:整数:带符号的32位整数(4字节)双:带符号的64位IEEE双精度浮点数(8字节)浮点数必须是数值。正无穷。在shapefile中不允许出现负无穷和非数字(NaN)值。然而,shapefiles支持“无数据”值的概念。但它们目前仅用于测量。shapefile读取器认为任何小于10的浮点数表示“无数据”值。

2.Main File(.shx)的文件结构

主文件(.shp)包含一个固定长度的文件头,后面跟着可变长度的记录。每个可变长度的记录由固定长度的记录头和可变长度的记录内容组成。图1说明了主文件的组织。
Unity读取并解析Shapefile地图文件_第1张图片
字节序
shapefile中的所有内容可以分为两类:

  • 相关的数据
    • 主文件的记录内容
    • 主文件头的数据描述字段(Shape Type)。Bounding Box等)
  • 相关文件管理
    • 文件和记录长度
    • 记录偏移量。等等

组成文件头(下面标识)中的数据描述字段和主文件中的记录内容的整数和双精度整数采用小端字节顺序(PC或Intel)。构成文件和文件管理的其余部分的整数和双精度浮点数采用大端字节顺序(Sun或Motorola)。相关参考:浅谈字节序(Byte Order)及其相关操作

主文件的Header
主文件头的长度为100字节。表1显示了文件头中的字段及其字节位置、值、类型和字节顺序。在表中,位置与文件的开始有关。
Unity读取并解析Shapefile地图文件_第2张图片
文件长度的值是以16位字表示的文件总长度(包括组成头的50个16位字)。shapefile中的所有非空形状都需要具有相同的形状类型。形状类型的值如下:
Unity读取并解析Shapefile地图文件_第3张图片
目前,shapefile被限制为包含与上面指定的形状相同类型的形状。在未来。shapefiles可以允许包含一种以上的形状类型。如果实现了混合形状类型,头中的形状类型字段将标志该文件主文件头中的Bounding Box文件中形状的实际范围:与包含所有形状的X和Y轴(可能还有M和Z轴)正交的最小边框。如果shapefile是空的(即没有record)。Xmin,Ymin,Xmax,Ymax是未指定的。Mmin和Mmax可以包含“no data”值,用于测量形状类型的shapefile,这些形状文件不包含度量值。

Record Headers
每个记录的头存储记录编号和记录的内容长度。记录头的长度为8字节。表2显示了文件头中的字段及其字节位置、值、类型和字节序。在表中,position和record的start有关。
Unity读取并解析Shapefile地图文件_第4张图片
记录数字从1开始。记录的内容长度是记录内容部分的长度,用16位的字来度量。每条记录,因此。将(4 +内容长度)16位的字作为文件的总长度,存储在文件头的第24字节。

Record Content
Shapefile记录内容由形状类型和形状的几何数据组成。记录内容的长度取决于形状中部件和顶点的数量。每个形状类型。我们首先描述形状,然后它映射到磁盘上的记录内容。举几个例子:

Point
Unity读取并解析Shapefile地图文件_第5张图片
Polyline
折线是顶点的有序集合,由一个或多个部分组成。部分是由两个或多个点组成的连通序列。各部分之间可能有连接,也可能没有连接。各部分可能相互交叉,也可能不相互交叉。因为这个规范不禁止使用相同坐标的连续点。shapefile阅读器必须处理这种情况。另一方面,退化的,零长度的部分是不允许的。
Unity读取并解析Shapefile地图文件_第6张图片
Unity读取并解析Shapefile地图文件_第7张图片
Polygon
多边形由一个或多个环组成。环是由四个或四个以上的点组成的闭合序列。non-self-intersecting循环。一个多边形可以包含多个外圈。顶点的顺序或环的方向表示环的哪一边是多边形的内部。沿着环按顶点顺序行走的观察者的右邻域就是多边形内的邻域。多边形中定义孔的环的顶点是逆时针方向的。顶点为单个。被包围的多边形。因此。总是顺时针方向。一个多边形的环被称为它的各个部分因为该规范不禁止使用相同坐标的连续点,所以shapefile阅读器必须处理这种情况。
Unity读取并解析Shapefile地图文件_第8张图片
图2中的实例图演示了多边形的表示。这个图显示了一个有一个洞和八个顶点的多边形以下是关于多边形形状的重要注意事项:

  • 环是闭合的(环的第一个顶点和最后一个顶点必须是相同的)。
  • 在点阵中,环的顺序不显著。
  • 存储在形状文件中的多边形必须是干净的。一个干净的多边形就是

1.没有self-intersections。这意味着属于一个环的线段不能与属于另一个环的线段相交。多边形的环可以在顶点上相互接触,但不能沿着线段接触。共线线段被认为是相交的

2.多边形的内部在定义它的线的“正确”边上。沿着环按顶点顺序行走的观察者的右邻域是多边形的内部。因此,单个环形多边形的顶点总是按顺时针顺序排列。在这些多边形中定义孔的环具有逆时针方向。当在多边形中定义孔的环也是顺时针方向时,就会出现“脏”多边形,这会导致内部重叠。

在本例中,NumParts等于2,NumPoints等于10。注意,甜甜圈(洞)多边形的points的顺序是颠倒的。
Unity读取并解析Shapefile地图文件_第9张图片
Unity读取并解析Shapefile地图文件_第10张图片

3.Index File(.shx)的文件结构

Unity读取并解析Shapefile地图文件_第11张图片
索引文件头在组织上与上面描述的主文件头相同。存储在索引文件头中的文件长度是索引文件的总长度(16位字)(头的50个16位字加上记录数的4倍)。

索引文件中的第i条记录存储主文件中第i条记录的偏移量和内容长度。表17显示了文件头中的字段及其字节位置、值…类型和字节顺序。在表中。位置是相对于索引文件记录的开始位置。
Unity读取并解析Shapefile地图文件_第12张图片
主文件中记录的偏移量是从主文件开始到该记录的记录头的第一个字节的16位字数。因此。主文件中的firs记录的偏移量是50。给定100字节的头存储在索引记录中的内容长度与存储在主文件记录头中的值相同。

4.dBASE(.dbf)的文件结构

dBASE文件(.dbf)包含任何所需的特性属性或其他表可以连接到的属性键。它的格式是标准的DBF文件,被WindowsM和DOS中许多基于表的应用程序使用。表中可以出现任何字段集。有三个要求。如下:

  • 文件名必须具有与形状和索引文件相同的前缀。它的后缀must he。dbf。(见第2页的例子。在命名约定。
  • 该表必须为每个形状特性包含一条记录
  • 记录顺序必须与主(*.shp)文件中形状特征的顺序相同。
  • dBASE头中的年份值必须是1900年以来的vear。

有关dBASE文件格式的更多信息,请访问INPRISE公司的网站。

二、读取shp文件

使用C#中的FileStream和BinaryReader。

using System.IO;

public void Load()
{
    string path="xxx.shp";
	FileStream fs = File.OpenRead(path);
	BinaryReader br = new BinaryReader(fs);
	#【1】读取文件头
    FileCode = Util.FromBigEndian(br.ReadInt32());//对应Header结构表中的Big的字节序,需要使用FromBigEndian函数进行转换
    //具体实现:using static System.Net.IPAddress;
    //public static int FromBigEndian(this int value) => NetworkToHostOrder(value);
    br.BaseStream.Seek(20, SeekOrigin.Current);
    FileLength = Util.FromBigEndian(br.ReadInt32()) * 2;
    FileVersion = br.ReadInt32();//Little字节序的则可以直接读取
    ShpType = (ShapeType)br.ReadInt32();

    TotalXYRange = new RangeXY();
    ZRange = new Range();
    MRange = new Range();
    TotalXYRange.Load(ref br);
    ZRange.Load(ref br);
    MRange.Load(ref br);
    /* 读取浮点值的具体实现:
    public void Load(ref BinaryReader br)
        {
            MinX = br.ReadDouble();
            MaxX = br.ReadDouble();
            MinY = br.ReadDouble();
            MaxY = br.ReadDouble();
        }
	*/
	
	#【2】读取Records
    ContentLength = FileLength - 100;//减去Header大小
    long curPoint = 0;
    
    RecordSet = new List<ShpRecord>();
    while (curPoint < ContentLength)
    {
        ShpRecord record = new ShpRecord(ShpType);
        record.Load(ref br);
        /*
        public void Load(ref BinaryReader br)
        {
            Header.Load(ref br);
            Contents.Load(ref br);
        }
        */
        long size = record.GetLength();
        RecordSet.Add(record);
        curPoint += size;
    }
}

你可能感兴趣的:(自动驾驶仿真)