среда, 28 октября 2009 г.

Преобразование координат

Разбираясь в своих архивах, нашел много всего почти позабытого. В том числе утилитки для преобразования координат из WGS84 в Пулково 1942 и "морских" координат. Разумеется, эти преобразования можно выполнить с помощью универсальных библиотек, но они огромны и не всегда эффективны, не говоря уж про зависимости. Так что любителям минимализма и встраиваемых решений посвящается.

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

double pifact = 0.017453292519943295; // PI/180 - перевод градусов в радианы

// параметры референц-эллипсоида Красовского
double aval = 6378245.0;    // полуось эллипсоида
double f = 298.3;           // величина сжатия
// параметры системы координат 42 года (СК Пулково 42)
double cmlon = 45;          // центральный меридиан 8-й зоны
double orglat = 0;          // центральная параллель (экватор)
double scale = 1;           // масштабный коэффициент
double fe = 500000;         // восточное смещение (без номера зоны)
double fn = 0;              // северное смещение (в нашем полушарии 0)
int latNS = 1;              // полушарие (1 - северное, -1 - южное)
int lonEW = 1;              // смещение от Гринвича (1 - E, -1 - W)

int main(int argc, char *argv[])
{
  // пересчет координат GPS из геодезических в картографические
  double g = 1/f;
  double esq = 2*g-g*g;
  double epsq = esq/(1-esq);
  // координаты точки в десятичных градусах
  double inlat = 56.33847;    // широта
  double inlon = 43.98538;    // долгота

  printf("latitude = %g\n",inlat);
  printf("longitude = %g\n",inlon);

  inlat = inlat * pifact * latNS;
  orglat = orglat * pifact * latNS;
  inlon = inlon * pifact * lonEW;
  cmlon = cmlon * pifact * lonEW;
  double t = tan(inlat) * tan(inlat);//T
  //printf("T = %g\n",t);
  double c = epsq * cos(inlat) * cos(inlat);//C
  //printf("C = %g\n",c);
  double a = (inlon - cmlon) * cos(inlat);//A
  //printf("A = %g\n",a);
  double mint;
  mint = inlat * (1.-esq/4.-3*esq*esq/64.-5*esq*esq*esq/256);
  mint = mint - sin(2.*inlat)*(3*esq/8+3*esq*esq/32+45*esq*esq*esq/1024);
  mint = mint + sin(4.*inlat)*esq*esq*(15/256 + 45*esq/1024);
  double m = 1.*aval*(mint - sin(6.*inlat)*35*esq*esq*esq/3072);//M
  //printf("M = %g\n",m);
  mint = orglat * (1.-esq/4.-3*esq*esq/64.-5*esq*esq*esq/256);
  mint = mint - sin(2.*orglat)*(3*esq/8+3*esq*esq/32+45*esq*esq*esq/1024);
  mint = mint + sin(4.*orglat)*esq*esq*(15/256 + 45*esq/1024);
  double m0 = 1.*aval*(mint - sin(6.*orglat)*35*esq*esq*esq/3072);//M0
  //printf("M0 = %g\n",m0);
  double nu = 1.*aval/sqrt(1.-esq*sin(inlat)*sin(inlat));//NU
  //printf("NU = %g\n",nu);
  double easting = (5-18*t+t*t+72*c-58*epsq)*a*a/120 + (1-t+c)/6;
  easting = (1 +easting*a*a)*a*scale*nu + fe;
  double northing = a*a*(61-58*t+t*t+600*c-330*epsq)/720 + (5-t+9*c+4*c*c)/24;
  northing = (.5 + a*a*northing)*a*a*nu*tan(inlat)+m-m0;
  northing = fn + scale * northing;

  // координаты точки в СК Пулково 42, метры
  // в соответствии с правилами геодезии, приняты следующие обозначения
  // X - отсчитывается вверх от экватора (ось ординат)
  // Y - отсчитывается вправо от начального меридиана зоны (ось абсцисс)
  printf("X = %g\n",northing);
  printf("Y = %g\n",easting);

  return 0;        // завершение программы
}


#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
 double xpos = 4784270;
 double ypos = 7803506;

 double RadToDeg = 57.2957795132;
 double DegToRad = 0.0174532925199;
 double b = 6356752.3142;
 double PI = 3.141592654;
 double HALF_PI = 1.570796327;

 double MerToGeoLong = xpos * RadToDeg / b;
 printf("GeoLong = %f\n",MerToGeoLong);

 double MerToGeoLat = RadToDeg * (2 * atan(exp(ypos / b)) - HALF_PI);
 printf("GeoLat = %f\n",MerToGeoLat);
}

2 комментария:

imagovrn комментирует...

Вы упоминули "универсальные библиотеки" для преобразования координат. Не могли бы вы привести примеры достойных, на Ваш взгляд, решений?

Печников Алексей комментирует...

Есть стандартные пакеты:

gdal - для растров

ogr - для векторов

Оба пакета понимают уйму самых различных форматов ГИС-данных.


(C) Alexey Pechnikov aka MBG, mobigroup.ru