You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

geodesic.cpp 49 kB

2 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466
  1. /**
  2. * \file Geodesic.cpp
  3. * \brief Implementation for GeographicLib::Geodesic class
  4. *
  5. * Copyright (c) Charles Karney (2009-2017) <charles@karney.com> and licensed
  6. * under the MIT/X11 License. For more information, see
  7. * https://geographiclib.sourceforge.io/
  8. *
  9. * This is a reformulation of the geodesic problem. The notation is as
  10. * follows:
  11. * - at a general point (no suffix or 1 or 2 as suffix)
  12. * - phi = latitude
  13. * - beta = latitude on auxiliary sphere
  14. * - omega = longitude on auxiliary sphere
  15. * - lambda = longitude
  16. * - alpha = azimuth of great circle
  17. * - sigma = arc length along great circle
  18. * - s = distance
  19. * - tau = scaled distance (= sigma at multiples of pi/2)
  20. * - at northwards equator crossing
  21. * - beta = phi = 0
  22. * - omega = lambda = 0
  23. * - alpha = alpha0
  24. * - sigma = s = 0
  25. * - a 12 suffix means a difference, e.g., s12 = s2 - s1.
  26. * - s and c prefixes mean sin and cos
  27. **********************************************************************/
  28. #include "geodesic.h"
  29. #include <iostream>
  30. void static_assertC(bool status, const char *putLog)
  31. {
  32. if (!status)
  33. {
  34. std::cout << putLog << std::endl;
  35. exit(-1);
  36. }
  37. }
  38. namespace GeographicLib {
  39. using namespace std;
  40. Geodesic::Geodesic(real a, real f)
  41. : maxit2_(maxit1_ + Math::digits() + 10)
  42. // Underflow guard. We require
  43. // tiny_ * epsilon() > 0
  44. // tiny_ + epsilon() == epsilon()
  45. ,
  46. tiny_(sqrt(numeric_limits<real>::min())),
  47. tol0_(numeric_limits<real>::epsilon())
  48. // Increase multiplier in defn of tol1_ from 100 to 200 to fix inverse
  49. // case 52.784459512564 0 -52.784459512563990912 179.634407464943777557
  50. // which otherwise failed for Visual Studio 10 (Release and Debug)
  51. ,
  52. tol1_(200 * tol0_),
  53. tol2_(sqrt(tol0_)),
  54. tolb_(tol0_ * tol2_) // Check on bisection interval
  55. ,
  56. xthresh_(1000 * tol2_),
  57. _a(a),
  58. _f(f),
  59. _f1(1 - _f),
  60. _e2(_f * (2 - _f)),
  61. _ep2(_e2 / Math::sq(_f1)) // e2 / (1 - e2)
  62. ,
  63. _n(_f / (2 - _f)),
  64. _b(_a * _f1),
  65. _c2((Math::sq(_a) +
  66. Math::sq(_b) *
  67. (_e2 == 0 ? 1
  68. : Math::eatanhe(real(1),
  69. (_f < 0 ? -1 : 1) * sqrt(abs(_e2))) /
  70. _e2)) /
  71. 2) // authalic radius squared
  72. // The sig12 threshold for "really short". Using the auxiliary sphere
  73. // solution with dnm computed at (bet1 + bet2) / 2, the relative error in
  74. // the azimuth consistency check is sig12^2 * abs(f) * min(1, 1-f/2) / 2.
  75. // (Error measured for 1/100 < b/a < 100 and abs(f) >= 1/1000. For a
  76. // given f and sig12, the max error occurs for lines near the pole. If
  77. // the old rule for computing dnm = (dn1 + dn2)/2 is used, then the error
  78. // increases by a factor of 2.) Setting this equal to epsilon gives
  79. // sig12 = etol2. Here 0.1 is a safety factor (error decreased by 100)
  80. // and max(0.001, abs(f)) stops etol2 getting too large in the nearly
  81. // spherical case.
  82. ,
  83. _etol2(0.1 * tol2_ /
  84. sqrt(max(real(0.001), abs(_f)) * min(real(1), 1 - _f / 2) / 2))
  85. {
  86. if (!(Math::isfinite(_a) && _a > 0))
  87. {
  88. std::cerr << "Equatorial radius is not positive" << std::endl;
  89. return;
  90. }
  91. if (!(Math::isfinite(_b) && _b > 0))
  92. {
  93. std::cerr << "Polar semi-axis is not positive" << std::endl;
  94. return;
  95. }
  96. A3coeff();
  97. C3coeff();
  98. C4coeff();
  99. }
  100. const Geodesic &Geodesic::WGS84()
  101. {
  102. static const Geodesic wgs84(6378137,
  103. 1 / ((double)(298257223563LL) / 1000000000));
  104. // static const Geodesic wgs84(Constants::WGS84_a(),
  105. // Constants::WGS84_f());
  106. return wgs84;
  107. }
  108. Math::real Geodesic::SinCosSeries(bool sinp, real sinx, real cosx,
  109. const real c[], int n)
  110. {
  111. // Evaluate
  112. // y = sinp ? sum(c[i] * sin( 2*i * x), i, 1, n) :
  113. // sum(c[i] * cos((2*i+1) * x), i, 0, n-1)
  114. // using Clenshaw summation. N.B. c[0] is unused for sin series
  115. // Approx operation count = (n + 5) mult and (2 * n + 2) add
  116. c += (n + sinp); // Point to one beyond last element
  117. real ar = 2 * (cosx - sinx) * (cosx + sinx), // 2 * cos(2 * x)
  118. y0 = n & 1 ? *--c : 0, y1 = 0; // accumulators for sum
  119. // Now n is even
  120. n /= 2;
  121. while (n--)
  122. {
  123. // Unroll loop x 2, so accumulators return to their original role
  124. y1 = ar * y0 - y1 + *--c;
  125. y0 = ar * y1 - y0 + *--c;
  126. }
  127. return sinp ? 2 * sinx * cosx * y0 // sin(2 * x) * y0
  128. : cosx * (y0 - y1); // cos(x) * (y0 - y1)
  129. }
  130. Math::real Geodesic::GenInverse(real lat1, real lon1, real lat2, real lon2,
  131. unsigned outmask, real &s12, real &salp1,
  132. real &calp1, real &salp2, real &calp2,
  133. real &m12, real &M12, real &M21,
  134. real &S12) const
  135. {
  136. // Compute longitude difference (AngDiff does this carefully). Result is
  137. // in [-180, 180] but -180 is only for west-going geodesics. 180 is for
  138. // east-going and meridional geodesics.
  139. real lon12s, lon12 = Math::AngDiff(lon1, lon2, lon12s);
  140. // Make longitude difference positive.
  141. int lonsign = lon12 >= 0 ? 1 : -1;
  142. // If very close to being on the same half-meridian, then make it so.
  143. lon12 = lonsign * Math::AngRound(lon12);
  144. lon12s = Math::AngRound((180 - lon12) - lonsign * lon12s);
  145. real lam12 = lon12 * Math::degree(), slam12, clam12;
  146. if (lon12 > 90)
  147. {
  148. Math::sincosd(lon12s, slam12, clam12);
  149. clam12 = -clam12;
  150. }
  151. else
  152. {
  153. Math::sincosd(lon12, slam12, clam12);
  154. }
  155. // If really close to the equator, treat as on equator.
  156. lat1 = Math::AngRound(Math::LatFix(lat1));
  157. lat2 = Math::AngRound(Math::LatFix(lat2));
  158. // Swap points so that point with higher (abs) latitude is point 1
  159. // If one latitude is a nan, then it becomes lat1.
  160. int swapp = abs(lat1) < abs(lat2) ? -1 : 1;
  161. if (swapp < 0)
  162. {
  163. lonsign *= -1;
  164. swap(lat1, lat2);
  165. }
  166. // Make lat1 <= 0
  167. int latsign = lat1 < 0 ? 1 : -1;
  168. lat1 *= latsign;
  169. lat2 *= latsign;
  170. // Now we have
  171. //
  172. // 0 <= lon12 <= 180
  173. // -90 <= lat1 <= 0
  174. // lat1 <= lat2 <= -lat1
  175. //
  176. // longsign, swapp, latsign register the transformation to bring the
  177. // coordinates to this canonical form. In all cases, 1 means no change was
  178. // made. We make these transformations so that there are few cases to
  179. // check, e.g., on verifying quadrants in atan2. In addition, this
  180. // enforces some symmetries in the results returned.
  181. real sbet1, cbet1, sbet2, cbet2, s12x, m12x;
  182. Math::sincosd(lat1, sbet1, cbet1);
  183. sbet1 *= _f1;
  184. // Ensure cbet1 = +epsilon at poles; doing the fix on beta means that sig12
  185. // will be <= 2*tiny for two points at the same pole.
  186. Math::norm(sbet1, cbet1);
  187. cbet1 = max(tiny_, cbet1);
  188. Math::sincosd(lat2, sbet2, cbet2);
  189. sbet2 *= _f1;
  190. // Ensure cbet2 = +epsilon at poles
  191. Math::norm(sbet2, cbet2);
  192. cbet2 = max(tiny_, cbet2);
  193. // If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
  194. // |bet1| - |bet2|. Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
  195. // a better measure. This logic is used in assigning calp2 in Lambda12.
  196. // Sometimes these quantities vanish and in that case we force bet2 = +/-
  197. // bet1 exactly. An example where is is necessary is the inverse problem
  198. // 48.522876735459 0 -48.52287673545898293 179.599720456223079643
  199. // which failed with Visual Studio 10 (Release and Debug)
  200. if (cbet1 < -sbet1)
  201. {
  202. if (cbet2 == cbet1)
  203. {
  204. sbet2 = sbet2 < 0 ? sbet1 : -sbet1;
  205. }
  206. }
  207. else
  208. {
  209. if (abs(sbet2) == -sbet1)
  210. {
  211. cbet2 = cbet1;
  212. }
  213. }
  214. real dn1 = sqrt(1 + _ep2 * Math::sq(sbet1)),
  215. dn2 = sqrt(1 + _ep2 * Math::sq(sbet2));
  216. real a12, sig12;
  217. // index zero element of this array is unused
  218. real Ca[nC_];
  219. bool meridian = lat1 == -90 || slam12 == 0;
  220. if (meridian)
  221. {
  222. // Endpoints are on a single full meridian, so the geodesic might lie on
  223. // a meridian.
  224. calp1 = clam12;
  225. salp1 = slam12; // Head to the target longitude
  226. calp2 = 1;
  227. salp2 = 0; // At the target we're heading north
  228. real
  229. // tan(bet) = tan(sig) * cos(alp)
  230. ssig1 = sbet1,
  231. csig1 = calp1 * cbet1, ssig2 = sbet2, csig2 = calp2 * cbet2;
  232. // sig12 = sig2 - sig1
  233. sig12 = atan2(max(real(0), csig1 * ssig2 - ssig1 * csig2),
  234. csig1 * csig2 + ssig1 * ssig2);
  235. {
  236. real dummy;
  237. Lengths(_n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1,
  238. cbet2, outmask | DISTANCE | REDUCEDLENGTH, s12x, m12x,
  239. dummy, M12, M21, Ca);
  240. }
  241. // Add the check for sig12 since zero length geodesics might yield m12 <
  242. // 0. Test case was
  243. //
  244. // echo 20.001 0 20.001 0 | GeodSolve -i
  245. //
  246. // In fact, we will have sig12 > pi/2 for meridional geodesic which is
  247. // not a shortest path.
  248. if (sig12 < 1 || m12x >= 0)
  249. {
  250. // Need at least 2, to handle 90 0 90 180
  251. if (sig12 < 3 * tiny_)
  252. {
  253. sig12 = m12x = s12x = 0;
  254. }
  255. m12x *= _b;
  256. s12x *= _b;
  257. a12 = sig12 / Math::degree();
  258. }
  259. else
  260. // m12 < 0, i.e., prolate and too close to anti-podal
  261. {
  262. meridian = false;
  263. }
  264. }
  265. // somg12 > 1 marks that it needs to be calculated
  266. real omg12 = 0, somg12 = 2, comg12 = 0;
  267. if (!meridian && sbet1 == 0 && // and sbet2 == 0
  268. (_f <= 0 || lon12s >= _f * 180))
  269. {
  270. // Geodesic runs along equator
  271. calp1 = calp2 = 0;
  272. salp1 = salp2 = 1;
  273. s12x = _a * lam12;
  274. sig12 = omg12 = lam12 / _f1;
  275. m12x = _b * sin(sig12);
  276. if (outmask & GEODESICSCALE)
  277. {
  278. M12 = M21 = cos(sig12);
  279. }
  280. a12 = lon12 / _f1;
  281. }
  282. else if (!meridian)
  283. {
  284. // Now point1 and point2 belong within a hemisphere bounded by a
  285. // meridian and geodesic is neither meridional or equatorial.
  286. // Figure a starting point for Newton's method
  287. real dnm;
  288. sig12 =
  289. InverseStart(sbet1, cbet1, dn1, sbet2, cbet2, dn2, lam12, slam12,
  290. clam12, salp1, calp1, salp2, calp2, dnm, Ca);
  291. if (sig12 >= 0)
  292. {
  293. // Short lines (InverseStart sets salp2, calp2, dnm)
  294. s12x = sig12 * _b * dnm;
  295. m12x = Math::sq(dnm) * _b * sin(sig12 / dnm);
  296. if (outmask & GEODESICSCALE)
  297. {
  298. M12 = M21 = cos(sig12 / dnm);
  299. }
  300. a12 = sig12 / Math::degree();
  301. omg12 = lam12 / (_f1 * dnm);
  302. }
  303. else
  304. {
  305. // Newton's method. This is a straightforward solution of f(alp1) =
  306. // lambda12(alp1) - lam12 = 0 with one wrinkle. f(alp) has exactly
  307. // one root in the interval (0, pi) and its derivative is positive
  308. // at the root. Thus f(alp) is positive for alp > alp1 and negative
  309. // for alp < alp1. During the course of the iteration, a range
  310. // (alp1a, alp1b) is maintained which brackets the root and with
  311. // each evaluation of f(alp) the range is shrunk, if possible.
  312. // Newton's method is restarted whenever the derivative of f is
  313. // negative (because the new value of alp1 is then further from the
  314. // solution) or if the new estimate of alp1 lies outside (0,pi); in
  315. // this case, the new starting guess is taken to be (alp1a + alp1b)
  316. // / 2.
  317. //
  318. // initial values to suppress warnings (if loop is executed 0 times)
  319. real ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0,
  320. domg12 = 0;
  321. unsigned numit = 0;
  322. // Bracketing range
  323. real salp1a = tiny_, calp1a = 1, salp1b = tiny_, calp1b = -1;
  324. for (bool tripn = false, tripb = false;
  325. numit < maxit2_ || GEOGRAPHICLIB_PANIC; ++numit)
  326. {
  327. // the WGS84 test set: mean = 1.47, sd = 1.25, max = 16
  328. // WGS84 and random input: mean = 2.85, sd = 0.60
  329. real dv;
  330. real v = Lambda12(sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1,
  331. calp1, slam12, clam12, salp2, calp2, sig12,
  332. ssig1, csig1, ssig2, csig2, eps, domg12,
  333. numit < maxit1_, dv, Ca);
  334. // Reversed test to allow escape with NaNs
  335. if (tripb || !(abs(v) >= (tripn ? 8 : 1) * tol0_))
  336. {
  337. break;
  338. }
  339. // Update bracketing values
  340. if (v > 0 &&
  341. (numit > maxit1_ || calp1 / salp1 > calp1b / salp1b))
  342. {
  343. salp1b = salp1;
  344. calp1b = calp1;
  345. }
  346. else if (v < 0 &&
  347. (numit > maxit1_ || calp1 / salp1 < calp1a / salp1a))
  348. {
  349. salp1a = salp1;
  350. calp1a = calp1;
  351. }
  352. if (numit < maxit1_ && dv > 0)
  353. {
  354. real dalp1 = -v / dv;
  355. real sdalp1 = sin(dalp1), cdalp1 = cos(dalp1),
  356. nsalp1 = salp1 * cdalp1 + calp1 * sdalp1;
  357. if (nsalp1 > 0 && abs(dalp1) < Math::pi())
  358. {
  359. calp1 = calp1 * cdalp1 - salp1 * sdalp1;
  360. salp1 = nsalp1;
  361. Math::norm(salp1, calp1);
  362. // In some regimes we don't get quadratic convergence
  363. // because slope -> 0. So use convergence conditions
  364. // based on epsilon instead of sqrt(epsilon).
  365. tripn = abs(v) <= 16 * tol0_;
  366. continue;
  367. }
  368. }
  369. // Either dv was not positive or updated value was outside legal
  370. // range. Use the midpoint of the bracket as the next estimate.
  371. // This mechanism is not needed for the WGS84 ellipsoid, but it
  372. // does catch problems with more eccentric ellipsoids. Its
  373. // efficacy is such for the WGS84 test set with the starting
  374. // guess set to alp1 = 90deg: the WGS84 test set: mean = 5.21,
  375. // sd = 3.93, max = 24 WGS84 and random input: mean = 4.74, sd =
  376. // 0.99
  377. salp1 = (salp1a + salp1b) / 2;
  378. calp1 = (calp1a + calp1b) / 2;
  379. Math::norm(salp1, calp1);
  380. tripn = false;
  381. tripb = (abs(salp1a - salp1) + (calp1a - calp1) < tolb_ ||
  382. abs(salp1 - salp1b) + (calp1 - calp1b) < tolb_);
  383. }
  384. {
  385. real dummy;
  386. // Ensure that the reduced length and geodesic scale are
  387. // computed in a "canonical" way, with the I2 integral.
  388. unsigned lengthmask =
  389. outmask |
  390. (outmask & (REDUCEDLENGTH | GEODESICSCALE) ? DISTANCE
  391. : NONE);
  392. Lengths(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1,
  393. cbet2, lengthmask, s12x, m12x, dummy, M12, M21, Ca);
  394. }
  395. m12x *= _b;
  396. s12x *= _b;
  397. a12 = sig12 / Math::degree();
  398. if (outmask & AREA)
  399. {
  400. // omg12 = lam12 - domg12
  401. real sdomg12 = sin(domg12), cdomg12 = cos(domg12);
  402. somg12 = slam12 * cdomg12 - clam12 * sdomg12;
  403. comg12 = clam12 * cdomg12 + slam12 * sdomg12;
  404. }
  405. }
  406. }
  407. if (outmask & DISTANCE)
  408. {
  409. s12 = 0 + s12x; // Convert -0 to 0
  410. }
  411. if (outmask & REDUCEDLENGTH)
  412. {
  413. m12 = 0 + m12x; // Convert -0 to 0
  414. }
  415. if (outmask & AREA)
  416. {
  417. real
  418. // From Lambda12: sin(alp1) * cos(bet1) = sin(alp0)
  419. salp0 = salp1 * cbet1,
  420. calp0 = Math::hypot(calp1, salp1 * sbet1); // calp0 > 0
  421. real alp12;
  422. if (calp0 != 0 && salp0 != 0)
  423. {
  424. real
  425. // From Lambda12: tan(bet) = tan(sig) * cos(alp)
  426. ssig1 = sbet1,
  427. csig1 = calp1 * cbet1, ssig2 = sbet2, csig2 = calp2 * cbet2,
  428. k2 = Math::sq(calp0) * _ep2,
  429. eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2),
  430. // Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0).
  431. A4 = Math::sq(_a) * calp0 * salp0 * _e2;
  432. Math::norm(ssig1, csig1);
  433. Math::norm(ssig2, csig2);
  434. C4f(eps, Ca);
  435. real B41 = SinCosSeries(false, ssig1, csig1, Ca, nC4_),
  436. B42 = SinCosSeries(false, ssig2, csig2, Ca, nC4_);
  437. S12 = A4 * (B42 - B41);
  438. }
  439. else
  440. // Avoid problems with indeterminate sig1, sig2 on equator
  441. {
  442. S12 = 0;
  443. }
  444. if (!meridian && somg12 > 1)
  445. {
  446. somg12 = sin(omg12);
  447. comg12 = cos(omg12);
  448. }
  449. if (!meridian &&
  450. // omg12 < 3/4 * pi
  451. comg12 > -real(0.7071) && // Long difference not too big
  452. sbet2 - sbet1 < real(1.75)) // Lat difference not too big
  453. {
  454. // Use tan(Gamma/2) = tan(omg12/2)
  455. // * (tan(bet1/2)+tan(bet2/2))/(1+tan(bet1/2)*tan(bet2/2))
  456. // with tan(x/2) = sin(x)/(1+cos(x))
  457. real domg12 = 1 + comg12, dbet1 = 1 + cbet1, dbet2 = 1 + cbet2;
  458. alp12 = 2 * atan2(somg12 * (sbet1 * dbet2 + sbet2 * dbet1),
  459. domg12 * (sbet1 * sbet2 + dbet1 * dbet2));
  460. }
  461. else
  462. {
  463. // alp12 = alp2 - alp1, used in atan2 so no need to normalize
  464. real salp12 = salp2 * calp1 - calp2 * salp1,
  465. calp12 = calp2 * calp1 + salp2 * salp1;
  466. // The right thing appears to happen if alp1 = +/-180 and alp2 = 0,
  467. // viz salp12 = -0 and alp12 = -180. However this depends on the
  468. // sign being attached to 0 correctly. The following ensures the
  469. // correct behavior.
  470. if (salp12 == 0 && calp12 < 0)
  471. {
  472. salp12 = tiny_ * calp1;
  473. calp12 = -1;
  474. }
  475. alp12 = atan2(salp12, calp12);
  476. }
  477. S12 += _c2 * alp12;
  478. S12 *= swapp * lonsign * latsign;
  479. // Convert -0 to 0
  480. S12 += 0;
  481. }
  482. // Convert calp, salp to azimuth accounting for lonsign, swapp, latsign.
  483. if (swapp < 0)
  484. {
  485. swap(salp1, salp2);
  486. swap(calp1, calp2);
  487. if (outmask & GEODESICSCALE)
  488. {
  489. swap(M12, M21);
  490. }
  491. }
  492. salp1 *= swapp * lonsign;
  493. calp1 *= swapp * latsign;
  494. salp2 *= swapp * lonsign;
  495. calp2 *= swapp * latsign;
  496. // Returned value in [0, 180]
  497. return a12;
  498. }
  499. Math::real Geodesic::GenInverse(real lat1, real lon1, real lat2, real lon2,
  500. unsigned outmask, real &s12, real &azi1,
  501. real &azi2, real &m12, real &M12, real &M21,
  502. real &S12) const
  503. {
  504. // Ignore the warning C4100
  505. azi1 = azi1;
  506. azi2 = azi2;
  507. outmask &= OUT_MASK;
  508. real salp1, calp1, salp2, calp2,
  509. a12 = GenInverse(lat1, lon1, lat2, lon2, outmask, s12, salp1, calp1,
  510. salp2, calp2, m12, M12, M21, S12);
  511. return a12;
  512. }
  513. void Geodesic::Lengths(real eps, real sig12, real ssig1, real csig1, real dn1,
  514. real ssig2, real csig2, real dn2, real cbet1, real cbet2,
  515. unsigned outmask, real &s12b, real &m12b, real &m0,
  516. real &M12, real &M21,
  517. // Scratch area of the right size
  518. real Ca[]) const
  519. {
  520. // Return m12b = (reduced length)/_b; also calculate s12b = distance/_b,
  521. // and m0 = coefficient of secular term in expression for reduced length.
  522. outmask &= OUT_MASK;
  523. // outmask & DISTANCE: set s12b
  524. // outmask & REDUCEDLENGTH: set m12b & m0
  525. // outmask & GEODESICSCALE: set M12 & M21
  526. real m0x = 0, J12 = 0, A1 = 0, A2 = 0;
  527. real Cb[nC2_ + 1];
  528. if (outmask & (DISTANCE | REDUCEDLENGTH | GEODESICSCALE))
  529. {
  530. A1 = A1m1f(eps);
  531. C1f(eps, Ca);
  532. if (outmask & (REDUCEDLENGTH | GEODESICSCALE))
  533. {
  534. A2 = A2m1f(eps);
  535. C2f(eps, Cb);
  536. m0x = A1 - A2;
  537. A2 = 1 + A2;
  538. }
  539. A1 = 1 + A1;
  540. }
  541. if (outmask & DISTANCE)
  542. {
  543. real B1 = SinCosSeries(true, ssig2, csig2, Ca, nC1_) -
  544. SinCosSeries(true, ssig1, csig1, Ca, nC1_);
  545. // Missing a factor of _b
  546. s12b = A1 * (sig12 + B1);
  547. if (outmask & (REDUCEDLENGTH | GEODESICSCALE))
  548. {
  549. real B2 = SinCosSeries(true, ssig2, csig2, Cb, nC2_) -
  550. SinCosSeries(true, ssig1, csig1, Cb, nC2_);
  551. J12 = m0x * sig12 + (A1 * B1 - A2 * B2);
  552. }
  553. }
  554. else if (outmask & (REDUCEDLENGTH | GEODESICSCALE))
  555. {
  556. // Assume here that nC1_ >= nC2_
  557. for (int l = 1; l <= nC2_; ++l)
  558. {
  559. Cb[l] = A1 * Ca[l] - A2 * Cb[l];
  560. }
  561. J12 = m0x * sig12 + (SinCosSeries(true, ssig2, csig2, Cb, nC2_) -
  562. SinCosSeries(true, ssig1, csig1, Cb, nC2_));
  563. }
  564. if (outmask & REDUCEDLENGTH)
  565. {
  566. m0 = m0x;
  567. // Missing a factor of _b.
  568. // Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
  569. // accurate cancellation in the case of coincident points.
  570. m12b =
  571. dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) - csig1 * csig2 * J12;
  572. }
  573. if (outmask & GEODESICSCALE)
  574. {
  575. real csig12 = csig1 * csig2 + ssig1 * ssig2;
  576. real t = _ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
  577. M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
  578. M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
  579. }
  580. }
  581. Math::real Geodesic::Astroid(real x, real y)
  582. {
  583. // Solve k^4+2*k^3-(x^2+y^2-1)*k^2-2*y^2*k-y^2 = 0 for positive root k.
  584. // This solution is adapted from Geocentric::Reverse.
  585. real k;
  586. real p = Math::sq(x), q = Math::sq(y), r = (p + q - 1) / 6;
  587. if (!(q == 0 && r <= 0))
  588. {
  589. real
  590. // Avoid possible division by zero when r = 0 by multiplying
  591. // equations for s and t by r^3 and r, resp.
  592. S = p * q / 4, // S = r^3 * s
  593. r2 = Math::sq(r), r3 = r * r2,
  594. // The discriminant of the quadratic equation for T3. This is
  595. // zero on the evolute curve p^(1/3)+q^(1/3) = 1
  596. disc = S * (S + 2 * r3);
  597. real u = r;
  598. if (disc >= 0)
  599. {
  600. real T3 = S + r3;
  601. // Pick the sign on the sqrt to maximize abs(T3). This minimizes
  602. // loss of precision due to cancellation. The result is unchanged
  603. // because of the way the T is used in definition of u.
  604. T3 += T3 < 0 ? -sqrt(disc) : sqrt(disc); // T3 = (r * t)^3
  605. // N.B. cbrt always returns the real root. cbrt(-8) = -2.
  606. real T = Math::cbrt(T3); // T = r * t
  607. // T can be zero; but then r2 / T -> 0.
  608. u += T + (T ? r2 / T : 0);
  609. }
  610. else
  611. {
  612. // T is complex, but the way u is defined the result is real.
  613. real ang = atan2(sqrt(-disc), -(S + r3));
  614. // There are three possible cube roots. We choose the root which
  615. // avoids cancellation. Note that disc < 0 implies that r < 0.
  616. u += 2 * r * cos(ang / 3);
  617. }
  618. real v = sqrt(Math::sq(u) + q), // guaranteed positive
  619. // Avoid loss of accuracy when u < 0.
  620. uv = u < 0 ? q / (v - u) : u + v, // u+v, guaranteed positive
  621. w = (uv - q) / (2 * v); // positive?
  622. // Rearrange expression for k to avoid loss of accuracy due to
  623. // subtraction. Division by 0 not possible because uv > 0, w >= 0.
  624. k = uv / (sqrt(uv + Math::sq(w)) + w); // guaranteed positive
  625. }
  626. else // q == 0 && r <= 0
  627. {
  628. // y = 0 with |x| <= 1. Handle this case directly.
  629. // for y small, positive root is k = abs(y)/sqrt(1-x^2)
  630. k = 0;
  631. }
  632. return k;
  633. }
  634. Math::real Geodesic::InverseStart(real sbet1, real cbet1, real dn1, real sbet2,
  635. real cbet2, real dn2, real lam12, real slam12,
  636. real clam12, real &salp1, real &calp1,
  637. // Only updated if return val >= 0
  638. real &salp2, real &calp2,
  639. // Only updated for short lines
  640. real &dnm,
  641. // Scratch area of the right size
  642. real Ca[]) const
  643. {
  644. // Return a starting point for Newton's method in salp1 and calp1 (function
  645. // value is -1). If Newton's method doesn't need to be used, return also
  646. // salp2 and calp2 and function value is sig12.
  647. real sig12 = -1, // Return value
  648. // bet12 = bet2 - bet1 in [0, pi); bet12a = bet2 + bet1 in (-pi, 0]
  649. sbet12 = sbet2 * cbet1 - cbet2 * sbet1,
  650. cbet12 = cbet2 * cbet1 + sbet2 * sbet1;
  651. #if defined(__GNUC__) && __GNUC__ == 4 && \
  652. (__GNUC_MINOR__ < 6 || defined(__MINGW32__))
  653. // Volatile declaration needed to fix inverse cases
  654. // 88.202499451857 0 -88.202499451857 179.981022032992859592
  655. // 89.262080389218 0 -89.262080389218 179.992207982775375662
  656. // 89.333123580033 0 -89.333123580032997687 179.99295812360148422
  657. // which otherwise fail with g++ 4.4.4 x86 -O3 (Linux)
  658. // and g++ 4.4.0 (mingw) and g++ 4.6.1 (tdm mingw).
  659. real sbet12a;
  660. {
  661. GEOGRAPHICLIB_VOLATILE real xx1 = sbet2 * cbet1;
  662. GEOGRAPHICLIB_VOLATILE real xx2 = cbet2 * sbet1;
  663. sbet12a = xx1 + xx2;
  664. }
  665. #else
  666. real sbet12a = sbet2 * cbet1 + cbet2 * sbet1;
  667. #endif
  668. bool shortline =
  669. cbet12 >= 0 && sbet12 < real(0.5) && cbet2 * lam12 < real(0.5);
  670. real somg12, comg12;
  671. if (shortline)
  672. {
  673. real sbetm2 = Math::sq(sbet1 + sbet2);
  674. // sin((bet1+bet2)/2)^2
  675. // = (sbet1 + sbet2)^2 / ((sbet1 + sbet2)^2 + (cbet1 + cbet2)^2)
  676. sbetm2 /= sbetm2 + Math::sq(cbet1 + cbet2);
  677. dnm = sqrt(1 + _ep2 * sbetm2);
  678. real omg12 = lam12 / (_f1 * dnm);
  679. somg12 = sin(omg12);
  680. comg12 = cos(omg12);
  681. }
  682. else
  683. {
  684. somg12 = slam12;
  685. comg12 = clam12;
  686. }
  687. salp1 = cbet2 * somg12;
  688. calp1 = comg12 >= 0
  689. ? sbet12 + cbet2 * sbet1 * Math::sq(somg12) / (1 + comg12)
  690. : sbet12a - cbet2 * sbet1 * Math::sq(somg12) / (1 - comg12);
  691. real ssig12 = Math::hypot(salp1, calp1),
  692. csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12;
  693. if (shortline && ssig12 < _etol2)
  694. {
  695. // really short lines
  696. salp2 = cbet1 * somg12;
  697. calp2 = sbet12 - cbet1 * sbet2 *
  698. (comg12 >= 0 ? Math::sq(somg12) / (1 + comg12)
  699. : 1 - comg12);
  700. Math::norm(salp2, calp2);
  701. // Set return value
  702. sig12 = atan2(ssig12, csig12);
  703. }
  704. else if (abs(_n) > real(0.1) || // Skip astroid calc if too eccentric
  705. csig12 >= 0 ||
  706. ssig12 >= 6 * abs(_n) * Math::pi() * Math::sq(cbet1))
  707. {
  708. // Nothing to do, zeroth order spherical approximation is OK
  709. }
  710. else
  711. {
  712. // Scale lam12 and bet2 to x, y coordinate system where antipodal point
  713. // is at origin and singular point is at y = 0, x = -1.
  714. real y, lamscale, betscale;
  715. // Volatile declaration needed to fix inverse case
  716. // 56.320923501171 0 -56.320923501171 179.664747671772880215
  717. // which otherwise fails with g++ 4.4.4 x86 -O3
  718. GEOGRAPHICLIB_VOLATILE real x;
  719. real lam12x = atan2(-slam12, -clam12); // lam12 - pi
  720. if (_f >= 0) // In fact f == 0 does not get here
  721. {
  722. // x = dlong, y = dlat
  723. {
  724. real k2 = Math::sq(sbet1) * _ep2,
  725. eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
  726. lamscale = _f * cbet1 * A3f(eps) * Math::pi();
  727. }
  728. betscale = lamscale * cbet1;
  729. x = lam12x / lamscale;
  730. y = sbet12a / betscale;
  731. }
  732. else // _f < 0
  733. {
  734. // x = dlat, y = dlong
  735. real cbet12a = cbet2 * cbet1 - sbet2 * sbet1,
  736. bet12a = atan2(sbet12a, cbet12a);
  737. real m12b, m0, dummy;
  738. // In the case of lon12 = 180, this repeats a calculation made in
  739. // Inverse.
  740. Lengths(_n, Math::pi() + bet12a, sbet1, -cbet1, dn1, sbet2, cbet2,
  741. dn2, cbet1, cbet2, REDUCEDLENGTH, dummy, m12b, m0, dummy,
  742. dummy, Ca);
  743. x = -1 + m12b / (cbet1 * cbet2 * m0 * Math::pi());
  744. betscale = x < -real(0.01) ? sbet12a / x
  745. : -_f * Math::sq(cbet1) * Math::pi();
  746. lamscale = betscale / cbet1;
  747. y = lam12x / lamscale;
  748. }
  749. if (y > -tol1_ && x > -1 - xthresh_)
  750. {
  751. // strip near cut
  752. // Need real(x) here to cast away the volatility of x for min/max
  753. if (_f >= 0)
  754. {
  755. salp1 = min(real(1), -real(x));
  756. calp1 = -sqrt(1 - Math::sq(salp1));
  757. }
  758. else
  759. {
  760. calp1 = max(real(x > -tol1_ ? 0 : -1), real(x));
  761. salp1 = sqrt(1 - Math::sq(calp1));
  762. }
  763. }
  764. else
  765. {
  766. // Estimate alp1, by solving the astroid problem.
  767. //
  768. // Could estimate alpha1 = theta + pi/2, directly, i.e.,
  769. // calp1 = y/k; salp1 = -x/(1+k); for _f >= 0
  770. // calp1 = x/(1+k); salp1 = -y/k; for _f < 0 (need to check)
  771. //
  772. // However, it's better to estimate omg12 from astroid and use
  773. // spherical formula to compute alp1. This reduces the mean number
  774. // of Newton iterations for astroid cases from 2.24 (min 0, max 6)
  775. // to 2.12 (min 0 max 5). The changes in the number of iterations
  776. // are as follows:
  777. //
  778. // change percent
  779. // 1 5
  780. // 0 78
  781. // -1 16
  782. // -2 0.6
  783. // -3 0.04
  784. // -4 0.002
  785. //
  786. // The histogram of iterations is (m = number of iterations
  787. // estimating alp1 directly, n = number of iterations estimating via
  788. // omg12, total number of trials = 148605):
  789. //
  790. // iter m n
  791. // 0 148 186
  792. // 1 13046 13845
  793. // 2 93315 102225
  794. // 3 36189 32341
  795. // 4 5396 7
  796. // 5 455 1
  797. // 6 56 0
  798. //
  799. // Because omg12 is near pi, estimate work with omg12a = pi - omg12
  800. real k = Astroid(x, y);
  801. real omg12a =
  802. lamscale * (_f >= 0 ? -x * k / (1 + k) : -y * (1 + k) / k);
  803. somg12 = sin(omg12a);
  804. comg12 = -cos(omg12a);
  805. // Update spherical estimate of alp1 using omg12 instead of lam12
  806. salp1 = cbet2 * somg12;
  807. calp1 = sbet12a - cbet2 * sbet1 * Math::sq(somg12) / (1 - comg12);
  808. }
  809. }
  810. // Sanity check on starting guess. Backwards check allows NaN through.
  811. if (!(salp1 <= 0))
  812. {
  813. Math::norm(salp1, calp1);
  814. }
  815. else
  816. {
  817. salp1 = 1;
  818. calp1 = 0;
  819. }
  820. return sig12;
  821. }
  822. Math::real Geodesic::Lambda12(real sbet1, real cbet1, real dn1, real sbet2,
  823. real cbet2, real dn2, real salp1, real calp1,
  824. real slam120, real clam120, real &salp2,
  825. real &calp2, real &sig12, real &ssig1,
  826. real &csig1, real &ssig2, real &csig2, real &eps,
  827. real &domg12, bool diffp, real &dlam12,
  828. // Scratch area of the right size
  829. real Ca[]) const
  830. {
  831. if (sbet1 == 0 && calp1 == 0)
  832. // Break degeneracy of equatorial line. This case has already been
  833. // handled.
  834. {
  835. calp1 = -tiny_;
  836. }
  837. real
  838. // sin(alp1) * cos(bet1) = sin(alp0)
  839. salp0 = salp1 * cbet1,
  840. calp0 = Math::hypot(calp1, salp1 * sbet1); // calp0 > 0
  841. real somg1, comg1, somg2, comg2, somg12, comg12, lam12;
  842. // tan(bet1) = tan(sig1) * cos(alp1)
  843. // tan(omg1) = sin(alp0) * tan(sig1) = tan(omg1)=tan(alp1)*sin(bet1)
  844. ssig1 = sbet1;
  845. somg1 = salp0 * sbet1;
  846. csig1 = comg1 = calp1 * cbet1;
  847. Math::norm(ssig1, csig1);
  848. // Math::norm(somg1, comg1); -- don't need to normalize!
  849. // Enforce symmetries in the case abs(bet2) = -bet1. Need to be careful
  850. // about this case, since this can yield singularities in the Newton
  851. // iteration.
  852. // sin(alp2) * cos(bet2) = sin(alp0)
  853. salp2 = cbet2 != cbet1 ? salp0 / cbet2 : salp1;
  854. // calp2 = sqrt(1 - sq(salp2))
  855. // = sqrt(sq(calp0) - sq(sbet2)) / cbet2
  856. // and subst for calp0 and rearrange to give (choose positive sqrt
  857. // to give alp2 in [0, pi/2]).
  858. calp2 = cbet2 != cbet1 || abs(sbet2) != -sbet1
  859. ? sqrt(Math::sq(calp1 * cbet1) +
  860. (cbet1 < -sbet1 ? (cbet2 - cbet1) * (cbet1 + cbet2)
  861. : (sbet1 - sbet2) * (sbet1 + sbet2))) /
  862. cbet2
  863. : abs(calp1);
  864. // tan(bet2) = tan(sig2) * cos(alp2)
  865. // tan(omg2) = sin(alp0) * tan(sig2).
  866. ssig2 = sbet2;
  867. somg2 = salp0 * sbet2;
  868. csig2 = comg2 = calp2 * cbet2;
  869. Math::norm(ssig2, csig2);
  870. // Math::norm(somg2, comg2); -- don't need to normalize!
  871. // sig12 = sig2 - sig1, limit to [0, pi]
  872. sig12 = atan2(max(real(0), csig1 * ssig2 - ssig1 * csig2),
  873. csig1 * csig2 + ssig1 * ssig2);
  874. // omg12 = omg2 - omg1, limit to [0, pi]
  875. somg12 = max(real(0), comg1 * somg2 - somg1 * comg2);
  876. comg12 = comg1 * comg2 + somg1 * somg2;
  877. // eta = omg12 - lam120
  878. real eta = atan2(somg12 * clam120 - comg12 * slam120,
  879. comg12 * clam120 + somg12 * slam120);
  880. real B312;
  881. real k2 = Math::sq(calp0) * _ep2;
  882. eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
  883. C3f(eps, Ca);
  884. B312 = (SinCosSeries(true, ssig2, csig2, Ca, nC3_ - 1) -
  885. SinCosSeries(true, ssig1, csig1, Ca, nC3_ - 1));
  886. domg12 = -_f * A3f(eps) * salp0 * (sig12 + B312);
  887. lam12 = eta + domg12;
  888. if (diffp)
  889. {
  890. if (calp2 == 0)
  891. {
  892. dlam12 = -2 * _f1 * dn1 / sbet1;
  893. }
  894. else
  895. {
  896. real dummy;
  897. Lengths(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1,
  898. cbet2, REDUCEDLENGTH, dummy, dlam12, dummy, dummy, dummy,
  899. Ca);
  900. dlam12 *= _f1 / (calp2 * cbet2);
  901. }
  902. }
  903. return lam12;
  904. }
  905. Math::real Geodesic::A3f(real eps) const
  906. {
  907. // Evaluate A3
  908. return Math::polyval(nA3_ - 1, _A3x, eps);
  909. }
  910. void Geodesic::C3f(real eps, real c[]) const
  911. {
  912. // Evaluate C3 coeffs
  913. // Elements c[1] thru c[nC3_ - 1] are set
  914. real mult = 1;
  915. int o = 0;
  916. for (int l = 1; l < nC3_; ++l) // l is index of C3[l]
  917. {
  918. int m = nC3_ - l - 1; // order of polynomial in eps
  919. mult *= eps;
  920. c[l] = mult * Math::polyval(m, _C3x + o, eps);
  921. o += m + 1;
  922. }
  923. // Post condition: o == nC3x_
  924. }
  925. void Geodesic::C4f(real eps, real c[]) const
  926. {
  927. // Evaluate C4 coeffs
  928. // Elements c[0] thru c[nC4_ - 1] are set
  929. real mult = 1;
  930. int o = 0;
  931. for (int l = 0; l < nC4_; ++l) // l is index of C4[l]
  932. {
  933. int m = nC4_ - l - 1; // order of polynomial in eps
  934. c[l] = mult * Math::polyval(m, _C4x + o, eps);
  935. o += m + 1;
  936. mult *= eps;
  937. }
  938. // Post condition: o == nC4x_
  939. }
  940. // The static const coefficient arrays in the following functions are
  941. // generated by Maxima and give the coefficients of the Taylor expansions for
  942. // the geodesics. The convention on the order of these coefficients is as
  943. // follows:
  944. //
  945. // ascending order in the trigonometric expansion,
  946. // then powers of eps in descending order,
  947. // finally powers of n in descending order.
  948. //
  949. // (For some expansions, only a subset of levels occur.) For each polynomial
  950. // of order n at the lowest level, the (n+1) coefficients of the polynomial
  951. // are followed by a divisor which is applied to the whole polynomial. In
  952. // this way, the coefficients are expressible with no round off error. The
  953. // sizes of the coefficient arrays are:
  954. //
  955. // A1m1f, A2m1f = floor(N/2) + 2
  956. // C1f, C1pf, C2f, A3coeff = (N^2 + 7*N - 2*floor(N/2)) / 4
  957. // C3coeff = (N - 1) * (N^2 + 7*N - 2*floor(N/2)) / 8
  958. // C4coeff = N * (N + 1) * (N + 5) / 6
  959. //
  960. // where N = GEOGRAPHICLIB_GEODESIC_ORDER
  961. // = nA1 = nA2 = nC1 = nC1p = nA3 = nC4
  962. // The scale factor A1-1 = mean value of (d/dsigma)I1 - 1
  963. Math::real Geodesic::A1m1f(real eps)
  964. {
  965. static const real coeff[] = {
  966. // (1-eps)*A1-1, polynomial in eps2 of order 3
  967. 1, 4, 64, 0, 256,
  968. };
  969. GEOGRAPHICLIB_STATIC_ASSERT(sizeof(coeff) / sizeof(real) == nA1_ / 2 + 2,
  970. "Coefficient array size mismatch in A1m1f");
  971. int m = nA1_ / 2;
  972. real t = Math::polyval(m, coeff, Math::sq(eps)) / coeff[m + 1];
  973. return (t + eps) / (1 - eps);
  974. }
  975. // The coefficients C1[l] in the Fourier expansion of B1
  976. void Geodesic::C1f(real eps, real c[])
  977. {
  978. static const real coeff[] = {
  979. // C1[1]/eps^1, polynomial in eps2 of order 2
  980. -1,
  981. 6,
  982. -16,
  983. 32,
  984. // C1[2]/eps^2, polynomial in eps2 of order 2
  985. -9,
  986. 64,
  987. -128,
  988. 2048,
  989. // C1[3]/eps^3, polynomial in eps2 of order 1
  990. 9,
  991. -16,
  992. 768,
  993. // C1[4]/eps^4, polynomial in eps2 of order 1
  994. 3,
  995. -5,
  996. 512,
  997. // C1[5]/eps^5, polynomial in eps2 of order 0
  998. -7,
  999. 1280,
  1000. // C1[6]/eps^6, polynomial in eps2 of order 0
  1001. -7,
  1002. 2048,
  1003. };
  1004. GEOGRAPHICLIB_STATIC_ASSERT(
  1005. sizeof(coeff) / sizeof(real) ==
  1006. (nC1_ * nC1_ + 7 * nC1_ - 2 * (nC1_ / 2)) / 4,
  1007. "Coefficient array size mismatch in C1f");
  1008. real eps2 = Math::sq(eps), d = eps;
  1009. int o = 0;
  1010. for (int l = 1; l <= nC1_; ++l) // l is index of C1p[l]
  1011. {
  1012. int m = (nC1_ - l) / 2; // order of polynomial in eps^2
  1013. c[l] = d * Math::polyval(m, coeff + o, eps2) / coeff[o + m + 1];
  1014. o += m + 2;
  1015. d *= eps;
  1016. }
  1017. // Post condition: o == sizeof(coeff) / sizeof(real)
  1018. }
  1019. // The coefficients C1p[l] in the Fourier expansion of B1p
  1020. void Geodesic::C1pf(real eps, real c[])
  1021. {
  1022. static const real coeff[] = {
  1023. // C1p[1]/eps^1, polynomial in eps2 of order 2
  1024. 205,
  1025. -432,
  1026. 768,
  1027. 1536,
  1028. // C1p[2]/eps^2, polynomial in eps2 of order 2
  1029. 4005,
  1030. -4736,
  1031. 3840,
  1032. 12288,
  1033. // C1p[3]/eps^3, polynomial in eps2 of order 1
  1034. -225,
  1035. 116,
  1036. 384,
  1037. // C1p[4]/eps^4, polynomial in eps2 of order 1
  1038. -7173,
  1039. 2695,
  1040. 7680,
  1041. // C1p[5]/eps^5, polynomial in eps2 of order 0
  1042. 3467,
  1043. 7680,
  1044. // C1p[6]/eps^6, polynomial in eps2 of order 0
  1045. 38081,
  1046. 61440,
  1047. };
  1048. GEOGRAPHICLIB_STATIC_ASSERT(
  1049. sizeof(coeff) / sizeof(real) ==
  1050. (nC1p_ * nC1p_ + 7 * nC1p_ - 2 * (nC1p_ / 2)) / 4,
  1051. "Coefficient array size mismatch in C1pf");
  1052. real eps2 = Math::sq(eps), d = eps;
  1053. int o = 0;
  1054. for (int l = 1; l <= nC1p_; ++l) // l is index of C1p[l]
  1055. {
  1056. int m = (nC1p_ - l) / 2; // order of polynomial in eps^2
  1057. c[l] = d * Math::polyval(m, coeff + o, eps2) / coeff[o + m + 1];
  1058. o += m + 2;
  1059. d *= eps;
  1060. }
  1061. // Post condition: o == sizeof(coeff) / sizeof(real)
  1062. }
  1063. // The scale factor A2-1 = mean value of (d/dsigma)I2 - 1
  1064. Math::real Geodesic::A2m1f(real eps)
  1065. {
  1066. static const real coeff[] = {
  1067. // (eps+1)*A2-1, polynomial in eps2 of order 3
  1068. -11, -28, -192, 0, 256,
  1069. }; // count = 5
  1070. GEOGRAPHICLIB_STATIC_ASSERT(sizeof(coeff) / sizeof(real) == nA2_ / 2 + 2,
  1071. "Coefficient array size mismatch in A2m1f");
  1072. int m = nA2_ / 2;
  1073. real t = Math::polyval(m, coeff, Math::sq(eps)) / coeff[m + 1];
  1074. return (t - eps) / (1 + eps);
  1075. }
  1076. // The coefficients C2[l] in the Fourier expansion of B2
  1077. void Geodesic::C2f(real eps, real c[])
  1078. {
  1079. static const real coeff[] = {
  1080. // C2[1]/eps^1, polynomial in eps2 of order 2
  1081. 1,
  1082. 2,
  1083. 16,
  1084. 32,
  1085. // C2[2]/eps^2, polynomial in eps2 of order 2
  1086. 35,
  1087. 64,
  1088. 384,
  1089. 2048,
  1090. // C2[3]/eps^3, polynomial in eps2 of order 1
  1091. 15,
  1092. 80,
  1093. 768,
  1094. // C2[4]/eps^4, polynomial in eps2 of order 1
  1095. 7,
  1096. 35,
  1097. 512,
  1098. // C2[5]/eps^5, polynomial in eps2 of order 0
  1099. 63,
  1100. 1280,
  1101. // C2[6]/eps^6, polynomial in eps2 of order 0
  1102. 77,
  1103. 2048,
  1104. };
  1105. GEOGRAPHICLIB_STATIC_ASSERT(
  1106. sizeof(coeff) / sizeof(real) ==
  1107. (nC2_ * nC2_ + 7 * nC2_ - 2 * (nC2_ / 2)) / 4,
  1108. "Coefficient array size mismatch in C2f");
  1109. real eps2 = Math::sq(eps), d = eps;
  1110. int o = 0;
  1111. for (int l = 1; l <= nC2_; ++l) // l is index of C2[l]
  1112. {
  1113. int m = (nC2_ - l) / 2; // order of polynomial in eps^2
  1114. c[l] = d * Math::polyval(m, coeff + o, eps2) / coeff[o + m + 1];
  1115. o += m + 2;
  1116. d *= eps;
  1117. }
  1118. // Post condition: o == sizeof(coeff) / sizeof(real)
  1119. }
  1120. // The scale factor A3 = mean value of (d/dsigma)I3
  1121. void Geodesic::A3coeff()
  1122. {
  1123. static const real coeff[] = {
  1124. // A3, coeff of eps^5, polynomial in n of order 0
  1125. -3,
  1126. 128,
  1127. // A3, coeff of eps^4, polynomial in n of order 1
  1128. -2,
  1129. -3,
  1130. 64,
  1131. // A3, coeff of eps^3, polynomial in n of order 2
  1132. -1,
  1133. -3,
  1134. -1,
  1135. 16,
  1136. // A3, coeff of eps^2, polynomial in n of order 2
  1137. 3,
  1138. -1,
  1139. -2,
  1140. 8,
  1141. // A3, coeff of eps^1, polynomial in n of order 1
  1142. 1,
  1143. -1,
  1144. 2,
  1145. // A3, coeff of eps^0, polynomial in n of order 0
  1146. 1,
  1147. 1,
  1148. };
  1149. GEOGRAPHICLIB_STATIC_ASSERT(
  1150. sizeof(coeff) / sizeof(real) ==
  1151. (nA3_ * nA3_ + 7 * nA3_ - 2 * (nA3_ / 2)) / 4,
  1152. "Coefficient array size mismatch in A3f");
  1153. int o = 0, k = 0;
  1154. for (int j = nA3_ - 1; j >= 0; --j) // coeff of eps^j
  1155. {
  1156. int m = min(nA3_ - j - 1, j); // order of polynomial in n
  1157. _A3x[k++] = Math::polyval(m, coeff + o, _n) / coeff[o + m + 1];
  1158. o += m + 2;
  1159. }
  1160. // Post condition: o == sizeof(coeff) / sizeof(real) && k == nA3x_
  1161. }
  1162. // The coefficients C3[l] in the Fourier expansion of B3
  1163. void Geodesic::C3coeff()
  1164. {
  1165. static const real coeff[] = {
  1166. // C3[1], coeff of eps^5, polynomial in n of order 0
  1167. 3,
  1168. 128,
  1169. // C3[1], coeff of eps^4, polynomial in n of order 1
  1170. 2,
  1171. 5,
  1172. 128,
  1173. // C3[1], coeff of eps^3, polynomial in n of order 2
  1174. -1,
  1175. 3,
  1176. 3,
  1177. 64,
  1178. // C3[1], coeff of eps^2, polynomial in n of order 2
  1179. -1,
  1180. 0,
  1181. 1,
  1182. 8,
  1183. // C3[1], coeff of eps^1, polynomial in n of order 1
  1184. -1,
  1185. 1,
  1186. 4,
  1187. // C3[2], coeff of eps^5, polynomial in n of order 0
  1188. 5,
  1189. 256,
  1190. // C3[2], coeff of eps^4, polynomial in n of order 1
  1191. 1,
  1192. 3,
  1193. 128,
  1194. // C3[2], coeff of eps^3, polynomial in n of order 2
  1195. -3,
  1196. -2,
  1197. 3,
  1198. 64,
  1199. // C3[2], coeff of eps^2, polynomial in n of order 2
  1200. 1,
  1201. -3,
  1202. 2,
  1203. 32,
  1204. // C3[3], coeff of eps^5, polynomial in n of order 0
  1205. 7,
  1206. 512,
  1207. // C3[3], coeff of eps^4, polynomial in n of order 1
  1208. -10,
  1209. 9,
  1210. 384,
  1211. // C3[3], coeff of eps^3, polynomial in n of order 2
  1212. 5,
  1213. -9,
  1214. 5,
  1215. 192,
  1216. // C3[4], coeff of eps^5, polynomial in n of order 0
  1217. 7,
  1218. 512,
  1219. // C3[4], coeff of eps^4, polynomial in n of order 1
  1220. -14,
  1221. 7,
  1222. 512,
  1223. // C3[5], coeff of eps^5, polynomial in n of order 0
  1224. 21,
  1225. 2560,
  1226. };
  1227. GEOGRAPHICLIB_STATIC_ASSERT(
  1228. sizeof(coeff) / sizeof(real) ==
  1229. ((nC3_ - 1) * (nC3_ * nC3_ + 7 * nC3_ - 2 * (nC3_ / 2))) / 8,
  1230. "Coefficient array size mismatch in C3coeff");
  1231. int o = 0, k = 0;
  1232. for (int l = 1; l < nC3_; ++l) // l is index of C3[l]
  1233. {
  1234. for (int j = nC3_ - 1; j >= l; --j) // coeff of eps^j
  1235. {
  1236. int m = min(nC3_ - j - 1, j); // order of polynomial in n
  1237. _C3x[k++] = Math::polyval(m, coeff + o, _n) / coeff[o + m + 1];
  1238. o += m + 2;
  1239. }
  1240. }
  1241. // Post condition: o == sizeof(coeff) / sizeof(real) && k == nC3x_
  1242. }
  1243. void Geodesic::C4coeff()
  1244. {
  1245. // Generated by Maxima on 2015-05-05 18:08:13-04:00
  1246. static const real coeff[] = {
  1247. // C4[0], coeff of eps^5, polynomial in n of order 0
  1248. 97,
  1249. 15015,
  1250. // C4[0], coeff of eps^4, polynomial in n of order 1
  1251. 1088,
  1252. 156,
  1253. 45045,
  1254. // C4[0], coeff of eps^3, polynomial in n of order 2
  1255. -224,
  1256. -4784,
  1257. 1573,
  1258. 45045,
  1259. // C4[0], coeff of eps^2, polynomial in n of order 3
  1260. -10656,
  1261. 14144,
  1262. -4576,
  1263. -858,
  1264. 45045,
  1265. // C4[0], coeff of eps^1, polynomial in n of order 4
  1266. 64,
  1267. 624,
  1268. -4576,
  1269. 6864,
  1270. -3003,
  1271. 15015,
  1272. // C4[0], coeff of eps^0, polynomial in n of order 5
  1273. 100,
  1274. 208,
  1275. 572,
  1276. 3432,
  1277. -12012,
  1278. 30030,
  1279. 45045,
  1280. // C4[1], coeff of eps^5, polynomial in n of order 0
  1281. 1,
  1282. 9009,
  1283. // C4[1], coeff of eps^4, polynomial in n of order 1
  1284. -2944,
  1285. 468,
  1286. 135135,
  1287. // C4[1], coeff of eps^3, polynomial in n of order 2
  1288. 5792,
  1289. 1040,
  1290. -1287,
  1291. 135135,
  1292. // C4[1], coeff of eps^2, polynomial in n of order 3
  1293. 5952,
  1294. -11648,
  1295. 9152,
  1296. -2574,
  1297. 135135,
  1298. // C4[1], coeff of eps^1, polynomial in n of order 4
  1299. -64,
  1300. -624,
  1301. 4576,
  1302. -6864,
  1303. 3003,
  1304. 135135,
  1305. // C4[2], coeff of eps^5, polynomial in n of order 0
  1306. 8,
  1307. 10725,
  1308. // C4[2], coeff of eps^4, polynomial in n of order 1
  1309. 1856,
  1310. -936,
  1311. 225225,
  1312. // C4[2], coeff of eps^3, polynomial in n of order 2
  1313. -8448,
  1314. 4992,
  1315. -1144,
  1316. 225225,
  1317. // C4[2], coeff of eps^2, polynomial in n of order 3
  1318. -1440,
  1319. 4160,
  1320. -4576,
  1321. 1716,
  1322. 225225,
  1323. // C4[3], coeff of eps^5, polynomial in n of order 0
  1324. -136,
  1325. 63063,
  1326. // C4[3], coeff of eps^4, polynomial in n of order 1
  1327. 1024,
  1328. -208,
  1329. 105105,
  1330. // C4[3], coeff of eps^3, polynomial in n of order 2
  1331. 3584,
  1332. -3328,
  1333. 1144,
  1334. 315315,
  1335. // C4[4], coeff of eps^5, polynomial in n of order 0
  1336. -128,
  1337. 135135,
  1338. // C4[4], coeff of eps^4, polynomial in n of order 1
  1339. -2560,
  1340. 832,
  1341. 405405,
  1342. // C4[5], coeff of eps^5, polynomial in n of order 0
  1343. 128,
  1344. 99099,
  1345. };
  1346. GEOGRAPHICLIB_STATIC_ASSERT(
  1347. sizeof(coeff) / sizeof(real) == (nC4_ * (nC4_ + 1) * (nC4_ + 5)) / 6,
  1348. "Coefficient array size mismatch in C4coeff");
  1349. int o = 0, k = 0;
  1350. for (int l = 0; l < nC4_; ++l) // l is index of C4[l]
  1351. {
  1352. for (int j = nC4_ - 1; j >= l; --j) // coeff of eps^j
  1353. {
  1354. int m = nC4_ - j - 1; // order of polynomial in n
  1355. _C4x[k++] = Math::polyval(m, coeff + o, _n) / coeff[o + m + 1];
  1356. o += m + 2;
  1357. }
  1358. }
  1359. // Post condition: o == sizeof(coeff) / sizeof(real) && k == nC4x_
  1360. }
  1361. } // namespace GeographicLib