shpmap解析(不用AE)
shp地图解析(不用AE)
AE太重型,还收费,如果只是加载地图作为底图,可以用纯C#实现。
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); //画边框 double x = CenterX - screenWidth / 2.0; double y = CenterY - screenHeight / 2.0; x = Math.Round(x); y = Math.Round(y); screenWidth = Math.Round(screenWidth); screenHeight = Math.Round(screenHeight); g.DrawRectangle(new Pen(Color.Red), (int)x, (int)y, (int)screenWidth, (int)screenHeight); 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) //线类型 { //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); } } } else if (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 { Point MouseOldPosition; List<ClassMap> ListMap; //######################################################################################## //主函数 //######################################################################################## public FormMain() { InitializeComponent(); ClassShp ShapeChina;
string mapChinaPathName= new ClassShp(@"D:\map\地图\国界.shp", pictureBoxMap.Width, pictureBoxMap.Height);
pictureBoxMap.Refresh();
}
Bitmap bmp = new Bitmap(pictureBoxMap.Width, pictureBoxMap.Height);//创建画布
for (int i = 0; i < ListMap.Count; i++)
{
if (ListMap[i].Actived)
{
ListMap[i].Shp.DrawBmp(pictureBoxMap.Width, pictureBoxMap.Height);
e.Graphics.DrawImage(ListMap[i].Shp.Bmp, 0, 0);
}
}