• 上一篇介绍了Shape files文件结构,在这一篇,以面文件为例,写一下如何读取.shp文件,以面文件为例。 首先在ArcMap里面新建一个名为 三角形面 的 shp文件,用做测试数据。如下 测试数据下载地址为:...

    上一篇介绍了Shape files文件结构,在这一篇,以面文件为例,写一下如何读取.shp文件,以面文件为例。

    首先在ArcMap里面新建一个名为  三角形面   的 shp文件,用做测试数据。如下

    测试数据下载地址为:http://download.csdn.net/detail/gis0911178/9650967

    在Arcmap中显示如下

    测试数据准备好之后,就可以在C#里面写代码来读取这个shp文件;代码如下

    private void button1_Click(object sender, EventArgs e)
            {
                string shpfilepath = "";
                OpenFileDialog openFileDialog1 = new OpenFileDialog();
                openFileDialog1.Filter = "shapefile(*.shp)|*.shp|All files(*.*)|*.*"; //打开文件路径
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    shpfilepath = openFileDialog1.FileName;
                    BinaryReader br = new BinaryReader(openFileDialog1.OpenFile());


                    //读取文件过程
                    br.ReadBytes(24);
                    int FileLength = br.ReadInt32();
                    Console.WriteLine("文件长度:" + ChangeByteOrder(FileLength));
                    int FileBanben = br.ReadInt32();
                    ShapeType = br.ReadInt32();
                    xmin = br.ReadDouble();
                    ymin = br.ReadDouble();
                    xmax = br.ReadDouble();
                    ymax = br.ReadDouble();
                    Console.WriteLine("Xmin:" + xmin);
                    Console.WriteLine("Ymin:" + ymin);
                    Console.WriteLine("Xmax:" + xmax);
                    Console.WriteLine("Ymax:" + ymax);
                    double width = xmax - xmin;
                    double height = ymax - ymin;
                    n1 = (float)(this.panel1.Width * 0.9 / width);//x轴放大倍数
                    n2 = (float)(this.panel1.Height * 0.9 / height);//y轴放大倍数
                    br.ReadBytes(32);


                    switch (ShapeType)
                    {
                        case 1:
                            points.Clear();
                            while (br.PeekChar() != -1)
                            {
                                Point point = new Point();


                                uint RecordNum = br.ReadUInt32();
                                int DataLength = br.ReadInt32();
                                //读取第i个记录
                                br.ReadInt32();
                                point.X = br.ReadDouble();
                                point.Y = br.ReadDouble();
                                points.Add(point);


                            }
                            StreamWriter sw = new StreamWriter("point.txt");
                            foreach (Point p in points)
                            {
                                sw.WriteLine("{0},{1},{2}", p.X, -1 * p.Y, 0);
                            }
                            sw.Close();
                            break;
                        case 3:
                            polylines.Clear();
                            while (br.PeekChar() != -1)
                            {
                                Polyline polyline = new Polyline();
                                polyline.Box = new double[4];
                                polyline.Parts = new ArrayList();
                                polyline.Points = new ArrayList();


                                uint RecordNum = br.ReadUInt32();
                                int DataLength = br.ReadInt32();
                                //读取第i个记录
                                br.ReadInt32();
                                polyline.Box[0] = br.ReadDouble();
                                polyline.Box[1] = br.ReadDouble();
                                polyline.Box[2] = br.ReadDouble();
                                polyline.Box[3] = br.ReadDouble();
                                polyline.NumParts = br.ReadInt32();
                                polyline.NumPoints = br.ReadInt32();
                                for (int i = 0; i < polyline.NumParts; i++)
                                {
                                    int parts = new int();
                                    parts = br.ReadInt32();
                                    polyline.Parts.Add(parts);
                                }
                                for (int j = 0; j < polyline.NumPoints; j++)
                                {
                                    Point pointtemp = new Point();
                                    pointtemp.X = br.ReadDouble();
                                    pointtemp.Y = br.ReadDouble();
                                    polyline.Points.Add(pointtemp);
                                }
                                polylines.Add(polyline);
                            }
                            StreamWriter sw2 = new StreamWriter("line.txt");
                            count = 1;
                            foreach (Polyline p in polylines)
                            {
                                for (int i = 0; i < p.NumParts; i++)
                                {
                                    int startpoint;
                                    int endpoint;
                                    if (i == p.NumParts - 1)
                                    {
                                        startpoint = (int)p.Parts[i];
                                        endpoint = p.NumPoints;
                                    }
                                    else
                                    {
                                        startpoint = (int)p.Parts[i];
                                        endpoint = (int)p.Parts[i + 1];
                                    }
                                    sw2.WriteLine("线" + count.ToString() + ":");
                                    for (int k = 0, j = startpoint; j < endpoint; j++, k++)
                                    {
                                        Point ps = (Point)p.Points[j];
                                        sw2.WriteLine("    {0},{1},{2}", ps.X, ps.Y, 0);
                                    }
                                    count++;
                                }
                            }
                            sw2.Close();
                            break;
                        case 5:
                            polygons.Clear();
                            while(br.PeekChar()!=-1)
                            {
                                Polygon polygon = new Polygon();
                                polygon.Parts = new ArrayList();
                                polygon.Points = new ArrayList();


                                uint RecordNum = br.ReadUInt32();
                                //Console.Write("文件记录号为:"+RecordNum);
                                Console.WriteLine("文件记录号为:" + ChangeByteOrder((int)RecordNum));
                                int DataLength = br.ReadInt32();
                                //Console.Write("坐标长度为:"+DataLength);
                                Console.WriteLine("坐标长度为:" + ChangeByteOrder(DataLength));


                                //读取第i个记录
                                int m = br.ReadInt32();
                                Console.WriteLine("几何类型:"+m);
                                for (int i = 0; i < 4;i++ )
                                {
                                    polygon.Box[i] = br.ReadDouble();
                                    Console.WriteLine("Box[" + i + "]:" + polygon.Box[i]);
                                }


                                polygon.NumParts = br.ReadInt32();
                                Console.WriteLine("子面个数:"+polygon.NumParts);
                                polygon.NumPoints = br.ReadInt32();
                                Console.WriteLine("坐标点个数:" + polygon.NumPoints);


                                Console.WriteLine("每个子环在坐标点内的起始位置:");
                                for (int j = 0; j < polygon.NumParts;j++ )
                                {
                                    int parts = new int();
                                    parts = br.ReadInt32();
                                    polygon.Parts.Add(parts);
                                    Console.WriteLine("parts[" + j + "]:" + parts);
                                }


                                Console.WriteLine("Points数组:");
                                for (int j = 0; j < polygon.NumPoints;j++ )
                                {
                                    Point pointtemp = new Point();
                                    pointtemp.X = br.ReadDouble();
                                    pointtemp.Y = br.ReadDouble();
                                    polygon.Points.Add(pointtemp);
                                    Console.WriteLine("Points["+j+"]:"+pointtemp.X+" "+pointtemp.Y);
                                }
                                polygons.Add(polygon);
                                Console.WriteLine("--------------------------");


                            }
                            break;
                    }
                }
            }

    读取文件可以了解.shp文件的构成,这样才知道怎么去生成.shp文件。

    为了清晰的看到结果,在这里我将每次读取到的东西都打印了出来,结果如下

    --------------------------------------------------------------------------------

    文件长度:110
    Xmin:120.062485706624
    Ymin:27.752624080108
    Xmax:120.102341678472
    Ymax:27.7716597681547
    文件记录号为:1
    坐标长度为:56
    几何类型:5
    Box[0]:120.062485706624
    Box[1]:27.752624080108
    Box[2]:120.102341678472
    Box[3]:27.7716597681547
    子面个数:1
    坐标点个数:4
    每个子环在坐标点内的起始位置:
    parts[0]:0
    Points数组:
    Points[0]:120.062485706624 27.7618444915056
    Points[1]:120.102341678472 27.7716597681547
    Points[2]:120.081521394671 27.752624080108
    Points[3]:120.062485706624 27.7618444915056

    ------------------------------------------------------------------------------------------------------

    要注意.shp文件里面,文件长度、文件记录号、坐标长度 均为位序为big,读取跟写入的时候都要转换为little。位序转换函数如下:

    private int ChangeByteOrder(int indata)
            {
                byte[] src = new byte[4];
                src[0] = (byte)((indata >> 24) & 0xFF);
                src[1] = (byte)((indata >> 16) & 0xFF);
                src[2] = (byte)((indata >> 8) & 0xFF);
                src[3] = (byte)(indata  & 0xFF);


                int value ;
                value = (int)((src[0] & 0xFF) | ((src[1] & 0xFF) << 8) | ((src[2] & 0xFF) << 16) | ((src[3] & 0xFF) << 24));
                return value;
            }

    代码里使用到的polygon.cs如下

    class Polygon
        {
            public double[] Box=new double[4];
            public int NumParts;
            public int NumPoints;
            public ArrayList Parts;
            public ArrayList Points;
        }

     

    微信关注  奔跑的GISer  获取更多资源

    展开全文
  • GDAL C#读取shp文件

    2020-07-02 21:12:03
    使用 GDAL C#读取SHP空间数据的C#代码,已经经过测试了,大家放心使用哈,对应的gdal本人提供下载了
  • 学会用C#文件读取shp(shapefile格式)文件,内有说明文档
  • 根据网络资源,整理的用C#读写shp文件的源码,包括对shp文件格式的代码实现,比较详细,在vs2008下编译通过,对于复杂的面状数据需要进一步拓展功能
  • C#中Gdal读取SHP文件

    2016-08-02 13:35:47
    1.主要是C# 版本下载,尽量最新吧! 在这里 http://www.gisinternals.com/sdk/  点击打开链接 下了 适合自己的版本。我下载的是\release-1600-gdal-1-10-mapserver-6-2版本, 把所需要的C#的的dll库,\release-...

    1.主要是C# 版本下载,尽量最新吧!

    在这里  http://www.gisinternals.com/sdk/  点击打开链接 下了 适合自己的版本。我下载的是\release-1600-gdal-1-10-mapserver-6-2版本,

    把所需要的C#的的dll库,\release-1600-gdal-1-10-mapserver-6-2\bin\gdal\csharp在这里找到。 


    主要的DLL有8个DLL文件gdal_csharp,gdal_wrap,gdalconst_csharp,gdalconst_wrap,ogr_csharp,ogr_warp,osr_csharp,osr_wrap  拷贝到VS项目的程序文件夹bin中。

    当然\release-1600-gdal-1-10-mapserver-6-2\bin 下面的那么多DLL也做好拷贝到你的工程的bin下,因为里面的依赖关系我也分不清。


    2.  写了个简单的读取类,名称为GdalRead.cs。当然,要在工程里引用四个含有*-csharp的DLL。

    来个截图:




    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    //
    using System.IO;
    using OSGeo.GDAL;
    using OSGeo.OGR;
    using OSGeo.OSR;
    using System.Collections;
    
    namespace GdalReadSHP
    {
        /// <summary>
        /// 定义SHP解析类
        /// </summary>
        public class ShpRead
        {
            /// 保存SHP属性字段
            public OSGeo.OGR.Driver oDerive;
            public List<string> m_FeildList;
            private Layer oLayer;
            public string sCoordiantes;
            public ShpRead()
            {
                m_FeildList = new List<string>();
                oLayer = null;
                sCoordiantes = null;
            }
    
            /// <summary>
            /// 初始化Gdal
            /// </summary>
            public void InitinalGdal()
            {
                // 为了支持中文路径
                Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
                // 为了使属性表字段支持中文
                Gdal.SetConfigOption("SHAPE_ENCODING", "");
                Gdal.AllRegister();
                Ogr.RegisterAll();
                
                oDerive = Ogr.GetDriverByName("ESRI Shapefile");
                if (oDerive == null)
                {
                    MessageBox.Show("文件不能打开,请检查");
                }
            }
    
            /// <summary>
            /// 获取SHP文件的层
            /// </summary>
            /// <param name="sfilename"></param>
            /// <param name="oLayer"></param>
            /// <returns></returns>
            public bool GetShpLayer(string sfilename)
            {
                if (null == sfilename || sfilename.Length <= 3)
                {
                    oLayer = null;
                    return false;
                }
                if (oDerive == null)
                {
                    MessageBox.Show("文件不能打开,请检查");
                }
                DataSource ds = oDerive.Open(sfilename, 1);
                if (null == ds)
                {
                    oLayer = null;
                    return false;
                }
                int iPosition = sfilename.LastIndexOf("\\");
                string sTempName = sfilename.Substring(iPosition + 1, sfilename.Length - iPosition - 4 - 1);
                oLayer = ds.GetLayerByName(sTempName);
                if (oLayer == null)
                {
                    ds.Dispose();
                    return false;
                }
                return true;
            }
            /// <summary>
            /// 获取所有的属性字段
            /// </summary>
            /// <returns></returns>
            public bool GetFeilds()
            {
                if (null == oLayer)
                {
                    return false;
                }
                m_FeildList.Clear();
                wkbGeometryType oTempGeometryType = oLayer.GetGeomType();
                List<string> TempstringList = new List<string>();
    
                //
                FeatureDefn oDefn = oLayer.GetLayerDefn();
                int iFieldCount = oDefn.GetFieldCount();
                for (int iAttr = 0; iAttr < iFieldCount; iAttr++)
                {
                    FieldDefn oField = oDefn.GetFieldDefn(iAttr);
                    if (null != oField)
                    {
                        m_FeildList.Add(oField.GetNameRef());
                    }
                }
                return true;
            }
            /// <summary>
            ///  获取某条数据的字段内容
            /// </summary>
            /// <param name="iIndex"></param>
            /// <param name="FeildStringList"></param>
            /// <returns></returns>
            public bool GetFeildContent(int iIndex, out List<string> FeildStringList)
            {
                FeildStringList = new List<string>();
                Feature oFeature = null;
                if ((oFeature = oLayer.GetFeature(iIndex)) != null)
                {
                    
                    FeatureDefn oDefn = oLayer.GetLayerDefn();
                    int iFieldCount = oDefn.GetFieldCount();
                    // 查找字段属性
                    for (int iAttr = 0; iAttr < iFieldCount; iAttr++)
                    {
                        FieldDefn oField = oDefn.GetFieldDefn(iAttr);
                        string sFeildName = oField.GetNameRef();
    
                        #region 获取属性字段
                        FieldType Ftype = oFeature.GetFieldType(sFeildName);
                        switch (Ftype)
                        {
                            case FieldType.OFTString:
                                string sFValue = oFeature.GetFieldAsString(sFeildName);
                                string sTempType = "string";
                                FeildStringList.Add(sFValue);
                                break;
                            case FieldType.OFTReal:
                                double dFValue = oFeature.GetFieldAsDouble(sFeildName);
                                sTempType = "float";
                                FeildStringList.Add(dFValue.ToString());
                                break;
                            case FieldType.OFTInteger:
                                int iFValue = oFeature.GetFieldAsInteger(sFeildName);
                                sTempType = "int";
                                FeildStringList.Add(iFValue.ToString());
                                break;
                            default:
                                //sFValue = oFeature.GetFieldAsString(ChosenFeildIndex[iFeildIndex]);
                                sTempType = "string";
                                break;
                        }
                        #endregion
                    }
                }
                return true;
            }
            /// <summary>
            /// 获取数据
            /// </summary>
            /// <returns></returns>
            public bool GetGeometry(int iIndex)
            {
                if (null == oLayer)
                {
                    return false;
                }
                int iFeatureCout = oLayer.GetFeatureCount(0);
                Feature oFeature = null;
                oFeature = oLayer.GetFeature(iIndex);
                //  Geometry
                Geometry oGeometry = oFeature.GetGeometryRef();
                wkbGeometryType oGeometryType = oGeometry.GetGeometryType();
                switch (oGeometryType)
                {
                    case wkbGeometryType.wkbPoint:
                        oGeometry.ExportToWkt(out sCoordiantes);
                        sCoordiantes = sCoordiantes.ToUpper().Replace("POINT (", "").Replace(")", "");
                        break;
                    case wkbGeometryType.wkbLineString:
                    case wkbGeometryType.wkbLinearRing:
                        oGeometry.ExportToWkt(out sCoordiantes);
                        sCoordiantes = sCoordiantes.ToUpper().Replace("LINESTRING (", "").Replace(")", "");
                        break;
                    default:
                        break;
                }
                return false;
            }
    
        }//END class
    }
    

    3. 在program.cs中调用。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    
    using System.Windows.Forms;
    
    using OSGeo.GDAL;
    using OSGeo.OGR;
    using OSGeo.OSR;
    using System.Collections;
    
    namespace GdalReadSHP
    {
        class Program
        {
            static void Main(string[] args)
            {   
                string sShpFileName = @"D:\VRMap6_Data\line92\RainMainPipe.shp";
                ShpRead m_Shp = new ShpRead();
                // 初始化GDAL和OGR
                m_Shp.InitinalGdal();
                // 
                m_Shp.GetShpLayer(sShpFileName);
                // 获取所有属性字段名称,存放在m_FeildList中
                m_Shp.GetFeilds();
                
                List<string> FeildStringList = null;
                m_Shp.GetFeildContent(0, out FeildStringList);
    
                // 获取某条FID的数据
                m_Shp.GetGeometry(0);
                MessageBox.Show(m_Shp.sCoordiantes);
            }
        }
    }
    


    一开始自己疏忽了,总是报错。最后才发现,自己没初始化GDAL和OGR,我类个去!!


    /// <summary>
            /// 初始化Gdal
            /// </summary>
            public void InitinalGdal()
            {
                // 为了支持中文路径
                Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
                // 为了使属性表字段支持中文
                Gdal.SetConfigOption("SHAPE_ENCODING", "");
                Gdal.AllRegister();
                Ogr.RegisterAll();
                
                oDerive = Ogr.GetDriverByName("ESRI Shapefile");
                if (oDerive == null)
                {
                    MessageBox.Show("文件不能打开,请检查");
                }
            }

    至于对SHP用C#写,目前咩有用到。

    说明:

    网上好多Gdal支持中文路径说需要:

    Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
    我试了一下,貌似用YES才行。

                // 为了支持中文路径
                Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");

    若中文名称的SHP文件,用GetLayerByName(stirng sName); 我测试是不行的。

    需要改为Layer oLayer = ds.GetLayerByIndex(0);

    展开全文
  • C#语言在VS上实现shp文件读取和显示的窗体程序
  • 学会用C#文件读取shp(shapefile格式)文件并在窗口绘制,内加入说明文档
  • 利用C#实现shp文件读取并在视图窗口中显示,显示类型包括点线面。
  • C# 读取 Shp文件 源码

    2020-07-04 23:30:36
    C# 读取 Shp 文件 并显示地图 源码有详细注释
  • c#读写shp文件

    2020-06-03 23:32:06
    shp文件是地理信息系统开发中的一种重要格式,本例是一个C#读写shp的典型案例
  • 读写shp文件的动态库,封装成dotnet,c#可直接调用,包含读写shp源码。
  • 下面会持续更新,下一篇帖代码,介绍读取.shp文件和生成.shp文件的方法。   Shape files数据说明   Shapefile文件是美国环境系统研究所(ESRI)所研制的GIS文件系统格式文件,是工业标准的矢量数据文件。 ...

    由于篇幅限制本篇就来单独介绍一下.shp文件的结构;下面会持续更新,下一篇帖代码,介绍读取.shp文件和生成.shp文件的方法。

     

    Shape files数据说明

     

    Shapefile文件是美国环境系统研究所(ESRI)所研制的GIS文件系统格式文件,是工业标准的矢量数据文件。 Shapefile将空间特征表中的非拓扑几何对象和属性信息存储在数据集中,特征表中的几何对象存为以坐标点集表示的图形文件—SHP文件,Shapefile文件并不含拓扑(Topological)数据结构。一个Shape文件包括三个文件:一个主文件(*.shp),一个索引文件(*.shx),和一个dBASE(*.dbf)表。主文件是一个直接存取,变长度记录的文件,其中每个记录描述构成一个地理特征(Feature)的所有vertices坐标值。在索引文件中,每条记录包含对应主文件记录距离主文件头开始的偏移量,dBASE表包含SHP文件中每一个Feature的特征属性,表中几何记录和属性数据之间的一一对应关系是基于记录数目的ID。在dBASE文件中的属性记录必须和主文件中的记录顺序是相同的。图形数据和属性数据通过索引号建立一一对应的关系。

     

    1.        坐标文件的结构说明

    坐标文件(.shp)用于记录空间坐标信息。它由头文件和实体信息两部分构成。

    1)     坐标文件的文件头

    坐标文件的文件头是一个长度固定(100 bytes)的记录段,一共有9个int型和7个double型数据。

    坐标文件的结构:

    文件头

    记录头

    记录内容

    记录头

    记录内容

    记录头

    记录内容

    记录头

    记录内容

    ……

    ……

    记录头

    记录内容


    shapefiles 头文件表:

     

    起始位置

    名称

    数值

    类型

    位序

    0

    File Code

    9994

    Integer

    big

    4

    Unused

    0

    Integer

    big

    8

    Unused

    0

    Integer

    big

    12

    Unused

    0

    Integer

    big

    16

    Unused

    0

    Integer

    big

    20

    Unused

    0

    Integer

    big

    24

    文件长度

    文件的实际长度

    Integer

    big

    28

    版本号

    1000

    Integer

    Little

    32

    几何类型

    表示这个Shapefile文件所记录的空间数据的几何类型

    Integer

    Little

    36

    Xmin

    空间数据所占空间范围的X方向最小值

    Double

    Little

    44

    Ymin

    空间数据所占空间范围的Y方向最小值

    Double

    Little

    52

    Xmax

    空间数据所占空间范围的X方向最大值

    Double

    Little

    60

    Ymax

    空间数据所占空间范围的Y方向最大值

    Double

    Little

    68*

    Zmin

    空间数据所占空间范围的Z方向最小值

    Double

    Little

    76*

    Zmax

    空间数据所占空间范围的Z方向最大值

    Double

    Little

    84*

    Mmin

    最小Measure值

    Double

    Little

    92*

    Mmax

    最大Measure值

    Double

    Little

     

    (2)    Shapefile文件支持的几何类型(ShapeType)

    Shapefile文件所支持的几何类型:

    编号

    几何类型

    0

    Null Shape(表示这个Shapefile文件不含坐标)

    1

    Point(表示Shapefile文件记录的是点状目标,但不是多点)

    3

    PolyLine(表示Shapefile文件记录的是线状目标)

    5

    Polygon(表示Shapefile文件记录的是面状目标)

    8

    MultiPoint(表示Shapefile文件记录的是多点,即点集合)

    11

    PointZ(表示Shapefile文件记录的是三维点状目标)

    13

    PolyLineZ(表示Shapefile文件记录的是三维线状目标)

    15

    PolygonZ(表示Shapefile文件记录的是三维面状目标)

    18

    MultiPointZ(表示Shapefile文件记录的是三维点集合目标)

    21

    PointM(表示含有Measure值的点状目标)

    23

    PolyLineM(表示含有Measure值的线状目标)

    25

    PolygonM(表示含有Measure值的面状目标)

    28

    MultiPointM(表示含有Measure值的多点目标)

    31

    MultiPatch(表示复合目标)

    2)      实体信息的内容

    实体信息负责记录坐标信息,它以记录段为基本单位,每一个记录段记录一个地理实体目标的坐标信息,每个记录段分为记录头和记录内容两部分。

    记录头的内容包括记录号(Record Number)和坐标记录长度(Content Length) 两个记录项。它们的位序都是big。记录号(Record Number)和坐标记录长度(Content Length) 两个记录项都是int型,并且shapefile文件中的记录号都是从1开始的。

    记录内容包括目标的几何类型(ShapeType)和具体的坐标记录(X、Y) ,记录内容因要素几何类型的不同其具体的内容及格式都有所不同。下面分别介绍点状目标(Point)、线状目标(PolyLine)和面状目标(Polygon)三种几何类型的.shp文件的记录内容:

    (1)    点状目标

    shapefile中的点状目标由一对X、Y坐标构成,坐标值为双精度型(double)。点状目标的记录内容如表2.4:

    记录项

    数值

    数据类型

    长度

    个数

    位序

    几何类型(ShapeType)

    1(表示点状目标)

    int型

    4

    1

    Little

    X方向坐标

    X方向坐标值

    double型

    8

    1

    Little

    Y方向坐标

    Y方向坐标值

    double型

    8

    1

    Little

    (2)    线状目标

    shapefile中的线状目标是由一系列点坐标串构成,一个线目标可能包括多个子线段,子线段之间可以是相离的,同时子线段之间也可以相交。Shapefile允许出现多个坐标完全相同的连续点,当读取文件时一定要注意这种情况,但是不允许出现某个退化的、长度为0的子线段出现。线状目标的记录内容:

    记录项

    数值

    数据类型

    长度

    个数

    位序

    几何类型(ShapeType)

    3(表示线状目标)

    int型

    4

    1

    Little

    坐标范围(Box)

    表示当前线目标的坐标范围

    double型

    32

    4

    Little

    子线段个数(NumParts)

    表示构成当前线目标的子线段的个数

    int型

    4

    1

    Little

    坐标点数(NumPoints)

    表示构成当前线目标所包含的坐标点个数

    int型

    4

    1

    Little

    Parts数组

    记录了每个子线段的坐标在Points数组中的起始位置

    int型

    4×NumParts

    NumParts

    Little

    Points数组

    记录了所有的坐标信息

    Point型

    根据点个数来确定

    NumPoints

    Little

     

    (3)    面状目标

     

    shapefile中 的面状目标是由多个子环构成,每个子环是由至少四个顶点构成的封闭的、无自相交现象的环。对于含有岛的多边形,构成它的环有内外环之分,每个环的顶点的排列顺序或者方向说明了这个环到底是内环还是外环。一个内环的顶点是按照逆时针顺序排列的;而对于外环,它的顶点排列顺序是顺时针方向。如果一个多边形只由 一个环构成,那么它的顶点排列顺序肯定是顺时针方向。

    每条多边形记录的数据结构与线目标的数据结构完全相同,

    Polygon

    {

    Double[4]             Box              // 当前面状目标的坐标范围

    Integer                 NumParts     // 当前面目标所包含的子环的个数

    Integer                 NumPoints   // 构成当前面状目标的所有顶点的个数

    Integer[NumParts]   Parts             // 每个子环的第一个坐标点在Points的位置

    Point[NumPoints]    Points            // 记录所有坐标点的数组

    }

    对于一个shapefile中的多边形,它必须满足下面三个条件:

    l        构成多边形的每个子环都必须是闭合的,即每个子环的第一个顶点跟最后一个顶点是同一个点;

    l        每个子环在Points数组中的排列顺序并不重要,但每个子环的顶点必须按照一定的顺序连续排列;

    l        存储在shapefile 中的多边形必须是干净的。所谓一个干净的多边形,它必须满足两点:

    ¨       没有自相交现象。这就要求任何一个子环不能跟其它的子环相交,共线的现  象也将被当作相交。但是允许两个子环的顶点重合;

    ¨       对于一个不含岛的多边形或者是含岛的多边形的外环,它们的顶点排列顺序必须是顺时针方向;而对于内环,它的排列顺序必须是逆时针方向。所谓的“脏多边形”就是指顶点排列顺序为顺时针的内环。

    面状目标的记录内容:

    记录项

    数值

    数据类型

    长度

    个数

    位序

    几何类型(ShapeType)

    5(表示面状目标)

    int型

    4

    1

    Little

    坐标范围(Box)

    表示当前面目标的坐标范围

    double型

    32

    4

    Little

    子线段个数(NumParts)

    表示构成当前面状目标的子环的个数

    int型

    4

    1

    Little

    坐标点数(NumPoints)

    表示构成当前面状目标所包含的坐标点个数

    int型

    4

    1

    Little

    Parts数组

    记录了每个子环的坐标在Points数组中的起始位置

    int型

    4×NumParts

    NumParts

    Little

    2.        属性文件的结构说明

    属性文件(.dbf)用于记录属性信息。它是一个标准的DBF文件,也是由头文件和实体信息两部分构成。

    文件头

    记录1

     

    记录2

     

    记录3

     

    记录4

     

    ……

    ……

    记录n

    1)     属性文件的文件头

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

    属性文件(.dbf)的文件头:

    在文件中的位置

    内容

    说明

    0

    1个字节

    表示当前的版本信息

    1-3

    3个字节

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

    4-7

    1个32位数

    文件中的记录条数。

    8-9

    1个16位数

    文件头中的字节数。

    10-11

    1个16位数

    一条记录中的字节长度。

    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来填写。

    32-X

    (n*32)个字节

    记录项信息描述数组。n表示记录项的个数。这个数组的结构在表2.8中有详细的解释。

    X+1

    1个字节

    作为记录项终止标识。

    记录项信息描述:

     

    位置

    内容

    说明

    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 格式的索引文件,那么这个记录项为真,否则为空。

    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)

    各种字符。

     

    2)      属性文件的实体信息

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

    3.        索引文件的结构说明

    索引文件(.shx)主要包含坐标文件的索引信息,文件中每个记录包含对应的坐标文件记录距离坐标文件的文件头的偏移量。通过索引文件可以很方便地在坐标文件中定位到指定目标的坐标信息。

    索引文件也是由头文件和实体信息两部分构成(如图2.5),其中文件头部分是一个长度固定(100 bytes)的记录段,其内容与坐标文件的文件头基本一致。它的实体信息以记录为基本单位,每一条记录包括偏移量(offset)和记录段长度(Content Length)两个记录项,它们的位序都是big,两个记录项都是int型。

    索引文件的结构:

    文件头

    记录1

     

    记录2

     

    记录3

     

    记录4

     

    ……

    ……

    记录n

    索引文件的记录内容:

     

     

     

    记录项

    数值

    数据类型

    长度

    个数

    位序

    位移量(Offset)

    表示坐标文件中的对应记录的起始位置相对于坐标文件起始位置的位移量。

    int型

    4

    1

    Big

    记录长度

    (Content Length)

    表示坐标文件中的对应记录的长度。

    int型

    4

    1

    Big

     

    微信关注  奔跑的GISer  获取更多资源

    展开全文
  • 用上一篇里面 C#不用ArcEngine,生成Shp文件(二) 读取到的.shp文件信息,生成一个一样的.shp文件。测试数据下载地址为:http://download.csdn.net/detail/gis0911178/9650967 读取到的信息如下:   -------------...

    用上一篇里面 C#不用ArcEngine,生成Shp文件(二)  读取到的.shp文件信息,生成一个一样的.shp文件。测试数据下载地址为:http://download.csdn.net/detail/gis0911178/9650967

    读取到的信息如下:

     

    --------------------------------------------------------------------------------

    文件长度:110
    Xmin:120.062485706624
    Ymin:27.752624080108
    Xmax:120.102341678472
    Ymax:27.7716597681547
    文件记录号为:1
    坐标长度为:56
    几何类型:5
    Box[0]:120.062485706624
    Box[1]:27.752624080108
    Box[2]:120.102341678472
    Box[3]:27.7716597681547
    子面个数:1
    坐标点个数:4
    每个子环在坐标点内的起始位置:
    parts[0]:0
    Points数组:
    Points[0]:120.062485706624 27.7618444915056
    Points[1]:120.102341678472 27.7716597681547
    Points[2]:120.081521394671 27.752624080108
    Points[3]:120.062485706624 27.7618444915056

    ------------------------------------------------------------------------------------------------------

    按照以上信息,生成.shp文件的代码(代码下载地址http://download.csdn.net/detail/gis0911178/9598945):

    string path = @shpFullNameDir;
                    if (!File.Exists(path))
                    {
                        using (FileStream fs = new FileStream(path, FileMode.Create,FileAccess.Write))
                        {
                            //byte[] data = new UTF8Encoding().GetBytes("abcdefg");
                            //fs.Write(data, 0, data.Length);
                            //写入FileCode
                            int fileCode = ChangeByteOrder(9994);
                            byte[] fc = System.BitConverter.GetBytes(fileCode);
                            fs.Seek(0,SeekOrigin.Begin);
                            fs.Write(fc,0,fc.Length);
                            //写入文件长度
                            int fileLength = ChangeByteOrder(110);
                            byte[] fl = System.BitConverter.GetBytes(fileLength);
                            fs.Seek(24, SeekOrigin.Begin);
                            fs.Write(fl, 0, fl.Length);
                            //写入版本号
                            int versionNumber = 1000;
                            byte[] vn = System.BitConverter.GetBytes(versionNumber);
                            fs.Seek(28, SeekOrigin.Begin);
                            fs.Write(vn, 0, vn.Length);
                            //写入文件类型
                            int fileType = 5;
                            byte[] ft = System.BitConverter.GetBytes(fileType); ;
                            fs.Seek(32, SeekOrigin.Begin);
                            fs.Write(ft, 0, ft.Length);
                            //写入Extent范围
                            double xMin = 120.062485706624;
                            byte[] xin = System.BitConverter.GetBytes(xMin);
                            fs.Seek(36, SeekOrigin.Begin);
                            fs.Write(xin, 0, xin.Length);
                            double yMin = 27.752624080108;
                            byte[] yin = System.BitConverter.GetBytes(yMin);
                            fs.Seek(44, SeekOrigin.Begin);
                            fs.Write(yin, 0, yin.Length);
                            double xMax = 120.102341678472;
                            byte[] xax = System.BitConverter.GetBytes(xMax);
                            fs.Seek(52, SeekOrigin.Begin);
                            fs.Write(xax, 0, xax.Length);
                            double yMax = 27.7716597681547;
                            byte[] yax = System.BitConverter.GetBytes(yMax);
                            fs.Seek(60, SeekOrigin.Begin);
                            fs.Write(yax, 0, yax.Length);

                            int currentByte = 100;//从101位开始写入实体内容
                            //文件记录号
                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] fn1 = System.BitConverter.GetBytes(ChangeByteOrder(1));
                            fs.Write(fn1,0,fn1.Length);
                            currentByte += 4;
                            //坐标长度
                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] fn1_length = System.BitConverter.GetBytes(ChangeByteOrder(56));
                            fs.Write(fn1_length,0,fn1_length.Length);
                            currentByte += 4;
                            //几何类型
                            fs.Seek(currentByte, SeekOrigin.Begin);
                            fs.Write(ft, 0, ft.Length);
                            currentByte += 4;
                            //坐标范围
                            fs.Seek(currentByte, SeekOrigin.Begin);
                            double Box1 = 120.062485706624;
                            byte[] b1 = System.BitConverter.GetBytes(Box1);
                            fs.Write(b1, 0, b1.Length);
                            currentByte += 8;

                            fs.Seek(currentByte, SeekOrigin.Begin);
                            double Box2 = 27.752624080108;
                            byte[] b2 = System.BitConverter.GetBytes(Box2);
                            fs.Write(b2, 0, b2.Length);
                            currentByte += 8;

                            fs.Seek(currentByte, SeekOrigin.Begin);
                            double Box3 = 120.102341678472;
                            byte[] b3 = System.BitConverter.GetBytes(Box3);
                            fs.Write(b3, 0, b3.Length);
                            currentByte += 8;

                            fs.Seek(currentByte, SeekOrigin.Begin);
                            double Box4 = 27.7716597681547;
                            byte[] b4 = System.BitConverter.GetBytes(Box4);
                            fs.Write(b4, 0, b4.Length);
                            currentByte += 8;
                            //子面个数
                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] zm = System.BitConverter.GetBytes(1);
                            fs.Write(zm, 0, zm.Length);
                            currentByte += 4;
                            //坐标点数
                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] zb = System.BitConverter.GetBytes(4);
                            fs.Write(zb, 0, zb.Length);
                            currentByte += 4;
                            //每个子面在坐标数组内的起始位置
                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] p1 = System.BitConverter.GetBytes(0);
                            fs.Write(p1, 0, p1.Length);
                            currentByte += 4;
                            //写入坐标数组,本例只有三个点,首尾重合 写入四个点
                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] zz1 = System.BitConverter.GetBytes(120.062485706624);
                            fs.Write(zz1, 0, zz1.Length);
                            currentByte += 8;

                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] zz2 = System.BitConverter.GetBytes(27.7618444915056);
                            fs.Write(zz2, 0, zz2.Length);
                            currentByte += 8;

                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] zz3 = System.BitConverter.GetBytes(120.102341678472);
                            fs.Write(zz3, 0, zz3.Length);
                            currentByte += 8;

                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] zz4 = System.BitConverter.GetBytes(27.7716597681547);
                            fs.Write(zz4, 0, zz4.Length);
                            currentByte += 8;

                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] zz5 = System.BitConverter.GetBytes(120.081521394671);
                            fs.Write(zz5, 0, zz5.Length);
                            currentByte += 8;

                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] zz6 = System.BitConverter.GetBytes(27.752624080108);
                            fs.Write(zz6, 0, zz6.Length);
                            currentByte += 8;
                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] zz7 = System.BitConverter.GetBytes(120.062485706624);
                            fs.Write(zz7, 0, zz7.Length);
                            currentByte += 8;
                            fs.Seek(currentByte, SeekOrigin.Begin);
                            byte[] zz8 = System.BitConverter.GetBytes(27.7618444915056);
                            fs.Write(zz8, 0, zz8.Length);
                            currentByte += 8;


                            //清空缓冲区、关闭流
                            fs.Flush();
                            fs.Close();
                        }
                    }

    在写入的时候,同样要注意位序转换,位序转换函数ChangeByteOrder()在第二篇有。现在只是生成了.shp文件。         

    dbf文件还在学习中........

     

    微信关注  奔跑的GISer  获取更多资源

    展开全文
  •     //转换位字节 大小位转换  private int ChangeByteOrder(int indata)  {  byte[] src = new byte[4];  src[0] = (byte)((indata &gt;&gt; 24) &amp; 0xFF);... src[1] ...

     

     

     

    //转换位字节 大小位转换
            private int ChangeByteOrder(int indata)
            {
                byte[] src = new byte[4];
                src[0] = (byte)((indata >> 24) & 0xFF);
                src[1] = (byte)((indata >> 16) & 0xFF);
                src[2] = (byte)((indata >> 8) & 0xFF);
                src[3] = (byte)(indata & 0xFF);


                int value;
                value = (int)((src[0] & 0xFF) | ((src[1] & 0xFF) << 8) | ((src[2] & 0xFF) << 16) | ((src[3] & 0xFF) << 24));
                return value;
            }
            int ShapeType;//shp文件类型,点1 线3 面5


            double[] fileBox = new double[4];


            string[] nameArr = { "name1镇", "name2镇", "name3镇"};
            List<int> partsArr = new List<int>();//多部分的
            List<double> coorsArr = new List<double>();//坐标

     

     

     

            StringBuilder sb = new StringBuilder("[");

    private void read()
            {
                fileBox[0] = double.MaxValue;
                fileBox[1] = double.MaxValue;
                fileBox[2] = double.MinValue;
                fileBox[3] = double.MinValue;


                //sb.Append("\r\n");
                //sb.Append("]");


                //writeTxt(sb.ToString());
                //return;


                string shpfilepath = @"F:\test\shp\test.shp";
                FileStream fs = new FileStream(shpfilepath, FileMode.Open, FileAccess.Read);
                BinaryReader br = new BinaryReader(fs);
                //Console.WriteLine("开始读取面文件...");
                //读取文件过程
                br.ReadBytes(24);
                int FileLength = br.ReadInt32();
                //Console.WriteLine("文件长度:" + ChangeByteOrder(FileLength));
                int FileBanben = br.ReadInt32();
                //Console.WriteLine("版本号:" + FileBanben);
                ShapeType = br.ReadInt32();
                //Console.WriteLine("几何类型:" + ShapeType);
                fileBox[0] = br.ReadDouble();
                //Console.WriteLine("空间数据所占空间范围的X方向最小值:" + fileBox[0]);
                fileBox[1] = br.ReadDouble();
                //Console.WriteLine("空间数据所占空间范围的Y方向最小值:" + fileBox[1]);
                fileBox[2] = br.ReadDouble();
                //Console.WriteLine("空间数据所占空间范围的X方向最大值:" + fileBox[2]);
                fileBox[3] = br.ReadDouble();
                //Console.WriteLine("空间数据所占空间范围的Y方向最大值:" + fileBox[3]);
                br.ReadBytes(32);
                switch (ShapeType)
                {
                    case 5:
                        while (br.PeekChar() != -1)
                        {
                            uint RecordNum = br.ReadUInt32();
                            int index = ChangeByteOrder((int)RecordNum);
                            //Console.WriteLine("文件记录号为:" + index);
                            int DataLength = br.ReadInt32();
                            //Console.WriteLine("坐标长度为:" + ChangeByteOrder(DataLength));


                            //读取第i个记录
                            int m = br.ReadInt32();
                            //Console.WriteLine("几何类型:" + m);
                            for (int i = 0; i < 4; i++)
                            {
                                br.ReadDouble();
                                //Console.WriteLine("Box[" + i + "]:" + br.ReadDouble());
                            }


                            int numParts = br.ReadInt32();
                            //Console.WriteLine("子面个数:" + numParts);
                            int numPoints = br.ReadInt32();
                            //Console.WriteLine("坐标点个数:" + numPoints);


                            //Console.WriteLine("每个子环在坐标点内的起始位置:");
                            for (int j = 0; j < numParts; j++)
                            {
                                int parts = new int();
                                parts = br.ReadInt32();
                                partsArr.Add(parts);
                                //Console.WriteLine("parts[" + j + "]:" + parts);
                            }


                            //Console.WriteLine("Points数组:");
                            for (int j = 0; j < numPoints; j++)
                            {
                                double X = br.ReadDouble();
                                double Y = br.ReadDouble();
                                coorsArr.Add(X);
                                coorsArr.Add(Y);
                                //Console.WriteLine("Points[" + j + "]:" + X + " " + Y);
                                //Console.Write("{\"X\":" + X + ",\"Y\":" + Y + "},");
                            }
                            for (int i=0;i<partsArr.Count;i++)
                            {
                                sb.Append("\r\n{");
                                sb.Append("\"Name\":\""+nameArr[index-1]+"\",\r\n");
                                sb.Append("\"Value\":0,\r\n");
                                sb.Append("\"PointCollection\":\r\n[");
                                int startIndex = partsArr[i];
                                startIndex = startIndex * 2;
                                int endIndex = partsArr[partsArr.Count-1];
                                string coorJson = "";
                                if (i== partsArr.Count - 1)//最后一个走这里
                                {
                                    while (startIndex < coorsArr.Count)
                                    {
                                        coorJson += "{\"X\":" + coorsArr[startIndex++] + ",\"Y\":" + coorsArr[startIndex++] + "},";
                                        //sb.Append();
                                    }
                                }
                                else {
                                    while (startIndex< partsArr[i+1]*2)
                                    {
                                        coorJson += "{\"X\":" + coorsArr[startIndex++] + ",\"Y\":" + coorsArr[startIndex++] + "},";
                                        //sb.Append();
                                    }
                                }
                                coorJson = coorJson.Substring(0,coorJson.Length-1);
                                sb.Append(coorJson);
                                sb.Append("]\r\n},\r\n");
                                //string jstring = "";
                                //jstring += "\r\n{";
                                //jstring += "\"Name\":\"" + nameArr[index] + "\",\r\n";
                                //jstring += "\"Value\":0,\r\n";
                                //jstring += "\"PointCollection\":\r\n[";


                            }


                            partsArr.Clear();
                            coorsArr.Clear();


                            //Console.WriteLine();
                            //Console.WriteLine("--------------------------");


                        }
                        break;
                    default:
                        Console.WriteLine("shp文件必须为面类型,且不带Z、M值");
                        break;




                }
                sb.Append("]");
                writeTxt(sb.ToString());
                fs.Flush();
                fs.Close();
            }


            private bool writeTxt(string s)
            {
                try {
                    FileStream fs = new FileStream("C:\\json.txt",FileMode.Create);
                    byte[] data = System.Text.Encoding.Default.GetBytes(s);
                    fs.Write(data,0,data.Length);
                    fs.Flush();
                    fs.Close();
                    return true;
                }
                catch  {
                    return false;
                }
            }

     

    以上是读取shp面图层转换成json字符串的代码。读取点和线文件类似。参照我之前的博客( C#不用ArcEngine生成shp文件 ) ,把代码改成点或者面的,就可以了

     

    微信关注  奔跑的GISer  获取更多资源

    展开全文
  • 加载Shp文件到地图控件MapControl有一般有两种方式。 1、用MapControl控件的AddShapeFile方法可加载Shape格式文件,调用该方法需要传入两个参数,分别是文件路径和不带扩展名的文件名,其调用方法如下: ...
  • 首先要装一个驱动 VFPODBC.msi ,没有就在网上搜一个,下载并安装读取代码如下using (var oleconn = new OdbcConnection(connStr)) { oleconn.Open(); //打开shp dbf连接 var sql = @"select * from " + dbf文件...
  • SHP文件读写源代码

    2020-06-10 15:22:04
    利用C#编写的SHP文件读写源代码,在VS2005下测试通过
  • C#合并shp文件

    2018-10-24 18:48:27
    shp shape文件由ESRI开发,一个ESRI(Environmental Systems Research Institute)的shape...常用于地图绘制,此处用c#来写一个shp合并程序 窗体设计 Program.cs using System; using System.Collections.Gene...
  • 在VS中新建一个windows窗体结构,如何实现将两个Shp文件合并成一个Shp文件???
1 2 3 4 5 ... 20
收藏数 756
精华内容 302