日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

C#测绘兰勃特墨卡托投影

發(fā)布時(shí)間:2023/12/10 C# 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#测绘兰勃特墨卡托投影 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

先上圖

下載鏈接:程序下載

一、投影變換

正軸等角割圓錐投影:由德國數(shù)學(xué)家Lambert擬定,屬于蘭勃特正形投影(Lambert projection)之一。


緯線為同心圓弧,經(jīng)線為放射性直線;相割的兩條緯線是標(biāo)準(zhǔn)緯線,其長度比為1;無角度變形;在兩條割線之內(nèi),緯線長度比小于1,之外長度比大于1;離開標(biāo)緯越遠(yuǎn),變形絕對值越大

正軸等角切圓柱投影,由荷蘭制圖學(xué)家Mercator (Mercator Gerardus,1512-1594)于1569年創(chuàng)建,又被稱為墨卡托投影。


經(jīng)線與緯線是兩組相互垂直的平行直線,經(jīng)線間距相等,緯線間距由赤道向兩極逐漸增大。
赤道為標(biāo)準(zhǔn)緯線,其余各緯線與赤道等長;無角度變形,但長度和面積變形隨著緯度增高而逐漸增大;等角航線表現(xiàn)為直線

二、變換參數(shù)及公式

80坐標(biāo)系(Xian_1980)
長半軸:6378140 偏心率: 1/298.257
短半軸:6356755.28816
極曲率半徑:6399596.65199
第一偏心率平方: 0.006694384999588
第二偏心率平方: 0.006739501819473

54坐標(biāo)系(Krasovsky_1940)
長半軸:6378245 偏心率: 1/298.3
短半軸:6356863.01877
極曲率半徑:6399698.90178
第一偏心率平方: 0.006693421622966
第二偏心率平方: 0.006738525414684

蘭勃特正角投影公式


反解公式

墨卡托投影正解

反解公式

三、程序

界面基本的就是 button、 textbox控件
圖可以繪制在 Picturebox 控件,也可以直接畫在form窗體里
可以加入splitContainer控件和groupbox控件

思路
1、讀入數(shù)據(jù)


CHINA_Arc.gen.txt的數(shù)據(jù),將經(jīng)緯度讀入一個(gè)數(shù)組,另外定義一個(gè)數(shù)組專門記錄下標(biāo)
2、投影變換
將經(jīng)緯度帶入帶入變換的成員函數(shù)進(jìn)行投影變換
3、畫圖
一共有四百多個(gè)環(huán),用for循環(huán)依此繪制每個(gè)環(huán),如33號(hào)環(huán)內(nèi)12個(gè)點(diǎn)順序畫線,注意數(shù)組的下標(biāo)錯(cuò)位現(xiàn)象,不然會(huì)導(dǎo)致33號(hào)環(huán)的最后一個(gè)點(diǎn)與34號(hào)環(huán)的第一個(gè)點(diǎn)連線出錯(cuò)。

老師說經(jīng)常用For循環(huán)會(huì)變傻,就這么吧我也想不出更好的方法

源碼

1、輸入?yún)?shù)定義數(shù)組

//54坐標(biāo)系參數(shù)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];//存儲(chǔ)轉(zhuǎn)換后的B坐標(biāo)double[] LLambert = new double[L.Length];//存儲(chǔ)轉(zhuǎn)換后的L坐標(biāo)double[] BMercator = new double[B.Length];//存儲(chǔ)轉(zhuǎn)換后的B坐標(biāo)double[] LMercator = new double[L.Length];//存儲(chǔ)轉(zhuǎn)換后的L坐標(biāo)

2、路徑及數(shù)據(jù)讀入
可以單獨(dú)寫一個(gè)事件來選擇文件的路徑,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("文件選擇完成!");

也可以寫死路徑,兩種寫路徑方法,\ 第一個(gè)反斜號(hào)是轉(zhuǎn)義字符的意思

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

數(shù)據(jù)讀入成員函數(shù)(注意引用類)

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)//把數(shù)據(jù)與編號(hào)分開存,H[]數(shù)組存行號(hào){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、投影成員函數(shù)及事件

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("請輸入數(shù)據(jù)");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("請輸入數(shù)據(jù)");DateTime t1 = DateTime.Now;TxtTime.Text = (t1 - t0).ToString();}

成員函數(shù)

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常數(shù)double m1 = Math.Cos(B1) / Math.Sqrt(1 - e1 * e1 * Math.Sin(B1) * Math.Sin(B1));//mB1常數(shù)double m2 = Math.Cos(B2) / Math.Sqrt(1 - e1 * e1 * Math.Sin(B2) * Math.Sin(B2));//mB2常數(shù)double t0 = Math.Tan(Math.PI / 4 - B0 / 2) / Math.Pow((1 - e1 * Math.Sin(B0) / (1 + e1 * Math.Sin(B0))), (e1 / 2));//t0常數(shù)double t1 = Math.Tan(Math.PI / 4 - B1 / 2) / Math.Pow((1 - e1 * Math.Sin(B1) / (1 + e1 * Math.Sin(B1))), (e1 / 2));//tB1常數(shù)double t2 = Math.Tan(Math.PI / 4 - B2 / 2) / Math.Pow((1 - e1 * Math.Sin(B2) / (1 + e1 * Math.Sin(B2))), (e1 / 2));//tB2常數(shù)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;}}

畫圖成員函數(shù)

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; //定義兩個(gè)循環(huán)體變量,一共462個(gè)環(huán),循環(huán)462次,每次畫一個(gè)環(huán)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);}}}

畫線函數(shù)
用的是隨機(jī)顏色,Random類和 timer控件很好用
投影坐標(biāo)系和笛卡爾坐標(biāo)系是反著的(學(xué)測繪的都知道的吧)
投影后的坐標(biāo)都是幾千上萬左右的,需要按比例縮放和平移才能顯示到屏幕上

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浮點(diǎn)數(shù)g.ScaleTransform(0.00009f, 0.00009f);//畫面縮小g.TranslateTransform(4000000, 6400000);//平移g.RotateTransform(-90);//旋轉(zhuǎn) g.DrawLine(map, x1, y1, x2, y2);//每次兩個(gè)點(diǎn)連線 }

四、代碼改進(jìn)

重寫窗口大小

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){//遍歷窗體中的控件,重新設(shè)置控件的值foreach (Control con in cons.Controls){//獲取控件的Tag屬性值,并分割后存儲(chǔ)字符串?dāng)?shù)組if (con.Tag != null){string[] mytag = con.Tag.ToString().Split(new char[] { ';' });//根據(jù)窗體縮放的比例確定控件的值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);}}}}

總結(jié)

以上是生活随笔為你收集整理的C#测绘兰勃特墨卡托投影的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。