首页 > 代码库 > shp地图解析(不用AE)

shp地图解析(不用AE)

AE太重型,还收费,如果只是加载地图作为底图,可以用纯C#实现。

总体架构

文件头
记录头记录内容
记录头记录内容
。。。。。。。。。。。。
记录头记录内容

文件头

位置类型字段说明
Byte 0intFile Code文件代码
Byte 4int无用 
Byte 8int无用 
Byte 12int无用 
Byte 16int无用 
Byte 20int无用 
Byte 24intFile Length文件长度
Byte 28intVersion版本
Byte 32intShape Type图形类型1:Point,点类型3:PolyLine,线类型5:Polygon,面类型
Byte 36doubleXmin整图的X轴坐标最小值
Byte 44doubleYmin整图的Y轴坐标最小值
Byte 52doubleXmax整图的X轴坐标最大值
Byte 60doubleYmax整图的Y轴坐标最大值
Byte 68*doubleZmin 
Byte 76*doubleZmax 
Byte 84*doubleMmin 
Byte 92*doubleMmax 

 

记录头

位置类型字段说明
Byte 0intRecord Number记录号,从1开始
Byte 4intContent Length内容长度,内容的16位字数,不包括记录号。

 

记录内容

位置类型字段说明
Byte 0intShapeTypeShape类型
Byte 4double [4]Box该线条的边界盒,以Xmin,Ymin,Xmax,Ymax的顺序存储
Byte 36intNumParts是PolyLine中部分的数目
Byte 40intNumPoints是PolyLine中的数目
Byte 44int [NumParts]Parts每条PolyLine存储它在点数列中的第一个点的索引。数列索引是从0开始的。Parts[NumParts]数组是Points[NumPoints]数组的目录
XPoint[NumPoints]Points本条记录的所有点。Struct Point {Double  X;Double  Y;}

PartsPoints之间的关系:

如果Parts [0]=0Parts [1]=3Parts [2]=11Parts [3]=15那么

第0条线:(Points[0], Points[1] , Points[2])三个点依次连结

第1条线:(Points[3], Points[4] , Points[5] , Points[6] , Points[7] , Points[8] , Points[9] , Points[10])这几个点依次连结

第3条线:(Points[11], Points[12] , Points[13] , Points[14])三个点依次连结

 

ClassShp类:

