C#绘制中国地图(兰勃特、墨卡托投影)

C#绘制中国地图(兰勃特、墨卡托投影)

话不多说,直接上代码:

public partial class Form1 : Form
    {
     
        List<PointP> points = new List<PointP>();
        public Form1()
        {
     
            InitializeComponent();
            
        }

        private void button1_Click(object sender, EventArgs e)
        {
     
            //DateTime t1 = DateTime.Now;
            //在80坐标系下兰伯特等角投影转换(正角)

            string Chinapath = @"。。。";         //地图数据路径,自己填叭
            Graphics gobj = this.pictureBox1.CreateGraphics();              //建立画板
            Pen pen = new Pen(Color.SkyBlue, 3);                                //建立画笔
            //对坐标系进行缩放平移
            gobj.ScaleTransform(0.00009f, 0.00009f);               //画面缩小
            gobj.TranslateTransform(4000000 ,6400000);              //平移
            gobj.RotateTransform(-90);                              //旋转


            //Draw China
            FileStream fs = File.OpenRead(Chinapath);               //创建文件流
            StreamReader sr = new StreamReader(fs, Encoding.Default);     //读取器
            string lineData = sr.ReadLine();                     //读取每行的数据



            while (lineData != null)                              //每行读取数据
            {
     
                string[] TemData;                           //存放每行转换的数组
                TemData = lineData.Split(',');             //每行数据以逗号分隔,存成长度为2的字符数组
                if (lineData == null)                       //如果此行数据为空,读取完成,直接结束
                {
      break; }
                else if (TemData.Length == 1)              //如果一行只有一个字符串,认为是无效行,跳至下一行
                {
     
                    lineData = sr.ReadLine();
                }
                else if (TemData.Length != 1)              //如果含多个字符串,进行继续读取并画图
                {
     
                    points.Clear();                 //创建点集合
                    while (TemData.Length != 1)                               //此循环为不断读取某圈所有数据,并存入点集合中
                    {
     
                        double B, L, X, Y, e2, e1, a;                     //参数设置
                        a = 6378140;
                        e2 = 0.006694384999588;
                        e1 = Math.Sqrt(e2);
                        B = Math.PI * (double.Parse(TemData[1])) / 180;
                        L = Math.PI * (double.Parse(TemData[0])) / 180;
                        double B0 = 0;                                   //定义原点纬度
                        double L0 = Math.PI * 105 / 180;                 //定义原点经度
                        double B1 = Math.PI * 20 / 180;                 //定义第一标准纬线
                        double B2 = Math.PI * 40 / 180;                 //定义第二标准纬线

                        //公式计算
                        double m = Math.Cos(B) / Math.Sqrt(1 - e1 * e1 * Math.Sin(B) * Math.Sin(B));
                        double t = Math.Tan(Math.PI / 4 - B / 2) / Math.Pow((1 - e1 * Math.Sin(B)) / (1 + e1 * Math.Sin(B)), (e1 / 2));
                        double mB1 = Math.Cos(B1) / Math.Sqrt(1 - e1 * e1 * Math.Sin(B1) * Math.Sin(B1));
                        double mB2 = Math.Cos(B2) / Math.Sqrt(1 - e1 * e1 * Math.Sin(B2) * Math.Sin(B2));
                        double tB0 = Math.Tan(Math.PI / 4 - B0 / 2) / Math.Pow((1 - e1 * Math.Sin(B0)) / (1 + e1 * Math.Sin(B0)), (e1 / 2));
                        double tB1 = Math.Tan(Math.PI / 4 - B1 / 2) / Math.Pow((1 - e1 * Math.Sin(B1)) / (1 + e1 * Math.Sin(B1)), (e1 / 2));
                        double tB2 = Math.Tan(Math.PI / 4 - B2 / 2) / Math.Pow((1 - e1 * Math.Sin(B2)) / (1 + e1 * Math.Sin(B2)), (e1 / 2));
                        double n = Math.Log(mB1 / mB2) / Math.Log(tB1 / tB2);
                        double F = mB1 / (n * Math.Pow(tB1, n));
                        double r = a * F * Math.Pow(t, n);
                        double r0 = a * F * Math.Pow(tB0, n);
                        double Theta = n * (L - L0);

                        //坐标转换
                        X = r0 - r * Math.Cos(Theta);
                        Y = r * Math.Sin(Theta);

                        //存入点集合,并继续读数据
                        PointP P;
                        P.X = Convert.ToSingle(X);
                        P.Y = Convert.ToSingle(Y);
                        points.Add(P);
                        lineData = sr.ReadLine();
                        TemData = lineData.Split(',');
                    }
                    for (int i = 0; i < points.Count - 1; i++)                                 //按照存入的点集合画图
                    {
     

                        gobj.DrawLine(pen, points[i].X, points[i].Y, points[i + 1].X, points[i + 1].Y);
                    }
                    lineData = sr.ReadLine();                                  //读取下一行数据,经过判断,若不是有效数据行,跳出此循环,进入大循环继续跳行判断
                }
            }
            sr.Close();            //关闭读取器
            fs.Close();            //关闭文件流
        }
        public struct PointP
{
     
    public float X;
    public float Y;
}
}

公式部分没什么难度,老师一般直接就给了,自己慢慢敲就是(其实挺长的)。我只给了兰伯特投影的,墨卡托的话,自己敲吧,原理一样的。
最开始准备作业的时候,准备改一改网上代码就交上去,结果看到挺多其他人写的代码,有一些特别复杂冗长,读起来很费力气,于是就准备自己写了hh。
这个程序主要是利用了一下readline函数的特点和循环吧,简化挺多过程的。大体的思路是利用两个循环,每读一条线,就画一条线。(我的注释应该已经写的比较清楚了,如果有看不懂、有问题可以再问~)为了看起来逻辑连贯一些,我没有封装函数,当然有心修改的话,可以自己试着改一下。
没花时间回头修改和优化,难免会有不足和错误之处,如果有修改意见欢迎评论交流,一起进步!~
(17 测绘 HHU)

你可能感兴趣的:(c#,兰勃特,墨卡托投影,中国地图绘制)