示例#1
0
        //反算
        public override void GetBLFromXY(decimal x, decimal y, ref decimal B, ref decimal L)
        {
            //this.GetBLFromXY(x, y, ref B, ref L, 0, EnumProjectionDatum.Xian80, this.Strip, this.L0, this.IsBigNumber);
            //去掉大数和东移500公里
            decimal y1 = y - 500000.0M;

            if (this.IsBigNumber == true)
            {
                y1 = y1 - (this.L0 / (int)this.Strip) * 1000000M;
            }
            //计算临时参数
            decimal E     = K0 * x;
            decimal CosE  = Maths.Cos(E);
            decimal SinE  = Maths.Sin(E);
            decimal SinE3 = SinE * SinE * SinE;
            decimal SinE5 = SinE3 * SinE * SinE;
            decimal SinE7 = SinE5 * SinE * SinE;

            //求底点纬度
            decimal Bf = E + CosE * (K1 * SinE - K2 * SinE3 + K3 * SinE5 - K4 * SinE7);

            //计算临时参数
            decimal CosBf  = Maths.Cos(Bf);
            decimal CosBf2 = CosBf * CosBf;
            decimal t      = Maths.Tan(Bf);
            decimal η2     = e12 * CosBf2;
            decimal C      = a * a / b;
            decimal V      = Maths.Sqrt(1 + η2);
            decimal N      = C / V;
            decimal V2     = V * V;
            decimal t2     = t * t;
            decimal t4     = t2 * t2;
            decimal y1_N   = y1 / N;
            decimal y1_N2  = y1_N * y1_N;
            decimal y1_N3  = y1_N2 * y1_N;
            decimal y1_N4  = y1_N3 * y1_N;
            decimal y1_N5  = y1_N4 * y1_N;
            decimal y1_N6  = y1_N5 * y1_N;
            decimal V2t    = V * V * t;

            //计算经纬度值B,L
            B = Bf - (V2t * y1_N2) / 2 + ((5 + 3 * t2 + η2 - 9 * η2 * t2) * V2t * y1_N4 * 1.0M) / 24 - ((61 + 90 * t2 + 45 * t4) * V2t * y1_N6 * 1.0M) / 720;

            L = y1_N * 1.0M / CosBf - (1 + 2 * t2 + η2) * (1.0M / CosBf) * y1_N3 / 6 + (5 + 28 * t2 + 24 * t2 + 6 * η2 + 8 * η2 * t2) * (1.0M / CosBf) * y1_N5 * 1.0M / 120;
            AngleUnit_D dUnit = new AngleUnit_D(this.L0);

            L = L + dUnit.getArcDValue();  //弧度

            //弧度->度
            AngleUnit_ArcD acUnit = new AngleUnit_ArcD(B);

            dUnit = new AngleUnit_D(acUnit);
            B     = (decimal)dUnit.getAngle();

            acUnit = new AngleUnit_ArcD(L);
            dUnit  = new AngleUnit_D(acUnit);
            L      = (decimal)dUnit.getAngle();
        }
        /// <summary>
        ///  计算IGeometry的椭球面的 理论面积
        /// </summary>
        /// <param name="geo">输入的分幅图的几何对象IGeometry(矩形状)</param>
        /// <returns>(单位:平方米)</returns>
        public override decimal Compute(IGeometry geo)
        {
            decimal P = 0.0M;
            //(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);

            //(2)转为经纬度坐标
            decimal Bmin = 0.0M;//ToWGS84(xmin,ymin)
            decimal Lmin = 0.0M;

            decimal BMax = 0.0M;//ToWGS84(xmax,ymax)
            decimal Lmax = 0.0M;

            //double dL = Lmax - Lmin; //经差△L
            //double dB = BMax - Bmin; //纬差(B2-B1)

            //比例尺 5千
            IMapScale scale = new MapScale_5000();
            decimal   dL    = scale.L2_L1; //(单位:弧度)
            decimal   dB    = scale.B2_B1; //(单位:弧度)

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

            P = ((4 * PI * b * b * dL) / (360 * 60)) * (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);



            return(P); //(单位:平方米)
        }
        /// <summary>
        /// 求(B1,L1)-(B2,L2)的任意梯形椭球面积
        /// </summary>
        /// <param name="B1"></param>
        /// <param name="L1"></param>
        /// <param name="B2"></param>
        /// <param name="L2"></param>
        /// <returns></returns>
        public decimal Compute(decimal B1, decimal L1, decimal B2, decimal L2)
        {
            decimal P    = 0;
            decimal Lany = 60.0M;

            decimal dL = (L2 + L1) / 2 - Lany; //经差△L
            decimal dB = B2 - B1;              //纬差(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 = (B1 + B2) / 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);

            //求任意梯形椭球面积
            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);
            return(P);
        }
        /// <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;
            }
        }
        /// <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); //(单位:平方米)
        }