public static double convertBToThetha(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))); }
/// <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()); }
/// <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; }
//Формування рядка матриці коефіцієнтів рівнянь поправок 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()); }
/// <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); }
/// <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); }