OpenCPN Partial API docs
georef.cpp
1 /******************************************************************************
2  *
3  * Project: OpenCPN
4  * Purpose: OpenCPN Georef utility
5  * Author: David Register
6  *
7  ***************************************************************************
8  * Copyright (C) 2010 by David S. Register *
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  * This program is distributed in the hope that it will be useful, *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18  * GNU General Public License for more details. *
19  * *
20  * You should have received a copy of the GNU General Public License *
21  * along with this program; if not, write to the *
22  * Free Software Foundation, Inc., *
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24  ***************************************************************************
25 
26  ***************************************************************************
27  * Parts of this file were adapted from source code found in *
28  * John F. Waers (jfwaers@csn.net) public domain program MacGPS45 *
29  ***************************************************************************
30  */
31 #include <vector>
32 #include <utility>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <math.h>
37 #include <algorithm>
38 
39 #include <wx/debug.h>
40 
41 #include "model/georef.h"
42 #include "model/cutil.h"
43 
44 #ifdef __MSVC__
45 #define snprintf mysnprintf
46 #endif
47 
48 #if !defined(NAN)
49 static const long long lNaN = 0xfff8000000000000;
50 #define NAN (*(double *)&lNaN)
51 #endif
52 
53 // ellipsoid: index into the gEllipsoid[] array, in which
54 // a is the ellipsoid semimajor axis
55 // invf is the inverse of the ellipsoid flattening f
56 // dx, dy, dz: ellipsoid center with respect to WGS84 ellipsoid center
57 // x axis is the prime meridian
58 // y axis is 90 degrees east longitude
59 // z axis is the axis of rotation of the ellipsoid
60 
61 // The following values for dx, dy and dz were extracted from the output of
62 // the GARMIN PCX5 program. The output also includes values for da and df, the
63 // difference between the reference ellipsoid and the WGS84 ellipsoid semi-
64 // major axis and flattening, respectively. These are replaced by the
65 // data contained in the structure array gEllipsoid[], which was obtained from
66 // the Defence Mapping Agency document number TR8350.2, "Department of Defense
67 // World Geodetic System 1984."
68 
69 struct DATUM const gDatum[] = {
70  // name ellipsoid dx dy dz
71  {"Adindan", 5, -162, -12, 206}, // 0
72  {"Afgooye", 15, -43, -163, 45}, // 1
73  {"Ain el Abd 1970", 14, -150, -251, -2}, // 2
74  {"Anna 1 Astro 1965", 2, -491, -22, 435}, // 3
75  {"Arc 1950", 5, -143, -90, -294}, // 4
76  {"Arc 1960", 5, -160, -8, -300}, // 5
77  {"Ascension Island 58", 14, -207, 107, 52}, // 6
78  {"Astro B4 Sorol Atoll", 14, 114, -116, -333}, // 7
79  {"Astro Beacon E ", 14, 145, 75, -272}, // 8
80  {"Astro DOS 71/4", 14, -320, 550, -494}, // 9
81  {"Astronomic Stn 52", 14, 124, -234, -25}, // 10
82  {"Australian Geod 66", 2, -133, -48, 148}, // 11
83  {"Australian Geod 84", 2, -134, -48, 149}, // 12
84  {"Bellevue (IGN)", 14, -127, -769, 472}, // 13
85  {"Bermuda 1957", 4, -73, 213, 296}, // 14
86  {"Bogota Observatory", 14, 307, 304, -318}, // 15
87  {"Campo Inchauspe", 14, -148, 136, 90}, // 16
88  {"Canton Astro 1966", 14, 298, -304, -375}, // 17
89  {"Cape", 5, -136, -108, -292}, // 18
90  {"Cape Canaveral", 4, -2, 150, 181}, // 19
91  {"Carthage", 5, -263, 6, 431}, // 20
92  {"CH-1903", 3, 674, 15, 405}, // 21
93  {"Chatham 1971", 14, 175, -38, 113}, // 22
94  {"Chua Astro", 14, -134, 229, -29}, // 23
95  {"Corrego Alegre", 14, -206, 172, -6}, // 24
96  {"Djakarta (Batavia)", 3, -377, 681, -50}, // 25
97  {"DOS 1968", 14, 230, -199, -752}, // 26
98  {"Easter Island 1967", 14, 211, 147, 111}, // 27
99  {"European 1950", 14, -87, -98, -121}, // 28
100  {"European 1979", 14, -86, -98, -119}, // 29
101  {"Finland Hayford", 14, -78, -231, -97}, // 30
102  {"Gandajika Base", 14, -133, -321, 50}, // 31
103  {"Geodetic Datum 49", 14, 84, -22, 209}, // 32
104  {"Guam 1963", 4, -100, -248, 259}, // 33
105  {"GUX 1 Astro", 14, 252, -209, -751}, // 34
106  {"Hermannskogel Datum", 3, 682, -203, 480}, // 35
107  {"Hjorsey 1955", 14, -73, 46, -86}, // 36
108  {"Hong Kong 1963", 14, -156, -271, -189}, // 37
109  {"Indian Bangladesh", 6, 289, 734, 257}, // 38
110  {"Indian Thailand", 6, 214, 836, 303}, // 39
111  {"Ireland 1965", 1, 506, -122, 611}, // 40
112  {"ISTS 073 Astro 69", 14, 208, -435, -229}, // 41
113  {"Johnston Island", 14, 191, -77, -204}, // 42
114  {"Kandawala", 6, -97, 787, 86}, // 43
115  {"Kerguelen Island", 14, 145, -187, 103}, // 44
116  {"Kertau 1948", 7, -11, 851, 5}, // 45
117  {"L.C. 5 Astro", 4, 42, 124, 147}, // 46
118  {"Liberia 1964", 5, -90, 40, 88}, // 47
119  {"Luzon Mindanao", 4, -133, -79, -72}, // 48
120  {"Luzon Philippines", 4, -133, -77, -51}, // 49
121  {"Mahe 1971", 5, 41, -220, -134}, // 50
122  {"Marco Astro", 14, -289, -124, 60}, // 51
123  {"Massawa", 3, 639, 405, 60}, // 52
124  {"Merchich", 5, 31, 146, 47}, // 53
125  {"Midway Astro 1961", 14, 912, -58, 1227}, // 54
126  {"Minna", 5, -92, -93, 122}, // 55
127  {"NAD27 Alaska", 4, -5, 135, 172}, // 56
128  {"NAD27 Bahamas", 4, -4, 154, 178}, // 57
129  {"NAD27 Canada", 4, -10, 158, 187}, // 58
130  {"NAD27 Canal Zone", 4, 0, 125, 201}, // 59
131  {"NAD27 Caribbean", 4, -7, 152, 178}, // 60
132  {"NAD27 Central", 4, 0, 125, 194}, // 61
133  {"NAD27 CONUS", 4, -8, 160, 176}, // 62
134  {"NAD27 Cuba", 4, -9, 152, 178}, // 63
135  {"NAD27 Greenland", 4, 11, 114, 195}, // 64
136  {"NAD27 Mexico", 4, -12, 130, 190}, // 65
137  {"NAD27 San Salvador", 4, 1, 140, 165}, // 66
138  {"NAD83", 11, 0, 0, 0}, // 67
139  {"Nahrwn Masirah Ilnd", 5, -247, -148, 369}, // 68
140  {"Nahrwn Saudi Arbia", 5, -231, -196, 482}, // 69
141  {"Nahrwn United Arab", 5, -249, -156, 381}, // 70
142  {"Naparima BWI", 14, -2, 374, 172}, // 71
143  {"Observatorio 1966", 14, -425, -169, 81}, // 72
144  {"Old Egyptian", 12, -130, 110, -13}, // 73
145  {"Old Hawaiian", 4, 61, -285, -181}, // 74
146  {"Oman", 5, -346, -1, 224}, // 75
147  {"Ord Srvy Grt Britn", 0, 375, -111, 431}, // 76
148  {"Pico De Las Nieves", 14, -307, -92, 127}, // 77
149  {"Pitcairn Astro 1967", 14, 185, 165, 42}, // 78
150  {"Prov So Amrican 56", 14, -288, 175, -376}, // 79
151  {"Prov So Chilean 63", 14, 16, 196, 93}, // 80
152  {"Puerto Rico", 4, 11, 72, -101}, // 81
153  {"Qatar National", 14, -128, -283, 22}, // 82
154  {"Qornoq", 14, 164, 138, -189}, // 83
155  {"Reunion", 14, 94, -948, -1262}, // 84
156  {"Rome 1940", 14, -225, -65, 9}, // 85
157  {"RT 90", 3, 498, -36, 568}, // 86
158  {"Santo (DOS)", 14, 170, 42, 84}, // 87
159  {"Sao Braz", 14, -203, 141, 53}, // 88
160  {"Sapper Hill 1943", 14, -355, 16, 74}, // 89
161  {"Schwarzeck", 21, 616, 97, -251}, // 90
162  {"South American 69", 16, -57, 1, -41}, // 91
163  {"South Asia", 8, 7, -10, -26}, // 92
164  {"Southeast Base", 14, -499, -249, 314}, // 93
165  {"Southwest Base", 14, -104, 167, -38}, // 94
166  {"Timbalai 1948", 6, -689, 691, -46}, // 95
167  {"Tokyo", 3, -128, 481, 664}, // 96
168  {"Tristan Astro 1968", 14, -632, 438, -609}, // 97
169  {"Viti Levu 1916", 5, 51, 391, -36}, // 98
170  {"Wake-Eniwetok 60", 13, 101, 52, -39}, // 99
171  {"WGS 72", 19, 0, 0, 5}, // 100
172  {"WGS 84", 20, 0, 0, 0}, // 101
173  {"Zanderij", 14, -265, 120, -358}, // 102
174  {"WGS_84", 20, 0, 0, 0}, // 103
175  {"WGS-84", 20, 0, 0, 0}, // 104
176  {"EUROPEAN DATUM 1950", 14, -87, -98, -121},
177  {"European 1950 (Norway Finland)", 14, -87, -98, -121},
178  {"ED50", 14, -87, -98, -121},
179  {"RT90 (Sweden)", 3, 498, -36, 568},
180  {"Monte Mario 1940", 14, -104, -49, 10},
181  {"Ord Surv of Gr Britain 1936", 0, 375, -111, 431},
182  {"South American 1969", 16, -57, 1, -41},
183  {"PULKOVO 1942 (2)", 15, 25, -141, -79},
184  {"EUROPEAN DATUM", 14, -87, -98, -121},
185  {"BERMUDA DATUM 1957", 4, -73, 213, 296},
186  {"COA", 14, -206, 172, -6},
187  {"COABR", 14, -206, 172, -6},
188  {"Roma 1940", 14, -225, -65, 9},
189  {"ITALIENISCHES LANDESNETZ", 14, -87, -98, -121},
190  {"HERMANSKOGEL DATUM", 3, 682, -203, 480},
191  {"AGD66", 2, -128, -52, 153},
192  {"ED", 14, -87, -98, -121},
193  {"EUROPEAN 1950 (SPAIN AND PORTUGAL)", 14, -87, -98, -121},
194  {"ED-50", 14, -87, -98, -121},
195  {"EUROPEAN", 14, -87, -98, -121},
196  {"POTSDAM", 14, -87, -98, -121},
197  {"GRACIOSA SW BASE DATUM", 14, -104, 167, -38},
198  {"WGS 1984", 20, 0, 0, 0},
199  {"WGS 1972", 19, 0, 0, 5},
200  {"WGS", 19, 0, 0, 5}
201 
202 };
203 struct ELLIPSOID const gEllipsoid[] = {
204  // name a 1/f
205  {"Airy 1830", 6377563.396, 299.3249646}, // 0
206  {"Modified Airy", 6377340.189, 299.3249646}, // 1
207  {"Australian National", 6378160.0, 298.25}, // 2
208  {"Bessel 1841", 6377397.155, 299.1528128}, // 3
209  {"Clarke 1866", 6378206.4, 294.9786982}, // 4
210  {"Clarke 1880", 6378249.145, 293.465}, // 5
211  {"Everest (India 1830)", 6377276.345, 300.8017}, // 6
212  {"Everest (1948)", 6377304.063, 300.8017}, // 7
213  {"Modified Fischer 1960", 6378155.0, 298.3}, // 8
214  {"Everest (Pakistan)", 6377309.613, 300.8017}, // 9
215  {"Indonesian 1974", 6378160.0, 298.247}, // 10
216  {"GRS 80", 6378137.0, 298.257222101}, // 11
217  {"Helmert 1906", 6378200.0, 298.3}, // 12
218  {"Hough 1960", 6378270.0, 297.0}, // 13
219  {"International 1924", 6378388.0, 297.0}, // 14
220  {"Krassovsky 1940", 6378245.0, 298.3}, // 15
221  {"South American 1969", 6378160.0, 298.25}, // 16
222  {"Everest (Malaysia 1969)", 6377295.664, 300.8017}, // 17
223  {"Everest (Sabah Sarawak)", 6377298.556, 300.8017}, // 18
224  {"WGS 72", 6378135.0, 298.26}, // 19
225  {"WGS 84", 6378137.0, 298.257223563}, // 20
226  {"Bessel 1841 (Namibia)", 6377483.865, 299.1528128}, // 21
227  {"Everest (India 1956)", 6377301.243, 300.8017}, // 22
228  {"Struve 1860", 6378298.3, 294.73} // 23
229 
230 };
231 
232 short nDatums = sizeof(gDatum) / sizeof(struct DATUM);
233 
234 /* define constants */
235 
236 void datumParams(short datum, double *a, double *es) {
237  extern struct DATUM const gDatum[];
238  extern struct ELLIPSOID const gEllipsoid[];
239 
240  if (datum < nDatums) {
241  double f = 1.0 / gEllipsoid[gDatum[datum].ellipsoid].invf; // flattening
242  if (es) *es = 2 * f - f * f; // eccentricity^2
243  if (a) *a = gEllipsoid[gDatum[datum].ellipsoid].a; // semimajor axis
244  } else {
245  double f = 1.0 / 298.257223563; // WGS84
246  if (es) *es = 2 * f - f * f;
247  if (a) *a = 6378137.0;
248  }
249 }
250 
251 static int datumNameCmp(const char *n1, const char *n2) {
252  while (*n1 || *n2) {
253  if (*n1 == ' ')
254  n1++;
255  else if (*n2 == ' ')
256  n2++;
257  else if (toupper(*n1) == toupper(*n2))
258  n1++, n2++;
259  else
260  return 1; // No string match
261  }
262  return 0; // String match
263 }
264 static int isWGS84(int i) {
265  // DATUM_INDEX_WGS84 is an optimization
266  // but there's more than on in gDatum table
267  if (i == DATUM_INDEX_WGS84) return i;
268 
269  if (gDatum[i].ellipsoid != gDatum[DATUM_INDEX_WGS84].ellipsoid) return i;
270 
271  if (gDatum[i].dx != gDatum[DATUM_INDEX_WGS84].dx) return i;
272 
273  if (gDatum[i].dy != gDatum[DATUM_INDEX_WGS84].dy) return i;
274 
275  if (gDatum[i].dz != gDatum[DATUM_INDEX_WGS84].dz) return i;
276 
277  return DATUM_INDEX_WGS84;
278 
279 }
280 
281 int GetDatumIndex(const char *str) {
282  int i = 0;
283  while (i < (int)nDatums) {
284  if (!datumNameCmp(str, gDatum[i].name)) {
285  return isWGS84(i);
286  }
287  i++;
288  }
289 
290  return -1;
291 }
292 /****************************************************************************/
293 /* Convert degrees to dd mm'ss.s" (DMS-Format) */
294 /****************************************************************************/
295 void toDMS(double a, char *bufp, int bufplen) {
296  bool neg = a < 0.0;
297  a = fabs(a);
298  int n = (int)((a - (int)a) * 36000.0);
299  int m = n / 600;
300  int s = n % 600;
301  sprintf(bufp, "%d%02d'%02d.%01d\"", (int)(neg ? -a : a), m, s / 10, s % 10);
302 }
303 
304 /****************************************************************************/
305 /* Convert dd mm'ss.s" (DMS-Format) to degrees. */
306 /****************************************************************************/
307 
308 double fromDMS(char *dms) {
309  int d = 0, m = 0;
310  double s = 0.0;
311  char buf[20] = {'\0'};
312 
313  sscanf(dms, "%d%[ ]%d%[ ']%lf%[ \"NSWEnswe]", &d, buf, &m, buf, &s, buf);
314 
315  s = (double)(abs(d)) + ((double)m + s / 60.0) / 60.0;
316 
317  if (d >= 0 && strpbrk(buf, "SWsw") == NULL) return s;
318 
319  return -s;
320 }
321 
322 /****************************************************************************/
323 /* Convert degrees to dd mm.mmm' (DMM-Format) */
324 /****************************************************************************/
325 
326 void todmm(int flag, double a, char *bufp, int bufplen) {
327  bool bNeg = a < 0.0;
328  a = fabs(a);
329 
330  int m = (int)((a - (int)a) * 60000.0);
331 
332  if (!flag)
333  snprintf(bufp, bufplen, "%d %02d.%03d'", (int)a, m / 1000, m % 1000);
334  else {
335  if (flag == 1) {
336  snprintf(bufp, bufplen, "%02d %02d.%03d %c", (int)a, m / 1000, (m % 1000),
337  bNeg ? 'S' : 'N');
338  } else if (flag == 2) {
339  snprintf(bufp, bufplen, "%03d %02d.%03d %c", (int)a, m / 1000, (m % 1000),
340  bNeg ? 'W' : 'E');
341  }
342  }
343 }
344 
345 void toDMM(double a, char *bufp, int bufplen) {
346  todmm(0, a, bufp, bufplen);
347  return;
348 }
349 
350 /* ---------------------------------------------------------------------------------
351  */
352 /****************************************************************************/
353 /* Convert Lat/Lon <-> Simple Mercator */
354 /****************************************************************************/
355 void toSM(double lat, double lon, double lat0, double lon0, double *x,
356  double *y) {
357  double xlon = lon;
358 
359  /* Make sure lon and lon0 are same phase */
360 
361  if ((lon * lon0 < 0.) && (fabs(lon - lon0) > 180.)) {
362  lon < 0.0 ? xlon += 360.0 : xlon -= 360.0;
363  }
364 
365  const double z = WGS84_semimajor_axis_meters * mercator_k0;
366 
367  *x = (xlon - lon0) * DEGREE * z;
368 
369  // y =.5 ln( (1 + sin t) / (1 - sin t) )
370  const double s = sin(lat * DEGREE);
371  const double y3 = (.5 * log((1 + s) / (1 - s))) * z;
372 
373  const double s0 = sin(lat0 * DEGREE);
374  const double y30 = (.5 * log((1 + s0) / (1 - s0))) * z;
375  *y = y3 - y30;
376 }
377 
378 double toSMcache_y30(double lat0) {
379  const double z = WGS84_semimajor_axis_meters * mercator_k0;
380  const double s0 = sin(lat0 * DEGREE);
381  const double y30 = (.5 * log((1 + s0) / (1 - s0))) * z;
382  return y30;
383 }
384 
385 void toSMcache(double lat, double lon, double y30, double lon0, double *x,
386  double *y) {
387  double xlon = lon;
388 
389  /* Make sure lon and lon0 are same phase */
390 
391  if ((lon * lon0 < 0.) && (fabs(lon - lon0) > 180.)) {
392  lon < 0.0 ? xlon += 360.0 : xlon -= 360.0;
393  }
394 
395  const double z = WGS84_semimajor_axis_meters * mercator_k0;
396 
397  *x = (xlon - lon0) * DEGREE * z;
398 
399  // y =.5 ln( (1 + sin t) / (1 - sin t) )
400  const double s = sin(lat * DEGREE);
401  const double y3 = (.5 * log((1 + s) / (1 - s))) * z;
402 
403  *y = y3 - y30;
404 }
405 
406 void fromSM(double x, double y, double lat0, double lon0, double *lat,
407  double *lon) {
408  const double z = WGS84_semimajor_axis_meters * mercator_k0;
409 
410  // lat = arcsin((e^2(y+y0) - 1)/(e^2(y+y0) + 1))
411  /*
412  double s0 = sin(lat0 * DEGREE);
413  double y0 = (.5 * log((1 + s0) / (1 - s0))) * z;
414 
415  double e = exp(2 * (y0 + y) / z);
416  double e11 = (e - 1)/(e + 1);
417  double lat2 =(atan2(e11, sqrt(1 - e11 * e11))) / DEGREE;
418  */
419  // which is the same as....
420 
421  const double s0 = sin(lat0 * DEGREE);
422  const double y0 = (.5 * log((1 + s0) / (1 - s0))) * z;
423 
424  *lat = (2.0 * atan(exp((y0 + y) / z)) - PI / 2.) / DEGREE;
425 
426  // lon = x + lon0
427  *lon = lon0 + (x / (DEGREE * z));
428 }
429 
430 void fromSMR(double x, double y, double lat0, double lon0, double axis_meters,
431  double *lat, double *lon) {
432  const double s0 = sin(lat0 * DEGREE);
433  const double y0 = (.5 * log((1 + s0) / (1 - s0))) * axis_meters;
434 
435  *lat = (2.0 * atan(exp((y0 + y) / axis_meters)) - PI / 2.) / DEGREE;
436 
437  // lon = x + lon0
438  *lon = lon0 + (x / (DEGREE * axis_meters));
439 }
440 
441 void toSM_ECC(double lat, double lon, double lat0, double lon0, double *x,
442  double *y) {
443  const double f = 1.0 / WGSinvf; // WGS84 ellipsoid flattening parameter
444  const double e2 = 2 * f - f * f; // eccentricity^2 .006700
445  const double e = sqrt(e2);
446 
447  const double z = WGS84_semimajor_axis_meters * mercator_k0;
448 
449  *x = (lon - lon0) * DEGREE * z;
450 
451  // y =.5 ln( (1 + sin t) / (1 - sin t) )
452  const double s = sin(lat * DEGREE);
453  // const double y3 = (.5 * log((1 + s) / (1 - s))) * z;
454 
455  const double s0 = sin(lat0 * DEGREE);
456  // const double y30 = (.5 * log((1 + s0) / (1 - s0))) * z;
457 
458  // Add eccentricity terms
459 
460  const double falsen = z * log(tan(PI / 4 + lat0 * DEGREE / 2) *
461  pow((1. - e * s0) / (1. + e * s0), e / 2.));
462  const double test = z * log(tan(PI / 4 + lat * DEGREE / 2) *
463  pow((1. - e * s) / (1. + e * s), e / 2.));
464  *y = test - falsen;
465 }
466 
467 void fromSM_ECC(double x, double y, double lat0, double lon0, double *lat,
468  double *lon) {
469  const double f = 1.0 / WGSinvf; // WGS84 ellipsoid flattening parameter
470  const double es = 2 * f - f * f; // eccentricity^2 .006700
471  const double e = sqrt(es);
472 
473  const double z = WGS84_semimajor_axis_meters * mercator_k0;
474 
475  *lon = lon0 + (x / (DEGREE * z));
476 
477  const double s0 = sin(lat0 * DEGREE);
478 
479  const double falsen = z * log(tan(PI / 4 + lat0 * DEGREE / 2) *
480  pow((1. - e * s0) / (1. + e * s0), e / 2.));
481  const double t = exp((y + falsen) / (z));
482  const double xi = (PI / 2.) - 2.0 * atan(t);
483 
484  // Add eccentricity terms
485 
486  double esf = (es / 2. + (5 * es * es / 24.) + (es * es * es / 12.) +
487  (13.0 * es * es * es * es / 360.)) *
488  sin(2 * xi);
489  esf += ((7. * es * es / 48.) + (29. * es * es * es / 240.) +
490  (811. * es * es * es * es / 11520.)) *
491  sin(4. * xi);
492  esf += ((7. * es * es * es / 120.) + (81 * es * es * es * es / 1120.) +
493  (4279. * es * es * es * es / 161280.)) *
494  sin(8. * xi);
495 
496  *lat = -(xi + esf) / DEGREE;
497 }
498 
499 #define TOL 1e-10
500 #define CONV 1e-10
501 #define N_ITER 10
502 #define I_ITER 20
503 #define ITOL 1.e-12
504 
505 void toPOLY(double lat, double lon, double lat0, double lon0, double *x,
506  double *y) {
507  const double z = WGS84_semimajor_axis_meters * mercator_k0;
508 
509  if (fabs((lat - lat0) * DEGREE) <= TOL) {
510  *x = (lon - lon0) * DEGREE * z;
511  *y = 0.;
512 
513  } else {
514  const double E = (lon - lon0) * DEGREE * sin(lat * DEGREE);
515  const double cot = 1. / tan(lat * DEGREE);
516  *x = sin(E) * cot;
517  *y = (lat * DEGREE) - (lat0 * DEGREE) + cot * (1. - cos(E));
518 
519  *x *= z;
520  *y *= z;
521  }
522 
523  /*
524  if (fabs(lp.phi) <= TOL) { xy.x = lp.lam; xy.y = P->ml0; }
525  else {
526  cot = 1. / tan(lp.phi);
527  xy.x = sin(E = lp.lam * sin(lp.phi)) * cot;
528  xy.y = lp.phi - P->phi0 + cot * (1. - cos(E));
529  }
530  */
531 }
532 
533 void fromPOLY(double x, double y, double lat0, double lon0, double *lat,
534  double *lon) {
535  const double z = WGS84_semimajor_axis_meters * mercator_k0;
536 
537  double yp = y - (lat0 * DEGREE * z);
538  if (fabs(yp) <= TOL) {
539  *lon = lon0 + (x / (DEGREE * z));
540  *lat = lat0;
541  } else {
542  yp = y / z;
543  const double xp = x / z;
544 
545  double lat3 = yp;
546  const double B = (xp * xp) + (yp * yp);
547  int i = N_ITER;
548  double dphi;
549  do {
550  double tp = tan(lat3);
551  dphi = (yp * (lat3 * tp + 1.) - lat3 - .5 * (lat3 * lat3 + B) * tp) /
552  ((lat3 - yp) / tp - 1.);
553  lat3 -= dphi;
554  } while (fabs(dphi) > CONV && --i);
555  if (!i) {
556  *lon = 0.;
557  *lat = 0.;
558  } else {
559  *lon = asin(xp * tan(lat3)) / sin(lat3);
560  *lon /= DEGREE;
561  *lon += lon0;
562 
563  *lat = lat3 / DEGREE;
564  }
565  }
566 }
567 
568 /****************************************************************************/
569 /* Convert Lat/Lon <-> Transverse Mercator */
570 /****************************************************************************/
571 
572 // converts lat/long to TM coords. Equations from USGS Bulletin 1532
573 // East Longitudes are positive, West longitudes are negative.
574 // North latitudes are positive, South latitudes are negative
575 // Lat and Long are in decimal degrees.
576 // Written by Chuck Gantz- chuck.gantz@globalstar.com
577 // Adapted for opencpn by David S. Register
578 
579 void toTM(float lat, float lon, float lat0, float lon0, double *x, double *y) {
580  // constants for WGS-84
581  const double f = 1.0 / WGSinvf; /* WGS84 ellipsoid flattening parameter */
582  const double a = WGS84_semimajor_axis_meters;
583  const double k0 = 1.; /* Scaling factor */
584 
585  const double eccSquared = 2 * f - f * f;
586  const double eccPrimeSquared = (eccSquared) / (1 - eccSquared);
587  const double LatRad = lat * DEGREE;
588  const double LongOriginRad = lon0 * DEGREE;
589  const double LongRad = lon * DEGREE;
590 
591  const double N = a / sqrt(1 - eccSquared * sin(LatRad) * sin(LatRad));
592  const double T = tan(LatRad) * tan(LatRad);
593  const double C = eccPrimeSquared * cos(LatRad) * cos(LatRad);
594  const double A = cos(LatRad) * (LongRad - LongOriginRad);
595 
596  const double MM =
597  a *
598  ((1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 -
599  5 * eccSquared * eccSquared * eccSquared / 256) *
600  LatRad -
601  (3 * eccSquared / 8 + 3 * eccSquared * eccSquared / 32 +
602  45 * eccSquared * eccSquared * eccSquared / 1024) *
603  sin(2 * LatRad) +
604  (15 * eccSquared * eccSquared / 256 +
605  45 * eccSquared * eccSquared * eccSquared / 1024) *
606  sin(4 * LatRad) -
607  (35 * eccSquared * eccSquared * eccSquared / 3072) * sin(6 * LatRad));
608 
609  *x = (k0 * N *
610  (A + (1 - T + C) * A * A * A / 6 +
611  (5 - 18 * T + T * T + 72 * C - 58 * eccPrimeSquared) * A * A * A * A *
612  A / 120));
613 
614  *y =
615  (k0 *
616  (MM + N * tan(LatRad) *
617  (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24 +
618  (61 - 58 * T + T * T + 600 * C - 330 * eccPrimeSquared) * A *
619  A * A * A * A * A / 720)));
620 }
621 
622 /* ---------------------------------------------------------------------------------
623  */
624 
625 // converts TM coords to lat/long. Equations from USGS Bulletin 1532
626 // East Longitudes are positive, West longitudes are negative.
627 // North latitudes are positive, South latitudes are negative
628 // Lat and Long are in decimal degrees
629 // Written by Chuck Gantz- chuck.gantz@globalstar.com
630 // Adapted for opencpn by David S. Register
631 
632 void fromTM(double x, double y, double lat0, double lon0, double *lat,
633  double *lon) {
634  const double rad2deg = 1. / DEGREE;
635  // constants for WGS-84
636 
637  const double f = 1.0 / WGSinvf; /* WGS84 ellipsoid flattening parameter */
638  const double a = WGS84_semimajor_axis_meters;
639  const double k0 = 1.; /* Scaling factor */
640 
641  const double eccSquared = 2 * f - f * f;
642 
643  const double eccPrimeSquared = (eccSquared) / (1 - eccSquared);
644  const double e1 =
645  (1.0 - sqrt(1.0 - eccSquared)) / (1.0 + sqrt(1.0 - eccSquared));
646 
647  const double MM = y / k0;
648  const double mu =
649  MM / (a * (1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 -
650  5 * eccSquared * eccSquared * eccSquared / 256));
651 
652  const double phi1Rad =
653  mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * sin(2 * mu) +
654  (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * sin(4 * mu) +
655  (151 * e1 * e1 * e1 / 96) * sin(6 * mu);
656 
657  const double N1 = a / sqrt(1 - eccSquared * sin(phi1Rad) * sin(phi1Rad));
658  const double T1 = tan(phi1Rad) * tan(phi1Rad);
659  const double C1 = eccPrimeSquared * cos(phi1Rad) * cos(phi1Rad);
660  const double R1 = a * (1 - eccSquared) /
661  pow(1 - eccSquared * sin(phi1Rad) * sin(phi1Rad), 1.5);
662  const double D = x / (N1 * k0);
663 
664  *lat = phi1Rad -
665  (N1 * tan(phi1Rad) / R1) *
666  (D * D / 2 -
667  (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * eccPrimeSquared) * D *
668  D * D * D / 24 +
669  (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * eccPrimeSquared -
670  3 * C1 * C1) *
671  D * D * D * D * D * D / 720);
672  *lat = lat0 + (*lat * rad2deg);
673 
674  *lon = (D - (1 + 2 * T1 + C1) * D * D * D / 6 +
675  (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * eccPrimeSquared +
676  24 * T1 * T1) *
677  D * D * D * D * D / 120) /
678  cos(phi1Rad);
679  *lon = lon0 + *lon * rad2deg;
680 }
681 
682 /* orthographic, polar, stereographic, gnomonic and equirectangular projection
683  * routines, contributed by Sean D'Epagnier */
684 /****************************************************************************/
685 /* Convert Lat/Lon <-> Simple Polar */
686 /****************************************************************************/
687 void cache_phi0(double lat0, double *sin_phi0, double *cos_phi0) {
688  double phi0 = lat0 * DEGREE;
689  *sin_phi0 = sin(phi0);
690  *cos_phi0 = cos(phi0);
691 }
692 
693 void toORTHO(double lat, double lon, double sin_phi0, double cos_phi0,
694  double lon0, double *x, double *y) {
695  const double z = WGS84_semimajor_axis_meters * mercator_k0;
696 
697  double xlon = lon;
698  /* Make sure lon and lon0 are same phase */
699  if ((lon * lon0 < 0.) && (fabs(lon - lon0) > 180.))
700  lon < 0.0 ? xlon += 360.0 : xlon -= 360.0;
701 
702  double theta = (xlon - lon0) * DEGREE;
703  double phi = lat * DEGREE;
704  double cos_phi = cos(phi);
705 
706  double vy = sin(phi), vz = cos(theta) * cos_phi;
707 
708  if (vy * sin_phi0 + vz * cos_phi0 < 0) { // on the far side of the earth
709  *x = *y = NAN;
710  return;
711  }
712 
713  double vx = sin(theta) * cos_phi;
714  double vw = vy * cos_phi0 - vz * sin_phi0;
715 
716  *x = vx * z;
717  *y = vw * z;
718 }
719 
720 void fromORTHO(double x, double y, double lat0, double lon0, double *lat,
721  double *lon) {
722  const double z = WGS84_semimajor_axis_meters * mercator_k0;
723 
724  double vx = x / z;
725  double vw = y / z;
726 
727  double phi0 = lat0 * DEGREE;
728  double d = 1 - vx * vx - vw * vw;
729 
730  if (d < 0) { // position is outside of the earth
731  *lat = *lon = NAN;
732  return;
733  }
734 
735  double sin_phi0 = sin(phi0), cos_phi0 = cos(phi0);
736  double vy = vw * cos_phi0 + sqrt(d) * sin_phi0;
737  double phi = asin(vy);
738 
739  double vz = (vy * cos_phi0 - vw) / sin_phi0;
740  double theta = atan2(vx, vz);
741 
742  *lat = phi / DEGREE;
743  *lon = theta / DEGREE + lon0;
744 }
745 
746 double toPOLARcache_e(double lat0) {
747  double pole = lat0 > 0 ? 90 : -90;
748  return tan((pole - lat0) * DEGREE / 2);
749 }
750 
751 void toPOLAR(double lat, double lon, double e, double lat0, double lon0,
752  double *x, double *y) {
753  const double z = WGS84_semimajor_axis_meters * mercator_k0;
754 
755  double xlon = lon;
756  /* Make sure lon and lon0 are same phase */
757  if ((lon * lon0 < 0.) && (fabs(lon - lon0) > 180.))
758  lon < 0.0 ? xlon += 360.0 : xlon -= 360.0;
759 
760  double theta = (xlon - lon0) * DEGREE;
761  double pole = lat0 > 0 ? 90 : -90;
762 
763  double d = tan((pole - lat) * DEGREE / 2);
764 
765  *x = fabs(d) * sin(theta) * z;
766  *y = (e - d * cos(theta)) * z;
767 }
768 
769 void fromPOLAR(double x, double y, double lat0, double lon0, double *lat,
770  double *lon) {
771  const double z = WGS84_semimajor_axis_meters * mercator_k0;
772  double pole = lat0 > 0 ? 90 : -90;
773 
774  double e = tan((pole - lat0) * DEGREE / 2);
775 
776  double xn = x / z;
777  double yn = e - y / z;
778  double d = sqrt(xn * xn + yn * yn);
779  if (pole < 0) // south polar (negative root and correct branch from cosine)
780  d = -d, yn = -yn;
781 
782  *lat = pole - atan(d) * 2 / DEGREE;
783 
784  double theta = atan2(xn, yn);
785  *lon = theta / DEGREE + lon0;
786 }
787 
788 static inline void toSTEREO1(double &u, double &v, double &w, double lat,
789  double lon, double sin_phi0, double cos_phi0,
790  double lon0) {
791  double xlon = lon;
792  /* Make sure lon and lon0 are same phase */
793  if ((lon * lon0 < 0.) && (fabs(lon - lon0) > 180.))
794  lon < 0.0 ? xlon += 360.0 : xlon -= 360.0;
795 
796  double theta = (xlon - lon0) * DEGREE, phi = lat * DEGREE;
797  double cos_phi = cos(phi), v0 = sin(phi), w0 = cos(theta) * cos_phi;
798 
799  u = sin(theta) * cos_phi;
800  v = cos_phi0 * v0 - sin_phi0 * w0;
801  w = sin_phi0 * v0 + cos_phi0 * w0;
802 }
803 
804 static inline void fromSTEREO1(double *lat, double *lon, double lat0,
805  double lon0, double u, double v, double w) {
806  double phi0 = lat0 * DEGREE;
807  double v0 = sin(phi0) * w + cos(phi0) * v;
808  double w0 = cos(phi0) * w - sin(phi0) * v;
809  double phi = asin(v0);
810  double theta = atan2(u, w0);
811 
812  *lat = phi / DEGREE;
813  *lon = theta / DEGREE + lon0;
814 }
815 
816 void toSTEREO(double lat, double lon, double sin_phi0, double cos_phi0,
817  double lon0, double *x, double *y) {
818  const double z = WGS84_semimajor_axis_meters * mercator_k0;
819 
820  double u, v, w;
821  toSTEREO1(u, v, w, lat, lon, sin_phi0, cos_phi0, lon0);
822 
823  double t = 2 / (w + 1);
824  *x = u * t * z;
825  *y = v * t * z;
826 }
827 
828 void fromSTEREO(double x, double y, double lat0, double lon0, double *lat,
829  double *lon) {
830  const double z = WGS84_semimajor_axis_meters * mercator_k0;
831 
832  x /= z, y /= z;
833 
834  double t = (x * x + y * y) / 4 + 1;
835 
836  double u = x / t;
837  double v = y / t;
838  double w = 2 / t - 1;
839 
840  fromSTEREO1(lat, lon, lat0, lon0, u, v, w);
841 }
842 
843 void toGNO(double lat, double lon, double sin_phi0, double cos_phi0,
844  double lon0, double *x, double *y) {
845  const double z = WGS84_semimajor_axis_meters * mercator_k0;
846 
847  double u, v, w;
848  toSTEREO1(u, v, w, lat, lon, sin_phi0, cos_phi0, lon0);
849 
850  if (w <= 0) {
851  *x = *y = NAN; // far side of world
852  return;
853  }
854 
855  *x = u / w * z;
856  *y = v / w * z;
857 }
858 
859 void fromGNO(double x, double y, double lat0, double lon0, double *lat,
860  double *lon) {
861  const double z = WGS84_semimajor_axis_meters * mercator_k0;
862 
863  x /= z, y /= z;
864 
865  double w = 1 / sqrt(x * x + y * y + 1);
866  double u = x * w;
867  double v = y * w;
868 
869  fromSTEREO1(lat, lon, lat0, lon0, u, v, w);
870 }
871 
872 void toEQUIRECT(double lat, double lon, double lat0, double lon0, double *x,
873  double *y) {
874  const double z = WGS84_semimajor_axis_meters * mercator_k0;
875  double xlon = lon;
876  /* Make sure lon and lon0 are same phase */
877  if ((lon * lon0 < 0.) && (fabs(lon - lon0) > 180.))
878  lon < 0.0 ? xlon += 360.0 : xlon -= 360.0;
879 
880  *x = (xlon - lon0) * DEGREE * z;
881  *y = (lat - lat0) * DEGREE * z;
882 }
883 
884 void fromEQUIRECT(double x, double y, double lat0, double lon0, double *lat,
885  double *lon) {
886  const double z = WGS84_semimajor_axis_meters * mercator_k0;
887 
888  *lat = lat0 + (y / (DEGREE * z));
889  // if(fabs(*lat) > 90) *lat = NAN;
890  *lon = lon0 + (x / (DEGREE * z));
891 }
892 
893 /* ---------------------------------------------------------------------------------
894  *
895 
896  *Molodensky
897  *In the listing below, the class GeodeticPosition has three members, lon, lat,
898  and h. *They are double-precision values indicating the longitude and latitude
899  in radians,
900  * and height in meters above the ellipsoid.
901 
902  * The source code in the listing below may be copied and reused without
903  restriction,
904  * but it is offered AS-IS with NO WARRANTY.
905 
906  * Adapted for opencpn by David S. Register
907 
908  * --------------------------------------------------------------------------------- */
909 
910 void MolodenskyTransform(double lat, double lon, double *to_lat, double *to_lon,
911  int from_datum_index, int to_datum_index) {
912  double dlat = 0;
913  double dlon = 0;
914 
915  if (from_datum_index < nDatums) {
916  const double from_lat = lat * DEGREE;
917  const double from_lon = lon * DEGREE;
918  const double from_f =
919  1.0 /
920  gEllipsoid[gDatum[from_datum_index].ellipsoid].invf; // flattening
921  const double from_esq = 2 * from_f - from_f * from_f; // eccentricity^2
922  const double from_a =
923  gEllipsoid[gDatum[from_datum_index].ellipsoid].a; // semimajor axis
924  const double dx = gDatum[from_datum_index].dx;
925  const double dy = gDatum[from_datum_index].dy;
926  const double dz = gDatum[from_datum_index].dz;
927  const double to_f =
928  1.0 / gEllipsoid[gDatum[to_datum_index].ellipsoid].invf; // flattening
929  const double to_a =
930  gEllipsoid[gDatum[to_datum_index].ellipsoid].a; // semimajor axis
931  const double da = to_a - from_a;
932  const double df = to_f - from_f;
933  const double from_h = 0;
934 
935  const double slat = sin(from_lat);
936  const double clat = cos(from_lat);
937  const double slon = sin(from_lon);
938  const double clon = cos(from_lon);
939  const double ssqlat = slat * slat;
940  const double adb = 1.0 / (1.0 - from_f); // "a divided by b"
941 
942  const double rn = from_a / sqrt(1.0 - from_esq * ssqlat);
943  const double rm =
944  from_a * (1. - from_esq) / pow((1.0 - from_esq * ssqlat), 1.5);
945 
946  dlat = (((((-dx * slat * clon - dy * slat * slon) + dz * clat) +
947  (da * ((rn * from_esq * slat * clat) / from_a))) +
948  (df * (rm * adb + rn / adb) * slat * clat))) /
949  (rm + from_h);
950 
951  dlon = (-dx * slon + dy * clon) / ((rn + from_h) * clat);
952  }
953 
954  *to_lon = lon + dlon / DEGREE;
955  *to_lat = lat + dlat / DEGREE;
956  //
957  return;
958 }
959 
960 /* ---------------------------------------------------------------------------------
961  */
962 /*
963  Geodesic Forward and Reverse calculation functions
964  Abstracted and adapted from PROJ-4.5.0 by David S.Register
965 
966  Original source code contains the following license:
967 
968  Copyright (c) 2000, Frank Warmerdam
969 
970  Permission is hereby granted, free of charge, to any person obtaining a
971  copy of this software and associated documentation files (the "Software"),
972  to deal in the Software without restriction, including without limitation
973  the rights to use, copy, modify, merge, publish, distribute, sublicense,
974  and/or sell copies of the Software, and to permit persons to whom the
975  Software is furnished to do so, subject to the following conditions:
976 
977  The above copyright notice and this permission notice shall be included
978  in all copies or substantial portions of the Software.
979 
980  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
981  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
982  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
983  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
984  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
985  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
986  DEALINGS IN THE SOFTWARE.
987 */
988 /* ---------------------------------------------------------------------------------
989  */
990 
991 #define DTOL 1e-12
992 
993 #define HALFPI 1.5707963267948966
994 #define SPI 3.14159265359
995 #define TWOPI 6.2831853071795864769
996 #define ONEPI 3.14159265358979323846
997 #define MERI_TOL 1e-9
998 
999 double adjlon(double lon) {
1000  if (fabs(lon) <= SPI) return (lon);
1001  lon += ONEPI; /* adjust to 0..2pi rad */
1002  lon -= TWOPI * floor(lon / TWOPI); /* remove integral # of 'revolutions'*/
1003  lon -= ONEPI; /* adjust back to -pi..pi rad */
1004  return (lon);
1005 }
1006 
1007 /* ---------------------------------------------------------------------------------
1008  */
1009 /*
1010 // Given the lat/long of starting point, and traveling a specified distance,
1011 // at an initial bearing, calculates the lat/long of the resulting location.
1012 // using sphere earth model.
1013 */
1014 /* ---------------------------------------------------------------------------------
1015  */
1016 void ll_gc_ll(double lat, double lon, double brg, double dist, double *dlat,
1017  double *dlon) {
1018  double th1, costh1, sinth1, sina12, cosa12, M, N, c1, c2, D, P, s1;
1019  int merid, signS;
1020 
1021  if((brg == 90.) || (brg == 180.)){
1022  brg += 1e-9;
1023  }
1024 
1025  /* Input/Output from geodesic functions */
1026  double al12; /* Forward azimuth */
1027  double al21; /* Back azimuth */
1028  double geod_S; /* Distance */
1029  double phi1, lam1, phi2, lam2;
1030 
1031  int ellipse;
1032  double geod_f;
1033  double geod_a;
1034  double es, onef, f, f4;
1035 
1036  /* Setup the static parameters */
1037  phi1 = lat * DEGREE; /* Initial Position */
1038  lam1 = lon * DEGREE;
1039  al12 = brg * DEGREE; /* Forward azimuth */
1040  geod_S = dist * 1852.0; /* Distance */
1041 
1042  // void geod_pre(struct georef_state *state)
1043  {
1044  /* Stuff the WGS84 projection parameters as necessary
1045  * To avoid having to include <geodesic,h>
1046  */
1047  ellipse = 1;
1048  f = 1.0 / WGSinvf; /* WGS84 ellipsoid flattening parameter */
1049  geod_a = WGS84_semimajor_axis_meters;
1050 
1051  es = 2 * f - f * f;
1052  onef = sqrt(1. - es);
1053  geod_f = 1 - onef;
1054  f4 = geod_f / 4;
1055 
1056  al12 = adjlon(al12); /* reduce to +- 0-PI */
1057  signS = fabs(al12) > HALFPI ? 1 : 0;
1058  th1 = ellipse ? atan(onef * tan(phi1)) : phi1;
1059  costh1 = cos(th1);
1060  sinth1 = sin(th1);
1061  if ((merid = fabs(sina12 = sin(al12)) < MERI_TOL)) {
1062  sina12 = 0.;
1063  cosa12 = fabs(al12) < HALFPI ? 1. : -1.;
1064  M = 0.;
1065  } else {
1066  cosa12 = cos(al12);
1067  M = costh1 * sina12;
1068  }
1069  N = costh1 * cosa12;
1070  if (ellipse) {
1071  if (merid) {
1072  c1 = 0.;
1073  c2 = f4;
1074  D = 1. - c2;
1075  D *= D;
1076  P = c2 / D;
1077  } else {
1078  c1 = geod_f * M;
1079  c2 = f4 * (1. - M * M);
1080  D = (1. - c2) * (1. - c2 - c1 * M);
1081  P = (1. + .5 * c1 * M) * c2 / D;
1082  }
1083  }
1084  if (merid)
1085  s1 = HALFPI - th1;
1086  else {
1087  s1 = (fabs(M) >= 1.) ? 0. : acos(M);
1088  s1 = sinth1 / sin(s1);
1089  s1 = (fabs(s1) >= 1.) ? 0. : acos(s1);
1090  }
1091  }
1092 
1093  // void geod_for(struct georef_state *state)
1094  {
1095  double d, sind, u, V, X, ds, cosds, sinds, ss, de;
1096 
1097  ss = 0.;
1098 
1099  if (ellipse) {
1100  d = geod_S / (D * geod_a);
1101  if (signS) d = -d;
1102  u = 2. * (s1 - d);
1103  V = cos(u + d);
1104  X = c2 * c2 * (sind = sin(d)) * cos(d) * (2. * V * V - 1.);
1105  ds = d + X - 2. * P * V * (1. - 2. * P * cos(u)) * sind;
1106  ss = s1 + s1 - ds;
1107  } else {
1108  ds = geod_S / geod_a;
1109  if (signS) ds = -ds;
1110  }
1111  cosds = cos(ds);
1112  sinds = sin(ds);
1113  if (signS) sinds = -sinds;
1114  al21 = N * cosds - sinth1 * sinds;
1115  if (merid) {
1116  phi2 = atan(tan(HALFPI + s1 - ds) / onef);
1117  if (al21 > 0.) {
1118  al21 = PI;
1119  if (signS)
1120  de = PI;
1121  else {
1122  phi2 = -phi2;
1123  de = 0.;
1124  }
1125  } else {
1126  al21 = 0.;
1127  if (signS) {
1128  phi2 = -phi2;
1129  de = 0;
1130  } else
1131  de = PI;
1132  }
1133  } else {
1134  al21 = atan(M / al21);
1135  if (al21 > 0) al21 += PI;
1136  if (al12 < 0.) al21 -= PI;
1137  al21 = adjlon(al21);
1138  phi2 = atan(-(sinth1 * cosds + N * sinds) * sin(al21) /
1139  (ellipse ? onef * M : M));
1140  de = atan2(sinds * sina12, (costh1 * cosds - sinth1 * sinds * cosa12));
1141  if (ellipse) {
1142  if (signS)
1143  de += c1 * ((1. - c2) * ds + c2 * sinds * cos(ss));
1144  else
1145  de -= c1 * ((1. - c2) * ds - c2 * sinds * cos(ss));
1146  }
1147  }
1148  lam2 = adjlon(lam1 + de);
1149  }
1150 
1151  *dlat = phi2 / DEGREE;
1152  *dlon = lam2 / DEGREE;
1153 }
1154 
1155 void ll_gc_ll_reverse(double lat1, double lon1, double lat2, double lon2,
1156  double *bearing, double *dist) {
1157  // For small distances do an ordinary mercator calc. (To prevent return of
1158  // nan's )
1159  if ((fabs(lon2 - lon1) < 0.1) && (fabs(lat2 - lat1) < 0.1)) {
1160  DistanceBearingMercator(lat2, lon2, lat1, lon1, bearing, dist);
1161  return;
1162  } else {
1163  /* Input/Output from geodesic functions */
1164  double al12; /* Forward azimuth */
1165  double al21; /* Back azimuth */
1166  double geod_S; /* Distance */
1167  double phi1, lam1, phi2, lam2;
1168 
1169  int ellipse;
1170  double geod_f;
1171  double geod_a;
1172  double es, onef, f, f64, f2, f4;
1173 
1174  /* Setup the static parameters */
1175  phi1 = lat1 * DEGREE; /* Initial Position */
1176  lam1 = lon1 * DEGREE;
1177  phi2 = lat2 * DEGREE;
1178  lam2 = lon2 * DEGREE;
1179 
1180  // void geod_inv(struct georef_state *state)
1181  {
1182  double th1, th2, thm, dthm, dlamm, dlam, sindlamm, costhm, sinthm,
1183  cosdthm, sindthm, L, E, cosd, d, X, Y, T, sind, tandlammp, u, v, D, A,
1184  B;
1185 
1186  /* Stuff the WGS84 projection parameters as necessary
1187  * To avoid having to include <geodesic,h>
1188  */
1189 
1190  ellipse = 1;
1191  f = 1.0 / WGSinvf; /* WGS84 ellipsoid flattening parameter */
1192  geod_a = WGS84_semimajor_axis_meters;
1193 
1194  es = 2 * f - f * f;
1195  onef = sqrt(1. - es);
1196  geod_f = 1 - onef;
1197  f2 = geod_f / 2;
1198  f4 = geod_f / 4;
1199  f64 = geod_f * geod_f / 64;
1200 
1201  if (ellipse) {
1202  th1 = atan(onef * tan(phi1));
1203  th2 = atan(onef * tan(phi2));
1204  } else {
1205  th1 = phi1;
1206  th2 = phi2;
1207  }
1208  thm = .5 * (th1 + th2);
1209  dthm = .5 * (th2 - th1);
1210  dlamm = .5 * (dlam = adjlon(lam2 - lam1));
1211  if (fabs(dlam) < DTOL && fabs(dthm) < DTOL) {
1212  al12 = al21 = geod_S = 0.;
1213  if (bearing) *bearing = 0.;
1214  if (dist) *dist = 0.;
1215  return;
1216  }
1217  sindlamm = sin(dlamm);
1218  costhm = cos(thm);
1219  sinthm = sin(thm);
1220  cosdthm = cos(dthm);
1221  sindthm = sin(dthm);
1222  L = sindthm * sindthm +
1223  (cosdthm * cosdthm - sinthm * sinthm) * sindlamm * sindlamm;
1224  d = acos(cosd = 1 - L - L);
1225  if (ellipse) {
1226  E = cosd + cosd;
1227  sind = sin(d);
1228  Y = sinthm * cosdthm;
1229  Y *= (Y + Y) / (1. - L);
1230  T = sindthm * costhm;
1231  T *= (T + T) / L;
1232  X = Y + T;
1233  Y -= T;
1234  T = d / sind;
1235  D = 4. * T * T;
1236  A = D * E;
1237  B = D + D;
1238  geod_S = geod_a * sind *
1239  (T - f4 * (T * X - Y) +
1240  f64 * (X * (A + (T - .5 * (A - E)) * X) - Y * (B + E * Y) +
1241  D * X * Y));
1242  tandlammp =
1243  tan(.5 * (dlam - .25 * (Y + Y - E * (4. - X)) *
1244  (f2 * T + f64 * (32. * T - (20. * T - A) * X -
1245  (B + 4.) * Y)) *
1246  tan(dlam)));
1247  } else {
1248  geod_S = geod_a * d;
1249  tandlammp = tan(dlamm);
1250  }
1251  u = atan2(sindthm, (tandlammp * costhm));
1252  v = atan2(cosdthm, (tandlammp * sinthm));
1253  al12 = adjlon(TWOPI + v - u);
1254  al21 = adjlon(TWOPI - v - u);
1255  if (al12 < 0) al12 += 2 * PI;
1256  if (bearing) *bearing = al12 / DEGREE;
1257  if (dist) *dist = geod_S / 1852.0;
1258  }
1259  }
1260 }
1261 
1262 void PositionBearingDistanceMercator(double lat, double lon, double brg,
1263  double dist, double *dlat, double *dlon) {
1264  ll_gc_ll(lat, lon, brg, dist, dlat, dlon);
1265 }
1266 
1267 double DistLoxodrome(double slat, double slon, double dlat, double dlon) {
1268  double dist =
1269  60 * sqrt(pow(slat - dlat, 2) +
1270  pow((slon - dlon) * cos((slat + dlat) / 2 * DEGREE), 2));
1271  // Crossing IDL or Greenwich?
1272  if (slon * dlon < 0){
1273  if (slon < 0) slon += 360.;
1274  else if (dlon < 0) dlon += 360.;
1275  double distrtw =
1276  60 * sqrt(pow(slat - dlat, 2) +
1277  pow((slon - dlon) * cos((slat + dlat) / 2 * DEGREE), 2));
1278  return (std::min)(dist, distrtw);
1279  }
1280  return dist;
1281 }
1282 
1283 /* ---------------------------------------------------------------------------------
1284  */
1285 /*
1286 // Given the lat/long of starting point and ending point,
1287 // calculates the distance (in Nm) along a geodesic curve, using sphere earth
1288 model.
1289 */
1290 /* ---------------------------------------------------------------------------------
1291  */
1292 
1293 double DistGreatCircle(double slat, double slon, double dlat, double dlon) {
1294  double d5;
1295  d5 = DistLoxodrome(slat, slon, dlat, dlon);
1296  if (d5 < 10) // Miles
1297  return d5;
1298 
1299  /* Input/Output from geodesic functions */
1300  // double al12; /* Forward azimuth */
1301  // double al21; /* Back azimuth */
1302  double geod_S; /* Distance */
1303  double phi1, lam1, phi2, lam2;
1304 
1305  int ellipse;
1306  double geod_f;
1307  double geod_a;
1308  double es, onef, f, f64, f4;
1309 
1310  phi1 = slat * DEGREE;
1311  lam1 = slon * DEGREE;
1312  phi2 = dlat * DEGREE;
1313  lam2 = dlon * DEGREE;
1314 
1315  // void geod_inv(struct georef_state *state)
1316  {
1317  double th1, th2, thm, dthm, dlamm, dlam, sindlamm, costhm, sinthm, cosdthm,
1318  sindthm, L, E, cosd, d, X, Y, T, sind, D, A, B;
1319  // double tandlammp,u,v;
1320 
1321  /* Stuff the WGS84 projection parameters as necessary
1322  * To avoid having to include <geodesic,h>
1323  */
1324 
1325  ellipse = 0;
1326  f = 1.0 / WGSinvf; /* WGS84 ellipsoid flattening parameter */
1327  geod_a = WGS84_semimajor_axis_meters;
1328 
1329  es = 2 * f - f * f;
1330  onef = sqrt(1. - es);
1331  geod_f = 1 - onef;
1332  // f2 = geod_f/2;
1333  f4 = geod_f / 4;
1334  f64 = geod_f * geod_f / 64;
1335 
1336  if (ellipse) {
1337  th1 = atan(onef * tan(phi1));
1338  th2 = atan(onef * tan(phi2));
1339  } else {
1340  th1 = phi1;
1341  th2 = phi2;
1342  }
1343  thm = .5 * (th1 + th2);
1344  dthm = .5 * (th2 - th1);
1345  dlamm = .5 * (dlam = adjlon(lam2 - lam1));
1346  if (fabs(dlam) < DTOL && fabs(dthm) < DTOL) {
1347  return 0.0;
1348  }
1349  sindlamm = sin(dlamm);
1350  costhm = cos(thm);
1351  sinthm = sin(thm);
1352  cosdthm = cos(dthm);
1353  sindthm = sin(dthm);
1354  L = sindthm * sindthm +
1355  (cosdthm * cosdthm - sinthm * sinthm) * sindlamm * sindlamm;
1356  d = acos(cosd = 1 - L - L);
1357 
1358  if (ellipse) {
1359  E = cosd + cosd;
1360  sind = sin(d);
1361  Y = sinthm * cosdthm;
1362  Y *= (Y + Y) / (1. - L);
1363  T = sindthm * costhm;
1364  T *= (T + T) / L;
1365  X = Y + T;
1366  Y -= T;
1367  T = d / sind;
1368  D = 4. * T * T;
1369  A = D * E;
1370  B = D + D;
1371  geod_S = geod_a * sind *
1372  (T - f4 * (T * X - Y) +
1373  f64 * (X * (A + (T - .5 * (A - E)) * X) - Y * (B + E * Y) +
1374  D * X * Y));
1375  // tandlammp = tan(.5 * (dlam - .25 * (Y + Y - E * (4. - X))
1376  // *
1377  // (f2 * T + f64 * (32. * T - (20. * T - A)
1378  // * X - (B + 4.) * Y)) * tan(dlam)));
1379  } else {
1380  geod_S = geod_a * d;
1381  // tandlammp = tan(dlamm);
1382  }
1383  // u = atan2(sindthm , (tandlammp * costhm));
1384  // v = atan2(cosdthm , (tandlammp * sinthm));
1385  // al12 = adjlon(TWOPI + v - u);
1386  // al21 = adjlon(TWOPI - v - u);
1387  }
1388 
1389  d5 = geod_S / 1852.0;
1390 
1391  return d5;
1392 }
1393 
1394 void DistanceBearingMercator(double lat1, double lon1, double lat0, double lon0,
1395  double *brg, double *dist) {
1396  // Calculate bearing and distance between two points
1397  double latm = (lat0 + lat1) / 2 * DEGREE; // median of latitude
1398  double delta_lat = (lat1 - lat0);
1399  double delta_lon = (lon1 - lon0);
1400  double ex_lat0, ex_lat1;
1401  double bearing, distance;
1402  // make sure we calc the shortest route, even if this across the date line.
1403  if (delta_lon < -180) delta_lon += 360;
1404  if (delta_lon > 180) delta_lon -= 360;
1405 
1406  if (delta_lon == 0)
1407  bearing = .0; // delta lon = 0 so course is due N or S
1408  else if (fabs(delta_lat) != .0)
1409  bearing = atan(delta_lon * cos(latm) / delta_lat);
1410  else
1411  bearing = PI / 2; // delta lat = 0 so course must be E or W
1412 
1413  distance = sqrt(pow(delta_lat, 2) + pow(delta_lon * cos(latm), 2));
1414 
1415  if (distance >
1416  0.01745) // > 1 degree we use exaggerated latitude to be more exact
1417  {
1418  if (delta_lat != 0.) {
1419  ex_lat0 = 10800 / PI * log(tan(PI / 4 + lat0 * DEGREE / 2));
1420  ex_lat1 = 10800 / PI * log(tan(PI / 4 + lat1 * DEGREE / 2));
1421  bearing = atan(delta_lon * 60 / (ex_lat1 - ex_lat0));
1422  distance = fabs(delta_lat / cos(bearing));
1423  } else {
1424  bearing = PI / 2;
1425  }
1426  }
1427 
1428  bearing = fabs(bearing);
1429  if (lat1 > lat0) {
1430  if (delta_lon < 0) bearing = 2 * PI - bearing;
1431  } // NW
1432  else {
1433  if (delta_lon > 0)
1434  bearing = PI - bearing; // SE
1435  else
1436  bearing = PI + bearing;
1437  } // SW
1438 
1439  if (brg) *brg = bearing * RADIAN; // in degrees
1440  if (dist) *dist = distance * 60; // in NM
1441 }
1442 
1443 /* ---------------------------------------------------------------------------------
1444  */
1445 /*
1446  * lmfit
1447  *
1448  * Solves or minimizes the sum of squares of m nonlinear
1449  * functions of n variables.
1450  *
1451  * From public domain Fortran version
1452  * of Argonne National Laboratories MINPACK
1453  * argonne national laboratory. minpack project. march 1980.
1454  * burton s. garbow, kenneth e. hillstrom, jorge j. more
1455  * C translation by Steve Moshier
1456  * Joachim Wuttke converted the source into C++ compatible ANSI style
1457  * and provided a simplified interface
1458  */
1459 
1460 //#include "lmmin.h" // all moved to georef.h
1461 #define _LMDIF
1462 
1465 
1466 double my_fit_function(double tx, double ty, int n_par, double *p) {
1467  double ret = p[0] + p[1] * tx;
1468 
1469  if (n_par > 2) ret += p[2] * ty;
1470  if (n_par > 3) {
1471  ret += p[3] * tx * tx;
1472  ret += p[4] * tx * ty;
1473  ret += p[5] * ty * ty;
1474  }
1475  if (n_par > 6) {
1476  ret += p[6] * tx * tx * tx;
1477  ret += p[7] * tx * tx * ty;
1478  ret += p[8] * tx * ty * ty;
1479  ret += p[9] * ty * ty * ty;
1480  }
1481 
1482  return ret;
1483 }
1484 
1485 int Georef_Calculate_Coefficients_Onedir(int n_points, int n_par, double *tx,
1486  double *ty, double *y, double *p,
1487  double hintp0, double hintp1,
1488  double hintp2)
1489 /*
1490 n_points : number of sample points
1491 n_par : 3, 6, or 10, 6 is probably good
1492 tx: sample data independent variable 1
1493 ty: sample data independent variable 2
1494 y: sample data dependent result
1495 p: curve fit result coefficients
1496 */
1497 {
1498  int i;
1499  lm_control_type control;
1500  lm_data_type data;
1501 
1502  lm_initialize_control(&control);
1503 
1504  for (i = 0; i < 12; i++) p[i] = 0.;
1505 
1506  // memset(p, 0, 12 * sizeof(double));
1507 
1508  // Insert hints
1509  p[0] = hintp0;
1510  p[1] = hintp1;
1511  p[2] = hintp2;
1512 
1513  data.user_func = my_fit_function;
1514  data.user_tx = tx;
1515  data.user_ty = ty;
1516  data.user_y = y;
1517  data.n_par = n_par;
1518  data.print_flag = 0;
1519 
1520  // perform the fit:
1521 
1522  lm_minimize(n_points, n_par, p, lm_evaluate_default, lm_print_default, &data,
1523  &control);
1524 
1525  // print results:
1526  // printf( "status: %s after %d evaluations\n",
1527  // lm_infmsg[control.info], control.nfev );
1528 
1529  // Control.info results [1,2,3] are success, other failure
1530  return control.info;
1531 }
1532 
1533 int Georef_Calculate_Coefficients(struct GeoRef *cp, int nlin_lon) {
1534  // Zero out the points
1535  for (int i = 0; i < 10; ++i)
1536  cp->pwx[i] = cp->pwy[i] = cp->wpx[i] = cp->wpy[i] = 0.0;
1537 
1538  int mp = 3;
1539 
1540  switch (cp->order) {
1541  case 1:
1542  mp = 3;
1543  break;
1544  case 2:
1545  mp = 6;
1546  break;
1547  case 3:
1548  mp = 10;
1549  break;
1550  default:
1551  mp = 3;
1552  break;
1553  }
1554 
1555  const int mp_lat = mp;
1556 
1557  // Force linear fit for longitude if nlin_lon > 0
1558  const int mp_lon = nlin_lon ? 2 : mp;
1559 
1560  // Make a dummy double array
1561  std::vector<double> pnull(cp->count, 1.0);
1562 
1563  // pixel(tx,ty) to (lat,lon)
1564  // Calculate and use a linear equation for p[0..2] to hint the solver
1565 
1566  int r1 = Georef_Calculate_Coefficients_Onedir(
1567  cp->count, mp_lon, cp->tx, cp->ty, cp->lon, cp->pwx,
1568  cp->lonmin -
1569  (cp->txmin * (cp->lonmax - cp->lonmin) / (cp->txmax - cp->txmin)),
1570  (cp->lonmax - cp->lonmin) / (cp->txmax - cp->txmin), 0.);
1571 
1572  // if blin_lon > 0, force cross terms in latitude equation coefficients
1573  // to be zero by making lat not dependent on tx,
1574  double *px = nlin_lon ? &pnull[0] : cp->tx;
1575 
1576  int r2 = Georef_Calculate_Coefficients_Onedir(
1577  cp->count, mp_lat, px, cp->ty, cp->lat, cp->pwy,
1578  cp->latmin -
1579  (cp->tymin * (cp->latmax - cp->latmin) / (cp->tymax - cp->tymin)),
1580  0., (cp->latmax - cp->latmin) / (cp->tymax - cp->tymin));
1581 
1582  // (lat,lon) to pixel(tx,ty)
1583  // Calculate and use a linear equation for p[0..2] to hint the solver
1584 
1585  int r3 = Georef_Calculate_Coefficients_Onedir(
1586  cp->count, mp_lon, cp->lon, cp->lat, cp->tx, cp->wpx,
1587  cp->txmin -
1588  ((cp->txmax - cp->txmin) * cp->lonmin / (cp->lonmax - cp->lonmin)),
1589  (cp->txmax - cp->txmin) / (cp->lonmax - cp->lonmin), 0.0);
1590 
1591  // if blin_lon > 0, force cross terms in latitude equation coefficients
1592  // to be zero by making ty not dependent on lon,
1593  px = nlin_lon ? &pnull[0] : cp->lon;
1594 
1595  int r4 = Georef_Calculate_Coefficients_Onedir(
1596  cp->count, mp_lat, &pnull[0] /*cp->lon*/, cp->lat, cp->ty, cp->wpy,
1597  cp->tymin -
1598  ((cp->tymax - cp->tymin) * cp->latmin / (cp->latmax - cp->latmin)),
1599  0.0, (cp->tymax - cp->tymin) / (cp->latmax - cp->latmin));
1600 
1601  if ((r1) && (r1 < 4) && (r2) && (r2 < 4) && (r3) && (r3 < 4) && (r4) &&
1602  (r4 < 4))
1603  return 0;
1604 
1605  return 1;
1606 }
1607 
1608 int Georef_Calculate_Coefficients_Proj(struct GeoRef *cp) {
1609  int r1, r2, r3, r4;
1610  int mp;
1611 
1612  // Zero out the points
1613  cp->pwx[6] = cp->pwy[6] = cp->wpx[6] = cp->wpy[6] = 0.;
1614  cp->pwx[7] = cp->pwy[7] = cp->wpx[7] = cp->wpy[7] = 0.;
1615  cp->pwx[8] = cp->pwy[8] = cp->wpx[8] = cp->wpy[8] = 0.;
1616  cp->pwx[9] = cp->pwy[9] = cp->wpx[9] = cp->wpy[9] = 0.;
1617  cp->pwx[3] = cp->pwy[3] = cp->wpx[3] = cp->wpy[3] = 0.;
1618  cp->pwx[4] = cp->pwy[4] = cp->wpx[4] = cp->wpy[4] = 0.;
1619  cp->pwx[5] = cp->pwy[5] = cp->wpx[5] = cp->wpy[5] = 0.;
1620  cp->pwx[0] = cp->pwy[0] = cp->wpx[0] = cp->wpy[0] = 0.;
1621  cp->pwx[1] = cp->pwy[1] = cp->wpx[1] = cp->wpy[1] = 0.;
1622  cp->pwx[2] = cp->pwy[2] = cp->wpx[2] = cp->wpy[2] = 0.;
1623 
1624  mp = 3;
1625 
1626  // pixel(tx,ty) to (northing,easting)
1627  // Calculate and use a linear equation for p[0..2] to hint the solver
1628 
1629  r1 = Georef_Calculate_Coefficients_Onedir(
1630  cp->count, mp, cp->tx, cp->ty, cp->lon, cp->pwx,
1631  cp->lonmin -
1632  (cp->txmin * (cp->lonmax - cp->lonmin) / (cp->txmax - cp->txmin)),
1633  (cp->lonmax - cp->lonmin) / (cp->txmax - cp->txmin), 0.);
1634 
1635  r2 = Georef_Calculate_Coefficients_Onedir(
1636  cp->count, mp, cp->tx, cp->ty, cp->lat, cp->pwy,
1637  cp->latmin -
1638  (cp->tymin * (cp->latmax - cp->latmin) / (cp->tymax - cp->tymin)),
1639  0., (cp->latmax - cp->latmin) / (cp->tymax - cp->tymin));
1640 
1641  // (northing/easting) to pixel(tx,ty)
1642  // Calculate and use a linear equation for p[0..2] to hint the solver
1643 
1644  r3 = Georef_Calculate_Coefficients_Onedir(
1645  cp->count, mp, cp->lon, cp->lat, cp->tx, cp->wpx,
1646  cp->txmin -
1647  ((cp->txmax - cp->txmin) * cp->lonmin / (cp->lonmax - cp->lonmin)),
1648  (cp->txmax - cp->txmin) / (cp->lonmax - cp->lonmin), 0.0);
1649 
1650  r4 = Georef_Calculate_Coefficients_Onedir(
1651  cp->count, mp, cp->lon, cp->lat, cp->ty, cp->wpy,
1652  cp->tymin -
1653  ((cp->tymax - cp->tymin) * cp->latmin / (cp->latmax - cp->latmin)),
1654  0.0, (cp->tymax - cp->tymin) / (cp->latmax - cp->latmin));
1655 
1656  if ((r1) && (r1 < 4) && (r2) && (r2 < 4) && (r3) && (r3 < 4) && (r4) &&
1657  (r4 < 4))
1658  return 0;
1659  else
1660  return 1;
1661 }
1662 
1663 /*
1664  * This file contains default implementation of the evaluate and printout
1665  * routines. In most cases, customization of lmfit can be done by modifying
1666  * these two routines. Either modify them here, or copy and rename them.
1667  */
1668 
1669 void lm_evaluate_default(double *par, int m_dat, double *fvec, void *data,
1670  int *info)
1671 /*
1672  * par is an input array. At the end of the minimization, it contains
1673  * the approximate solution vector.
1674  *
1675  * m_dat is a positive integer input variable set to the number
1676  * of functions.
1677  *
1678  * fvec is an output array of length m_dat which contains the function
1679  * values the square sum of which ought to be minimized.
1680  *
1681  * data is a read-only pointer to lm_data_type, as specified by lmuse.h.
1682  *
1683  * info is an integer output variable. If set to a negative value, the
1684  * minimization procedure will stop.
1685  */
1686 {
1687  lm_data_type *mydata = (lm_data_type *)data;
1688 
1689  for (int i = 0; i < m_dat; i++) {
1690  fvec[i] = mydata->user_y[i] - mydata->user_func(mydata->user_tx[i],
1691  mydata->user_ty[i],
1692  mydata->n_par, par);
1693  }
1694  *info = *info; /* to prevent a 'unused variable' warning */
1695  /* if <parameters drifted away> { *info = -1; } */
1696 }
1697 
1698 void lm_print_default(int n_par, double *par, int m_dat, double *fvec,
1699  void *data, int iflag, int iter, int nfev)
1700 /*
1701  * data : for soft control of printout behaviour, add control
1702  * variables to the data struct
1703  * iflag : 0 (init) 1 (outer loop) 2(inner loop) -1(terminated)
1704  * iter : outer loop counter
1705  * nfev : number of calls to *evaluate
1706  */
1707 {
1708  lm_data_type *mydata = (lm_data_type *)data;
1709 
1710  if (mydata->print_flag) {
1711  if (iflag == 2) {
1712  printf("trying step in gradient direction\n");
1713  } else if (iflag == 1) {
1714  printf("determining gradient (iteration %d)\n", iter);
1715  } else if (iflag == 0) {
1716  printf("starting minimization\n");
1717  } else if (iflag == -1) {
1718  printf("terminated after %d evaluations\n", nfev);
1719  }
1720 
1721  printf(" par: ");
1722  for (int i = 0; i < n_par; ++i) printf(" %12g", par[i]);
1723  printf(" => norm: %12g\n", lm_enorm(m_dat, fvec));
1724 
1725  if (iflag == -1) {
1726  printf(" fitting data as follows:\n");
1727  for (int i = 0; i < m_dat; ++i) {
1728  const double tx = (mydata->user_tx)[i];
1729  const double ty = (mydata->user_ty)[i];
1730  const double y = (mydata->user_y)[i];
1731  const double f = mydata->user_func(tx, ty, mydata->n_par, par);
1732  printf(
1733  " tx[%2d]=%8g ty[%2d]=%8g y=%12g fit=%12g "
1734  "residue=%12g\n",
1735  i, tx, i, ty, y, f, y - f);
1736  }
1737  }
1738  } // if print_flag
1739 }
1740 
1742 
1743 /* *********************** high-level interface **************************** */
1744 
1745 void lm_initialize_control(lm_control_type *control) {
1746  control->maxcall = 100;
1747  control->epsilon = 1.e-10; // 1.e-14;
1748  control->stepbound = 100; // 100.;
1749  control->ftol = 1.e-14;
1750  control->xtol = 1.e-14;
1751  control->gtol = 1.e-14;
1752 }
1753 
1754 void lm_minimize(int m_dat, int n_par, double *par, lm_evaluate_ftype *evaluate,
1755  lm_print_ftype *printout, void *data,
1756  lm_control_type *control) {
1757  std::vector<double> fvec(m_dat);
1758  std::vector<double> diag(n_par);
1759  std::vector<double> qtf(n_par);
1760  std::vector<double> fjac(n_par * m_dat);
1761  std::vector<double> wa1(n_par);
1762  std::vector<double> wa2(n_par);
1763  std::vector<double> wa3(n_par);
1764  std::vector<double> wa4(m_dat);
1765  std::vector<int> ipvt(n_par);
1766 
1767  // *** perform fit.
1768 
1769  control->info = 0;
1770  control->nfev = 0;
1771 
1772  // this goes through the modified legacy interface:
1773  lm_lmdif(m_dat, n_par, par, &fvec[0], control->ftol, control->xtol,
1774  control->gtol, control->maxcall * (n_par + 1), control->epsilon,
1775  &diag[0], 1, control->stepbound, &(control->info), &(control->nfev),
1776  &fjac[0], &ipvt[0], &qtf[0], &wa1[0], &wa2[0], &wa3[0], &wa4[0],
1777  evaluate, printout, data);
1778 
1779  (*printout)(n_par, par, m_dat, &fvec[0], data, -1, 0, control->nfev);
1780  control->fnorm = lm_enorm(m_dat, &fvec[0]);
1781  if (control->info < 0) control->info = 10;
1782 }
1783 
1784 // ***** the following messages are referenced by the variable info.
1785 
1786 const char *lm_infmsg[] = {
1787  "improper input parameters",
1788  "the relative error in the sum of squares is at most tol",
1789  "the relative error between x and the solution is at most tol",
1790  "both errors are at most tol",
1791  "fvec is orthogonal to the columns of the jacobian to machine precision",
1792  "number of calls to fcn has reached or exceeded 200*(n+1)",
1793  "ftol is too small. no further reduction in the sum of squares is possible",
1794  "xtol too small. no further improvement in approximate solution x possible",
1795  "gtol too small. no further improvement in approximate solution x possible",
1796  "not enough memory",
1797  "break requested within function evaluation"};
1798 
1799 const char *lm_shortmsg[] = {"invalid input", "success (f)", "success (p)",
1800  "success (f,p)", "degenerate", "call limit",
1801  "failed (f)", "failed (p)", "failed (o)",
1802  "no memory", "user break"};
1803 
1804 /* ************************** implementation ******************************* */
1805 
1806 #define BUG 0
1807 #if BUG
1808 #include <stdio.h>
1809 #endif
1810 
1811 // the following values seem good for an x86:
1812 //#define LM_MACHEP .555e-16 /* resolution of arithmetic */
1813 //#define LM_DWARF 9.9e-324 /* smallest nonzero number */
1814 // the follwoing values should work on any machine:
1815 #define LM_MACHEP 1.2e-16
1816 #define LM_DWARF 1.0e-38
1817 
1818 // the squares of the following constants shall not under/overflow:
1819 // these values seem good for an x86:
1820 //#define LM_SQRT_DWARF 1.e-160
1821 //#define LM_SQRT_GIANT 1.e150
1822 // the following values should work on any machine:
1823 #define LM_SQRT_DWARF 3.834e-20
1824 #define LM_SQRT_GIANT 1.304e19
1825 
1826 void lm_qrfac(int m, int n, double *a, int pivot, int *ipvt, double *rdiag,
1827  double *acnorm, double *wa);
1828 void lm_qrsolv(int n, double *r, int ldr, int *ipvt, double *diag, double *qtb,
1829  double *x, double *sdiag, double *wa);
1830 void lm_lmpar(int n, double *r, int ldr, int *ipvt, double *diag, double *qtb,
1831  double delta, double *par, double *x, double *sdiag, double *wa1,
1832  double *wa2);
1833 
1834 #define MIN(a, b) (((a) <= (b)) ? (a) : (b))
1835 #define MAX(a, b) (((a) >= (b)) ? (a) : (b))
1836 #define SQR(x) (x) * (x)
1837 
1838 // ***** the low-level legacy interface for full control.
1839 
1840 void lm_lmdif(int m, int n, double *x, double *fvec, double ftol, double xtol,
1841  double gtol, int maxfev, double epsfcn, double *diag, int mode,
1842  double factor, int *info, int *nfev, double *fjac, int *ipvt,
1843  double *qtf, double *wa1, double *wa2, double *wa3, double *wa4,
1844  lm_evaluate_ftype *evaluate, lm_print_ftype *printout,
1845  void *data) {
1846  /*
1847  * the purpose of lmdif is to minimize the sum of the squares of
1848  * m nonlinear functions in n variables by a modification of
1849  * the levenberg-marquardt algorithm. the user must provide a
1850  * subroutine evaluate which calculates the functions. the jacobian
1851  * is then calculated by a forward-difference approximation.
1852  *
1853  * the multi-parameter interface lm_lmdif is for users who want
1854  * full control and flexibility. most users will be better off using
1855  * the simpler interface lmfit provided above.
1856  *
1857  * the parameters are the same as in the legacy FORTRAN implementation,
1858  * with the following exceptions:
1859  * the old parameter ldfjac which gave leading dimension of fjac has
1860  * been deleted because this C translation makes no use of two-
1861  * dimensional arrays;
1862  * the old parameter nprint has been deleted; printout is now controlled
1863  * by the user-supplied routine *printout;
1864  * the parameter field *data and the function parameters *evaluate and
1865  * *printout have been added; they help avoiding global variables.
1866  *
1867  * parameters:
1868  *
1869  * m is a positive integer input variable set to the number
1870  * of functions.
1871  *
1872  * n is a positive integer input variable set to the number
1873  * of variables. n must not exceed m.
1874  *
1875  * x is an array of length n. on input x must contain
1876  * an initial estimate of the solution vector. on output x
1877  * contains the final estimate of the solution vector.
1878  *
1879  * fvec is an output array of length m which contains
1880  * the functions evaluated at the output x.
1881  *
1882  * ftol is a nonnegative input variable. termination
1883  * occurs when both the actual and predicted relative
1884  * reductions in the sum of squares are at most ftol.
1885  * therefore, ftol measures the relative error desired
1886  * in the sum of squares.
1887  *
1888  * xtol is a nonnegative input variable. termination
1889  * occurs when the relative error between two consecutive
1890  * iterates is at most xtol. therefore, xtol measures the
1891  * relative error desired in the approximate solution.
1892  *
1893  * gtol is a nonnegative input variable. termination
1894  * occurs when the cosine of the angle between fvec and
1895  * any column of the jacobian is at most gtol in absolute
1896  * value. therefore, gtol measures the orthogonality
1897  * desired between the function vector and the columns
1898  * of the jacobian.
1899  *
1900  * maxfev is a positive integer input variable. termination
1901  * occurs when the number of calls to lm_fcn is at least
1902  * maxfev by the end of an iteration.
1903  *
1904  * epsfcn is an input variable used in determining a suitable
1905  * step length for the forward-difference approximation. this
1906  * approximation assumes that the relative errors in the
1907  * functions are of the order of epsfcn. if epsfcn is less
1908  * than the machine precision, it is assumed that the relative
1909  * errors in the functions are of the order of the machine
1910  * precision.
1911  *
1912  * diag is an array of length n. if mode = 1 (see below), diag is
1913  * internally set. if mode = 2, diag must contain positive entries
1914  * that serve as multiplicative scale factors for the variables.
1915  *
1916  * mode is an integer input variable. if mode = 1, the
1917  * variables will be scaled internally. if mode = 2,
1918  * the scaling is specified by the input diag. other
1919  * values of mode are equivalent to mode = 1.
1920  *
1921  * factor is a positive input variable used in determining the
1922  * initial step bound. this bound is set to the product of
1923  * factor and the euclidean norm of diag*x if nonzero, or else
1924  * to factor itself. in most cases factor should lie in the
1925  * interval (.1,100.). 100. is a generally recommended value.
1926  *
1927  * info is an integer output variable that indicates the termination
1928  * status of lm_lmdif as follows:
1929  *
1930  * info < 0 termination requested by user-supplied routine *evaluate;
1931  *
1932  * info = 0 improper input parameters;
1933  *
1934  * info = 1 both actual and predicted relative reductions
1935  * in the sum of squares are at most ftol;
1936  *
1937  * info = 2 relative error between two consecutive iterates
1938  * is at most xtol;
1939  *
1940  * info = 3 conditions for info = 1 and info = 2 both hold;
1941  *
1942  * info = 4 the cosine of the angle between fvec and any
1943  * column of the jacobian is at most gtol in
1944  * absolute value;
1945  *
1946  * info = 5 number of calls to lm_fcn has reached or
1947  * exceeded maxfev;
1948  *
1949  * info = 6 ftol is too small. no further reduction in
1950  * the sum of squares is possible;
1951  *
1952  * info = 7 xtol is too small. no further improvement in
1953  * the approximate solution x is possible;
1954  *
1955  * info = 8 gtol is too small. fvec is orthogonal to the
1956  * columns of the jacobian to machine precision;
1957  *
1958  * nfev is an output variable set to the number of calls to the
1959  * user-supplied routine *evaluate.
1960  *
1961  * fjac is an output m by n array. the upper n by n submatrix
1962  * of fjac contains an upper triangular matrix r with
1963  * diagonal elements of nonincreasing magnitude such that
1964  *
1965  * t t t
1966  * p *(jac *jac)*p = r *r,
1967  *
1968  * where p is a permutation matrix and jac is the final
1969  * calculated jacobian. column j of p is column ipvt(j)
1970  * (see below) of the identity matrix. the lower trapezoidal
1971  * part of fjac contains information generated during
1972  * the computation of r.
1973  *
1974  * ipvt is an integer output array of length n. ipvt
1975  * defines a permutation matrix p such that jac*p = q*r,
1976  * where jac is the final calculated jacobian, q is
1977  * orthogonal (not stored), and r is upper triangular
1978  * with diagonal elements of nonincreasing magnitude.
1979  * column j of p is column ipvt(j) of the identity matrix.
1980  *
1981  * qtf is an output array of length n which contains
1982  * the first n elements of the vector (q transpose)*fvec.
1983  *
1984  * wa1, wa2, and wa3 are work arrays of length n.
1985  *
1986  * wa4 is a work array of length m.
1987  *
1988  * the following parameters are newly introduced in this C translation:
1989  *
1990  * evaluate is the name of the subroutine which calculates the functions.
1991  * a default implementation lm_evaluate_default is provided in
1992  * lm_eval.c; alternatively, evaluate can be provided by a user calling
1993  * program. it should be written as follows:
1994  *
1995  * void evaluate ( double* par, int m_dat, double* fvec,
1996  * void *data, int *info )
1997  * {
1998  * // for ( i=0; i<m_dat; ++i )
1999  * // calculate fvec[i] for given parameters par;
2000  * // to stop the minimization,
2001  * // set *info to a negative integer.
2002  * }
2003  *
2004  * printout is the name of the subroutine which nforms about fit
2005  * progress. a default implementation lm_print_default is provided in
2006  * lm_eval.c; alternatively, printout can be provided by a user calling
2007  * program. it should be written as follows:
2008  *
2009  * void printout ( int n_par, double* par, int m_dat, double* fvec,
2010  * void *data, int iflag, int iter, int nfev )
2011  * {
2012  * // iflag : 0 (init) 1 (outer loop) 2(inner loop) -1(terminated)
2013  * // iter : outer loop counter
2014  * // nfev : number of calls to *evaluate
2015  * }
2016  *
2017  * data is an input pointer to an arbitrary structure that is passed to
2018  * evaluate. typically, it contains experimental data to be fitted.
2019  *
2020  */
2021 
2022  *nfev = 0; // function evaluation counter
2023 
2024  // *** check the input parameters for errors.
2025 
2026  if ((n <= 0) || (m < n) || (ftol < 0.) || (xtol < 0.) || (gtol < 0.) ||
2027  (maxfev <= 0) || (factor <= 0.)) {
2028  *info = 0; // invalid parameter
2029  return;
2030  }
2031 
2032  if (mode == 2) /* scaling by diag[] */
2033  {
2034  for (int j = 0; j < n; j++) /* check for non positive elements */
2035  {
2036  if (diag[j] <= 0.0) {
2037  *info = 0; // invalid parameter
2038  return;
2039  }
2040  }
2041  }
2042 #if BUG
2043  printf("lmdif\n");
2044 #endif
2045 
2046  // *** evaluate the function at the starting point and calculate its norm.
2047 
2048  *info = 0;
2049  (*evaluate)(x, m, fvec, data, info);
2050  (*printout)(n, x, m, fvec, data, 0, 0, ++(*nfev));
2051  if (*info < 0) return;
2052 
2053  // *** the outer loop.
2054  int iter = 1; // outer loop counter
2055  double delta =
2056  0.0; // just to prevent a warning (initialization within if-clause)
2057  double xnorm = 0.0;
2058  double fnorm = lm_enorm(m, fvec);
2059  const double eps = sqrt(MAX(
2060  epsfcn,
2061  LM_MACHEP)); // used in calculating the Jacobian by forward differences
2062 
2063  do {
2064 #if BUG
2065  printf("lmdif/ outer loop iter=%d nfev=%d fnorm=%.10e\n", iter, *nfev,
2066  fnorm);
2067 #endif
2068 
2069  // O** calculate the jacobian matrix.
2070 
2071  for (int j = 0; j < n; j++) {
2072  const double temp = x[j];
2073  const double step = eps * fabs(temp) == 0.0 ? eps : eps * fabs(temp);
2074 
2075  x[j] = temp + step;
2076  *info = 0;
2077  (*evaluate)(x, m, wa4, data, info);
2078  (*printout)(n, x, m, wa4, data, 1, iter, ++(*nfev));
2079  if (*info < 0) return; // user requested break
2080  x[j] = temp;
2081  for (int i = 0; i < m; i++) fjac[j * m + i] = (wa4[i] - fvec[i]) / step;
2082  }
2083 #if BUG > 1
2084  // DEBUG: print the entire matrix
2085  for (i = 0; i < m; i++) {
2086  for (j = 0; j < n; j++) printf("%.5e ", y[j * m + i]);
2087  printf("\n");
2088  }
2089 #endif
2090 
2091  // O** compute the qr factorization of the jacobian.
2092 
2093  lm_qrfac(m, n, fjac, 1, ipvt, wa1, wa2, wa3);
2094 
2095  // O** on the first iteration ...
2096 
2097  if (iter == 1) {
2098  if (mode != 2)
2099  // ... scale according to the norms of the columns of the initial
2100  // jacobian.
2101  {
2102  for (int j = 0; j < n; j++) {
2103  diag[j] = wa2[j];
2104  if (wa2[j] == 0.) diag[j] = 1.;
2105  }
2106  }
2107 
2108  // ... calculate the norm of the scaled x and
2109  // initialize the step bound delta.
2110 
2111  for (int j = 0; j < n; j++) wa3[j] = diag[j] * x[j];
2112 
2113  xnorm = lm_enorm(n, wa3);
2114  delta = factor * xnorm;
2115  if (delta == 0.) delta = factor;
2116  }
2117 
2118  // O** form (q transpose)*fvec and store the first n components in qtf.
2119 
2120  for (int i = 0; i < m; i++) wa4[i] = fvec[i];
2121 
2122  for (int j = 0; j < n; j++) {
2123  double temp3 = fjac[j * m + j];
2124  if (temp3 != 0.) {
2125  double sum = 0.0;
2126  for (int i = j; i < m; i++) sum += fjac[j * m + i] * wa4[i];
2127  double temp = -sum / temp3;
2128  for (int i = j; i < m; i++) wa4[i] += fjac[j * m + i] * temp;
2129  }
2130  fjac[j * m + j] = wa1[j];
2131  qtf[j] = wa4[j];
2132  }
2133 
2134  // O** compute the norm of the scaled gradient and test for convergence.
2135 
2136  double gnorm = 0;
2137  if (fnorm != 0) {
2138  for (int j = 0; j < n; j++) {
2139  if (wa2[ipvt[j]] == 0) continue;
2140 
2141  double sum = 0.0;
2142  for (int i = 0; i <= j; i++) sum += fjac[j * m + i] * qtf[i] / fnorm;
2143  gnorm = MAX(gnorm, fabs(sum / wa2[ipvt[j]]));
2144  }
2145  }
2146 
2147  if (gnorm <= gtol) {
2148  *info = 4;
2149  return;
2150  }
2151 
2152  // O** rescale if necessary.
2153 
2154  if (mode != 2) {
2155  for (int j = 0; j < n; j++) diag[j] = MAX(diag[j], wa2[j]);
2156  }
2157 
2158  // O** the inner loop.
2159  const double kP0001 = 1.0e-4;
2160  double ratio = 0.0;
2161  do {
2162 #if BUG
2163  printf("lmdif/ inner loop iter=%d nfev=%d\n", iter, *nfev);
2164 #endif
2165 
2166  // OI* determine the levenberg-marquardt parameter.
2167  double par = 0; // levenberg-marquardt parameter
2168  lm_lmpar(n, fjac, m, ipvt, diag, qtf, delta, &par, wa1, wa2, wa3, wa4);
2169 
2170  // OI* store the direction p and x + p. calculate the norm of p.
2171 
2172  for (int j = 0; j < n; j++) {
2173  wa1[j] = -wa1[j];
2174  wa2[j] = x[j] + wa1[j];
2175  wa3[j] = diag[j] * wa1[j];
2176  }
2177  double pnorm = lm_enorm(n, wa3);
2178 
2179  // OI* on the first iteration, adjust the initial step bound.
2180 
2181  if (*nfev <= 1 + n) // bug corrected by J. Wuttke in 2004
2182  delta = MIN(delta, pnorm);
2183 
2184  // OI* evaluate the function at x + p and calculate its norm.
2185 
2186  *info = 0;
2187  (*evaluate)(wa2, m, wa4, data, info);
2188  (*printout)(n, x, m, wa4, data, 2, iter, ++(*nfev));
2189  if (*info < 0) return; // user requested break
2190 
2191  double fnorm1 = lm_enorm(m, wa4);
2192 #if BUG
2193  printf(
2194  "lmdif/ pnorm %.10e fnorm1 %.10e fnorm %.10e"
2195  " delta=%.10e par=%.10e\n",
2196  pnorm, fnorm1, fnorm, delta, par);
2197 #endif
2198 
2199  // OI* compute the scaled actual reduction.
2200  const double kP1 = 0.1;
2201  const double actred = kP1 * fnorm1 < fnorm ? 1 - SQR(fnorm1 / fnorm) : -1;
2202 
2203  // OI* compute the scaled predicted reduction and
2204  // the scaled directional derivative.
2205 
2206  for (int j = 0; j < n; j++) {
2207  wa3[j] = 0;
2208  for (int i = 0; i <= j; i++) wa3[i] += fjac[j * m + i] * wa1[ipvt[j]];
2209  }
2210  const double temp1 = lm_enorm(n, wa3) / fnorm;
2211  const double temp2 = sqrt(par) * pnorm / fnorm;
2212  const double prered = SQR(temp1) + 2 * SQR(temp2);
2213  const double dirder = -(SQR(temp1) + SQR(temp2));
2214 
2215  // OI* compute the ratio of the actual to the predicted reduction.
2216 
2217  ratio = prered != 0 ? actred / prered : 0.0;
2218 #if BUG
2219  printf(
2220  "lmdif/ actred=%.10e prered=%.10e ratio=%.10e"
2221  " sq(1)=%.10e sq(2)=%.10e dd=%.10e\n",
2222  actred, prered, prered != 0 ? ratio : 0., SQR(temp1), SQR(temp2),
2223  dirder);
2224 #endif
2225 
2226  // OI* update the step bound.
2227  const double kP5 = 0.5;
2228  const double kP25 = 0.25;
2229  const double kP75 = 0.75;
2230 
2231  if (ratio <= kP25) {
2232  double temp =
2233  actred >= 0.0 ? kP5 : kP5 * dirder / (dirder + kP5 * actred);
2234  if (kP1 * fnorm1 >= fnorm || temp < kP1) temp = kP1;
2235  delta = temp * MIN(delta, pnorm / kP1);
2236  par /= temp;
2237  } else if (par == 0. || ratio >= kP75) {
2238  delta = pnorm / kP5;
2239  par *= kP5;
2240  }
2241 
2242  // OI* test for successful iteration...
2243  if (ratio >= kP0001) {
2244  // ... successful iteration. update x, fvec, and their norms.
2245 
2246  for (int j = 0; j < n; j++) {
2247  x[j] = wa2[j];
2248  wa2[j] = diag[j] * x[j];
2249  }
2250  for (int i = 0; i < m; i++) fvec[i] = wa4[i];
2251  xnorm = lm_enorm(n, wa2);
2252  fnorm = fnorm1;
2253  iter++;
2254  }
2255 #if BUG
2256  else {
2257  printf("ATTN: iteration considered unsuccessful\n");
2258  }
2259 #endif
2260 
2261  // OI* tests for convergence ( otherwise *info = 1, 2, or 3 )
2262 
2263  *info = 0; // do not terminate (unless overwritten by nonzero value)
2264  if (fabs(actred) <= ftol && prered <= ftol && kP5 * ratio <= 1) *info = 1;
2265  if (delta <= xtol * xnorm) *info += 2;
2266  if (*info != 0) return;
2267 
2268  // OI* tests for termination and stringent tolerances.
2269 
2270  if (*nfev >= maxfev) *info = 5;
2271  if (fabs(actred) <= LM_MACHEP && prered <= LM_MACHEP && kP5 * ratio <= 1)
2272  *info = 6;
2273  if (delta <= LM_MACHEP * xnorm) *info = 7;
2274  if (gnorm <= LM_MACHEP) *info = 8;
2275  if (*info != 0) return;
2276 
2277  // OI* end of the inner loop. repeat if iteration unsuccessful.
2278 
2279  } while (ratio < kP0001);
2280 
2281  // O** end of the outer loop.
2282 
2283  } while (1);
2284 }
2285 
2286 void lm_lmpar(int n, double *r, int ldr, int *ipvt, double *diag, double *qtb,
2287  double delta, double *par, double *x, double *sdiag, double *wa1,
2288  double *wa2) {
2289  /* given an m by n matrix a, an n by n nonsingular diagonal
2290  * matrix d, an m-vector b, and a positive number delta,
2291  * the problem is to determine a value for the parameter
2292  * par such that if x solves the system
2293  *
2294  * a*x = b , sqrt(par)*d*x = 0 ,
2295  *
2296  * in the least squares sense, and dxnorm is the euclidean
2297  * norm of d*x, then either par is 0. and
2298  *
2299  * (dxnorm-delta) .le. 0.1*delta ,
2300  *
2301  * or par is positive and
2302  *
2303  * abs(dxnorm-delta) .le. 0.1*delta .
2304  *
2305  * this subroutine completes the solution of the problem
2306  * if it is provided with the necessary information from the
2307  * qr factorization, with column pivoting, of a. that is, if
2308  * a*p = q*r, where p is a permutation matrix, q has orthogonal
2309  * columns, and r is an upper triangular matrix with diagonal
2310  * elements of nonincreasing magnitude, then lmpar expects
2311  * the full upper triangle of r, the permutation matrix p,
2312  * and the first n components of (q transpose)*b. on output
2313  * lmpar also provides an upper triangular matrix s such that
2314  *
2315  * t t t
2316  * p *(a *a + par*d*d)*p = s *s .
2317  *
2318  * s is employed within lmpar and may be of separate interest.
2319  *
2320  * only a few iterations are generally needed for convergence
2321  * of the algorithm. if, however, the limit of 10 iterations
2322  * is reached, then the output par will contain the best
2323  * value obtained so far.
2324  *
2325  * parameters:
2326  *
2327  * n is a positive integer input variable set to the order of r.
2328  *
2329  * r is an n by n array. on input the full upper triangle
2330  * must contain the full upper triangle of the matrix r.
2331  * on output the full upper triangle is unaltered, and the
2332  * strict lower triangle contains the strict upper triangle
2333  * (transposed) of the upper triangular matrix s.
2334  *
2335  * ldr is a positive integer input variable not less than n
2336  * which specifies the leading dimension of the array r.
2337  *
2338  * ipvt is an integer input array of length n which defines the
2339  * permutation matrix p such that a*p = q*r. column j of p
2340  * is column ipvt(j) of the identity matrix.
2341  *
2342  * diag is an input array of length n which must contain the
2343  * diagonal elements of the matrix d.
2344  *
2345  * qtb is an input array of length n which must contain the first
2346  * n elements of the vector (q transpose)*b.
2347  *
2348  * delta is a positive input variable which specifies an upper
2349  * bound on the euclidean norm of d*x.
2350  *
2351  * par is a nonnegative variable. on input par contains an
2352  * initial estimate of the levenberg-marquardt parameter.
2353  * on output par contains the final estimate.
2354  *
2355  * x is an output array of length n which contains the least
2356  * squares solution of the system a*x = b, sqrt(par)*d*x = 0,
2357  * for the output par.
2358  *
2359  * sdiag is an output array of length n which contains the
2360  * diagonal elements of the upper triangular matrix s.
2361  *
2362  * wa1 and wa2 are work arrays of length n.
2363  *
2364  */
2365 
2366 #if BUG
2367  printf("lmpar\n");
2368 #endif
2369 
2370  // *** compute and store in x the gauss-newton direction. if the
2371  // jacobian is rank-deficient, obtain a least squares solution.
2372 
2373  int nsing = n;
2374  for (int j = 0; j < n; j++) {
2375  wa1[j] = qtb[j];
2376  if (r[j * ldr + j] == 0 && nsing == n) nsing = j;
2377  if (nsing < n) wa1[j] = 0;
2378  }
2379 #if BUG
2380  printf("nsing %d ", nsing);
2381 #endif
2382  for (int j = nsing - 1; j >= 0; j--) {
2383  wa1[j] = wa1[j] / r[j + ldr * j];
2384  const double temp = wa1[j];
2385  for (int i = 0; i < j; i++) wa1[i] -= r[j * ldr + i] * temp;
2386  }
2387 
2388  for (int j = 0; j < n; j++) x[ipvt[j]] = wa1[j];
2389 
2390  // *** initialize the iteration counter.
2391  // evaluate the function at the origin, and test
2392  // for acceptance of the gauss-newton direction.
2393 
2394  int iter = 0;
2395  for (int j = 0; j < n; j++) wa2[j] = diag[j] * x[j];
2396 
2397  double dxnorm = lm_enorm(n, wa2);
2398  double fp = dxnorm - delta;
2399  const double kP1 = 0.1;
2400  if (fp <= kP1 * delta) {
2401 #if BUG
2402  printf("lmpar/ terminate (fp<delta/10\n");
2403 #endif
2404  *par = 0;
2405  return;
2406  }
2407 
2408  // *** if the jacobian is not rank deficient, the newton
2409  // step provides a lower bound, parl, for the 0. of
2410  // the function. otherwise set this bound to 0..
2411 
2412  double parl = 0.0;
2413  if (nsing >= n) {
2414  for (int j = 0; j < n; j++) wa1[j] = diag[ipvt[j]] * wa2[ipvt[j]] / dxnorm;
2415 
2416  for (int j = 0; j < n; j++) {
2417  double sum = 0.0;
2418  for (int i = 0; i < j; i++) sum += r[j * ldr + i] * wa1[i];
2419  wa1[j] = (wa1[j] - sum) / r[j + ldr * j];
2420  }
2421  const double temp = lm_enorm(n, wa1);
2422  parl = fp / delta / temp / temp;
2423  }
2424 
2425  // *** calculate an upper bound, paru, for the 0. of the function.
2426 
2427  for (int j = 0; j < n; j++) {
2428  double sum = 0;
2429  for (int i = 0; i <= j; i++) sum += r[j * ldr + i] * qtb[i];
2430  wa1[j] = sum / diag[ipvt[j]];
2431  }
2432  const double gnorm = lm_enorm(n, wa1);
2433  double paru =
2434  gnorm / delta == 0.0 ? LM_DWARF / MIN(delta, kP1) : gnorm / delta;
2435 
2436  // *** if the input par lies outside of the interval (parl,paru),
2437  // set par to the closer endpoint.
2438 
2439  *par = MAX(*par, parl);
2440  *par = MIN(*par, paru);
2441  if (*par == 0.) *par = gnorm / dxnorm;
2442 #if BUG
2443  printf("lmpar/ parl %.4e par %.4e paru %.4e\n", parl, *par, paru);
2444 #endif
2445 
2446  // *** iterate.
2447 
2448  for (;; iter++) {
2449  // *** evaluate the function at the current value of par.
2450  const double kP001 = 0.001;
2451  if (*par == 0.) *par = MAX(LM_DWARF, kP001 * paru);
2452  double temp = sqrt(*par);
2453  for (int j = 0; j < n; j++) wa1[j] = temp * diag[j];
2454  lm_qrsolv(n, r, ldr, ipvt, wa1, qtb, x, sdiag, wa2);
2455  for (int j = 0; j < n; j++) wa2[j] = diag[j] * x[j];
2456  dxnorm = lm_enorm(n, wa2);
2457  const double fp_old = fp;
2458  fp = dxnorm - delta;
2459 
2460  // *** if the function is small enough, accept the current value
2461  // of par. also test for the exceptional cases where parl
2462  // is 0. or the number of iterations has reached 10.
2463 
2464  if (fabs(fp) <= kP1 * delta ||
2465  (parl == 0. && fp <= fp_old && fp_old < 0.) || iter == 10)
2466  break; // the only exit from this loop
2467 
2468  // *** compute the Newton correction.
2469 
2470  for (int j = 0; j < n; j++) wa1[j] = diag[ipvt[j]] * wa2[ipvt[j]] / dxnorm;
2471 
2472  for (int j = 0; j < n; j++) {
2473  wa1[j] = wa1[j] / sdiag[j];
2474  for (int i = j + 1; i < n; i++) wa1[i] -= r[j * ldr + i] * wa1[j];
2475  }
2476  temp = lm_enorm(n, wa1);
2477  double parc = fp / delta / temp / temp;
2478 
2479  // *** depending on the sign of the function, update parl or paru.
2480 
2481  if (fp > 0)
2482  parl = MAX(parl, *par);
2483  else if (fp < 0)
2484  paru = MIN(paru, *par);
2485  // the case fp==0 is precluded by the break condition
2486 
2487  // *** compute an improved estimate for par.
2488 
2489  *par = MAX(parl, *par + parc);
2490  }
2491 }
2492 
2493 void lm_qrfac(int m, int n, double *a, int pivot, int *ipvt, double *rdiag,
2494  double *acnorm, double *wa) {
2495  /*
2496  * this subroutine uses householder transformations with column
2497  * pivoting (optional) to compute a qr factorization of the
2498  * m by n matrix a. that is, qrfac determines an orthogonal
2499  * matrix q, a permutation matrix p, and an upper trapezoidal
2500  * matrix r with diagonal elements of nonincreasing magnitude,
2501  * such that a*p = q*r. the householder transformation for
2502  * column k, k = 1,2,...,min(m,n), is of the form
2503  *
2504  * t
2505  * i - (1/u(k))*u*u
2506  *
2507  * where u has 0.s in the first k-1 positions. the form of
2508  * this transformation and the method of pivoting first
2509  * appeared in the corresponding linpack subroutine.
2510  *
2511  * parameters:
2512  *
2513  * m is a positive integer input variable set to the number
2514  * of rows of a.
2515  *
2516  * n is a positive integer input variable set to the number
2517  * of columns of a.
2518  *
2519  * a is an m by n array. on input a contains the matrix for
2520  * which the qr factorization is to be computed. on output
2521  * the strict upper trapezoidal part of a contains the strict
2522  * upper trapezoidal part of r, and the lower trapezoidal
2523  * part of a contains a factored form of q (the non-trivial
2524  * elements of the u vectors described above).
2525  *
2526  * pivot is a logical input variable. if pivot is set true,
2527  * then column pivoting is enforced. if pivot is set false,
2528  * then no column pivoting is done.
2529  *
2530  * ipvt is an integer output array of length lipvt. ipvt
2531  * defines the permutation matrix p such that a*p = q*r.
2532  * column j of p is column ipvt(j) of the identity matrix.
2533  * if pivot is false, ipvt is not referenced.
2534  *
2535  * rdiag is an output array of length n which contains the
2536  * diagonal elements of r.
2537  *
2538  * acnorm is an output array of length n which contains the
2539  * norms of the corresponding columns of the input matrix a.
2540  * if this information is not needed, then acnorm can coincide
2541  * with rdiag.
2542  *
2543  * wa is a work array of length n. if pivot is false, then wa
2544  * can coincide with rdiag.
2545  *
2546  */
2547 
2548  // *** compute the initial column norms and initialize several arrays.
2549 
2550  for (int j = 0; j < n; j++) {
2551  acnorm[j] = lm_enorm(m, &a[j * m]);
2552  rdiag[j] = acnorm[j];
2553  wa[j] = rdiag[j];
2554  if (pivot) ipvt[j] = j;
2555  }
2556 #if BUG
2557  printf("qrfac\n");
2558 #endif
2559 
2560  // *** reduce a to r with householder transformations.
2561 
2562  const int minmn = MIN(m, n);
2563  for (int j = 0; j < minmn; j++) {
2564  int kmax = j, k;
2565  if (!pivot) goto pivot_ok;
2566 
2567  // *** bring the column of largest norm into the pivot position.
2568 
2569  for (k = j + 1; k < n; k++)
2570  if (rdiag[k] > rdiag[kmax]) kmax = k;
2571  if (kmax == j) goto pivot_ok; // bug fixed in rel 2.1
2572 
2573  for (int i = 0; i < m; i++) {
2574  std::swap(a[j * m + i], a[kmax * m + i]);
2575  // const double temp = a[j*m+i];
2576  // a[j*m+i] = a[kmax*m+i];
2577  // a[kmax*m+i] = temp;
2578  }
2579  rdiag[kmax] = rdiag[j];
2580  wa[kmax] = wa[j];
2581  std::swap(ipvt[j], ipvt[kmax]);
2582  // k = ipvt[j];
2583  // ipvt[j] = ipvt[kmax];
2584  // ipvt[kmax] = k;
2585 
2586  pivot_ok:
2587 
2588  // *** compute the Householder transformation to reduce the
2589  // j-th column of a to a multiple of the j-th unit vector.
2590 
2591  double ajnorm = lm_enorm(m - j, &a[j * m + j]);
2592  if (ajnorm == 0.) {
2593  rdiag[j] = 0;
2594  continue;
2595  }
2596 
2597  if (a[j * m + j] < 0.) ajnorm = -ajnorm;
2598  for (int i = j; i < m; i++) a[j * m + i] /= ajnorm;
2599  a[j * m + j] += 1;
2600 
2601  // *** apply the transformation to the remaining columns
2602  // and update the norms.
2603 
2604  for (k = j + 1; k < n; k++) {
2605  double sum = 0;
2606 
2607  for (int i = j; i < m; i++) sum += a[j * m + i] * a[k * m + i];
2608 
2609  double temp = sum / a[j + m * j];
2610 
2611  for (int i = j; i < m; i++) a[k * m + i] -= temp * a[j * m + i];
2612 
2613  if (pivot && rdiag[k] != 0.) {
2614  temp = a[m * k + j] / rdiag[k];
2615  temp = MAX(0., 1 - temp * temp);
2616  rdiag[k] *= sqrt(temp);
2617  temp = rdiag[k] / wa[k];
2618  const double kP05 = 0.05;
2619  if (kP05 * SQR(temp) <= LM_MACHEP) {
2620  rdiag[k] = lm_enorm(m - j - 1, &a[m * k + j + 1]);
2621  wa[k] = rdiag[k];
2622  }
2623  }
2624  }
2625 
2626  rdiag[j] = -ajnorm;
2627  }
2628 }
2629 
2630 void lm_qrsolv(int n, double *r, int ldr, int *ipvt, double *diag, double *qtb,
2631  double *x, double *sdiag, double *wa) {
2632  /*
2633  * given an m by n matrix a, an n by n diagonal matrix d,
2634  * and an m-vector b, the problem is to determine an x which
2635  * solves the system
2636  *
2637  * a*x = b , d*x = 0 ,
2638  *
2639  * in the least squares sense.
2640  *
2641  * this subroutine completes the solution of the problem
2642  * if it is provided with the necessary information from the
2643  * qr factorization, with column pivoting, of a. that is, if
2644  * a*p = q*r, where p is a permutation matrix, q has orthogonal
2645  * columns, and r is an upper triangular matrix with diagonal
2646  * elements of nonincreasing magnitude, then qrsolv expects
2647  * the full upper triangle of r, the permutation matrix p,
2648  * and the first n components of (q transpose)*b. the system
2649  * a*x = b, d*x = 0, is then equivalent to
2650  *
2651  * t t
2652  * r*z = q *b , p *d*p*z = 0 ,
2653  *
2654  * where x = p*z. if this system does not have full rank,
2655  * then a least squares solution is obtained. on output qrsolv
2656  * also provides an upper triangular matrix s such that
2657  *
2658  * t t t
2659  * p *(a *a + d*d)*p = s *s .
2660  *
2661  * s is computed within qrsolv and may be of separate interest.
2662  *
2663  * parameters
2664  *
2665  * n is a positive integer input variable set to the order of r.
2666  *
2667  * r is an n by n array. on input the full upper triangle
2668  * must contain the full upper triangle of the matrix r.
2669  * on output the full upper triangle is unaltered, and the
2670  * strict lower triangle contains the strict upper triangle
2671  * (transposed) of the upper triangular matrix s.
2672  *
2673  * ldr is a positive integer input variable not less than n
2674  * which specifies the leading dimension of the array r.
2675  *
2676  * ipvt is an integer input array of length n which defines the
2677  * permutation matrix p such that a*p = q*r. column j of p
2678  * is column ipvt(j) of the identity matrix.
2679  *
2680  * diag is an input array of length n which must contain the
2681  * diagonal elements of the matrix d.
2682  *
2683  * qtb is an input array of length n which must contain the first
2684  * n elements of the vector (q transpose)*b.
2685  *
2686  * x is an output array of length n which contains the least
2687  * squares solution of the system a*x = b, d*x = 0.
2688  *
2689  * sdiag is an output array of length n which contains the
2690  * diagonal elements of the upper triangular matrix s.
2691  *
2692  * wa is a work array of length n.
2693  *
2694  */
2695 
2696  // *** copy r and (q transpose)*b to preserve input and initialize s.
2697  // in particular, save the diagonal elements of r in x.
2698 
2699  for (int j = 0; j < n; j++) {
2700  for (int i = j; i < n; i++) r[j * ldr + i] = r[i * ldr + j];
2701  x[j] = r[j * ldr + j];
2702  wa[j] = qtb[j];
2703  }
2704 #if BUG
2705  printf("qrsolv\n");
2706 #endif
2707 
2708  // *** eliminate the diagonal matrix d using a givens rotation.
2709 
2710  for (int j = 0; j < n; j++) {
2711  // *** prepare the row of d to be eliminated, locating the
2712  // diagonal element using p from the qr factorization.
2713 
2714  double qtbpj = 0.0;
2715 
2716  if (diag[ipvt[j]] == 0.) goto L90;
2717  for (int k = j; k < n; k++) sdiag[k] = 0.;
2718  sdiag[j] = diag[ipvt[j]];
2719 
2720  // *** the transformations to eliminate the row of d
2721  // modify only a single element of (q transpose)*b
2722  // beyond the first n, which is initially 0..
2723 
2724  for (int k = j; k < n; k++) {
2725  const double p25 = 0.25;
2726  const double p5 = 0.5;
2727 
2728  // determine a givens rotation which eliminates the
2729  // appropriate element in the current row of d.
2730 
2731  if (sdiag[k] == 0.) continue;
2732  const int kk = k + ldr * k; // <! keep this shorthand !>
2733  double sin, cos; // these are local variables, not functions
2734 
2735  if (fabs(r[kk]) < fabs(sdiag[k])) {
2736  const double cotan = r[kk] / sdiag[k];
2737  sin = p5 / sqrt(p25 + p25 * SQR(cotan));
2738  cos = sin * cotan;
2739  } else {
2740  const double tan = sdiag[k] / r[kk];
2741  cos = p5 / sqrt(p25 + p25 * SQR(tan));
2742  sin = cos * tan;
2743  }
2744 
2745  // *** compute the modified diagonal element of r and
2746  // the modified element of ((q transpose)*b,0).
2747 
2748  r[kk] = cos * r[kk] + sin * sdiag[k];
2749  double temp = cos * wa[k] + sin * qtbpj;
2750  qtbpj = -sin * wa[k] + cos * qtbpj;
2751  wa[k] = temp;
2752 
2753  // *** accumulate the transformation in the row of s.
2754 
2755  for (int i = k + 1; i < n; i++) {
2756  temp = cos * r[k * ldr + i] + sin * sdiag[i];
2757  sdiag[i] = -sin * r[k * ldr + i] + cos * sdiag[i];
2758  r[k * ldr + i] = temp;
2759  }
2760  }
2761  L90:
2762 
2763  // *** store the diagonal element of s and restore
2764  // the corresponding diagonal element of r.
2765 
2766  sdiag[j] = r[j * ldr + j];
2767  r[j * ldr + j] = x[j];
2768  }
2769 
2770  // *** solve the triangular system for z. if the system is
2771  // singular, then obtain a least squares solution.
2772 
2773  int nsing = n;
2774  for (int j = 0; j < n; j++) {
2775  if (sdiag[j] == 0. && nsing == n) nsing = j;
2776  if (nsing < n) wa[j] = 0;
2777  }
2778 
2779  for (int j = nsing - 1; j >= 0; j--) {
2780  double sum = 0.0;
2781  for (int i = j + 1; i < nsing; i++) sum += r[j * ldr + i] * wa[i];
2782  wa[j] = (wa[j] - sum) / sdiag[j];
2783  }
2784 
2785  // *** permute the components of z back to components of x.
2786 
2787  for (int j = 0; j < n; j++) x[ipvt[j]] = wa[j];
2788 }
2789 
2790 double lm_enorm(int n, double *x) {
2791  /* given an n-vector x, this function calculates the
2792  * euclidean norm of x.
2793  *
2794  * the euclidean norm is computed by accumulating the sum of
2795  * squares in three different sums. the sums of squares for the
2796  * small and large components are scaled so that no overflows
2797  * occur. non-destructive underflows are permitted. underflows
2798  * and overflows do not occur in the computation of the unscaled
2799  * sum of squares for the intermediate components.
2800  * the definitions of small, intermediate and large components
2801  * depend on two constants, LM_SQRT_DWARF and LM_SQRT_GIANT. the main
2802  * restrictions on these constants are that LM_SQRT_DWARF**2 not
2803  * underflow and LM_SQRT_GIANT**2 not overflow.
2804  *
2805  * parameters
2806  *
2807  * n is a positive integer input variable.
2808  *
2809  * x is an input array of length n.
2810  */
2811 
2812  double s1 = 0.0, s2 = 0.0, s3 = 0.0;
2813  double x1max = 0.0, x3max = 0.0;
2814  const double agiant = LM_SQRT_GIANT / ((double)n);
2815 
2816  for (int i = 0; i < n; i++) {
2817  double xabs = fabs(x[i]);
2818  if (xabs > LM_SQRT_DWARF && xabs < agiant) {
2819  // ** sum for intermediate components.
2820  s2 += xabs * xabs;
2821  continue;
2822  }
2823 
2824  if (xabs > LM_SQRT_DWARF) {
2825  // ** sum for large components.
2826  if (xabs > x1max) {
2827  s1 = 1 + s1 * SQR(x1max / xabs);
2828  x1max = xabs;
2829  } else {
2830  s1 += SQR(xabs / x1max);
2831  }
2832  continue;
2833  }
2834  // ** sum for small components.
2835  if (xabs > x3max) {
2836  s3 = 1 + s3 * SQR(x3max / xabs);
2837  x3max = xabs;
2838  } else {
2839  if (xabs != 0.) {
2840  s3 += SQR(xabs / x3max);
2841  }
2842  }
2843  }
2844 
2845  // *** calculation of norm.
2846 
2847  if (s1 != 0) return x1max * sqrt(s1 + (s2 / x1max) / x1max);
2848  if (s2 != 0) {
2849  if (s2 >= x3max) return sqrt(s2 * (1 + (x3max / s2) * (x3max * s3)));
2850  return sqrt(x3max * ((s2 / x3max) + (x3max * s3)));
2851  }
2852 
2853  return x3max * sqrt(s3);
2854 }
2855 
2856 double lat_gc_crosses_meridian(double lat1, double lon1, double lat2,
2857  double lon2, double lon) {
2858  /*
2859  Calculates a latitude at which a GC route between two points crosses a given
2860  meridian
2861  */
2862 
2863  double dlon = lon * DEGREE;
2864  double dlat1 = lat1 * DEGREE;
2865  double dlat2 = lat2 * DEGREE;
2866  double dlon1 = lon1 * DEGREE;
2867  double dlon2 = lon2 * DEGREE;
2868 
2869  return RADIAN * atan((sin(dlat1) * cos(dlat2) * sin(dlon - dlon2) -
2870  sin(dlat2) * cos(dlat1) * sin(dlon - dlon1)) /
2871  (cos(dlat1) * cos(dlat2) * sin(dlon1 - dlon2)));
2872 }
2873 
2874 double lat_rl_crosses_meridian(double lat1, double lon1, double lat2,
2875  double lon2, double lon) {
2876  /*
2877  Calculates a latitude at which a loxodromic route between two points crosses a
2878  given meridian
2879  */
2880 
2881  double brg;
2882 
2883  DistanceBearingMercator(lat2, lon2, lat1, lon1, &brg, NULL);
2884 
2885  double x1, y1, x;
2886  toSM(lat1, lon1, 0., lon, &x1, &y1);
2887  toSM(lat1, lon, 0., lon, &x, &y1);
2888 
2889  double dir = 1.0;
2890  if (brg >= 270.0) {
2891  brg -= 270.0;
2892  } else if (brg >= 180.) {
2893  brg = 270.0 - brg;
2894  dir = -1.0;
2895  } else if (brg >= 90.) {
2896  brg -= 90.0;
2897  dir = -1.0;
2898  } else {
2899  brg = 90.0 - brg;
2900  }
2901 
2902  double ydelta = fabs(x1) * tan(brg * DEGREE);
2903 
2904  double crosslat, crosslon;
2905  fromSM(x, y1 + dir * ydelta, 0., lon, &crosslat, &crosslon);
2906 
2907  return crosslat;
2908 }
Definition: georef.h:41
Definition: georef.h:55