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);
}
}