using System;using System.Collections;using System.Collections.Generic;using System.Linq;using System.Text;using System.Drawing;using System.IO;namespace SDD{struct StructShapePoint    {        public double X;        public double Y;    }    struct StructShapePolyline    {        public int RecordNumber;//记录号        public int ContentLength;//内容长度        public int ShapeType;        public double[] Box;//长度为4        public int PartsCount;        public int PointsCount;        public List<int> Parts;//在部分中第一个点的索引        public List<StructShapePoint> Points;//所有部分的点        public List<StructShapePoint[]> Lines;//把点按线组织好    }    class ClassShp    {        public string FileName;        public int FileLength;        public int FileVersion;        public int ShapeType;//绘图类型:1-点,3-线,5-面        public double Xmin, Ymin, Xmax, Ymax;//地图边界尺寸        public double RawWidth, RawHeight;//地图大小,原始值        public double RawCenterX, RawCenterY;//shp原始坐标系的中心点        public List<StructShapePoint> ListPoints = new List<StructShapePoint>();//点集合        public List<StructShapePolyline> ListPolylines = new List<StructShapePolyline>();//线集合        public double Scale = 0;//放大倍数,原始数据中1表示的像素数        public double CenterX, CenterY;//地图缩放后的中心点在控件坐标系中的位置        public double WindowWidth;//显示控件大小        public double WindowHeight;        public Bitmap Bmp = null;//用于显示的画布,大小等于显示控件        public Pen ThePen = new Pen(Color.White, 1);        public ClassShp()        { }        public ClassShp(string pmtShpPathName, double pmtVisibleWidth, double pmtVisibleHeight)        {            if (File.Exists(pmtShpPathName) == false) return;            if (Init(pmtShpPathName, pmtVisibleWidth, pmtVisibleHeight))            {                SaveAsTxt(); //把数据保存成文本文档            }        }        //################################################################################        // 由Xmin等四个值计算出基本成员参数        //################################################################################        public void SetBaseParameter(double pmtXmin,double pmtYmin,double pmtXmax,double pmtYmax)        {            Xmin = pmtXmin;            Ymin = pmtYmin;            Xmax = pmtXmax;            Ymax = pmtYmax;            RawWidth = Xmax - Xmin;            RawHeight = Ymax - Ymin;            RawCenterX = (Xmin + Xmax) / 2;            RawCenterY = (Ymin + Ymax) / 2;            CenterX = WindowWidth / 2;            CenterY = WindowHeight / 2;            SetRelativityScale(1, WindowWidth, WindowHeight);            Console.WriteLine("绘图类型:{0}", ShapeType);            Console.WriteLine("地图边界:({0}, {1}), ({2}, {3})", Xmin, Ymin, Xmax, Ymax);            Console.WriteLine("地图大小:{0} * {1}", RawWidth, RawHeight);            Console.WriteLine("地图中心:({0}, {1})", RawCenterX, RawCenterY);        }        //################################################################################        // 初始化        //################################################################################        public bool Init(string pmtShpPathName, double pmtVisibleWidth, double pmtVisibleHeight)        {            if (File.Exists(pmtShpPathName) == false) return false;            int nameIndex = pmtShpPathName.LastIndexOf("\\")+1;            int nameLenght = pmtShpPathName.Length-5-pmtShpPathName.LastIndexOf("\\");            FileName = pmtShpPathName.Substring(nameIndex, nameLenght);            WindowWidth = pmtVisibleWidth;            WindowHeight = pmtVisibleHeight;            try            {                FileStream fs = new FileStream(pmtShpPathName, FileMode.Open);                BinaryReader br = new BinaryReader(fs, Encoding.Default);                br.ReadBytes(24);                FileLength = br.ReadInt32();                FileVersion = br.ReadInt32();                ShapeType = br.ReadInt32();                Xmin = br.ReadDouble();                Ymin = br.ReadDouble();                Xmax = br.ReadDouble();                Ymax = br.ReadDouble();                                br.ReadBytes(32);                if (ShapeType == 1)                {                    ListPoints.Clear();                    while (br.PeekChar() != -1)                    {                        StructShapePoint shapePoint = new StructShapePoint();                        uint recordNum = br.ReadUInt32();                        int dataLength = br.ReadInt32();                        br.ReadInt32();                        shapePoint.X = br.ReadDouble();                        shapePoint.Y = br.ReadDouble();                        ListPoints.Add(shapePoint);                    }                }//end of : if (ShpType==1)                else if (ShapeType == 3 || ShapeType == 5)                {                    ListPolylines.Clear();                    while (br.PeekChar() != -1)                    {                        StructShapePolyline shapePolyline = new StructShapePolyline();                        shapePolyline.Box = new double[4];                        shapePolyline.Parts = new List<int>();                        shapePolyline.Points = new List<StructShapePoint>();                        shapePolyline.Lines = new List<StructShapePoint[]>();                        shapePolyline.RecordNumber = br.ReadInt32();                        shapePolyline.ContentLength = br.ReadInt32();                        shapePolyline.ShapeType = br.ReadInt32();                        shapePolyline.Box[0] = br.ReadDouble();                        shapePolyline.Box[1] = br.ReadDouble();                        shapePolyline.Box[2] = br.ReadDouble();                        shapePolyline.Box[3] = br.ReadDouble();                        shapePolyline.PartsCount = br.ReadInt32();                        shapePolyline.PointsCount = br.ReadInt32();                        //把每一段线的开始点偏移读进Parts队列                        for (int i = 0; i < shapePolyline.PartsCount; i++)                        {                            int tmpPart = br.ReadInt32();                            shapePolyline.Parts.Add(tmpPart);                        }                        //把所有点读进Points队列                        for (int i = 0; i < shapePolyline.PointsCount; i++)                        {                            StructShapePoint tmpPoint = new StructShapePoint();                            tmpPoint.X = br.ReadDouble();                            tmpPoint.Y = br.ReadDouble();                            shapePolyline.Points.Add(tmpPoint);                        }                        //把该线的点读进Lines队列                        for (int i = 0; i < shapePolyline.PartsCount; i++)                        {                            int startpoint;                            int endpoint;                            if (i == shapePolyline.PartsCount - 1)                            {                                startpoint = (int)shapePolyline.Parts[i];                                endpoint = shapePolyline.PointsCount;                            }                            else                            {                                startpoint = (int)shapePolyline.Parts[i];                                endpoint = (int)shapePolyline.Parts[i + 1];                            }                            StructShapePoint[] shpPointArray = new StructShapePoint[endpoint - startpoint];                            for (int j = 0, k = startpoint; k < endpoint; j++, k++)                            {                                shpPointArray[j].X = shapePolyline.Points[k].X;                                shpPointArray[j].Y = shapePolyline.Points[k].Y;                            }                            shapePolyline.Lines.Add(shpPointArray);                        }                        //把该线条加进m_polylines队列                        ListPolylines.Add(shapePolyline);                    }                }//end of : else if (ShpType == 3)                SetBaseParameter(Xmin, Ymin, Xmax, Ymax);                return true;            }            catch (System.Exception ex)            {                Console.WriteLine("异常:ClassShp.Init()" + ex.ToString());                return false;            }        }        //################################################################################        // 把数据写成txt文本        //################################################################################        public void SaveAsTxt()        {            StreamWriter swLine = new StreamWriter(FileName+".txt");            swLine.WriteLine("绘图类型:{0}", ShapeType);            swLine.WriteLine("地图边界:({0}, {1}), ({2}, {3})", Xmin, Ymin, Xmax, Ymax);            swLine.WriteLine("地图大小:{0} * {1}", RawWidth, RawHeight);            swLine.WriteLine("地图中心:({0}, {1})", RawCenterX, RawCenterY);            int recordCount = 0;            if (ShapeType==1)            {                foreach (StructShapePoint p in ListPoints)                {                    swLine.WriteLine("点{0}:    ({1},    {2})", recordCount, p.X, p.Y);                    recordCount++;                }            }            else if (ShapeType==3 || ShapeType==5)            {                foreach (StructShapePolyline p in ListPolylines)                {                    for (int i = 0; i < p.Lines.Count; i++)                    {                        swLine.WriteLine("记录内容{0}:########################################################", recordCount, i);                        for (int j = 0; j < p.Lines[i].Length; j++)                        {                            StructShapePoint ps = p.Lines[i][j];                            swLine.WriteLine("线{0}:    ({1},    {2})", j, ps.X, ps.Y);                        }                    }                    recordCount++;                }//end of :foreach            }                        swLine.Close();        }        //################################################################################        // 把图绘进Bmp中        //################################################################################        public bool DrawBmp(int pmtWidth, int pmtHeight)        {            double screenWidth = RawWidth * Scale;            double screenHeight = RawHeight * Scale;            try            {                Bmp = new Bitmap(pmtWidth, pmtHeight);//创建画布                Graphics g = Graphics.FromImage(Bmp);                g.TranslateTransform((float)0, (float)pmtHeight);//变换坐标系,把左下角置为原点                g.ScaleTransform((float)1, (float)-1);                                if (ShapeType == 1) //点类型                {                    foreach (StructShapePoint p in ListPoints)                    {                        PointF pf = new PointF();                        double offsetX = CenterX - screenWidth / 2.0;                        double offsetY = CenterY - screenHeight / 2.0;                        pf.X = (float)((p.X - Xmin) * Scale + offsetX);                        pf.Y = (float)((p.Y - Ymin) * Scale + offsetY);                        float r = 3;                        //g.DrawEllipse(ThePen, pf.X - r / 2, pf.Y + r / 2, r * 2, r * 2);//画点                        Brush bs = new SolidBrush(Color.Green);//填充的颜色                        g.FillEllipse(bs, pf.X - r / 2, pf.Y + r / 2, r * 2, r * 2);                    }                }                else if (ShapeType == 3 || ShapeType == 5) //线类型和面类型是一样的                {                    //Console.WriteLine("线类型");                                foreach (StructShapePolyline p in ListPolylines)                    {                        for (int i = 0; i < p.Lines.Count; i++)                        {                            PointF[] pfArray = new PointF[p.Lines[i].Length];                            for (int j = 0; j < p.Lines[i].Length; j++)                            {                                StructShapePoint ps = p.Lines[i][j];                                double offsetX = CenterX - screenWidth / 2.0;                                double offsetY = CenterY - screenHeight / 2.0;                                pfArray[j].X = (float)((ps.X - Xmin) * Scale + offsetX);                                pfArray[j].Y = (float)((ps.Y - Ymin) * Scale + offsetY);                            }                            g.DrawLines(ThePen, pfArray);                        }                                            }                }        return true;            }            catch (System.Exception ex)            {                Console.WriteLine("异常:ClassShp.drawBmp" + ex.ToString());                return false;            }        }    }}

在主窗口放置一个pictureBox控件,名为pictureBoxMap.

主函数:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Drawing.Drawing2D;using System.Drawing.Imaging;namespace SDD{    public partial class FormMain : Form    {        ClassShp ShapeChina;        public FormMain()        {            InitializeComponent();            string mapChinaPathName = new ClassShp(@"D:\map\地图\国界.shp", pictureBoxMap.Width, pictureBoxMap.Height);            pictureBoxMap.Refresh();        }        private void pictureBoxMap_Paint(object sender, PaintEventArgs e)        {            Bitmap bmp = new Bitmap(pictureBoxMap.Width, pictureBoxMap.Height);//创建画布            ShapeChina.DrawBmp(pictureBoxMap.Width, pictureBoxMap.Height);            e.Graphics.DrawImage(ShapeChina.Bmp, 0, 0);        }    }}

shp地图解析(不用AE)