/Proj4/PJ_krovak.c

http://github.com/route-me/route-me · C · 280 lines · 114 code · 57 blank · 109 comment · 8 complexity · b535e1b3d33c62a0045281ee4e163810 MD5 · raw file

  1. /******************************************************************************
  2. * $Id: PJ_krovak.c,v 1.9 2007/03/07 17:32:32 fwarmerdam Exp $
  3. *
  4. * Project: PROJ.4
  5. * Purpose: Implementation of the krovak (Krovak) projection.
  6. * Definition: http://www.ihsenergy.com/epsg/guid7.html#1.4.3
  7. * Author: Thomas Flemming, tf@ttqv.com
  8. *
  9. ******************************************************************************
  10. * Copyright (c) 2001, Thomas Flemming, tf@ttqv.com
  11. *
  12. * Permission is hereby granted, free of charge, to any person obtaining a
  13. * copy of this software and associated documentation files (the "Software"),
  14. * to deal in the Software without restriction, including without limitation
  15. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  16. * and/or sell copies of the Software, and to permit persons to whom the
  17. * Software is furnished to do so, subject to the following conditions:
  18. *
  19. * The above copyright notice and this permission notice shall be included
  20. * in all copies or substantial portions of the Software.
  21. *
  22. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  26. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  27. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  28. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  29. * SOFTWARE.
  30. ******************************************************************************
  31. *
  32. * $Log: PJ_krovak.c,v $
  33. * Revision 1.9 2007/03/07 17:32:32 fwarmerdam
  34. * remove orphan semicolon.
  35. *
  36. * Revision 1.8 2007/03/07 17:28:08 fwarmerdam
  37. * Make it reasonably clear that this is ellipsoidal in the code.
  38. *
  39. * Revision 1.7 2007/03/07 17:25:34 fwarmerdam
  40. * report krovak as ellipsoidal, not spherical
  41. *
  42. * Revision 1.6 2006/09/14 13:10:50 fwarmerdam
  43. * Add +czech flag to control reversal of signs (bug 1133,147)
  44. *
  45. * Revision 1.5 2006/03/30 01:22:48 fwarmerdam
  46. * Removed win32 only debug hack.
  47. *
  48. * Revision 1.4 2002/12/15 22:31:04 warmerda
  49. * handle lon_0, k, and prime meridian properly
  50. *
  51. * Revision 1.3 2002/12/15 00:13:30 warmerda
  52. * lat_0 may now be set by user, but still defaults to 49d30N
  53. *
  54. * Revision 1.2 2002/12/14 19:35:21 warmerda
  55. * updated headers
  56. *
  57. */
  58. #define PROJ_PARMS__ \
  59. double C_x;
  60. #define PJ_LIB__
  61. #include "projects.h"
  62. #include <string.h>
  63. #include <stdio.h>
  64. PJ_CVSID("$Id: PJ_krovak.c,v 1.9 2007/03/07 17:32:32 fwarmerdam Exp $");
  65. PROJ_HEAD(krovak, "Krovak") "\n\tPCyl., Ellps.";
  66. /**
  67. NOTES: According to EPSG the full Krovak projection method should have
  68. the following parameters. Within PROJ.4 the azimuth, and pseudo
  69. standard parallel are hardcoded in the algorithm and can't be
  70. altered from outside. The others all have defaults to match the
  71. common usage with Krovak projection.
  72. lat_0 = latitude of centre of the projection
  73. lon_0 = longitude of centre of the projection
  74. ** = azimuth (true) of the centre line passing through the centre of the projection
  75. ** = latitude of pseudo standard parallel
  76. k = scale factor on the pseudo standard parallel
  77. x_0 = False Easting of the centre of the projection at the apex of the cone
  78. y_0 = False Northing of the centre of the projection at the apex of the cone
  79. **/
  80. FORWARD(e_forward); /* ellipsoid */
  81. /* calculate xy from lat/lon */
  82. char errmess[255];
  83. char tmp[16];
  84. /* Constants, identical to inverse transform function */
  85. double s45, s90, e2, e, alfa, uq, u0, g, k, k1, n0, ro0, ad, a, s0, n;
  86. double gfi, u, fi0, lon17, lamdd, deltav, s, d, eps, ro;
  87. s45 = 0.785398163397448; /* 45° */
  88. s90 = 2 * s45;
  89. fi0 = P->phi0; /* Latitude of projection centre 49° 30' */
  90. /* Ellipsoid is used as Parameter in for.c and inv.c, therefore a must
  91. be set to 1 here.
  92. Ellipsoid Bessel 1841 a = 6377397.155m 1/f = 299.1528128,
  93. e2=0.006674372230614;
  94. */
  95. a = 1; /* 6377397.155; */
  96. /* e2 = P->es;*/ /* 0.006674372230614; */
  97. e2 = 0.006674372230614;
  98. e = sqrt(e2);
  99. alfa = sqrt(1. + (e2 * pow(cos(fi0), 4)) / (1. - e2));
  100. uq = 1.04216856380474; /* DU(2, 59, 42, 42.69689) */
  101. u0 = asin(sin(fi0) / alfa);
  102. g = pow( (1. + e * sin(fi0)) / (1. - e * sin(fi0)) , alfa * e / 2. );
  103. k = tan( u0 / 2. + s45) / pow (tan(fi0 / 2. + s45) , alfa) * g;
  104. k1 = P->k0;
  105. n0 = a * sqrt(1. - e2) / (1. - e2 * pow(sin(fi0), 2));
  106. s0 = 1.37008346281555; /* Latitude of pseudo standard parallel 78° 30'00" N */
  107. n = sin(s0);
  108. ro0 = k1 * n0 / tan(s0);
  109. ad = s90 - uq;
  110. /* Transformation */
  111. gfi =pow ( ((1. + e * sin(lp.phi)) /
  112. (1. - e * sin(lp.phi))) , (alfa * e / 2.));
  113. u= 2. * (atan(k * pow( tan(lp.phi / 2. + s45), alfa) / gfi)-s45);
  114. deltav = - lp.lam * alfa;
  115. s = asin(cos(ad) * sin(u) + sin(ad) * cos(u) * cos(deltav));
  116. d = asin(cos(u) * sin(deltav) / cos(s));
  117. eps = n * d;
  118. ro = ro0 * pow(tan(s0 / 2. + s45) , n) / pow(tan(s / 2. + s45) , n) ;
  119. /* x and y are reverted! */
  120. xy.y = ro * cos(eps) / a;
  121. xy.x = ro * sin(eps) / a;
  122. if( !pj_param(P -> params, "tczech").i )
  123. {
  124. xy.y *= -1.0;
  125. xy.x *= -1.0;
  126. }
  127. return (xy);
  128. }
  129. INVERSE(e_inverse); /* ellipsoid */
  130. /* calculate lat/lon from xy */
  131. /* Constants, identisch wie in der Umkehrfunktion */
  132. double s45, s90, fi0, e2, e, alfa, uq, u0, g, k, k1, n0, ro0, ad, a, s0, n;
  133. double u, l24, lamdd, deltav, s, d, eps, ro, fi1, xy0, lon17;
  134. int ok;
  135. s45 = 0.785398163397448; /* 45° */
  136. s90 = 2 * s45;
  137. fi0 = P->phi0; /* Latitude of projection centre 49° 30' */
  138. /* Ellipsoid is used as Parameter in for.c and inv.c, therefore a must
  139. be set to 1 here.
  140. Ellipsoid Bessel 1841 a = 6377397.155m 1/f = 299.1528128,
  141. e2=0.006674372230614;
  142. */
  143. a = 1; /* 6377397.155; */
  144. /* e2 = P->es; */ /* 0.006674372230614; */
  145. e2 = 0.006674372230614;
  146. e = sqrt(e2);
  147. alfa = sqrt(1. + (e2 * pow(cos(fi0), 4)) / (1. - e2));
  148. uq = 1.04216856380474; /* DU(2, 59, 42, 42.69689) */
  149. u0 = asin(sin(fi0) / alfa);
  150. g = pow( (1. + e * sin(fi0)) / (1. - e * sin(fi0)) , alfa * e / 2. );
  151. k = tan( u0 / 2. + s45) / pow (tan(fi0 / 2. + s45) , alfa) * g;
  152. k1 = P->k0;
  153. n0 = a * sqrt(1. - e2) / (1. - e2 * pow(sin(fi0), 2));
  154. s0 = 1.37008346281555; /* Latitude of pseudo standard parallel 78° 30'00" N */
  155. n = sin(s0);
  156. ro0 = k1 * n0 / tan(s0);
  157. ad = s90 - uq;
  158. /* Transformation */
  159. /* revert y, x*/
  160. xy0=xy.x;
  161. xy.x=xy.y;
  162. xy.y=xy0;
  163. if( !pj_param(P -> params, "tczech").i )
  164. {
  165. xy.x *= -1.0;
  166. xy.y *= -1.0;
  167. }
  168. ro = sqrt(xy.x * xy.x + xy.y * xy.y);
  169. eps = atan2(xy.y, xy.x);
  170. d = eps / sin(s0);
  171. s = 2. * (atan( pow(ro0 / ro, 1. / n) * tan(s0 / 2. + s45)) - s45);
  172. u = asin(cos(ad) * sin(s) - sin(ad) * cos(s) * cos(d));
  173. deltav = asin(cos(s) * sin(d) / cos(u));
  174. lp.lam = P->lam0 - deltav / alfa;
  175. /* ITERATION FOR lp.phi */
  176. fi1 = u;
  177. ok = 0;
  178. do
  179. {
  180. lp.phi = 2. * ( atan( pow( k, -1. / alfa) *
  181. pow( tan(u / 2. + s45) , 1. / alfa) *
  182. pow( (1. + e * sin(fi1)) / (1. - e * sin(fi1)) , e / 2.)
  183. ) - s45);
  184. if (fabs(fi1 - lp.phi) < 0.000000000000001) ok=1;
  185. fi1 = lp.phi;
  186. }
  187. while (ok==0);
  188. lp.lam -= P->lam0;
  189. return (lp);
  190. }
  191. FREEUP; if (P) pj_dalloc(P); }
  192. ENTRY0(krovak)
  193. double ts;
  194. /* read some Parameters,
  195. * here Latitude Truescale */
  196. ts = pj_param(P->params, "rlat_ts").f;
  197. P->C_x = ts;
  198. /* we want Bessel as fixed ellipsoid */
  199. P->a = 6377397.155;
  200. P->e = sqrt(P->es = 0.006674372230614);
  201. /* if latitude of projection center is not set, use 49d30'N */
  202. if (!pj_param(P->params, "tlat_0").i)
  203. P->phi0 = 0.863937979737193;
  204. /* if center long is not set use 42d30'E of Ferro - 17d40' for Ferro */
  205. /* that will correspond to using longitudes relative to greenwich */
  206. /* as input and output, instead of lat/long relative to Ferro */
  207. if (!pj_param(P->params, "tlon_0").i)
  208. P->lam0 = 0.7417649320975901 - 0.308341501185665;
  209. /* if scale not set default to 0.9999 */
  210. if (!pj_param(P->params, "tk").i)
  211. P->k0 = 0.9999;
  212. /* always the same */
  213. P->inv = e_inverse;
  214. P->fwd = e_forward;
  215. ENDENTRY(P)