Экранные координаты в мировые - C#
Формулировка задачи:
Ребят всем доброго времени суток, подскажите как перевести координаты курсора т.е. (X и Y) в долготу и широту мировую куда копать что почитать? Может кто то делал и поделится. Я понимаю что нужно установить начальную точку в виде долготы и широты и от нее уже считать, только как считать не могу найти полезного ресурса что б изучить данный вопрос.
Всем спасибо!
Решение задачи: «Экранные координаты в мировые»
textual
Листинг программы
public class ClassGeoTransform : IClassGeoTransform
{
private const double M_PI = 3.14159265358979323846;
private const double M_PI_2 = M_PI / 2.0;
private const double D_R = (M_PI / 180.0);
private const double R_D = (180.0 / M_PI);
private const double R_MAJOR = 6378137.0;
private const double R_MINOR = 6356752.3142;
private static double R_MAJOR_POW_2 = System.Math.Pow(R_MAJOR, 2);
private static double R_MINOR_POW_2 = System.Math.Pow(R_MINOR, 2);
private const double RATIO = (R_MINOR / R_MAJOR);
private static double ECCENT = (System.Math.Sqrt(1.0 - (RATIO * RATIO)));
private double COM = (0.5 * ECCENT);
//private const double SPHERICAL_A = 6378137;
//private const double EQUATOR_R = 6378245.0; // Радиус по экватору
//private const double MERIDIAN_R = 6356863.0; // Радиус по меридиану
//#define min(a, b) (a <= b ? a : b)
//#define max(a, b) (a >= b ? a : b)
// Проекция Меркатора
public ClassPointD MercatorTransform(double longitude, double latitude)
{
//auto lat = min(89.5, max(latitude, -89.5));
double lat = (89.5 <= ((latitude >= -89.5) ? latitude : -89.5)) ? 89.5 : ((latitude >= -89.5) ? latitude : -89.5);
double phi = lat * D_R;
double sin_phi = System.Math.Sin(phi);
double con = ECCENT * sin_phi;
con = System.Math.Pow((1.0 - con) / (1.0 + con), COM);
double ts = System.Math.Tan(0.5 * (M_PI * 0.5 - phi)) / con;
double y = 0 - R_MAJOR * System.Math.Log(ts);
double x = R_MAJOR * longitude * D_R;
return new ClassPointD(x, y);
}
// Преобразование коодинат из одной системы в другую с учетом поворота
public ClassPointD VectorTransform(double csys1_ax1, double csys1_ay1, double csys1_ax2, double csys1_ay2, double csys1_bx2, double csys1_by2,
double csys2_ax1, double csys2_ay1, double csys2_ax2, double csys2_ay2)
{
double ax = csys1_ax2 - csys1_ax1;
double ay = csys1_ay2 - csys1_ay1;
double cx = ay;
double cy = -ax;
double csys2_ax = csys2_ax2 - csys2_ax1;
double csys2_ay = csys2_ay2 - csys2_ay1;
// Знаки выставлены наоборот по сравнению с географическими координатами, т.к. оси OY расположена в противоположную сторону
double csys2_cx = -csys2_ay;
double csys2_cy = csys2_ax;
double a_len_2 = ax * ax + ay * ay;
double bx = csys1_bx2 - csys1_ax1;
double by = csys1_by2 - csys1_ay1;
double d = (ax * bx + ay * by) / a_len_2;
double f = (cx * bx + cy * by) / a_len_2;
return new ClassPointD(csys2_ax * d + csys2_cx * f + csys2_ax1, csys2_ay * d + csys2_cy * f + csys2_ay1);
}
// Обратная проекция Меркатора
public ClassPointD RevertMercatorTransform(double x, double y)
{
double ts = System.Math.Exp(-y / R_MAJOR);
double phi = M_PI_2 - 2.0 * System.Math.Atan(ts);
double dphi = 1.0;
for (int i = 0; System.Math.Abs(dphi) > 0.000000001 && i < 15; i++)
{
double con = ECCENT * System.Math.Sin(phi);
dphi = M_PI_2 - 2 * System.Math.Atan(ts * System.Math.Pow((1.0 - con) / (1.0 + con), COM)) - phi;
phi += dphi;
}
double latitude = phi * R_D;
double longitude = x * R_D / R_MAJOR;
return new ClassPointD(longitude, latitude);
}
// Пресчёт гео в относительные
public ClassPointD GeoToRelative(double geo_coords_x, double geo_coords_y, anhorsPoins anh_points)
{
if (anh_points._Anchor_Longitude_1 == 0.0 || anh_points._Anchor_Latitude_1 == 0.0 || anh_points._Anchor_Longitude_2 == 0.0 || anh_points._Anchor_Latitude_2 == 0.0)
return new ClassPointD(0.0, 0.0);
if (anh_points._Anchor_X_1 == 0.0 || anh_points._Anchor_Y_1 == 0.0 || anh_points._Anchor_X_2 == 0.0 || anh_points._Anchor_Y_2 == 0.0)
return new ClassPointD(0.0, 0.0);
ClassPointD a1 = MercatorTransform(anh_points._Anchor_Longitude_1, anh_points._Anchor_Latitude_1);
ClassPointD a2 = MercatorTransform(anh_points._Anchor_Longitude_2, anh_points._Anchor_Latitude_2);
ClassPointD b2 = MercatorTransform(geo_coords_x, geo_coords_y);
ClassPointD res = VectorTransform(a1._X, a1._Y, a2._X, a2._Y, b2._X, b2._Y,
anh_points._Anchor_X_1, anh_points._Anchor_Y_1,
anh_points._Anchor_X_2, anh_points._Anchor_Y_2);
return res;
}
// Растояние между двумя точками
public static ClassPointD GetDistanceBetweenTwoPoint(double longitude1, double latitude1, double longitude2, double latitude2)
{
if (longitude1 == 0.0 || latitude1 == 0.0 || longitude2 == 0.0 || latitude2 == 0.0)
return null;
//Вычисляем угол с учетом радиусов элипсоида
double angle_1 = System.Math.Atan((R_MINOR_POW_2 / R_MAJOR_POW_2) * System.Math.Tan(M_PI / 180 * latitude1));
double angle_2 = System.Math.Atan((R_MINOR_POW_2 / R_MAJOR_POW_2) * System.Math.Tan(M_PI / 180 * latitude2));
//radius of small circle (radius between meridians)
double point_radius1 = (1 / System.Math.Sqrt((System.Math.Pow(System.Math.Cos(angle_1), 2) / R_MAJOR_POW_2) + (System.Math.Pow(System.Math.Sin(angle_1), 2) / R_MINOR_POW_2))); //+ высота точки;
double point_radius2 = (1 / System.Math.Sqrt((System.Math.Pow(System.Math.Cos(angle_2), 2) / R_MAJOR_POW_2) + (System.Math.Pow(System.Math.Sin(angle_2), 2) / R_MINOR_POW_2))); //+ высота точки;
double earth_point_1_x = point_radius1 * System.Math.Cos(angle_1);
double earth_point_1_y = point_radius1 * System.Math.Sin(angle_1);
double earth_point_2_x = point_radius2 * System.Math.Cos(angle_2);
double earth_point_2_y = point_radius2 * System.Math.Sin(angle_2);
double x = System.Math.Sqrt(System.Math.Pow((earth_point_1_x - earth_point_2_x), 2) + System.Math.Pow((earth_point_1_y - earth_point_2_y), 2));
double y = M_PI * ((earth_point_1_x + earth_point_2_x) / 360) * (longitude1 - longitude2);
return new ClassPointD(x, y);
}
// Относительные координаты в гео
public ClassPointD RelativeToGeo(anhorsPoins anh_points, double X_rel, double Y_rel)
{
ClassPointD a1 = MercatorTransform(anh_points._Anchor_Longitude_1, anh_points._Anchor_Latitude_1);
ClassPointD a2 = MercatorTransform(anh_points._Anchor_Longitude_2, anh_points._Anchor_Latitude_2);
ClassPointD metric_coords = VectorTransform(anh_points._Anchor_X_1, anh_points._Anchor_Y_1,
anh_points._Anchor_X_2, anh_points._Anchor_Y_2,
X_rel, Y_rel, a1._X, a1._Y, a2._X, a2._Y);
ClassPointD res = RevertMercatorTransform(metric_coords._X, metric_coords._Y);
return new ClassPointD(res._X, res._Y);
}
// Угол между точками
public int GetAngelTwoPoint(double longitude1, double latitude1, double longitude2, double latitude2)
{
// Результат
int angel_res = 0;
bool chetvertUP;
bool chetvertRIGHT;
// Точки
ClassPointD p_1 = new ClassPointD(longitude1, latitude1); // точка старта
ClassPointD p_2 = new ClassPointD(longitude2, latitude2); // текущая точка
ClassPointD range = ClassGeoTransform.GetDistanceBetweenTwoPoint(p_1._X, p_1._Y, p_2._X, p_2._Y);
// Длины сторон треугольника
double distance = (Math.Sqrt(Math.Pow(range._X, 2) + Math.Pow(range._Y, 2)));
double distanceX = range._X;
double distanceY = range._Y;
// Найдём углы треугольник
const int angel_distanceX_distanceY_GRAD = 90;
int angel_distance_distanceX_GRAD = (int)((double)angel_distanceX_distanceY_GRAD * distanceX / distance);
int angel_distance_distanceY_GRAD = 180 - angel_distanceX_distanceY_GRAD - angel_distance_distanceX_GRAD;
// Определим в какой мы четверти
if ((p_1._Y - p_2._Y) <= 0)
chetvertUP = true;
else
chetvertUP = false;
if ((p_1._X - p_2._X) <= 0)
chetvertRIGHT = true;
else
chetvertRIGHT = false;
//
if (chetvertUP && chetvertRIGHT)
angel_res = angel_distance_distanceX_GRAD + angel_distanceX_distanceY_GRAD;
else if (!chetvertUP && chetvertRIGHT)
angel_res = angel_distance_distanceY_GRAD;
else if (!chetvertUP && !chetvertRIGHT)
angel_res = 270 + angel_distance_distanceX_GRAD;
else if (chetvertUP && !chetvertRIGHT)
angel_res = 180 + angel_distance_distanceY_GRAD;
return angel_res;
}
// Расчет удаления от точки старта
public int GetRangeTwoPoint(double longitude1, double latitude1, double longitude2, double latitude2)
{
int distance;
ClassPointD p_1 = new ClassPointD(longitude1, latitude1);
ClassPointD p_2 = new ClassPointD(longitude2, latitude2);
ClassPointD range = ClassGeoTransform.GetDistanceBetweenTwoPoint(p_1._X, p_1._Y, p_2._X, p_2._Y);
if (range != null)
distance = (int)(Math.Sqrt(Math.Pow(range._X, 2) + Math.Pow(range._Y, 2)));
else
distance = 0;
return distance;
}
}
public class ClassPointD
{
public double _X;
public double _Y;
public ClassPointD()
{
_X = 0;
_Y = 0;
}
public ClassPointD(double x, double y)
{
_X = x;
_Y = y;
}
}