先上图

下载链接:程序下载

一、投影变换

正轴等角割圆锥投影:由德国数学家Lambert拟定,属于兰勃特正形投影(Lambert projection)之一。


纬线为同心圆弧,经线为放射性直线;相割的两条纬线是标准纬线,其长度比为1;无角度变形;在两条割线之内,纬线长度比小于1,之外长度比大于1;离开标纬越远,变形绝对值越大

正轴等角切圆柱投影,由荷兰制图学家Mercator (Mercator Gerardus,1512-1594)于1569年创建,又被称为墨卡托投影。


经线与纬线是两组相互垂直的平行直线,经线间距相等,纬线间距由赤道向两极逐渐增大。
赤道为标准纬线,其余各纬线与赤道等长;无角度变形,但长度和面积变形随着纬度增高而逐渐增大;等角航线表现为直线

二、变换参数及公式

80坐标系(Xian_1980)
长半轴:6378140 偏心率: 1/298.257
短半轴:6356755.28816
极曲率半径:6399596.65199
第一偏心率平方: 0.006694384999588
第二偏心率平方: 0.006739501819473

54坐标系(Krasovsky_1940)
长半轴:6378245 偏心率: 1/298.3
短半轴:6356863.01877
极曲率半径:6399698.90178
第一偏心率平方: 0.006693421622966
第二偏心率平方: 0.006738525414684

兰勃特正角投影公式


反解公式

墨卡托投影正解

反解公式

三、程序

界面基本的就是 button、 textbox控件
图可以绘制在 Picturebox 控件,也可以直接画在form窗体里
可以加入splitContainer控件和groupbox控件

思路
1、读入数据


CHINA_Arc.gen.txt的数据,将经纬度读入一个数组,另外定义一个数组专门记录下标
2、投影变换
将经纬度带入带入变换的成员函数进行投影变换
3、画图
一共有四百多个环,用for循环依此绘制每个环,如33号环内12个点顺序画线,注意数组的下标错位现象,不然会导致33号环的最后一个点与34号环的第一个点连线出错。

老师说经常用For循环会变傻,就这么吧我也想不出更好的方法

源码

1、输入参数定义数组

 //54坐标系参数double a = 6378245;double b = 6356863.01877;double e1 = Math.Sqrt(0.0066943849995888);double e2 = Math.Sqrt(0.006739501819473);static string path;int[] H = new int[465];static double[] B = new double[26689];static double[] L = new double[26689];double[] BLambert = new double[B.Length];//存储转换后的B坐标double[] LLambert = new double[L.Length];//存储转换后的L坐标double[] BMercator = new double[B.Length];//存储转换后的B坐标double[] LMercator = new double[L.Length];//存储转换后的L坐标

