geo.cpp
上传用户:lbr_007
上传日期:2019-05-31
资源大小:282k
文件大小:18k
源码类别:

传真(Fax)编程

开发平台:

Visual C++

  1. // geo.cpp
  2. //
  3. #include "stdafx.h"
  4. #pragma warning (disable:4786)
  5. #include "geo.h"
  6. #include <math.h>
  7. #include <UtilityParser.h>
  8. #include <StringUtil.h>
  9. double GeoCalc::EllipseArcLength(double lat1, double lat2, double a, double f)
  10. {
  11. double result = 0.0;
  12.   // if this path crosses the equator (i.e. lat1 & lat2 are different signs)
  13.   // then we have to break the path up into 2 parts, from the southern point
  14.   // up to the equator, then from the equator to the northern point.
  15.   // if this path is entirely on one side of the equator we can do it in one
  16.   // part.
  17. UINT32 numParts = 1;
  18. double multLat = lat1 * lat2;
  19. if (multLat < 0.0)
  20. {
  21. numParts = 2;
  22. }
  23. INT32 steps;
  24. double snLat1, snLat2, twoFF, x1, x2, dx, x, y1, y2, dy;
  25. double aOneF, dydx, adx, a2, oneF;
  26. double dlat1, dlat2;
  27. a2 = a * a;
  28. oneF = 1 - f;
  29. aOneF = a * oneF;
  30. for (UINT32 part = 0; part < numParts; part++){
  31. if (numParts == 2)
  32. {
  33. if (part == 0)
  34. {
  35. dlat1 = (lat1 < lat2) ? lat1 : lat2;
  36. dlat2 = 0.0;
  37. }
  38. else
  39. {
  40. dlat1 = 0.0;
  41. dlat2 = (lat1 > lat2) ? lat1 : lat2;
  42. }
  43. }
  44. else
  45. {
  46. dlat1 = (lat1 < lat2) ? lat1 : lat2;
  47. dlat2 = (lat1 > lat2) ? lat1 : lat2;
  48. }
  49. steps = 100;
  50. steps += 100 * (INT32)(0.50 + (dlat2-dlat1));
  51. steps = (steps > 4000) ? 4000 : steps;
  52. snLat1 = sin(GEO::DE2RA*dlat1);
  53. snLat2 = sin(GEO::DE2RA*dlat2);
  54. twoFF = 2 * f - f * f;
  55. x1 = a * cos(GEO::DE2RA * dlat1) / sqrt(1-twoFF*snLat1*snLat1);
  56. x2 = a * cos(GEO::DE2RA * dlat2) / sqrt(1-twoFF*snLat2*snLat2);
  57. dx = (x2 - x1) / (double)(steps - 1);
  58. x, y1, y2, dy, dydx;
  59. adx = (dx < 0.0) ? -dx : dx; // absolute value of dx
  60. for (INT32 i = 0; i < (steps - 1); i++){
  61. x = x1 + dx * i;
  62. dydx = ((aOneF * sqrt((1.0 - ((x+dx)*(x+dx))/a2))) -
  63. (aOneF * sqrt((1.0 - (x*x)/a2)))) / dx;
  64. result += adx * sqrt(1.0 + dydx*dydx);
  65. }
  66. }
  67. return result;
  68. }
  69. double GeoCalc::GCDistance(double lat1, double lon1, double lat2, double lon2)
  70. {
  71. lat1 *= GEO::DE2RA;
  72. lon1 *= GEO::DE2RA;
  73. lat2 *= GEO::DE2RA;
  74. lon2 *= GEO::DE2RA;
  75. double d = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(lon1 - lon2);
  76. return (GEO::AVG_ERAD * acos(d));
  77. }
  78. void GeoCalc::GCDistanceAzimuth(double lat1, double lon1, double dist, double az,
  79.    double& lat2, double& lon2)
  80. {
  81. double b = dist / GEO::AVG_ERAD;
  82. double sinb = sin(b);
  83. double cosb = cos(b);
  84. double sinc = sin(GEO::DE2RA * (90.0 - lat1));
  85. double cosc = cos(GEO::DE2RA * (90.0 - lat1));
  86. double azrad = GEO::DE2RA * az;
  87. double a = acos(cosb*cosc + sinc*sinb*cos(azrad));
  88. double B = asin(sinb*sin(azrad)/sin(a));
  89. lat2 = GEO::RA2DE * ((GEO::PIE/2.0) - a);
  90. lon2 = GEO::RA2DE * B + lon1;
  91. }
  92. double GeoCalc::GCAzimuth(double lat1, double lon1, double lat2, double lon2)
  93. {
  94. double result = 0.0;
  95. INT32 ilat1 = (INT32)(0.50 + lat1 * 360000.0);
  96. INT32 ilat2 = (INT32)(0.50 + lat2 * 360000.0);
  97. INT32 ilon1 = (INT32)(0.50 + lon1 * 360000.0);
  98. INT32 ilon2 = (INT32)(0.50 + lon2 * 360000.0);
  99. lat1 *= GEO::DE2RA;
  100. lon1 *= GEO::DE2RA;
  101. lat2 *= GEO::DE2RA;
  102. lon2 *= GEO::DE2RA;
  103. if ((ilat1 == ilat2) && (ilon1 == ilon2))
  104. {
  105. return result;
  106. }
  107. else if (ilon1 == ilon2)
  108. {
  109. if (ilat1 > ilat2)
  110. result = 180.0;
  111. }
  112. else
  113. {
  114. double c = acos(sin(lat2)*sin(lat1) + cos(lat2)*cos(lat1)*cos((lon2-lon1)));
  115. double A = asin(cos(lat2)*sin((lon2-lon1))/sin(c));
  116. result = (A * GEO::RA2DE);
  117. if ((ilat2 > ilat1) && (ilon2 > ilon1))
  118. {
  119. }
  120. else if ((ilat2 < ilat1) && (ilon2 < ilon1))
  121. {
  122. result = 180.0 - result;
  123. }
  124. else if ((ilat2 < ilat1) && (ilon2 > ilon1))
  125. {
  126. result = 180.0 - result;
  127. }
  128. else if ((ilat2 > ilat1) && (ilon2 < ilon1))
  129. {
  130. result += 360.0;
  131. }
  132. }
  133. return result;
  134. }
  135. double GeoCalc::ApproxDistance(double lat1, double lon1, double lat2, double lon2)
  136. {
  137. lat1 = GEO::DE2RA * lat1;
  138. lon1 = -GEO::DE2RA * lon1;
  139. lat2 = GEO::DE2RA * lat2;
  140. lon2 = -GEO::DE2RA * lon2;
  141. double F = (lat1 + lat2) / 2.0;
  142. double G = (lat1 - lat2) / 2.0;
  143. double L = (lon1 - lon2) / 2.0;
  144. double sing = sin(G);
  145. double cosl = cos(L);
  146. double cosf = cos(F);
  147. double sinl = sin(L);
  148. double sinf = sin(F);
  149. double cosg = cos(G);
  150. double S = sing*sing*cosl*cosl + cosf*cosf*sinl*sinl;
  151. double C = cosg*cosg*cosl*cosl + sinf*sinf*sinl*sinl;
  152. double W = atan2(sqrt(S),sqrt(C));
  153. double R = sqrt((S*C))/W;
  154. double H1 = (3 * R - 1.0) / (2.0 * C);
  155. double H2 = (3 * R + 1.0) / (2.0 * S);
  156. double D = 2 * W * GEO::ERAD;
  157. return (D * (1 + GEO::FLATTENING * H1 * sinf*sinf*cosg*cosg -
  158. GEO::FLATTENING*H2*cosf*cosf*sing*sing));
  159. }
  160. double GeoCalc::EllipsoidDistance(double lat1, double lon1, double lat2, double lon2)
  161. {
  162. double distance = 0.0;
  163. double  faz, baz;
  164. double  r = 1.0 - GEO::FLATTENING;
  165. double  tu1, tu2, cu1, su1, cu2, x, sx, cx, sy, cy, y, sa, c2a, cz, e, c, d;
  166. double  cosy1, cosy2;
  167. distance = 0.0;
  168. if((lon1 == lon2) && (lat1 == lat2)) return distance;
  169. lon1 *= GEO::DE2RA;
  170. lon2 *= GEO::DE2RA;
  171. lat1 *= GEO::DE2RA;
  172. lat2 *= GEO::DE2RA;
  173. cosy1 = cos(lat1);
  174. cosy2 = cos(lat2);
  175. if(cosy1 == 0.0) cosy1 = 0.0000000001;
  176. if(cosy2 == 0.0) cosy2 = 0.0000000001;
  177. tu1 = r * sin(lat1) / cosy1;
  178. tu2 = r * sin(lat2) / cosy2;
  179. cu1 = 1.0 / sqrt(tu1 * tu1 + 1.0);
  180. su1 = cu1 * tu1;
  181. cu2 = 1.0 / sqrt(tu2 * tu2 + 1.0);
  182. x = lon2 - lon1;
  183. distance = cu1 * cu2;
  184. baz = distance * tu2;
  185. faz = baz * tu1;
  186. do {
  187. sx = sin(x);
  188. cx = cos(x);
  189. tu1 = cu2 * sx;
  190. tu2 = baz - su1 * cu2 * cx;
  191. sy = sqrt(tu1 * tu1 + tu2 * tu2);
  192. cy = distance * cx + faz;
  193. y = atan2(sy, cy);
  194. sa = distance * sx / sy;
  195. c2a = -sa * sa + 1.0;
  196. cz = faz + faz;
  197. if(c2a > 0.0) cz = -cz / c2a + cy;
  198. e = cz * cz * 2. - 1.0;
  199. c = ((-3.0 * c2a + 4.0) * GEO::FLATTENING + 4.0) * c2a * GEO::FLATTENING / 16.0;
  200. d = x;
  201. x = ((e * cy * c + cz) * sy * c + y) * sa;
  202. x = (1.0 - c) * x * GEO::FLATTENING + lon2 - lon1;
  203. } while(fabs(d - x) > GEO::EPS);
  204. x = sqrt((1.0 / r / r - 1.0) * c2a + 1.0) + 1.0;
  205. x = (x - 2.0) / x;
  206. c = 1.0 - x;
  207. c = (x * x / 4.0 + 1.0) / c;
  208. d = (0.375 * x * x - 1.0) * x;
  209. x = e * cy;
  210. distance = 1.0 - e - e;
  211. distance = ((((sy * sy * 4.0 - 3.0) *
  212. distance * cz * d / 6.0 - x) * d / 4.0 + cz) * sy * d + y) * c * GEO::ERAD * r;
  213. return distance;
  214. }
  215. // the first path corresponds to { lat1A, lon1A, lat1B, lon1B }
  216. // second path is: { lat2A, lon2A, lat2B, lon2B }
  217. //
  218. // Any 3 non-coincident points form a plane, so the first plane is formed
  219. // by lat1A, lon1A, lat1B, lon1B, and the center of the earth, the second
  220. // plane is formed by lat2A, lon2A, lat2B, lon2B, and the earth's center.
  221. // You can get the normal to each plane by taking the cross product of
  222. // the vector from the Earth's center to the first path point with the 
  223. // vector from the Earth's center to the second path point. The cross
  224. // product guarantees a vector that is normal (perpendicular) to the
  225. // first two, and any vector normal to either of the respective normals
  226. // must lie in the corresponding plane, so by taking the cross product of
  227. // the two normals (normals to each path plane) you get the vector of the
  228. // line of intersection of the planes. From this vector its easy to deduce
  229. // if the intersection point of the planes is on either of the paths.
  230. //
  231. bool GeoCalc::GCIntersectSegment(double lat1A, double lon1A, double lat1B, double lon1B,
  232.    double lat2A, double lon2A, double lat2B, double lon2B,
  233.    double& lat3A, double& lon3A, double& lat3B, double& lon3B)
  234. {
  235. bool isInside = false;
  236. double v1[3], v2[3], v3a[3], v3b[3], n1[3], n2[3];
  237. double m;
  238. double d1 = ApproxDistance(lat1A, lon1A, lat1B, lon1B);
  239. double d2 = ApproxDistance(lat2A, lon2A, lat2B, lon2B);
  240.   //
  241.   // for path 1, setting up my 2 vectors, v1 is vector
  242.   // from center of the Earth to point A, v2 is vector
  243.   // from center of the Earth to point B.
  244.   //
  245. v1[0] = cos(lat1A * GEO::DE2RA) * cos(lon1A * GEO::DE2RA);
  246. v1[1] = sin(lat1A * GEO::DE2RA);
  247. v1[2] = cos(lat1A * GEO::DE2RA) * sin(lon1A * GEO::DE2RA);
  248. v2[0] = cos(lat1B * GEO::DE2RA) * cos(lon1B * GEO::DE2RA);
  249. v2[1] = sin(lat1B * GEO::DE2RA);
  250. v2[2] = cos(lat1B * GEO::DE2RA) * sin(lon1B * GEO::DE2RA);
  251.   //
  252.   // n1 is the normal to the plane formed by the three points:
  253.   // center of the Earth, point 1A, and point 1B
  254.   //
  255. n1[0] = (v1[1]*v2[2]) - (v1[2]*v2[1]);
  256. n1[1] = (v1[2]*v2[0]) - (v1[0]*v2[2]);
  257. n1[2] = (v1[0]*v2[1]) - (v1[1]*v2[0]);
  258.   //
  259.   // for path 2, setting up my 2 vectors, v1 is vector
  260.   // from center of the Earth to point A, v2 is vector
  261.   // from center of the Earth to point B.
  262.   //
  263. v1[0] = cos(lat2A * GEO::DE2RA) * cos(lon2A * GEO::DE2RA);
  264. v1[1] = sin(lat2A * GEO::DE2RA);
  265. v1[2] = cos(lat2A * GEO::DE2RA) * sin(lon2A * GEO::DE2RA);
  266. v2[0] = cos(lat2B * GEO::DE2RA) * cos(lon2B * GEO::DE2RA);
  267. v2[1] = sin(lat2B * GEO::DE2RA);
  268. v2[2] = cos(lat2B * GEO::DE2RA) * sin(lon2B * GEO::DE2RA);
  269.   //
  270.   // n1 is the normal to the plane formed by the three points:
  271.   // center of the Earth, point 2A, and point 2B
  272.   //
  273. n2[0] = (v1[1]*v2[2]) - (v1[2]*v2[1]);
  274. n2[1] = (v1[2]*v2[0]) - (v1[0]*v2[2]);
  275. n2[2] = (v1[0]*v2[1]) - (v1[1]*v2[0]);
  276.   //
  277.   // v3 is perpendicular to both normal 1 and normal 2, so
  278.   // it lies in both planes, so it must be the line of
  279.   // intersection of the planes. The question is: does it
  280.   // go towards the correct intersection point or away from
  281.   // it.
  282.   //
  283. v3a[0] = (n1[1]*n2[2]) - (n1[2]*n2[1]);
  284. v3a[1] = (n1[2]*n2[0]) - (n1[0]*n2[2]);
  285. v3a[2] = (n1[0]*n2[1]) - (n1[1]*n2[0]);
  286.   //
  287.   // want to make v3a a unit vector, so first have to get
  288.   // magnitude, then each component by magnitude
  289.   //
  290. m = sqrt(v3a[0]*v3a[0] + v3a[1]*v3a[1] + v3a[2]*v3a[2]);
  291. v3a[0] /= m;
  292. v3a[1] /= m;
  293. v3a[2] /= m;
  294.   //
  295.   // calculating intersection points 3A & 3B. A & B are
  296.   // arbitrary designations right now, later we make A
  297.   // the one close to, or within, the paths.
  298.   //
  299. lat3A = asin(v3a[1]);
  300. if ((lat3A > GEO::EPS) || (-lat3A > GEO::EPS))
  301. lon3A = asin(v3a[2]/cos(lat3A));
  302. else
  303. lon3A = 0.0;
  304. v3b[0] = (n2[1]*n1[2]) - (n2[2]*n1[1]);
  305. v3b[1] = (n2[2]*n1[0]) - (n2[0]*n1[2]);
  306. v3b[2] = (n2[0]*n1[1]) - (n2[1]*n1[0]);
  307. m = sqrt(v3b[0]*v3b[0] + v3b[1]*v3b[1] + v3b[2]*v3b[2]);
  308. v3b[0] /= m;
  309. v3b[1] /= m;
  310. v3b[2] /= m;
  311. lat3B = asin(v3b[1]);
  312. if ((lat3B > GEO::EPS) || (-lat3B > GEO::EPS))
  313. lon3B = asin(v3b[2]/cos(lat3B));
  314. else
  315. lon3B = 0.0;
  316.   //
  317.   // get the distances from the path endpoints to the two
  318.   // intersection points. these values will be used to determine
  319.   // which intersection point lies on the paths, or which one
  320.   // is closer.
  321.   //
  322. double d1a3a = ApproxDistance(lat1A, lon1A, lat3A, lon3A);
  323. double d1b3a = ApproxDistance(lat1B, lon1B, lat3A, lon3A);
  324. double d2a3a = ApproxDistance(lat2A, lon2A, lat3A, lon3A);
  325. double d2b3a = ApproxDistance(lat2B, lon2B, lat3A, lon3A);
  326. double d1a3b = ApproxDistance(lat1A, lon1A, lat3B, lon3B);
  327. double d1b3b = ApproxDistance(lat1B, lon1B, lat3B, lon3B);
  328. double d2a3b = ApproxDistance(lat2A, lon2A, lat3B, lon3B);
  329. double d2b3b = ApproxDistance(lat2B, lon2B, lat3B, lon3B);
  330. if ((d1a3a < d1) && (d1b3a < d1) && (d2a3a < d2) && (d2b3a < d2))
  331. {
  332. isInside = true;
  333. }
  334. else if ((d1a3b < d1) && (d1b3b < d1) && (d2a3b < d2) && (d2b3b < d2))
  335. {
  336.   //
  337.   // 3b is inside the two paths, so swap 3a & 3b
  338.   //
  339. isInside = true;
  340. m = lat3A;
  341. lat3A = lat3B;
  342. lat3B = m;
  343. m = lon3A;
  344. lon3A = lon3B;
  345. lon3B = m;
  346. }
  347. else
  348. {
  349.   //
  350.   // figure out which one is closer to the path
  351.   //
  352. d1 = d1a3a + d1b3a + d2a3a + d2b3a;
  353. d2 = d1a3b + d1b3b + d2a3b + d2b3b;
  354. if (d1 > d2)
  355. {
  356.   //
  357.   // ok, we are here because 3b {lat3B,lon3B} is closer to the
  358.   // paths, so we need to swap 3a & 3b. the other case is already
  359.   // the way 3a & 3b are organized, so no need to swap
  360.   //
  361. m = lat3A;
  362. lat3A = lat3B;
  363. lat3B = m;
  364. m = lon3A;
  365. lon3A = lon3B;
  366. lon3B = m;
  367. }
  368. }
  369.   //
  370.   // convert the intersection points to degrees
  371.   //
  372. lat3A *= GEO::RA2DE;
  373. lon3A *= GEO::RA2DE;
  374. lat3B *= GEO::RA2DE;
  375. lon3B *= GEO::RA2DE;
  376. return isInside;
  377. }
  378. void GeoCalc::GCSatellite(double lat1, double lon1, double satellite_lon,
  379.    double& az, double& elev)
  380. {
  381. double lat2 = 0.0;
  382. double lon2 = satellite_lon;
  383. // before we convert to radians, lets just get the azimuth
  384. az = GCAzimuth(lat1,lon1,lat2,lon2);
  385. lat1 *= GEO::DE2RA;
  386. lon1 *= GEO::DE2RA;
  387. lon2 *= GEO::DE2RA;
  388. double R = GEO::AVG_ERAD;
  389. double h = GEO::GEOSTATIONARY_ALT;
  390. // calculate "b" just like we did in GCDistance
  391. double b = acos(cos(lon2-lon1)*cos(lat1));//sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(lon1 - lon2);
  392. // calculate "d", the distance to the satellite in kilometers
  393. double d = sqrt(R*R + (R+h)*(R+h) - 2*R*(R+h)*cos(b));
  394. // now calculate the elevation angle above the horizon
  395. elev = GEO::RA2DE * acos((R+h)*sin(b)/d);
  396. }
  397. double GeoCalc::DecodeLatitude(const char * txt)
  398. {
  399. double result = 0.0;
  400. UtilityParser p;
  401. StringUtil su;
  402. std::string arg1, arg2, arg3, arg4;
  403. bool is_negative = false;
  404. std::string tmp = txt;
  405. su.StripSpaces(tmp);
  406. if (su.StartsWith(tmp, "-"))
  407. {
  408. is_negative = true;
  409. }
  410. p.SetDelimiters(" -:,");
  411. p.ParseString(txt);
  412. int size = p.GetSize();
  413. if (size > 0)
  414. {
  415. if (size == 1)
  416. {
  417. if (p.GetArgument(0,arg1))
  418. {
  419. if (p.IsNumber(arg1))
  420. {
  421. result = atof(arg1.c_str());
  422. }
  423. }
  424. }
  425. else if (size == 2)
  426. {
  427. if (p.GetArgument(0,arg1) && p.GetArgument(1,arg2))
  428. {
  429. if (p.IsNumber(arg1))
  430. {
  431. result = atof(arg1.c_str());
  432. if (p.IsNumber(arg2))
  433. {
  434. result += atof(arg2.c_str())/60.0;
  435. }
  436. else
  437. {
  438. su.Uppercase(arg2);
  439. su.StripControlCharacters(arg2);
  440. su.StripSpaces(arg2);
  441. if (arg2 == "N")
  442. {
  443. result = fabs(result);
  444. }
  445. else if (arg2 == "S")
  446. {
  447. result = -1.0000000 * fabs(result);
  448. }
  449. else if (arg2.length() > 0)
  450. {
  451. result = 0;
  452. }
  453. }
  454. }
  455. }
  456. }
  457. else if (size > 2)
  458. {
  459. p.GetArgument(0,arg1);
  460. p.GetArgument(1,arg2);
  461. p.GetArgument(2,arg3);
  462. p.GetArgument(3,arg4);
  463. if (p.IsNumber(arg1) && p.IsNumber(arg2) && p.IsNumber(arg3))
  464. {
  465. result = atof(arg1.c_str()) + atof(arg2.c_str())/60.0 + atof(arg3.c_str())/3600.0;
  466. su.Uppercase(arg4);
  467. su.StripControlCharacters(arg4);
  468. su.StripSpaces(arg4);
  469. if (arg4 == "N")
  470. {
  471. result = fabs(result);
  472. }
  473. else if (arg4 == "S")
  474. {
  475. result = -1.0000000 * fabs(result);
  476. }
  477. }
  478. else if (p.IsNumber(arg1) && p.IsNumber(arg2))
  479. {
  480. result = atof(arg1.c_str()) + atof(arg2.c_str())/60.0;
  481. su.Uppercase(arg3);
  482. su.StripControlCharacters(arg3);
  483. su.StripSpaces(arg3);
  484. if (arg3 == "N")
  485. {
  486. result = fabs(result);
  487. }
  488. else if (arg3 == "S")
  489. {
  490. result = -1.0000000 * fabs(result);
  491. }
  492. }
  493. }
  494. }
  495. if (is_negative)
  496. {
  497. result = -fabs(result);
  498. }
  499. return result;
  500. }
  501. double GeoCalc::DecodeLongitude(const char * txt)
  502. {
  503. double result = 0.0;
  504. UtilityParser p;
  505. StringUtil su;
  506. std::string arg1, arg2, arg3, arg4;
  507. bool is_negative = false;
  508. std::string tmp = txt;
  509. su.StripSpaces(tmp);
  510. if (su.StartsWith(tmp, "-"))
  511. {
  512. is_negative = true;
  513. }
  514. p.SetDelimiters(" -:,");
  515. p.ParseString(txt);
  516. int size = p.GetSize();
  517. if (size > 0)
  518. {
  519. if (size == 1)
  520. {
  521. if (p.GetArgument(0,arg1))
  522. {
  523. if (p.IsNumber(arg1))
  524. {
  525. result = atof(arg1.c_str());
  526. }
  527. }
  528. }
  529. else if (size == 2)
  530. {
  531. if (p.GetArgument(0,arg1) && p.GetArgument(1,arg2))
  532. {
  533. if (p.IsNumber(arg1))
  534. {
  535. result = atof(arg1.c_str());
  536. if (p.IsNumber(arg2))
  537. {
  538. result += atof(arg2.c_str())/60.0;
  539. }
  540. else
  541. {
  542. su.Uppercase(arg2);
  543. su.StripControlCharacters(arg2);
  544. su.StripSpaces(arg2);
  545. if (arg2 == "E")
  546. {
  547. result = fabs(result);
  548. }
  549. else if (arg2 == "W")
  550. {
  551. result = -1.0000000 * fabs(result);
  552. }
  553. else if (arg2.length() > 0)
  554. {
  555. result = 0;
  556. }
  557. }
  558. }
  559. }
  560. }
  561. else if (size > 2)
  562. {
  563. p.GetArgument(0,arg1);
  564. p.GetArgument(1,arg2);
  565. p.GetArgument(2,arg3);
  566. p.GetArgument(3,arg4);
  567. if (p.IsNumber(arg1) && p.IsNumber(arg2) && p.IsNumber(arg3))
  568. {
  569. result = atof(arg1.c_str()) + atof(arg2.c_str())/60.0 + atof(arg3.c_str())/3600.0;
  570. su.Uppercase(arg4);
  571. su.StripControlCharacters(arg4);
  572. su.StripSpaces(arg4);
  573. if (arg4 == "E")
  574. {
  575. result = fabs(result);
  576. }
  577. else if (arg4 == "W")
  578. {
  579. result = -1.0000000 * fabs(result);
  580. }
  581. }
  582. else if (p.IsNumber(arg1) && p.IsNumber(arg2))
  583. {
  584. result = atof(arg1.c_str()) + atof(arg2.c_str())/60.0;
  585. su.Uppercase(arg3);
  586. su.StripControlCharacters(arg3);
  587. su.StripSpaces(arg3);
  588. if (arg3 == "E")
  589. {
  590. result = fabs(result);
  591. }
  592. else if (arg3 == "W")
  593. {
  594. result = -1.0000000 * fabs(result);
  595. }
  596. }
  597. }
  598. }
  599. if (is_negative)
  600. {
  601. result = -fabs(result);
  602. }
  603. return result;
  604. }
  605. void GeoCalc::CoordinateToDMS(double coord, INT32& deg, INT32& minutes, double& secs)
  606. {
  607. double dlat, d, m, s;
  608. dlat = coord + (double)0.000001;
  609. d = (double)(long)dlat;
  610. m = (double)((dlat - d)*60.0);
  611. s = (double)((m - (double)(long)(m))*60.0);
  612. if (s >= 60.00)
  613. {
  614. if (m == 59)
  615. {
  616. d += 1;
  617. if (d < 0.0)
  618. d -= 1;
  619. else
  620. d += 1;
  621. m = 0;
  622. s -= 60.0;
  623. }
  624. else
  625. {
  626. s -= 60.00;
  627. s += 1;
  628. }
  629. }
  630. deg = (int)d;
  631. minutes = (int)m;
  632. secs = s;
  633. }
  634. #define IABS(a) ((a>0) ? a : -a)
  635. void GeoCalc::EncodeLatitude(double lat, std::string& s)
  636. {
  637. char txt[24];
  638. INT32 d, m;
  639. double seconds;
  640. CoordinateToDMS(lat,d,m,seconds);
  641. sprintf(txt,"%d-%.2d-%2.1f %c",IABS(d),IABS(m),fabs(seconds),(lat>0.0)?'N':'S');
  642. s = txt;
  643. }
  644. void GeoCalc::EncodeLongitude(double lon, std::string& s)
  645. {
  646. char txt[24];
  647. INT32 d, m;
  648. double seconds;
  649. CoordinateToDMS(lon,d,m,seconds);
  650. sprintf(txt,"%d-%.2d-%2.1f %c",IABS(d),IABS(m),fabs(seconds),(lon>0.0)?'E':'W');
  651. s = txt;
  652. }