AE太重型,还收费,如果只是加载地图作为底图,可以用纯C#实现。线类型用得最多,以下是线类型的数据结构:
总体架构
文件头 |
记录头 记录内容 |
记录头 记录内容 |
。。。。。。。。。。。。 |
记录头 记录内容 |
文件头
位置 | 类型 | 字段 | 说明 |
Byte 0 | int | File Code | 文件代码 |
Byte 4 | int | 无用 | |
Byte 8 | int | 无用 | |
Byte 12 | int | 无用 | |
Byte 16 | int | 无用 | |
Byte 20 | int | 无用 | |
Byte 24 | int | File Length | 文件长度 |
Byte 28 | int | Version | 版本 |
Byte 32 | int | Shape Type |
图形类型 1:Point,点类型 3:PolyLine,线类型 5:Polygon,面类型 |
Byte 36 | double | Xmin | 整图的X轴坐标最小值 |
Byte 44 | double | Ymin | 整图的Y轴坐标最小值 |
Byte 52 | double | Xmax | 整图的X轴坐标最大值 |
Byte 60 | double | Ymax | 整图的Y轴坐标最大值 |
Byte 68* | double | Zmin | |
Byte 76* | double | Zmax | |
Byte 84* | double | Mmin | |
Byte 92* | double | Mmax |
记录头
位置 | 类型 | 字段 | 说明 |
Byte 0 | int | Record Number | 记录号,从1开始 |
Byte 4 | int | Content Length | 内容长度,内容的16位字数,不包括记录号。 |
记录内容
点类型:
位置 | 类型 | 字段 | 说明 |
Byte 0 | int | ShapeType | Shape类型=1 |
Byte 4 | double | X | 点的X坐标 |
Byte 12 | double | Y | 点的Y坐标 |
线类型:
位置 | 类型 | 字段 | 说明 |
Byte 0 | int | ShapeType | Shape类型=3 |
Byte 4 | double [4] | Box | 该线条的边界盒,以Xmin,Ymin,Xmax,Ymax的顺序存储 |
Byte 36 | int | NumParts | 是PolyLine中部分的数目 |
Byte 40 | int | NumPoints | 是PolyLine中点的数目 |
Byte 44 | int [NumParts] | Parts | 每条PolyLine存储它在点数列中的第一个点的索引。数列索引是从0开始的。Parts[NumParts]数组是Points[NumPoints]数组的目录 |
X | Point[NumPoints] | Points | 本条记录的所有点。Struct Point {Double X;Double Y;} |
Parts和Points之间的关系: 如果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); } } }