예제 #1
0
        /// <summary>
        /// Генерує сітку
        /// </summary>
        public static List <double[]> generateGrid(
            double cellSize,
            out int outColumns,
            out int outRows,
            double coLatitudeBound  = 0,
            double coLatitudeBound2 = 180,
            double LongitudeBoundW  = 0,
            double LongitudeBoundE  = 360,
            AngleType resType       = AngleType.Radians
            )
        {
            if (coLatitudeBound > 90 || coLatitudeBound < 0)
            {
                throw new Exception("coLatitudeBound повинна бути: 0 <= coLatitude <= 90");
            }
            if (LongitudeBoundW >= 360 || LongitudeBoundW < 0 || LongitudeBoundE > 360 || LongitudeBoundE <= 0)
            {
                throw new Exception("LongitudeBounds must be 0<=LongitudeBound<360");
            }
            if (LongitudeBoundW > LongitudeBoundE)
            {
                throw new Exception("West longituge bound повинна бути менша за East longituge");
            }
            double gridRows = (180 - coLatitudeBound - (180 - coLatitudeBound2)) / cellSize;
            double gridColumns = (360 - LongitudeBoundW - (360 - LongitudeBoundE)) / cellSize;
            int    addRow = 0, addCol = 0;

            if ((Math.Round(gridRows) - gridRows) < 0)
            {
                addRow = 1;
            }
            if ((Math.Round(gridColumns) - gridColumns) < 0)
            {
                addCol = 1;
            }
            gridColumns = (int)gridColumns + addCol;
            outColumns  = (int)gridColumns;
            gridRows    = (int)gridRows + addRow;
            outRows     = (int)gridRows;
            int             gridCells       = (int)(gridColumns * gridRows);
            List <double[]> greed           = new List <double[]>(gridCells);
            double          coLatitudeStart = coLatitudeBound + (cellSize / 2D);
            double          LongStart       = deg2rad(LongitudeBoundW);

            #region ifRadians
            if (resType == AngleType.Radians)
            {
                MathFunc.deg2rad(ref cellSize);
                MathFunc.deg2rad(ref coLatitudeStart);
            }
            #endregion
            for (int r = 0; r < gridRows; r++)
            {
                for (int c = 0; c < gridColumns; c++)
                {
                    greed.Add(new double[] { coLatitudeStart + r * cellSize, LongStart + cellSize * (0.5 + c) });
                }
            }
            return(greed);
        }