2、路径及数据读入
可以单独写一个事件来选择文件的路径,OpenFileDialog类提供多种文件的操作,可返回路径,文件名、文件后缀等

            OpenFileDialog fdlg = new OpenFileDialog();fdlg.Title = "C# Corner Open FileDialog";fdlg.InitialDirectory = "";fdlg.Filter = "All files (*.*)|*.*|All files(*.*)|*.*";fdlg.FilterIndex = 2;fdlg.RestoreDirectory = true;if(fdlg .ShowDialog ()==DialogResult.OK ){path = Path.GetFullPath(fdlg.FileName);//获取绝对路径}MessageBox.Show("文件选择完成!");

也可以写死路径,两种写路径方法,\ 第一个反斜号是转义字符的意思

path=@"D:\CHINA_Arc.gen.txt";
path="D:\\CHINA_Arc.gen.txt";

数据读入成员函数(注意引用类)

public void inputdata(){StreamReader str = new StreamReader(path);string x;int i = 0;int j = 0;int k = 1;int T;while ((x = str.ReadLine()) != null)//把数据与编号分开存,H[]数组存行号{if (x.Length <= 3 && !x.Contains("END"))T = 1;else if (x.Contains("END"))T = 2;else T = 3;switch (T){case 1:H[i] = k;k++;i++;continue;case 2:k++;continue;case 3:string[] Q = x.Split(',');double u;u = Convert.ToDouble(Q[0]);B[j] = u ;u = Convert.ToDouble(Q[1]);L[j] = u ;j++; k++;continue;}}for (int rr = 0; rr <= 462; rr++){H[rr] = H[rr] - rr;H[462] = 27152;}str.Close();Console.ReadLine();}

3、投影成员函数及事件

button事件

       private void BtnLambert_Click(object sender, EventArgs e){DateTime t0 = DateTime.Now;Graphics g = this.picBox.CreateGraphics();g.Clear(this.BackColor);g.Dispose();if (TxtB0.Text != "" && TxtL0.Text != "" && TxtB1.Text != "" && TxtB2.Text != ""){                double B0 = Convert.ToDouble(TxtB0.Text) * Math.PI / 180;double L0 = Convert.ToDouble(TxtL0.Text) * Math.PI / 180;double B1 = Convert.ToDouble(TxtB1.Text) * Math.PI / 180;double B2 = Convert.ToDouble(TxtB2.Text) * Math.PI / 180;inputdata();Lambert(B0, B1, B2, e1, L0);drawchina(H, BLambert, LLambert);}elseMessageBox.Show("请输入数据");DateTime t1 = DateTime.Now;TxtTime.Text = (t1 - t0).ToString();}
 private void btnMocato_Click(object sender, EventArgs e){DateTime t0 = DateTime.Now;Graphics g = this.picBox.CreateGraphics();g.Clear(this.BackColor);g.Dispose();if (txtB00.Text != "" && txtL00.Text != "" && txtB11.Text != "" ){double B0 = Convert.ToDouble(txtB00.Text) * Math.PI / 180;double L0 = Convert.ToDouble(txtL00.Text) * Math.PI / 180;double B1 = Convert.ToDouble(txtB11.Text) * Math.PI / 180;inputdata();Mercator(B0, B1, e1, e2, L0);drawchina(H, BMercator, LMercator);}elseMessageBox.Show("请输入数据");DateTime t1 = DateTime.Now;TxtTime.Text = (t1 - t0).ToString();}

成员函数

public void Lambert(double B0,double B1,double B2,double e1,double L0){double[] m = new double[B.Length ];double[] t = new double[B.Length];double[] r = new double[B.Length];double[] q = new double[B.Length];double[] c = new double[B.Length];double m0 = Math.Cos(B0) / Math.Sqrt(1 - e1 * e1 * Math.Sin(B0) * Math.Sin(B0));//m0常数double m1 = Math.Cos(B1) / Math.Sqrt(1 - e1 * e1 * Math.Sin(B1) * Math.Sin(B1));//mB1常数double m2 = Math.Cos(B2) / Math.Sqrt(1 - e1 * e1 * Math.Sin(B2) * Math.Sin(B2));//mB2常数double t0 = Math.Tan(Math.PI / 4 - B0 / 2) / Math.Pow((1 - e1 * Math.Sin(B0) / (1 + e1 * Math.Sin(B0))), (e1 / 2));//t0常数double t1 = Math.Tan(Math.PI / 4 - B1 / 2) / Math.Pow((1 - e1 * Math.Sin(B1) / (1 + e1 * Math.Sin(B1))), (e1 / 2));//tB1常数double t2 = Math.Tan(Math.PI / 4 - B2 / 2) / Math.Pow((1 - e1 * Math.Sin(B2) / (1 + e1 * Math.Sin(B2))), (e1 / 2));//tB2常数double n = Math.Log10(m1 / m2) / Math.Log10(t1 / t2);double F = m1 / (n * Math.Pow(t1, n));double r0 = a * F * Math.Pow(t0, n);for (int i = 0; i < B.Length; i++){c[i] = B[i];B[i] = L[i] * Math.PI / 180;L[i] = c[i] * Math.PI / 180;m[i] = Math.Cos(B[i]) / (Math.Sqrt(1 - e1 * e1 * Math.Sin(B[i]) * Math.Sin(B[i])));t[i] = Math.Tan(Math.PI / 4 - B[i] / 2) / Math.Pow((1 - e1 * Math.Sin(B[i]) / (1 + e1 * Math.Sin(B[i]))), (e1 / 2));r[i] = a * F * Math.Pow(t[i], n);q[i] = n * (L[i] - L0);BLambert[i] = (r0 - r[i] * Math.Cos(q[i]));LLambert[i] = (r[i] * Math.Sin(q[i]));}}
public void Mercator(double B0, double B1, double e1, double e2, double L0){double K = Math .Pow (a,2) / b / Math.Sqrt(1 + Math.Pow(e2, 2) * Math.Pow(Math.Cos(B0), 2)) * Math.Cos(B0);double[] exchange = new double[B.Length];double[] m = new double[B.Length];double[] n = new double[B.Length];for (int i = 0; i < B.Length; i++){                exchange [i] = B[i];B[i] = L[i] * Math.PI / 180;L[i] = exchange [i] * Math.PI / 180;m[i] = Math.Tan(Math.PI / 4 + B[i] / 2);n[i] = (1 - e1 * Math.Sin(B[i])) / (1 + e1 * Math.Sin(B[i]));BMercator[i] = K*Math.Log(m[i] + Math.Pow(n[i], (e1 / 2)))-2800000;LMercator [i] = K*(L[i]-L0)-50000;}}

画图成员函数

public void drawchina(int []H,double [] BLambert,double [] LLambert){for (int i = 1; i <= 462; i++)H[i] = H[i] - i - 2;int j = 0;    //定义两个循环体变量,一共462个环,循环462次,每次画一个环for (int k = 1; k < 462; k++){for (; j < H[k]; j++){if (j == H[k - 1]){j++;}int x1 = (int)(BLambert[j]);int y1 = (int)(LLambert[j]);int x2 = (int)(BLambert[j + 1]);int y2 = (int)(LLambert[j + 1]);drawline(x1, y1, x2, y2);}}}

画线函数
用的是随机颜色,Random类和 timer控件很好用
投影坐标系和笛卡尔坐标系是反着的(学测绘的都知道的吧)
投影后的坐标都是几千上万左右的,需要按比例缩放和平移才能显示到屏幕上

public void drawline(int x1, int y1, int x2, int y2){Random rnd = new Random();Graphics g = this.picBox.CreateGraphics();Pen map = new Pen(Color.FromArgb (rnd.Next (256), rnd.Next (50), rnd.Next (50)), 2f);//定义画刷,黑色,线条宽度为1,f表示float浮点数g.ScaleTransform(0.00009f, 0.00009f);//画面缩小g.TranslateTransform(4000000, 6400000);//平移g.RotateTransform(-90);//旋转      g.DrawLine(map, x1, y1, x2, y2);//每次两个点连线  }

四、代码改进

重写窗口大小

private void ONresize(object sender, EventArgs e)//重写窗口大小事件{float newx = (this.Width) / x;float newy = (this.Height) / y;setControls(newx, newy, this);}private void setTag(Control cons){foreach (Control con in cons.Controls){con.Tag = con.Width + ";" + con.Height + ";" + con.Left + ";" + con.Top + ";" + con.Font.Size;if (con.Controls.Count > 0){setTag(con);}}}private void setControls(float newx, float newy, Control cons){//遍历窗体中的控件,重新设置控件的值foreach (Control con in cons.Controls){//获取控件的Tag属性值,并分割后存储字符串数组if (con.Tag != null){string[] mytag = con.Tag.ToString().Split(new char[] { ';' });//根据窗体缩放的比例确定控件的值con.Width = Convert.ToInt32(System.Convert.ToSingle(mytag[0]) * newx);//宽度con.Height = Convert.ToInt32(System.Convert.ToSingle(mytag[1]) * newy);//高度con.Left = Convert.ToInt32(System.Convert.ToSingle(mytag[2]) * newx);//左边距con.Top = Convert.ToInt32(System.Convert.ToSingle(mytag[3]) * newy);//顶边距Single currentSize = System.Convert.ToSingle(mytag[4]) * newy;//字体大小con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);if (con.Controls.Count > 0){setControls(newx, newy, con);}}}}

C#测绘兰勃特墨卡托投影相关推荐

  1. 地球坐标系与投影方式的理解(关于北京54,西安80,WGS84;高斯,兰勃特,墨卡托投影)

    一.地球模型 地球是一个近似椭球体,测绘时用椭球模型逼近,这个模型叫做参考椭球,如下图: 赤道是一个半径为a的近似圆,任一圈经线是一个半径为b的近似圆.a称为椭球的长轴半径,b称为椭球的短轴半径. a ...

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

    C#绘制中国地图(兰勃特.墨卡托投影) 话不多说,直接上代码: public partial class Form1 : Form{List<PointP> points = new Li ...

  3. [GIS] 常见地图投影 - 投影坐标系 - UTM|高斯克吕格|兰勃特等角投影|墨卡托投影

    文章目录 我国常见的地图投影情况 墨卡托投影 特征 适用 通用横轴墨卡托投影UTM 用途 类型 特点 座标编排 兰勃特等角投影 特点 适用 高斯-克吕格投影 形成条件 特点 适用 分带 6度带 3度带 ...

  4. Lambert(兰勃托)投影--我国天气图底图广泛采用的一种投影

    Lambert.java 001  /** 002  003     Lambert兰勃特投影 004  005        PACKAGE: cma.common.projection 006  ...

  5. 深入浅出谈GIS - 坐标体系

    零.综述 要搞懂坐标系,就从"地球模型 -> 坐标系 -> 平面投影"这三个方面来学习 1.地球模型: 价值:对于不规则的地球,选择一个曲面尽量逼近当地大地体的椭球作为 ...

  6. 直角坐标XY和经纬度BL正算反算(西安80坐标3度分带)php

    本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qyh666/article/details/80020876 我采用120度径线作为中央子午线,可采用3度带投 ...

  7. 墨卡托投影、高斯-克吕格投影、UTM投影、兰伯特等角圆锥投影

    1.墨卡托(Mercator)投影 1.1 墨卡托投影简介 墨卡托(Mercator)投影,是一种"等角正切圆柱投影",荷兰地图学家墨卡托(GerhardusMercator151 ...

  8. 横轴墨卡托投影参数_几种投影的主要参数【转】

    Gauss Kruger(高斯-克吕格投影):除中央经线和赤道为直线外,其他经线均为对称于中央经线的曲线.该投影没有角度变形,在长度和面积上变形也很小,中央经线无变形,自中央经线向投影带边缘,变形逐渐 ...

  9. 地理坐标系和投影坐标系的联系_收藏| 地图投影系列介绍(二)——地理坐标系...

     3.地理坐标系 地球的形状与大小确定之后,还必须确定椭球体与大地水准面的相对关系,这项工作称为椭球定位与定向.与大地水准面符合得最好的一个地球椭球体,称为参考椭球体,是地球形体三级逼近. 说到这里, ...

  10. ArcGIS Pro坐标系统

    目录 1 测量学基础 1.1 地球的形状和大小 1.1.1 大地水准面 1.1.2 大地体 1.1.3 地球椭球 2 坐标系统 2.1 地理坐标系 2.2 投影坐标系 2.3 局部坐标系(假定坐标系) ...

最新文章

  1. mysql 加密方式 caching_sha2_password 和 mysql_native_password 说明
  2. 导出matlab程序,Matlab数据导入导出
  3. 【BZOJ1042】硬币购物(动态规划,容斥原理)
  4. .NET架构小技巧(7)——做好小的项目
  5. RHEL6入门系列之二十六,利用rpm进行软件包管理
  6. (软件工程复习核心重点)第五章详细设计-第三节:过程设计工具
  7. vs2012+wdk8.0 搭建wdf驱动开发环境
  8. PHP 中 new static 和 new self 的区别
  9. c++编写手机小游戏代码_手机也能编程?盘点这6个可以用手机编程的App!快收藏!...
  10. cacti支持中文办法
  11. VS2005进行WORD文档开发
  12. Python学习笔记(一) 计算阶乘
  13. 网站开发用什么语言好_兰州网站开发哪家策划效果好
  14. Restlet Introduction
  15. Android 文字转语音之TextToSpeech
  16. bp神经网络算法的优缺点,bp神经网络算法的优点
  17. 北京游玩之北海首都博物馆
  18. 大恒相机(MER)驱动配置注意事项:
  19. 8.2 JVM命令行监控——jstat
  20. Python通过区号和校验位校验身份证号是否合法

热门文章

  1. Java9 基于异步响应式流的发布-订阅框架
  2. EditPlus 3 实现将JSON字符串格式化、排版成JSON格式数据
  3. 怎么将计算机的触摸鼠标锁定,怎么锁定笔记本触摸板_怎么锁定笔记本键盘
  4. 【githubboy】比较实用的 Python 翻译工具库,集成了谷歌、必应、有道、百度等多个翻译平台 API
  5. CF55D Beautiful numbers
  6. 微信小程序位置定位php,【微信开发】微信小程序通过经纬度计算两地距离php代码实现...
  7. 太阳影子定位问题研究
  8. hrbust/哈理工oj 1787 New Fibonacci Number【欧拉降幂+矩阵快速幂】
  9. LoadRunner11 压力测试
  10. matlab中的取整函数(ceil、floor、round)