/// <summary> /// 大地坐标转换为高斯投影坐标 正解公式 /// WGC84->高斯投影 /// Description: ///' 大地坐标转换为高斯投影坐标 ///' Parameters: ///' LX,BX - 输入,经纬度坐标 ///' x,y - 输出,高斯投影坐标(大数) ///' nearright - 输入,L是相邻两带的分界线时的取法,0 - 左带(小),1 - 右带(大) ///' ProjectionType - 输入,1 - 80坐标系,0 - 54坐标系 ///' StripType - 输入,1 - 6度分带,0 - 3度分带 /// 当只有一个已知控制点时,根据平移参数调整东伪偏移、北纬偏移值实现WGS84到北京54的转换 /// 东伪偏移=东伪偏移值=tpMainStrip * 1000000+500000.0 /// 北纬偏移值=0; /// </summary> /// <param name="BX">大地纬度B</param> /// <param name="LX">大地经度L</param> /// <param name="x">高斯投影X</param> /// <param name="y">高斯投影Y</param> /// <param name="nearright">输入,L是相邻两带的分界线时的取法,0 - 左带(小),1 - 右带(大)</param> /// <param name="ProjectionType"> 输入,1 - 80坐标系,0 - 54坐标系</param> /// <param name="StripType"> 输入,1 - 6度分带,0 - 3度分带</param> /// <param name="IsBigNumber">输入, 是大数坐标吗?</param> public void GetXYFromBL(decimal BX, decimal LX, ref decimal x, ref decimal y, long nearright, EnumProjectionDatum ProjectionType, EnumStrip StripType, bool IsBigNumber) { decimal t = 0; decimal B = 0; decimal L = 0; decimal x0 = 0; decimal y2 = 0; decimal E12 = 0; decimal c0 = 0; decimal n1 = 0; decimal m = 0; decimal temp1 = 0, temp2 = 0; decimal LX1 = 0; decimal fc_pi = 3.14159265358979M; //PI值 B = (BX / 180) * fc_pi; //转为弧度值bx*(PI/180) L = (LX / 180) * fc_pi; //转为弧度值lx*(PI/180) //求带内中央子午线经度 LX1 = GetLocalLongitude(LX, nearright, StripType); m = Maths.Cos(B) * fc_pi * LX1 / 180.0M; t = Maths.Tan(B); switch (ProjectionType) { case EnumProjectionDatum.Xian80: //80坐标 c0 = 6399596.65198801M; E12 = 0.0067395018195M; x0 = 111133.0047M * BX - (32009.8575M * Maths.Sin(B) + 133.9978M * (Maths.Pow(Maths.Sin(B), 3)) + 0.6975M * (Maths.Pow(Maths.Sin(B), 5)) + 0.0039M * (Maths.Pow(Maths.Sin(B), 7))) * Maths.Cos(B); break; case EnumProjectionDatum.Bejing54: //54坐标 c0 = 6399698.90178271M; E12 = 0.00673852541468M; x0 = 111134.8611M * BX - (32005.7798M * Maths.Sin(B) + 133.9614M * (Maths.Pow(Maths.Sin(B), 3)) + 0.6972M * (Maths.Pow(Maths.Sin(B), 5)) + 0.0039M * (Maths.Pow(Maths.Sin(B), 7))) * Maths.Cos(B); break; default: //其它暂为空 break; } y2 = E12 * (Maths.Pow(Maths.Cos(B), 2)); n1 = c0 / Maths.Sqrt(1.0M + y2); temp1 = (Maths.Pow(m, 2)) / 2.0M + (5.0M - (Maths.Pow(t, 2)) + 9.0M * y2 + 4 * (Maths.Pow(y2, 2))) * (Maths.Pow(m, 4)) / 24.0M + (61.0M - 58.0M * (Maths.Pow(t, 2)) + (Maths.Pow(t, 4))) * (Maths.Pow(m, 6)) / 720.0M; temp2 = m + (1.0M - (Maths.Pow(t, 2)) + y2) * (Maths.Pow(m, 3)) / 6.0M + (5.0M - 18.0M * (Maths.Pow(t, 2)) + (Maths.Pow(t, 4)) + 14.0M * y2 - 58.0M * y2 * (Maths.Pow(t, 2))) * (Maths.Pow(m, 5)) / 120.0M; x = x0 + n1 * t * temp1; y = n1 * temp2 + 500000.0M; //与中央经线的距离m //500000.0表示平移了500公里距离 目的是把负数坐标转为正数好处理 //主带数值(整数) decimal tpMainStrip = 0; //主带数值 switch (StripType) { case EnumStrip.Strip3: tpMainStrip = (int)Math.Truncate(LX / 3) + 1; break; case EnumStrip.Strip6: tpMainStrip = (int)Math.Truncate(LX / 6) + 1; break; default: //则自动计算 ,默认为3度带 tpMainStrip = (int)Math.Truncate(LX / 3) + 1; break; } //转为大数坐标y=带数*1000000+与中央经线的距离m //东伪偏移值=tpMainStrip * 1000000+500000.0 if (IsBigNumber == true) //转为高斯投影是大数投影吗?即Zone 35带数 (小数投影为CM_105E) { y = y + tpMainStrip * 1000000; } }
public decimal GetRingEllipse(IGeometry geo) { IPointCollection pointColl = geo as IPointCollection; IPoint point = null; decimal x = 0; decimal y = 0; decimal[] B = new decimal[pointColl.PointCount]; decimal[] L = new decimal[pointColl.PointCount]; int intPart = 0; if (this.Datum == EnumProjectionDatum.Xian80) { //西安80系 for (int i = 0; i < pointColl.PointCount; i++) { point = pointColl.get_Point(i); x = Maths.Todecimal(point.X); y = Maths.Todecimal(point.Y); intPart = (int)x; if (intPart.ToString().Length == 6) { //x坐标实质是小数坐标 this.IsBigNumber = false; } if (intPart.ToString().Length == 8) { //x坐标实质是小数坐标 this.IsBigNumber = true; } //高斯反算 if (this.gassConv is GSCoordConVertionClass_Xian80_Call2) { (this.gassConv as GSCoordConVertionClass_Xian80_Call2).IsBigNumber = this.IsBigNumber; (this.gassConv as GSCoordConVertionClass_Xian80_Call2).Strip = this.Strip; (this.gassConv as GSCoordConVertionClass_Xian80_Call2).L0 = this.L0; (this.gassConv as GSCoordConVertionClass_Xian80_Call2).GetBLFromXY(y, x, ref B[i], ref L[i]); } else { this.gassConv.GetBLFromXY(y, x, ref B[i], ref L[i], 1, this.Datum, this.Strip, this.L0, this.IsBigNumber); } } } else if (this.Datum == EnumProjectionDatum.CGCS2000) { //2000坐标系 for (int i = 0; i < pointColl.PointCount; i++) { point = pointColl.get_Point(i); x = Maths.Todecimal(point.X); y = Maths.Todecimal(point.Y); intPart = (int)x; if (intPart.ToString().Length == 6) { //x坐标实质是小数坐标 this.IsBigNumber = false; } if (intPart.ToString().Length == 8) { //x坐标实质是小数坐标 this.IsBigNumber = true; } //高斯反算 if (this.gassConv is GSCoordConvertionClass_CGCS_2000) { (this.gassConv as GSCoordConvertionClass_CGCS_2000).IsBigNumber = this.IsBigNumber; (this.gassConv as GSCoordConvertionClass_CGCS_2000).Strip = this.Strip; (this.gassConv as GSCoordConvertionClass_CGCS_2000).L0 = this.L0; (this.gassConv as GSCoordConvertionClass_CGCS_2000).GetBLFromXY(y, x, ref B[i], ref L[i]); } else { this.gassConv.GetBLFromXY(y, x, ref B[i], ref L[i], 1, this.Datum, this.Strip, this.L0, this.IsBigNumber); } } } else { //北京54 for (int i = 0; i < pointColl.PointCount; i++) { point = pointColl.get_Point(i); x = Maths.Todecimal(point.X); y = Maths.Todecimal(point.Y); //高斯反算 this.gassConv.GetBLFromXY(y, x, ref B[i], ref L[i], 1, this.Datum, this.Strip, this.L0, this.IsBigNumber); } } decimal sum = 0; for (int i = 0; i < B.Length; i++) { if (i < B.Length - 1) { //double n = GetSign(L[i], L[i + 1]) * (Math.Abs(B[i] + B[i + 1]) * Math.Abs(L[i + 1] - L[i])) / 2; decimal n = this.Compute(B[i + 1], L[i + 1], B[i], L[i]); //System.Diagnostics.Debug.WriteLine(n.ToString()); sum += n; } else { //double r = GetSign(L[B.Length - 1], L[0]) * (Math.Abs(B[0] + B[B.Length - 1]) * Math.Abs(L[0] - L[B.Length - 1])) / 2; decimal r = this.Compute(B[0], L[0], B[B.Length - 1], L[L.Length - 1]); //System.Diagnostics.Debug.WriteLine(r.ToString()); sum += r; } } sum = Math.Abs(sum); return(sum); }
/// <summary> /// 高斯投影坐标转换为大地坐标 反解公式 /// Parameters: /// x,y - 输入,高斯投影坐标(大数) /// LX,BX - 输出,经纬度坐标 /// nearright - 输入,L是相邻两带的分界线时的取法,0 - 左带(小),1 - 右带(大) /// ProjectionType - 输入,1 - 80坐标系,0 - 54坐标系 /// StripType - 输入,1 - 6度分带,0 - 3度分带 /// L0 - 输入, 3度或6度分带的中央子午线 单位为度 /// </summary> /// <param name="x"> 输入,高斯投影X坐标</param> /// <param name="y"> 输入,高斯投影Y坐标(大数)</param> /// <param name="BX">输入,纬度坐标</param> /// <param name="LX">输入,经度坐标</param> /// <param name="nearright">输入,L是相邻两带的分界线时的取法,0 - 左带(小),1 - 右带(大)</param> /// <param name="ProjectionType">输入,1 - 80坐标系,0 - 54坐标系</param> /// <param name="StripType">输入,1 - 6度分带,0 - 3度分带</param> /// <param name="L0">输入, 3度或6度分带的中央子午线 单位为度</param> /// <param name="IsBigNumber">输入, 是大数坐标吗?</param> /// <returns></returns> public bool GetBLFromXY(decimal x, decimal y, ref decimal BX, ref decimal LX, int nearright, EnumProjectionDatum ProjectionType, EnumStrip StripType, decimal L0, bool IsBigNumber) { decimal a0 = 0; decimal b0 = 0; decimal c0 = 0; decimal E12 = 0; decimal bf0 = 0; decimal bf = 0; decimal tf = 0; decimal yf2 = 0; decimal n = 0; decimal b1 = 0; decimal l1 = 0; decimal temp1 = 0; long iStripNum = 0; decimal fc_pi = 3.14159265358979M; //要素的Y坐标中是否含有大地坐标的大数? switch (StripType) { case EnumStrip.Strip6: iStripNum = (long)Math.Round(L0 / 6); break; case EnumStrip.Strip3: iStripNum = (long)Math.Round(L0 / 3); break; } //认为高斯投影Y坐标为大数(y=带数*1000000 + 与中央经线的距离m //要素的Y坐标包含有大地坐标吗?y=y+带数*1000000 + 与中央经线的距离m(500公里) if (IsBigNumber == true) { y = y - iStripNum * 1000000; } x = x / 1000000; y = y - 500000; switch (ProjectionType) { case EnumProjectionDatum.Bejing54: //北京54 a0 = 6378245M; //长半轴 a(米) b0 = 6356863.01877305M; //短半轴b(米) c0 = 6399698.90178271M; E12 = 0.0067385254147M; bf0 = 27.11115372595M + 9.02468257083M * (x - 3) - 0.00579740442M * (Maths.Pow((x - 3), 2)) - 0.00043532572M * (Maths.Pow((x - 3), 3)) + 0.00004857285M * (Maths.Pow((x - 3), 4)) + 0.00000215727M * (Maths.Pow((x - 3), 5)) - 0.00000019399M * (Maths.Pow((x - 3), 6)); break; case EnumProjectionDatum.Xian80: //西安80 a0 = 6378140M; //长半轴 a(米) b0 = 6356755.28815753M; //短半轴b(米) c0 = 6399596.65198801M; E12 = 0.0067395018195M; bf0 = 27.11162289465M + 9.02483657729M * (x - 3) - 0.00579850656M * (Maths.Pow((x - 3), 2)) - 0.00043540029M * (Maths.Pow((x - 3), 3)) + 0.00004858357M * (Maths.Pow((x - 3), 4)) + 0.00000215769M * (Maths.Pow((x - 3), 5)) - 0.00000019404M * (Maths.Pow((x - 3), 6)); break; default: //暂为空 break; } bf = bf0 * fc_pi / 180; tf = Maths.Tan(bf); yf2 = E12 * (Maths.Pow(Maths.Cos(bf), 2)); n = y * Maths.Sqrt(1 + yf2) / c0; temp1 = 90.0M * (Maths.Pow(n, 2)) - 7.5M * (5.0M + 3.0M * (Maths.Pow(tf, 2)) + yf2 - 9.0M * yf2 * (Maths.Pow(tf, 2))) * (Maths.Pow(n, 4)) + 0.25M * (61.0M + 90.0M * (Maths.Pow(tf, 2)) + 45.0M * (Maths.Pow(tf, 4))) * (Maths.Pow(n, 6)); b1 = bf0 - (1.0M + yf2) * tf * temp1 / fc_pi; l1 = (180.0M * n - 30.0M * (1.0M + 2.0M * (Maths.Pow(tf, 2)) + yf2) * (Maths.Pow(n, 3)) + 1.5M * (5.0M + 28.0M * (Maths.Pow(tf, 2)) + 24.0M * (Maths.Pow(tf, 4))) * (Maths.Pow(n, 5))) / fc_pi / Maths.Cos(bf); l1 = l1 + L0; if (l1 < 0.0M) { l1 = l1 + 360.0M; } if (l1 >= 360.0M) { l1 = l1 - 360.0M; } BX = b1; LX = l1; return(true); }
/// <summary> /// 计算IGeometry的椭球面的 理论面积 /// </summary> /// <param name="geo">输入的分幅图的几何对象IGeometry(矩形状)</param> /// <returns>(单位:平方米)</returns> public override decimal Compute(IGeometry geo) { decimal P = 0.0M; decimal Lany = 60.0M; decimal ShapeArea = 0; //(1)最大最小角计算出WGS84大地经纬度坐标(四个点) 经差/纬差 decimal xmin = Maths.Todecimal(geo.Envelope.XMin); decimal ymin = Maths.Todecimal(geo.Envelope.YMin); decimal xmax = Maths.Todecimal(geo.Envelope.XMax); decimal ymax = Maths.Todecimal(geo.Envelope.YMax); ShapeArea = Maths.Todecimal((geo as IArea).Area); //double blxs = (geo as IArea).Area / (geo.Envelope as IArea).Area; //(2)转为经纬度坐标 //ToWGS84(xmax,ymax) decimal Bmin = 0, Lmin = 0, Bmax = 0, Lmax = 0; this.gassConv.GetBLFromXY(ymin, xmin, ref Bmin, ref Lmin, 0, this.Datum, this.Strip, this.L0, this.IsBigNumber); //ToWGS84(xmin,ymin) this.gassConv.GetBLFromXY(ymax, xmax, ref Bmax, ref Lmax, 0, this.Datum, this.Strip, this.L0, this.IsBigNumber); //ToWGS84(xmin,ymin) decimal dL = (Lmax + Lmin) / 2 - Lany; //经差△L decimal dB = Bmax - Bmin; //纬差(B2-B1) dL = dL * PI / 180; //(单位:弧度) dB = dB * PI / 180; //(单位:弧度) //default=西安椭球体参数 decimal b = this.EllipseParameter.b; decimal a = this.EllipseParameter.a; decimal A = this.EllipseParameter.A; decimal B = this.EllipseParameter.B; decimal C = this.EllipseParameter.C; decimal D = this.EllipseParameter.D; decimal E = this.EllipseParameter.E; decimal Bm = (Bmin + Bmax) / 2; Bm = Bm * PI / 180; //(单位:弧度) decimal CosBm = Maths.Cos(Bm); decimal Cos3Bm = Maths.Cos(3 * Bm); decimal Cos5Bm = Maths.Cos(5 * Bm); decimal Cos7Bm = Maths.Cos(7 * Bm); decimal Cos9Bm = Maths.Cos(9 * Bm); //求geo几何体的包络矩形的椭球面积 P = (2 * b * b * dL) * (A * Maths.Sin(dB * 1 / 2) * CosBm - B * Maths.Sin(dB * 3 / 2) * Cos3Bm + C * Maths.Sin(dB * 5 / 2) * Cos5Bm - D * Maths.Sin(dB * 7 / 2) * Cos7Bm + E * Maths.Sin(dB * 9 / 2) * Cos9Bm); //正算经纬度矩形的另外两个点的投影坐标值 decimal x2 = 0, y2 = 0, x4 = 0, y4 = 0; this.gassConv.GetXYFromBL(Bmin, Lmax, ref y2, ref x2, 0, this.Datum, EnumStrip.Strip3, this.IsBigNumber); this.gassConv.GetXYFromBL(Bmax, Lmin, ref y4, ref x4, 0, this.Datum, EnumStrip.Strip3, this.IsBigNumber); //求经纬度矩形的投影梯形面积(上底+下底)*高/2 decimal BLTrapeziaArea = ((x2 - xmin) + (xmax - x4)) * (ymax - ymin) / 2; decimal LLmj = P * ShapeArea / BLTrapeziaArea; return(LLmj); //(单位:平方米) }