1. 程式人生 > >C#不用ArcEngine,生成Shp檔案(二)---------讀取.shp檔案格式

C#不用ArcEngine,生成Shp檔案(二)---------讀取.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;
    }