예제 #2
0
        //Зчитування даних з файлу .SGG
        public static double[][] read_SGG_data(string folder, MainForm.setProgressDel d)
        {
            System.IO.FileInfo fi = new FileInfo(folder);
            folder = fi.DirectoryName;
            List <string> files = new List <string>();

            foreach (var file in System.IO.Directory.GetFiles(folder))
            {
                var f = new FileInfo(file);
                if (f.Extension.Equals(".SGG", System.StringComparison.CurrentCultureIgnoreCase))
                {
                    files.Add(file);
                }
                ;
            }
            List <double[]> myList = new List <double[]>(getLines(files[0]));

            if (files.Count > 0)
            {
                foreach (string filename in files)
                {
                    string[] lines = System.IO.File.ReadAllLines(filename);
                    var      x     = Parallel.For(0, lines.Length, (i) => {
                        double[] temp = null;
                        double lat    = 0; int l = 0;
                        string[] line = null;
                        lock (lines)
                        {
                            line = lines[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        }
                        if (line.Length > 20)
                        {
                            lat = double.Parse(line[3]);
                            //if (lat < 0) lat += 360;
                            lat  = MathFunc.deg2rad(lat);
                            temp = new double[] { double.Parse(line[1]), MathFunc.deg2rad(90 - double.Parse(line[2])), lat, double.Parse(line[6]) };

                            if (Math.Abs(temp[1]) < Math.PI && Math.Abs(temp[2]) < 2D * Math.PI)
                            {
                                lock (myList) { myList.Add(temp); }
                            }
                            else
                            {
                                System.Windows.Forms.MessageBox.Show("Помилка в лінії номер " + i.ToString());
                            }
                            l++;
                            if (Math.Round(l / 20000D) == (double)l / 20000D)
                            {
                                d.Invoke(l / lines.Length, 1, "Обробка файлу вимірюваннь");
                            }
                            ;
                        }
                    });
                }
            }
            ;
            return(myList.ToArray());
        }
예제 #3
0
 //Запис висот геоїда і аномалій для сітки в текстовий файл
 public static void writeGeoidHeightsAndAnomalysToTxt(List <double[]> greed, double[] heights, double[] anomalies, ReferenceSystem rs, string file)
 {
     System.IO.TextWriter w = new System.IO.StreamWriter(file, false);
     for (int i = 0; i < greed.Count; i++)
     {
         w.WriteLine(string.Format("{0} {1} {2,10:0.0000} {3,10:0.0000}", MathFunc.rad2deg(MathFunc.convertThethaToB(greed[i][0], rs)), MathFunc.rad2deg(greed[i][1]), heights[i], anomalies[i]));
     }
     w.Close();
 }
예제 #4
0
        //Записує усереднені градієнти для кожної клітинки сітки
        public static void writeGreedToCsvFileWithMeasureS(List <double[]> greed, double[] data, string file)
        {
            System.IO.TextWriter tw = new System.IO.StreamWriter(file, false);
            int i = 0;

            foreach (var item in greed)
            {
                tw.WriteLine("{2:0.000};{1:0.000};{0}", data[i], MathFunc.rad2deg((Math.PI / 2D) - item[0]), MathFunc.rad2deg(item[1] - Math.PI));
                i++;
            }
            tw.Flush();
            tw.Close();
        }
예제 #5
0
        /// <summary>
        /// Визначає, до якої клітинки сітки відноситься кожен результат. Кожен елемент List() відповідає елементу Greed, і є масивом номерів точок з pointsData
        /// </summary>
        /// <param name="rs">Референсна система</param>
        /// <param name="pointsData">Масив точок типу: {radius,coLatitude,Longitude,Gradient}</param>
        /// <param name="greed">Масив з клітинками сітки типу: {{colat,long},{colat,long},{colat,long}...}</param>
        /// <param name="rowCount">Кількість рядків сітки</param>
        /// <param name="colsCount">Кількість стовпчиків сітки</param>
        /// <returns>Повертає масив з номерами точок з масиву pointsData</returns>
        public static List <int>[] getMappingOfPoints(ReferenceSystem rs, double[][] pointsData, double[][] greed, int rowCount, int colsCount, double avgRadius)
        {
            List <int>[] map = new List <int> [greed.Length];
            for (int i = 0; i < map.Length; i++)
            {
                map[i] = new List <int>();
            }
            double cellSize = MathFunc.deg2rad(rs.gridParameters.cellSize);
            double zero     = greed[0][0] - cellSize / 2D;
            double l_zero   = greed[0][1] - cellSize / 2d;

            Parallel.For(0, pointsData.Length, (i) =>
            {
                double fi, lambda, r;
                lock (pointsData)
                {
                    fi = pointsData[i][1]; lambda = pointsData[i][2]; r = pointsData[i][0];
                }
                if (fi >= greed[0][0] && fi <= greed[greed.Length - 1][0] && lambda >= greed[0][1] && lambda <= greed[greed.Length - 1][1] && Math.Abs(r - avgRadius) < 10000d)
                {
                    fi        = fi - (zero);
                    lambda    = lambda - l_zero;
                    int n     = (int)Math.Floor(fi / cellSize);
                    int m     = (int)Math.Floor(lambda / cellSize);
                    int index = (colsCount * n) + m;
                    lock (map)
                    {
                        var x1 = cellSize / 2D - Math.Abs(greed[index][0] - zero - fi);
                        var x2 = cellSize / 2D - Math.Abs(greed[index][1] - l_zero - lambda);
                        if (x1 < 0 || x2 < 0)
                        {
                            System.Windows.Forms.MessageBox.Show("getMappingOfPoints: неправильна визначена клітинка точки " + i.ToString());
                        }
                        else
                        {
                            map[index].Add(i);
                        }
                    }
                }
                ;
            });
            return(map);
        }
예제 #6
0
        //Записує кількість вимірів для кожної клітинки сітки
        public static void writeGreedToCsvFileWithMeasureCount(List <double[]> greed, List <int>[] map, string file)
        {
            System.IO.TextWriter tw = new System.IO.StreamWriter(file, false);
            int i  = 0;
            int ii = 0;

            foreach (var item in greed)
            {
                if (item[1] > Math.PI)
                {
                    ii++;
                }
                ;
                tw.WriteLine("{2:0.000};{1:0.000};{0}", map[i].Count, MathFunc.rad2deg((Math.PI / 2D) - item[0]), MathFunc.rad2deg(item[1] - Math.PI));
                i++;
            }
            tw.Flush();
            tw.Close();
        }
예제 #7
0
        /// <summary>
        /// Обчислення градієнту V_zz для заданих координат по моделі "in_model"
        /// </summary>
        public static double getGradient(ReferenceSystem rs, GravityModel in_model, double coLat, double longit, MathFunc.AngleType angType = MathFunc.AngleType.Radians)
        {
            GravityModel gm;

            if (in_model.model_a != rs.a || in_model.model_GM != rs.GM)
            {
                gm = in_model.rescaleModel(rs);
            }
            else
            {
                gm = new GravityModel(in_model);
            };
            if (angType == MathFunc.AngleType.Degrees)
            {
                MathFunc.deg2rad(ref longit);
            }
            double grad = 0;
            double tmp = 0, sum_tmp = 0, sum_tmp_2 = 0;

            double[] legendrePolynoms = null;
            MathFunc.getLegendre(rs.maxDegree, coLat, out legendrePolynoms, angType);
            for (int i = 0; i <= rs.maxDegree; i++)
            {
                int n = MathFunc.getArraySize(i - 1) - 1;
                sum_tmp_2 = 0;
                sum_tmp   = (i + 1) * (i + 2) * Math.Pow(rs.a / rs.satelliteSphere, i + 3);
                for (int m = 0; m < gm.c_coef[i].Length; m++)
                {
                    double a1 = legendrePolynoms[n + m + 1], a2 = gm.c_coef[i][m] * Math.Cos(m * longit), a3 = gm.s_coef[i][m] * Math.Sin(m * longit);
                    double x = a1 * (a2 + a3);
                    sum_tmp_2 += x;
                }
                tmp += sum_tmp * sum_tmp_2;
            }
            grad = rs.GM / Math.Pow(rs.a, 3D) * tmp;
            return(grad);
        }
예제 #8
0
        public static double[][] getGeoidHeightAndAnomalys(ReferenceSystem rs, GravityModel model, List <double[]> grid, System.Threading.CancellationToken ct, System.Threading.CancellationToken ct2, NormalGammaFormula gamma_0_formula = NormalGammaFormula.Somigliana, MainForm.setProgressDel d = null)
        {
            GravityModel gm;

            if (model.model_a != rs.a || model.model_GM != rs.GM)
            {
                gm = new GravityModel(model.rescaleModel(rs), rs.a, rs.GM);
            }
            else
            {
                gm = new GravityModel(model, model.model_a, model.model_GM);
            };
            gm = getDisturbingModel(rs, gm);
            double[]        heights = new double[grid.Count];
            double[]        anomaly = new double[grid.Count];
            int[][]         t_nm = MathFunc.get_nm(gm.maxDegree);
            double[]        legendrePolys_old = null; double point_old = double.MinValue; object locker = new object(), locker2 = new object();
            int             position = 0;
            int             count = grid.Count, position_p = (rs.maxDegree < 150)?(int)Math.Round(0.01d * count):5;
            ParallelOptions po = new ParallelOptions();

            po.MaxDegreeOfParallelism = Environment.ProcessorCount;
            po.CancellationToken      = ct;
            try
            {
                Parallel.For(0, grid.Count, po, (pointIndex) =>
                {
                    Label1: if (ct2.IsCancellationRequested)
                    {
                        System.Threading.Thread.Sleep(1000);
                    }
                    else
                    {
                        goto label2;
                    }
                    goto Label1;
                    label2:    double gamma_0 = 0, B = 0, r = 0;
                    double[] legendrePolys    = null;
                    double[] point            = grid[pointIndex];
                    lock (locker2)
                    {
                        if (point_old != double.MinValue)
                        {
                            if (point[0] == point_old)
                            {
                                legendrePolys = new double[legendrePolys_old.Length];
                                legendrePolys_old.CopyTo(legendrePolys, 0);
                            }
                            MathFunc.getLegendre(rs.maxDegree, point[0], out legendrePolys);
                            legendrePolys_old = new double[legendrePolys.Length];
                            legendrePolys.CopyTo(legendrePolys_old, 0);
                            point_old = point[0];
                        }
                        else
                        {
                            MathFunc.getLegendre(rs.maxDegree, point[0], out legendrePolys);
                            legendrePolys_old = new double[legendrePolys.Length];
                            legendrePolys.CopyTo(legendrePolys_old, 0);
                            point_old = point[0];
                        }
                    }
                    B = MathFunc.convertThethaToB(point[0], rs);
                    r = MathFunc.getGeocentrDistanceToPointOnElips(rs, B);
                    if (gamma_0_formula == NormalGammaFormula.Somigliana)
                    {
                        gamma_0 = rs.gamma_a * (1d + rs.k * Math.Pow(Math.Sin(B), 2d)) / Math.Sqrt(1d - rs.firstExcentricity_2 * Math.Pow(Math.Sin(B), 2d));
                    }
                    else
                    {
                        gamma_0 = 9.78030d * (1d + 0.005302 * Math.Pow(Math.Sin(B), 2d) - 0.000007 * Math.Pow(Math.Sin(2d * B), 2d));
                    }
                    double a1, a2_x = rs.a / r, a2_t, a3, cosMlambda, sinMlambda, a1_a, a2_a = 0, a2 = 0, a2_x_m = a2_x;
                    a1     = rs.GM / (r * gamma_0);
                    a1_a   = rs.GM / (r * r);
                    int az = 0;
                    for (int n = 0; n < rs.maxDegree; n++)
                    {
                        int x = (n == 0) ? 0 : -1;
                        a3    = 0;
                        az   += (n - 1) + 1;
                        for (int m = 0; m <= n; m++)
                        {
                            cosMlambda = Math.Cos(m * point[1]);
                            sinMlambda = Math.Sin(m * point[1]);
                            a3        += (gm.c_coef[n][m] * cosMlambda + gm.s_coef[n][m] * sinMlambda) * legendrePolys[az + (n - m)];
                        }
                        if (n > 1)
                        {
                            a2_x *= a2_x_m; a2_t = a2_x;
                        }
                        else
                        {
                            a2_t = Math.Pow(a2_x, n);
                        };
                        a2   += a2_t * a3;
                        a2_a += a2_t * (n - 1) * a3;
                    }

                    double tmp_h = a1 * a2, tmp_a = a1_a * a2_a * 1e5;
                    lock (heights)
                    { heights[pointIndex] = tmp_h; }
                    lock (anomaly)
                    { anomaly[pointIndex] = tmp_a; }
                    if (d != null)
                    {
                        position++;
                        if (position > position_p)
                        {
                            lock (locker) { position_p += position_p; }; d.Invoke(position, count, "Обчислено висоти для точок: ");
                        }
                        ;
                        if (position >= count)
                        {
                            d.Invoke(0, 1, "");
                        }
                        ;
                    }
                });
            }
            catch (OperationCanceledException)
            {
                return(new double[2][]);
            }
            return(new double[][] { heights, anomaly });
        }
예제 #9
0
        //Обчислення аномалій сили ваги для сітки (в мГал)
        public static double[] getAnomaly(ReferenceSystem rs, GravityModel model, List <double[]> grid, MainForm.setProgressDel d = null)
        {
            GravityModel gm;

            if (model.model_a != rs.a || model.model_GM != rs.GM)
            {
                gm = new GravityModel(model.rescaleModel(rs), rs.a, rs.GM);
            }
            else
            {
                gm = new GravityModel(model, model.model_a, model.model_GM);
            };
            gm = getDisturbingModel(rs, gm);
            double[] heights = new double[grid.Count];
            int[][]  t_nm = MathFunc.get_nm(gm.maxDegree);
            double[] legendrePolys_old = null; double point_old = double.MinValue; object locker = new object(), locker2 = new object();
            int      position = 0;
            int      count = grid.Count, position_p = (int)Math.Round(0.01d * count);

            Parallel.For(0, grid.Count, (pointIndex) =>
            {
                double B = 0, r = 0;
                double[] legendrePolys = null;
                double[] point         = grid[pointIndex];
                lock (locker2)
                {
                    if (point_old != double.MinValue)
                    {
                        if (point[0] == point_old)
                        {
                            legendrePolys = new double[legendrePolys_old.Length];
                            legendrePolys_old.CopyTo(legendrePolys, 0);
                        }
                        MathFunc.getLegendre(gm.maxDegree, point[0], out legendrePolys);
                        legendrePolys_old = new double[legendrePolys.Length];
                        legendrePolys.CopyTo(legendrePolys_old, 0);
                        point_old = point[0];
                    }
                    else
                    {
                        MathFunc.getLegendre(gm.maxDegree, point[0], out legendrePolys);
                        legendrePolys_old = new double[legendrePolys.Length];
                        legendrePolys.CopyTo(legendrePolys_old, 0);
                        point_old = point[0];
                    }
                }
                B             = MathFunc.convertThethaToB(point[0], rs);
                r             = MathFunc.getGeocentrDistanceToPointOnElips(rs, B);
                double a1, a2 = 0, a3, cosMlambda, sinMlambda;
                a1            = rs.GM / (r * r);
                for (int n = 0; n < gm.maxDegree; n++)
                {
                    a3 = 0;
                    for (int m = 0; m <= n; m++)
                    {
                        cosMlambda = Math.Cos(m * point[1]);
                        sinMlambda = Math.Sin(m * point[1]);
                        lock (gm)
                        { a3 += (gm.c_coef[n][m] * cosMlambda + gm.s_coef[n][m] * sinMlambda) * legendrePolys[MathFunc.getArraySize(n - 1) + (n - m)]; }
                    }
                    a2 += Math.Pow(rs.a / r, n) * (n - 1) * a3;
                }
                lock (heights)
                { heights[pointIndex] = a1 * a2; }
                if (d != null)
                {
                    position++;
                    if (position > position_p)
                    {
                        lock (locker) { position_p += position_p; }; d.Invoke(position, count, "Обчислено висоти для точок: ");
                    }
                    ;
                    if (position >= count)
                    {
                        d.Invoke(0, 1, "");
                    }
                    ;
                }
            });
            return(heights);
        }
예제 #10
0
 public static double convertThethaToB(double thetha, ReferenceSystem rs, MathFunc.AngleType angType = MathFunc.AngleType.Radians)
 {
     double phi = 0;
     if (angType == MathFunc.AngleType.Degrees) { phi = deg2rad(90d - thetha); } else { phi = Math.PI / 2d - thetha; };
     return (Math.Atan(Math.Tan(phi) / (1d - rs.firstExcentricity_2)));
 }
예제 #11
0
 /// <summary>
 /// Генерує повністю нормовані приєднані поліномами Лежандра для ступеня n і порядку від 0 до n, і полярної відстані  coLat
 /// </summary>
 /// <param name="n">Максимальний порядок</param>
 /// <param name="coLat">Полярна відстань theta=90deg-phi</param>
 /// <param name="resType">Одиниці, в яких задана полярна відстань</param>
 /// <returns>масив double[] з поліномами від нуля до n ({P_00,P_10,P_11,P_20,P_21,P_22,P_30,...,P_nn})</returns>
 public static double[] getLegendrePolynomialsMy(int maxDegree, double coLat, MathFunc.AngleType resType = AngleType.Radians)
 {
     func_l f1 = (l) => { return Math.Sqrt((2D*l+1)/(2D*l)); };
     func_l f2 = (l) => { return Math.Sqrt(2D * (double)l + 1D); };
     func_lm W3 = (l, m) => { return Math.Sqrt((4D * Math.Pow((double)l,2D) - 1D) / (double)(l*l-m*m)); };
     #region перевірка
     if (resType == MathFunc.AngleType.Degrees)
     {
         deg2rad(ref coLat);
     }
     #endregion
     List<double> res = new List<double> (getArraySize(maxDegree));
     double[][]tmp = new double[maxDegree+1][];
     int[][] indexes = get_nm(maxDegree);
     double sinColat = Math.Sin(coLat), cosColat = Math.Cos(coLat);
     tmp[0] = new double[] {1};
     tmp[1] = new double[2];
     tmp[1][1] = Math.Sqrt(3D) * sinColat;
     for (int i = 2; i < tmp.Length; i++)
     {
         tmp[i] = new double[i+1];
         tmp[i][i] = f1(i) * sinColat * tmp[i-1][i-1];
     }
     int mm = 0;
     for (int i = 1; i < tmp.Length; i++)
     {
         tmp[i][i-1] = f2(i) * cosColat * tmp[i-1][i-1];
         if (i > 1) {
             for (int j = 2; j <=i; j++)
             {
                 mm=i-j;
                 tmp[i][mm] = W3(i,mm)*(cosColat*tmp[i-1][mm]-1D/W3(i-1,mm)*tmp[i-2][mm]);
             }
         }
     }
     for (int i = 0; i < tmp.Length; i++)
     {
         foreach (var item in tmp[i])
         {
             res.Add(item);
         }
     }
     return res.ToArray();
 }
예제 #12
0
 /// <summary>
 /// Генерує повністю нормовані приєднані поліномами Лежандра для ступеня n і порядку від 0 до n, і полярної відстані  coLat
 /// </summary>
 /// <param name="i">Максимальний порядок</param>
 /// <param name="d">Полярна відстань d=90deg-phi</param>
 /// <param name="ad">Масив в який буде записано результат, він буде перезаписаний</param>
 /// <param name="angType">Одиниці, в яких задана полярна відстань</param>
 /// <returns>масив double[] з поліномами від нуля до n ({P_00,P_10,P_11,P_20,P_21,P_22,P_30,...,P_nn})</returns>
 public static void getLegendre(int i, double d, out double[] res, MathFunc.AngleType angType = AngleType.Radians)
 {
     #region proverka
     if (angType == MathFunc.AngleType.Degrees)
     {
         deg2rad(ref d);
     }
     #endregion
     int k_ = ((i + 1) * (i + 2)) / 2;
     double[] ad = new double[k_];
     ad[0] = 1.0D;                       //00
     double d1 = Math.Sin(d);
     double d2 = Math.Cos(d);
     ad[1] = Math.Sqrt(3D) * d1;         //11
     ad[2] = Math.Sqrt(3D) * d2;         //10
     if (i <= 1)
     {
         res = ad;
         return;
     }
     int j = 3;
     int k = 1;
     int l = 2;
     for (int i1 = 2; i1 <= i; i1++)
     {
         int j1 = 2 * i1 + 1;
         int k1 = j1 - 2;
         int l1 = k1 - 2;
         j++;
         ad[j - 1] = (Math.Sqrt((double)j1) / (double)i1) * (Math.Sqrt((double)k1) * d1 * ad[l - 1] - ((double)(i1 - 1) * ad[k - 1]) / Math.Sqrt((double)l1));
         double d3 = Math.Sqrt(k1) * d2;
         double d4 = Math.Sqrt(2D) * d3 * ad[l - 1];
         double d6 = Math.Sqrt(k1) * d1;
         j++;
         if (i1 >= 3)
             d4 += (Math.Sqrt((i1 - 1) * (i1 - 2)) * ad[k]) / Math.Sqrt(l1);
         ad[j - 1] = (Math.Sqrt(j1) * d4) / Math.Sqrt(i1 * (i1 + 1));
         for (int i2 = 2; i2 <= i1; i2++)
         {
             int j2 = i1 + i2;
             int k2 = j2 - 1;
             j++;
             double d5 = d3 * ad[(l + i2) - 2];
             double d7 = d6 * ad[(l + i2) - 1];
             if (i2 + 2 > i1)
             {
                 ad[j - 1] = (Math.Sqrt(j1) * d5) / Math.Sqrt(j2 * k2);
             }
             else
             {
                 d7 -= (Math.Sqrt(k2 * (i1 - i2 - 1)) * ad[(k + i2) - 1]) / Math.Sqrt(l1);
                 ad[j - 1] = (Math.Sqrt(j1) * d7) / Math.Sqrt(j2 * (i1 - i2));
             }
         }
         k += i1 - 1;
         l += i1;
     }
     res = ad;
 }
예제 #13
0
 //Формування рядка матриці коефіцієнтів рівнянь поправок
 public static double[] getCoefMatrixLineKoop(ReferenceSystem rs, int n, int[][] t_nm, double r, double coLatitude, double longitude, MathFunc.AngleType angType = AngleType.Radians)
 {
     if (angType == AngleType.Degrees) { deg2rad(ref longitude); }
     List<double> line = new List<double>((getArraySize(n) - 3) * 2 - (rs.maxDegree - 1));
     double[][] legPol = getLegendreP_lm_cos_phi(n, Math.PI / 2d - coLatitude);
     double u_1 = rs.GM / Math.Pow(rs.a, 3d), u_2 = rs.a / rs.satelliteSphere;
     for (int l = 2; l <= rs.maxDegree; l++)
     {
         double u_3 = u_1 * Math.Pow(u_2, l + 3)*(l+1)*(l+2);
         for (int m = 0; m <= l; m++)
         {
                 line.Add(u_3 * legPol[l][m] * Math.Cos((double)m * longitude));
             if (m != 0) {
                 line.Add(u_3 * legPol[l][m] * Math.Sin((double)m * longitude));
             }
         }
     }
     return line.ToArray();
 }
예제 #14
0
        /// <summary>
        /// Обчислює масив з коефіцієнтами рядка в матриці
        /// </summary>
        /// <param name="rs">Еліпсоїд</param>
        /// <param name="n">Порядок розвинення</param>
        /// <param name="r">Радіус сфери, до якої віднесені виміри</param>
        /// <param name="coLatitude">Полярний кут tetha = 90deg-phi</param>
        /// <param name="longitude">Довгота</param>
        /// <param name="angType">Одиниці, в яких задано попередні кути</param>
        /// <returns></returns>
        public static double[] getCoefMatrixLine(ReferenceSystem rs, int n, int[][] t_nm, double r, double coLatitude, double longitude, MathFunc.AngleType angType = AngleType.Radians)
        {
            if (angType == AngleType.Degrees) { deg2rad(ref longitude); }
            double[] line = new double[(getArraySize(n) - 3) * 2-(rs.maxDegree-1)];
            double u_1 = rs.GM / (Math.Pow(rs.a, 3d));
            double[] legPol = null;
            getLegendre(n, coLatitude, out legPol, angType);
            double tmp_n = 0;
            double tmp_m = 0;
            int lineIndex = 0;
            for (int i = 0; i <= legPol.Length; i++)
            {
                if (i < 4) { continue; }
                tmp_n = t_nm[i-1][0];
                tmp_m = t_nm[i-1][1];
                double b = legPol[getArraySize(t_nm[i - 1][0] - 1) + t_nm[i - 1][0] - t_nm[i - 1][1]];
                double a = (tmp_n + 1D) * (tmp_n + 2D) * Math.Pow(rs.a / rs.satelliteSphere, (double)tmp_n + 3d)*u_1;
                double a1 = a * Math.Cos(tmp_m * longitude);
                line[lineIndex] = a1 * b;
                if (tmp_m > 0)
                {
                    double a2 = a * Math.Sin(tmp_m * longitude);
                    line[lineIndex + 1] = a2 * b;
                    lineIndex += 2;
                }
                else {
                    lineIndex++;
                }

            }
            return line;
        }
예제 #15
0
 /// <summary>
 /// Обчислення градієнту V_zz для заданих координат по моделі "in_model"
 /// </summary>
 public static double getGradient(ReferenceSystem rs,GravityModel in_model, double coLat, double longit, MathFunc.AngleType angType = MathFunc.AngleType.Radians)
 {
     GravityModel gm;
     if (in_model.model_a != rs.a || in_model.model_GM != rs.GM) { gm = in_model.rescaleModel(rs); } else { gm = new GravityModel(in_model); };
     if (angType == MathFunc.AngleType.Degrees) { MathFunc.deg2rad(ref longit); }
     double grad = 0;
     double tmp = 0, sum_tmp = 0, sum_tmp_2 = 0;
     double[] legendrePolynoms = null;
     MathFunc.getLegendre(rs.maxDegree, coLat, out legendrePolynoms, angType);
     for (int i = 0; i <= rs.maxDegree; i++)
     {
         int n = MathFunc.getArraySize(i - 1) - 1;
         sum_tmp_2 = 0;
         sum_tmp = (i + 1) * (i + 2) * Math.Pow(rs.a / rs.satelliteSphere, i + 3);
         for (int m = 0; m < gm.c_coef[i].Length; m++)
         {
             double a1 = legendrePolynoms[n + m + 1], a2 = gm.c_coef[i][m] * Math.Cos(m * longit), a3 = gm.s_coef[i][m] * Math.Sin(m * longit);
             double x = a1 * (a2 + a3);
             sum_tmp_2 += x;
         }
         tmp += sum_tmp * sum_tmp_2;
     }
     grad = rs.GM / Math.Pow(rs.a, 3D) * tmp;
     return grad;
 }