/// <summary>
/// Возвращает плоскую координату X для пары угловых координат (зона проекции определена константой)
/// </summary>
/// <param name="Bd">Широта, град</param>
/// <param name="Ld">Долгота, град</param>
/// <returns></returns>
static public double flat_x(double Bd, double Ld)
{
int N = 6;
//int N = GetProjectionZone(Ld);
return flat_x(Bd, Ld, N);
}
/// <summary>
/// Возвращает плоскую координату X для пары угловых координат в заданной зоне проекции
/// </summary>
/// <param name="Bd">Широта, град</param>
/// <param name="Ld">Долгота, град</param>
/// <param name="N">Зона проекции</param>
/// <returns></returns>
static public double flat_x(double Bd, double Ld, int N)
{
double b, L, l_rad;
b = Bd * Math.PI / 180;
L = Ld * Math.PI / 180;
l_rad = (Ld - (3 + 6 * (N - 1))) / 57.29577951;
double Result, R1, R2, R3, R4, M1, M2;
R1 = 1594561.25 + 5336.535 * Math.Pow((Math.Sin(b)), 2) + 26.79 * Math.Pow((Math.Sin(b)), 4) + 0.149 * Math.Pow((Math.Sin(b)), 6);
R2 = 672483.4 - 811219.9 * Math.Pow((Math.Sin(b)), 2) + 5420.0 * Math.Pow((Math.Sin(b)), 4) - 10.6 * Math.Pow((Math.Sin(b)), 6);
R3 = 278194 - 830174 * Math.Pow((Math.Sin(b)), 2) + 572434 * Math.Pow((Math.Sin(b)), 4) - 16010 * Math.Pow((Math.Sin(b)), 6);
R4 = 109500 - 574700 * Math.Pow((Math.Sin(b)), 2) + 863700 * Math.Pow((Math.Sin(b)), 4) - 398600 * Math.Pow((Math.Sin(b)), 6);
M2 = (R2 + (Math.Pow(l_rad, 2)) * (R3 + (Math.Pow(l_rad, 2)) * (R4)));
M1 = (R1 + (Math.Pow(l_rad, 2)) * M2);
Result = 6367558.4698 * b - Math.Sin(2 * b) * (16002.89 + 66.9607 * Math.Pow((Math.Sin(b)), 2) + 0.3515 * Math.Pow((Math.Sin(b)), 4) - Math.Pow(l_rad, 2) * M1);
return Result;
}
/// <summary>
/// Возвращает плоскую координату Y для пары угловых координат (зона проекции определена константой)
/// </summary>
/// <param name="Bd">Широта, град</param>
/// <param name="Ld">Долгота, град</param>
/// <returns></returns>
static public double flat_y(double Bd, double Ld)
{
int N = 6;
//int N = GetProjectionZone(Ld);
return flat_y(Bd, Ld, N);
}
/// <summary>
/// Возвращает плоскую координату Y для пары угловых координат в заданной зоне проекции
/// </summary>
/// <param name="Bd">Широта, град</param>
/// <param name="Ld">Долгота, град</param>
/// <param name="N">Зона проекции</param>
/// <returns></returns>
static public double flat_y(double Bd, double Ld, int N)
{
double b, L, l_rad;
b = Bd * Math.PI / 180;
L = Ld * Math.PI / 180;
l_rad = (Ld - (3 + 6 * (N - 1))) / 57.29577951;
double Result, R1, R2, R3, R4, M1;
R1 = 6378245 + 21346.1415 * Math.Pow((Math.Sin(b)), 2) + 107.159 * Math.Pow((Math.Sin(b)), 4) + 0.5977 * Math.Pow((Math.Sin(b)), 6);
R2 = 1070204.16 - 2136826.66 * Math.Pow((Math.Sin(b)), 2) + 17.98 * Math.Pow((Math.Sin(b)), 4) - 11.99 * Math.Pow((Math.Sin(b)), 6);
R3 = 270806 - 1523417 * Math.Pow((Math.Sin(b)), 2) + 1327645 * Math.Pow((Math.Sin(b)), 4) - 21701 * Math.Pow((Math.Sin(b)), 6);
R4 = 79690 - 866190 * Math.Pow((Math.Sin(b)), 2) + 1730360 * Math.Pow((Math.Sin(b)), 4) - 945460 * Math.Pow((Math.Sin(b)), 6);
M1 = Math.Pow(l_rad, 2) * (R2 + Math.Pow(l_rad, 2) * (R3 + Math.Pow(l_rad, 2) * (R4)));
Result = (5 + 10 * N) * Math.Pow(10, 5) + l_rad * Math.Cos(b) * (R1 + M1);
return Result;
}
/// <summary>
/// Возвращает значение зоны проекции для заданного значения долготы
/// </summary>
/// <param name="Ld">Долгота, град</param>
/// <returns>Значение зоны</returns>
static public int GetProjectionZone(double Ld)
{
return Convert.ToInt32(Microsoft.VisualBasic.Conversion.Fix((6 + Ld) / 6));
}
/// <summary>
/// Возвращает значение зоны проекции, пригодное для проецирования большинства из массива долгот
/// </summary>
/// <param name="longitudes">Массив долгот, град</param>
/// <returns></returns>
static public int GetProjectionZone(double[] longitudes)
{
// Значения зон
List<int> lst_values = new List<int>();
// Количество вхождений
List<int> lst_valueCounts = new List<int>();
foreach (double longitude in longitudes)
{
// Зона для текущей долготы
int currentN = GetProjectionZone(longitude);
// Если значение новое, то занесем его в список и создадим нулевой счетчик этого значения
if (!lst_values.Exists(p => p == currentN))
{
lst_values.Add(currentN);
lst_valueCounts.Add(0);
}
int index = lst_values.IndexOf(currentN); // Иднекс этого значения
lst_valueCounts[index] += 1; // Увеличим счетчик этого значения
}
// Индекс значения с максимальным вхождением
int maxIndex = lst_valueCounts.IndexOf(lst_valueCounts.Max());
return lst_values[maxIndex];
}
static public double DegreesMinutesToDouble(int degrees, double minutes)
{
return DegreesMinutesSecondsToDouble((double)degrees, minutes, 0);
}
static public double DegreesMinutesSecondsToDouble(int degrees, int minutes, double seconds)
{
return DegreesMinutesSecondsToDouble((double)degrees, minutes, seconds);
}
static public double DegreesMinutesSecondsToDouble(double degrees, double minutes, double seconds)
{
minutes += seconds / 60;
degrees += minutes / 60;
return degrees;
}
}