20# pragma warning (disable: 4706)
23#if !defined(__cplusplus)
27static const double wgs84_a = 6378137, wgs84_f = 1/298.257223563;
29static int checkEquals(
double x,
double y,
double d) {
32 printf(
"checkEquals fails: %.7g != %.7g +/- %.7g\n", x, y, d);
36static int checkNaN(
double x) {
40 printf(
"checkNaN fails: %.7g\n", x);
44static const int ncases = 20;
45static const double testcases[20][12] = {
46 {35.60777, -139.44815, 111.098748429560326,
47 -11.17491, -69.95921, 129.289270889708762,
48 8935244.5604818305, 80.50729714281974, 6273170.2055303837,
49 0.16606318447386067, 0.16479116945612937, 12841384694976.432},
50 {55.52454, 106.05087, 22.020059880982801,
51 77.03196, 197.18234, 109.112041110671519,
52 4105086.1713924406, 36.892740690445894, 3828869.3344387607,
53 0.80076349608092607, 0.80101006984201008, 61674961290615.615},
54 {-21.97856, 142.59065, -32.44456876433189,
55 41.84138, 98.56635, -41.84359951440466,
56 8394328.894657671, 75.62930491011522, 6161154.5773110616,
57 0.24816339233950381, 0.24930251203627892, -6637997720646.717},
58 {-66.99028, 112.2363, 173.73491240878403,
59 -12.70631, 285.90344, 2.512956620913668,
60 11150344.2312080241, 100.278634181155759, 6289939.5670446687,
61 -0.17199490274700385, -0.17722569526345708, -121287239862139.744},
62 {-17.42761, 173.34268, -159.033557661192928,
63 -15.84784, 5.93557, -20.787484651536988,
64 16076603.1631180673, 144.640108810286253, 3732902.1583877189,
65 -0.81273638700070476, -0.81299800519154474, 97825992354058.708},
66 {32.84994, 48.28919, 150.492927788121982,
67 -56.28556, 202.29132, 48.113449399816759,
68 16727068.9438164461, 150.565799985466607, 3147838.1910180939,
69 -0.87334918086923126, -0.86505036767110637, -72445258525585.010},
70 {6.96833, 52.74123, 92.581585386317712,
71 -7.39675, 206.17291, 90.721692165923907,
72 17102477.2496958388, 154.147366239113561, 2772035.6169917581,
73 -0.89991282520302447, -0.89986892177110739, -1311796973197.995},
74 {-50.56724, -16.30485, -105.439679907590164,
75 -33.56571, -94.97412, -47.348547835650331,
76 6455670.5118668696, 58.083719495371259, 5409150.7979815838,
77 0.53053508035997263, 0.52988722644436602, 41071447902810.047},
78 {-58.93002, -8.90775, 140.965397902500679,
79 -8.91104, 133.13503, 19.255429433416599,
80 11756066.0219864627, 105.755691241406877, 6151101.2270708536,
81 -0.26548622269867183, -0.27068483874510741, -86143460552774.735},
82 {-68.82867, -74.28391, 93.774347763114881,
83 -50.63005, -8.36685, 34.65564085411343,
84 3956936.926063544, 35.572254987389284, 3708890.9544062657,
85 0.81443963736383502, 0.81420859815358342, -41845309450093.787},
86 {-10.62672, -32.0898, -86.426713286747751,
87 5.883, -134.31681, -80.473780971034875,
88 11470869.3864563009, 103.387395634504061, 6184411.6622659713,
89 -0.23138683500430237, -0.23155097622286792, 4198803992123.548},
90 {-21.76221, 166.90563, 29.319421206936428,
91 48.72884, 213.97627, 43.508671946410168,
92 9098627.3986554915, 81.963476716121964, 6299240.9166992283,
93 0.13965943368590333, 0.14152969707656796, 10024709850277.476},
94 {-19.79938, -174.47484, 71.167275780171533,
95 -11.99349, -154.35109, 65.589099775199228,
96 2319004.8601169389, 20.896611684802389, 2267960.8703918325,
97 0.93427001867125849, 0.93424887135032789, -3935477535005.785},
98 {-11.95887, -116.94513, 92.712619830452549,
99 4.57352, 7.16501, 78.64960934409585,
100 13834722.5801401374, 124.688684161089762, 5228093.177931598,
101 -0.56879356755666463, -0.56918731952397221, -9919582785894.853},
102 {-87.85331, 85.66836, -65.120313040242748,
103 66.48646, 16.09921, -4.888658719272296,
104 17286615.3147144645, 155.58592449699137, 2635887.4729110181,
105 -0.90697975771398578, -0.91095608883042767, 42667211366919.534},
106 {1.74708, 128.32011, -101.584843631173858,
107 -11.16617, 11.87109, -86.325793296437476,
108 12942901.1241347408, 116.650512484301857, 5682744.8413270572,
109 -0.44857868222697644, -0.44824490340007729, 10763055294345.653},
110 {-25.72959, -144.90758, -153.647468693117198,
111 -57.70581, -269.17879, -48.343983158876487,
112 9413446.7452453107, 84.664533838404295, 6356176.6898881281,
113 0.09492245755254703, 0.09737058264766572, 74515122850712.444},
114 {-41.22777, 122.32875, 14.285113402275739,
115 -7.57291, 130.37946, 10.805303085187369,
116 3812686.035106021, 34.34330804743883, 3588703.8812128856,
117 0.82605222593217889, 0.82572158200920196, -2456961531057.857},
118 {11.01307, 138.25278, 79.43682622782374,
119 6.62726, 247.05981, 103.708090215522657,
120 11911190.819018408, 107.341669954114577, 6070904.722786735,
121 -0.29767608923657404, -0.29785143390252321, 17121631423099.696},
122 {-29.47124, 95.14681, -163.779130441688382,
123 -27.46601, -69.15955, -15.909335945554969,
124 13487015.8381145492, 121.294026715742277, 5481428.9945736388,
125 -0.51527225545373252, -0.51556587964721788, 104679964020340.318}};
127static int testinverse() {
128 double lat1, lon1, azi1, lat2, lon2, azi2, s12, a12, m12, M12, M21, S12;
129 double azi1a, azi2a, s12a, a12a, m12a, M12a, M21a, S12a;
133 for (i = 0; i < ncases; ++i) {
134 lat1 = testcases[i][0]; lon1 = testcases[i][1]; azi1 = testcases[i][2];
135 lat2 = testcases[i][3]; lon2 = testcases[i][4]; azi2 = testcases[i][5];
136 s12 = testcases[i][6]; a12 = testcases[i][7]; m12 = testcases[i][8];
137 M12 = testcases[i][9]; M21 = testcases[i][10]; S12 = testcases[i][11];
138 a12a =
geod_geninverse(&g, lat1, lon1, lat2, lon2, &s12a, &azi1a, &azi2a,
139 &m12a, &M12a, &M21a, &S12a);
140 result += checkEquals(azi1, azi1a, 1e-13);
141 result += checkEquals(azi2, azi2a, 1e-13);
142 result += checkEquals(s12, s12a, 1e-8);
143 result += checkEquals(a12, a12a, 1e-13);
144 result += checkEquals(m12, m12a, 1e-8);
145 result += checkEquals(M12, M12a, 1e-15);
146 result += checkEquals(M21, M21a, 1e-15);
147 result += checkEquals(S12, S12a, 0.1);
152static int testdirect() {
153 double lat1, lon1, azi1, lat2, lon2, azi2, s12, a12, m12, M12, M21, S12;
154 double lat2a, lon2a, azi2a, a12a, m12a, M12a, M21a, S12a;
159 for (i = 0; i < ncases; ++i) {
160 lat1 = testcases[i][0]; lon1 = testcases[i][1]; azi1 = testcases[i][2];
161 lat2 = testcases[i][3]; lon2 = testcases[i][4]; azi2 = testcases[i][5];
162 s12 = testcases[i][6]; a12 = testcases[i][7]; m12 = testcases[i][8];
163 M12 = testcases[i][9]; M21 = testcases[i][10]; S12 = testcases[i][11];
165 &lat2a, &lon2a, &azi2a,
nullptr, &m12a, &M12a, &M21a, &S12a);
166 result += checkEquals(lat2, lat2a, 1e-13);
167 result += checkEquals(lon2, lon2a, 1e-13);
168 result += checkEquals(azi2, azi2a, 1e-13);
169 result += checkEquals(a12, a12a, 1e-13);
170 result += checkEquals(m12, m12a, 1e-8);
171 result += checkEquals(M12, M12a, 1e-15);
172 result += checkEquals(M21, M21a, 1e-15);
173 result += checkEquals(S12, S12a, 0.1);
178static int testarcdirect() {
179 double lat1, lon1, azi1, lat2, lon2, azi2, s12, a12, m12, M12, M21, S12;
180 double lat2a, lon2a, azi2a, s12a, m12a, M12a, M21a, S12a;
185 for (i = 0; i < ncases; ++i) {
186 lat1 = testcases[i][0]; lon1 = testcases[i][1]; azi1 = testcases[i][2];
187 lat2 = testcases[i][3]; lon2 = testcases[i][4]; azi2 = testcases[i][5];
188 s12 = testcases[i][6]; a12 = testcases[i][7]; m12 = testcases[i][8];
189 M12 = testcases[i][9]; M21 = testcases[i][10]; S12 = testcases[i][11];
191 &lat2a, &lon2a, &azi2a, &s12a, &m12a, &M12a, &M21a, &S12a);
192 result += checkEquals(lat2, lat2a, 1e-13);
193 result += checkEquals(lon2, lon2a, 1e-13);
194 result += checkEquals(azi2, azi2a, 1e-13);
195 result += checkEquals(s12, s12a, 1e-8);
196 result += checkEquals(m12, m12a, 1e-8);
197 result += checkEquals(M12, M12a, 1e-15);
198 result += checkEquals(M21, M21a, 1e-15);
199 result += checkEquals(S12, S12a, 0.1);
204static int GeodSolve0() {
205 double azi1, azi2, s12;
209 geod_inverse(&g, 40.6, -73.8, 49.01666667, 2.55, &s12, &azi1, &azi2);
210 result += checkEquals(azi1, 53.47022, 0.5e-5);
211 result += checkEquals(azi2, 111.59367, 0.5e-5);
212 result += checkEquals(s12, 5853226, 0.5);
216static int GeodSolve1() {
217 double lat2, lon2, azi2;
221 geod_direct(&g, 40.63972222, -73.77888889, 53.5, 5850e3,
222 &lat2, &lon2, &azi2);
223 result += checkEquals(lat2, 49.01467, 0.5e-5);
224 result += checkEquals(lon2, 2.56106, 0.5e-5);
225 result += checkEquals(azi2, 111.62947, 0.5e-5);
229static int GeodSolve2() {
231 double azi1, azi2, s12;
235 geod_inverse(&g, 0.07476, 0, -0.07476, 180, &s12, &azi1, &azi2);
236 result += checkEquals(azi1, 90.00078, 0.5e-5);
237 result += checkEquals(azi2, 90.00078, 0.5e-5);
238 result += checkEquals(s12, 20106193, 0.5);
239 geod_inverse(&g, 0.1, 0, -0.1, 180, &s12, &azi1, &azi2);
240 result += checkEquals(azi1, 90.00105, 0.5e-5);
241 result += checkEquals(azi2, 90.00105, 0.5e-5);
242 result += checkEquals(s12, 20106193, 0.5);
246static int GeodSolve4() {
252 geod_inverse(&g, 36.493349428792, 0, 36.49334942879201, .0000008,
253 &s12,
nullptr,
nullptr);
254 result += checkEquals(s12, 0.072, 0.5e-3);
258static int GeodSolve5() {
260 double lat2, lon2, azi2;
264 geod_direct(&g, 0.01777745589997, 30, 0, 10e6, &lat2, &lon2, &azi2);
265 result += checkEquals(lat2, 90, 0.5e-5);
267 result += checkEquals(lon2, -150, 0.5e-5);
268 result += checkEquals(fabs(azi2), 180, 0.5e-5);
270 result += checkEquals(lon2, 30, 0.5e-5);
271 result += checkEquals(azi2, 0, 0.5e-5);
276static int GeodSolve6() {
284 -88.202499451857, 179.981022032992859592,
285 &s12,
nullptr,
nullptr);
286 result += checkEquals(s12, 20003898.214, 0.5e-3);
288 -89.262080389218, 179.992207982775375662,
289 &s12,
nullptr,
nullptr);
290 result += checkEquals(s12, 20003925.854, 0.5e-3);
292 -89.333123580032997687, 179.99295812360148422,
293 &s12,
nullptr,
nullptr);
294 result += checkEquals(s12, 20003926.881, 0.5e-3);
298static int GeodSolve9() {
305 -56.320923501171, 179.664747671772880215,
306 &s12,
nullptr,
nullptr);
307 result += checkEquals(s12, 19993558.287, 0.5e-3);
311static int GeodSolve10() {
319 -52.784459512563990912, 179.634407464943777557,
320 &s12,
nullptr,
nullptr);
321 result += checkEquals(s12, 19991596.095, 0.5e-3);
325static int GeodSolve11() {
333 -48.52287673545898293, 179.599720456223079643,
334 &s12,
nullptr,
nullptr);
335 result += checkEquals(s12, 19989144.774, 0.5e-3);
339static int GeodSolve12() {
343 double azi1, azi2, s12;
348 result += checkEquals(azi1, 120.27, 1e-2);
349 result += checkEquals(azi2, 105.15, 1e-2);
350 result += checkEquals(s12, 266.7, 1e-1);
354static int GeodSolve14() {
356 double azi1, azi2, s12;
360 geod_inverse(&g, 0, 0, 1, nan(
"0"), &s12, &azi1, &azi2);
361 result += checkNaN(azi1);
362 result += checkNaN(azi2);
363 result += checkNaN(s12);
367static int GeodSolve15() {
375 nullptr,
nullptr,
nullptr,
nullptr, &S12);
376 result += checkEquals(S12, 23700, 0.5);
380static int GeodSolve17() {
382 double lat2, lon2, azi2;
389 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
390 result += checkEquals(lat2, -39, 1);
391 result += checkEquals(lon2, -254, 1);
392 result += checkEquals(azi2, -170, 1);
395 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
396 result += checkEquals(lat2, -39, 1);
397 result += checkEquals(lon2, -254, 1);
398 result += checkEquals(azi2, -170, 1);
399 geod_direct(&g, 40, -75, -10, 2e7, &lat2, &lon2, &azi2);
400 result += checkEquals(lat2, -39, 1);
401 result += checkEquals(lon2, 105, 1);
402 result += checkEquals(azi2, -170, 1);
404 result += checkEquals(lat2, -39, 1);
405 result += checkEquals(lon2, 105, 1);
406 result += checkEquals(azi2, -170, 1);
410static int GeodSolve26() {
417 nullptr,
nullptr,
nullptr, &S12);
418 result += checkEquals(S12, 49911046115.0, 0.5);
422static int GeodSolve28() {
429 a12 =
geod_gendirect(&g, 1, 2, 10, 0, 5e6,
nullptr,
nullptr,
nullptr,
430 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
431 result += checkEquals(a12, 48.55570690, 0.5e-8);
435static int GeodSolve33() {
439 double azi1, azi2, s12;
444 result += checkEquals(azi1, 90.00000, 0.5e-5);
445 result += checkEquals(azi2, 90.00000, 0.5e-5);
446 result += checkEquals(s12, 19926189, 0.5);
448 result += checkEquals(azi1, 55.96650, 0.5e-5);
449 result += checkEquals(azi2, 124.03350, 0.5e-5);
450 result += checkEquals(s12, 19980862, 0.5);
452 result += checkEquals(azi1, 0.00000, 0.5e-5);
453 result += checkEquals(fabs(azi2), 180.00000, 0.5e-5);
454 result += checkEquals(s12, 20003931, 0.5);
456 result += checkEquals(azi1, 0.00000, 0.5e-5);
457 result += checkEquals(fabs(azi2), 180.00000, 0.5e-5);
458 result += checkEquals(s12, 19893357, 0.5);
461 result += checkEquals(azi1, 90.00000, 0.5e-5);
462 result += checkEquals(azi2, 90.00000, 0.5e-5);
463 result += checkEquals(s12, 19994492, 0.5);
465 result += checkEquals(azi1, 0.00000, 0.5e-5);
466 result += checkEquals(fabs(azi2), 180.00000, 0.5e-5);
467 result += checkEquals(s12, 20106193, 0.5);
469 result += checkEquals(azi1, 0.00000, 0.5e-5);
470 result += checkEquals(fabs(azi2), 180.00000, 0.5e-5);
471 result += checkEquals(s12, 19994492, 0.5);
474 result += checkEquals(azi1, 90.00000, 0.5e-5);
475 result += checkEquals(azi2, 90.00000, 0.5e-5);
476 result += checkEquals(s12, 19994492, 0.5);
478 result += checkEquals(azi1, 90.00000, 0.5e-5);
479 result += checkEquals(azi2, 90.00000, 0.5e-5);
480 result += checkEquals(s12, 20106193, 0.5);
482 result += checkEquals(azi1, 33.02493, 0.5e-5);
483 result += checkEquals(azi2, 146.97364, 0.5e-5);
484 result += checkEquals(s12, 20082617, 0.5);
486 result += checkEquals(azi1, 0.00000, 0.5e-5);
487 result += checkEquals(fabs(azi2), 180.00000, 0.5e-5);
488 result += checkEquals(s12, 20027270, 0.5);
493static int GeodSolve55() {
496 double azi1, azi2, s12;
500 geod_inverse(&g, nan(
"0"), 0, 0, 90, &s12, &azi1, &azi2);
501 result += checkNaN(azi1);
502 result += checkNaN(azi2);
503 result += checkNaN(s12);
504 geod_inverse(&g, nan(
"0"), 0, 90, 9, &s12, &azi1, &azi2);
505 result += checkNaN(azi1);
506 result += checkNaN(azi2);
507 result += checkNaN(s12);
511static int GeodSolve59() {
513 double azi1, azi2, s12;
517 geod_inverse(&g, 5, 0.00000000000001, 10, 180, &s12, &azi1, &azi2);
518 result += checkEquals(azi1, 0.000000000000035, 1.5e-14);
519 result += checkEquals(azi2, 179.99999999999996, 1.5e-14);
520 result += checkEquals(s12, 18345191.174332713, 5e-9);
524static int GeodSolve61() {
526 double lat2, lon2, azi2;
534 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
535 result += checkEquals(lat2, 45.30632, 0.5e-5);
536 result += checkEquals(lon2, -180, 0.5e-5);
537 result += checkEquals(fabs(azi2), 180, 0.5e-5);
540 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
541 result += checkEquals(lat2, 45.30632, 0.5e-5);
542 result += checkEquals(lon2, -180, 0.5e-5);
543 result += checkEquals(fabs(azi2), 180, 0.5e-5);
547static int GeodSolve65() {
551 double lat2, lon2, azi2, s12, a12, m12, M12, M21, S12;
559 &lat2, &lon2, &azi2, &s12, &m12, &M12, &M21, &S12);
560 result += checkEquals(lat2, -60.23169, 0.5e-5);
561 result += checkEquals(lon2, -0.00000, 0.5e-5);
562 result += checkEquals(fabs(azi2), 180.00000, 0.5e-5);
563 result += checkEquals(s12, 10000000, 0.5);
564 result += checkEquals(a12, 90.06544, 0.5e-5);
565 result += checkEquals(m12, 6363636, 0.5);
566 result += checkEquals(M12, -0.0012834, 0.5e-7);
567 result += checkEquals(M21, 0.0013749, 0.5e-7);
568 result += checkEquals(S12, 0, 0.5);
570 &lat2, &lon2, &azi2, &s12, &m12, &M12, &M21, &S12);
571 result += checkEquals(lat2, -30.03547, 0.5e-5);
572 result += checkEquals(lon2, -180.00000, 0.5e-5);
573 result += checkEquals(azi2, -0.00000, 0.5e-5);
574 result += checkEquals(s12, 20000000, 0.5);
575 result += checkEquals(a12, 179.96459, 0.5e-5);
576 result += checkEquals(m12, 54342, 0.5);
577 result += checkEquals(M12, -1.0045592, 0.5e-7);
578 result += checkEquals(M21, -0.9954339, 0.5e-7);
579 result += checkEquals(S12, 127516405431022.0, 0.5);
583static int GeodSolve67() {
586 double lat2, lon2, azi2;
594 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
595 result += checkEquals(lat2, 4.96445, 0.5e-5);
596 result += checkEquals(lon2, -180.00000, 0.5e-5);
597 result += checkEquals(azi2, -0.00000, 0.5e-5);
599 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
600 result += checkEquals(lat2, -87.52461, 0.5e-5);
601 result += checkEquals(lon2, -0.00000, 0.5e-5);
602 result += checkEquals(azi2, -180.00000, 0.5e-5);
606static int GeodSolve71() {
608 double lat2, lon2, azi2;
615 result += checkEquals(lat2, 30.92625, 0.5e-5);
616 result += checkEquals(lon2, 37.54640, 0.5e-5);
617 result += checkEquals(azi2, 55.43104, 0.5e-5);
621static int GeodSolve73() {
627 double lat2, lon2, azi2;
632 &lat2, &lon2, &azi2);
633 result += checkEquals(lat2, 81.04623, 0.5e-5);
634 result += checkEquals(lon2, -170, 0.5e-5);
635 result += azi2 == 0 ? 0 : 1;
636 result += 1/azi2 > 0 ? 0 : 1;
641 double points[][2],
int N,
642 double* perimeter,
double* area) {
646 for (i = 0; i < N; ++i)
652 double points[][2],
int N,
657 for (i = 0; i < N; ++i)
662static int GeodSolve74() {
665 double a12, s12, azi1, azi2, m12, M12, M21, S12;
670 &s12, &azi1, &azi2, &m12, &M12, &M21, &S12);
671 result += checkEquals(azi1, 55.723110355, 5e-9);
672 result += checkEquals(azi2, 55.723515675, 5e-9);
673 result += checkEquals(s12, 39.527686385, 5e-9);
674 result += checkEquals(a12, 0.000355495, 5e-9);
675 result += checkEquals(m12, 39.527686385, 5e-9);
676 result += checkEquals(M12, 0.999999995, 5e-9);
677 result += checkEquals(M21, 0.999999995, 5e-9);
678 result += checkEquals(S12, 286698586.30197, 5e-4);
682static int GeodSolve76() {
685 double azi1, azi2, s12;
689 geod_inverse(&g, -(41+19/60.0), 174+49/60.0, 40+58/60.0, -(5+30/60.0),
691 result += checkEquals(azi1, 160.39137649664, 0.5e-11);
692 result += checkEquals(azi2, 19.50042925176, 0.5e-11);
693 result += checkEquals(s12, 19960543.857179, 0.5e-6);
697static int GeodSolve78() {
699 double azi1, azi2, s12;
703 geod_inverse(&g, 27.2, 0.0, -27.1, 179.5, &s12, &azi1, &azi2);
704 result += checkEquals(azi1, 45.82468716758, 0.5e-11);
705 result += checkEquals(azi2, 134.22776532670, 0.5e-11);
706 result += checkEquals(s12, 19974354.765767, 0.5e-6);
710static int GeodSolve80() {
714 double a12, s12, azi1, azi2, m12, M12, M21, S12;
721 nullptr, &M12, &M21,
nullptr);
722 result += checkEquals(M12, -0.00528427534, 0.5e-10);
723 result += checkEquals(M21, -0.00528427534, 0.5e-10);
726 nullptr, &M12, &M21,
nullptr);
727 result += checkEquals(M12, 1, 0.5e-10);
728 result += checkEquals(M21, 1, 0.5e-10);
731 &s12, &
azi1, &azi2, &m12, &M12, &M21, &S12);
732 result += checkEquals(a12, 0, 1e-13);
733 result += checkEquals(s12, 0, 1e-8);
734 result += checkEquals(
azi1, 180, 1e-13);
735 result += checkEquals(azi2, 180, 1e-13);
736 result += checkEquals(m12, 0, 1e-8);
737 result += checkEquals(M12, 1, 1e-15);
738 result += checkEquals(M21, 1, 1e-15);
739 result += checkEquals(S12, 0, 1e-10);
740 result += 1/a12 > 0 ? 0 : 1;
741 result += 1/s12 > 0 ? 0 : 1;
742 result += 1/m12 > 0 ? 0 : 1;
745 &s12, &
azi1, &azi2, &m12, &M12, &M21, &S12);
746 result += checkEquals(a12, 0, 1e-13);
747 result += checkEquals(s12, 0, 1e-8);
748 result += checkEquals(
azi1, 0, 1e-13);
749 result += checkEquals(azi2, 180, 1e-13);
750 result += checkEquals(m12, 0, 1e-8);
751 result += checkEquals(M12, 1, 1e-15);
752 result += checkEquals(M21, 1, 1e-15);
753 result += checkEquals(S12, 127516405431022.0, 0.5);
758 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
759 result += checkNaN(a12);
763static int GeodSolve84() {
767 double lat2, lon2, azi2, inf;
773 geod_direct(&g, 0, 0, 90, 0, &inf,
nullptr,
nullptr);
777 geod_direct(&g, 0, 0, 90, inf, &lat2, &lon2, &azi2);
778 result += checkNaN(lat2);
779 result += checkNaN(lon2);
780 result += checkNaN(azi2);
781 geod_direct(&g, 0, 0, 90, nan(
"0"), &lat2, &lon2, &azi2);
782 result += checkNaN(lat2);
783 result += checkNaN(lon2);
784 result += checkNaN(azi2);
785 geod_direct(&g, 0, 0, inf, 1000, &lat2, &lon2, &azi2);
786 result += checkNaN(lat2);
787 result += checkNaN(lon2);
788 result += checkNaN(azi2);
789 geod_direct(&g, 0, 0, nan(
"0"), 1000, &lat2, &lon2, &azi2);
790 result += checkNaN(lat2);
791 result += checkNaN(lon2);
792 result += checkNaN(azi2);
793 geod_direct(&g, 0, inf, 90, 1000, &lat2, &lon2, &azi2);
794 result += lat2 == 0 ? 0 : 1;
795 result += checkNaN(lon2);
796 result += azi2 == 90 ? 0 : 1;
797 geod_direct(&g, 0, nan(
"0"), 90, 1000, &lat2, &lon2, &azi2);
798 result += lat2 == 0 ? 0 : 1;
799 result += checkNaN(lon2);
800 result += azi2 == 90 ? 0 : 1;
801 geod_direct(&g, inf, 0, 90, 1000, &lat2, &lon2, &azi2);
802 result += checkNaN(lat2);
803 result += checkNaN(lon2);
804 result += checkNaN(azi2);
805 geod_direct(&g, nan(
"0"), 0, 90, 1000, &lat2, &lon2, &azi2);
806 result += checkNaN(lat2);
807 result += checkNaN(lon2);
808 result += checkNaN(azi2);
812static int GeodSolve92() {
816 double azi1, azi2, s12;
821 37.757540000000006, -122.47018,
822 37.75754, -122.470177,
824 result += checkEquals(azi1, 89.99999923, 1e-7 );
825 result += checkEquals(azi2, 90.00000106, 1e-7 );
826 result += checkEquals(s12, 0.264, 0.5e-3);
830static int Planimeter0() {
832 double pa[4][2] = {{89, 0}, {89, 90}, {89, 180}, {89, 270}};
833 double pb[4][2] = {{-89, 0}, {-89, 90}, {-89, 180}, {-89, 270}};
834 double pc[4][2] = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}};
835 double pd[3][2] = {{90, 0}, {0, 0}, {0, 90}};
837 double perimeter, area;
841 planimeter(&g, pa, 4, &perimeter, &area);
842 result += checkEquals(perimeter, 631819.8745, 1e-4);
843 result += checkEquals(area, 24952305678.0, 1);
845 planimeter(&g, pb, 4, &perimeter, &area);
846 result += checkEquals(perimeter, 631819.8745, 1e-4);
847 result += checkEquals(area, -24952305678.0, 1);
849 planimeter(&g, pc, 4, &perimeter, &area);
850 result += checkEquals(perimeter, 627598.2731, 1e-4);
851 result += checkEquals(area, 24619419146.0, 1);
853 planimeter(&g, pd, 3, &perimeter, &area);
854 result += checkEquals(perimeter, 30022685, 1);
855 result += checkEquals(area, 63758202715511.0, 1);
857 polylength(&g, pd, 3, &perimeter);
858 result += checkEquals(perimeter, 20020719, 1);
863static int Planimeter5() {
865 double points[3][2] = {{89, 0.1}, {89, 90.1}, {89, -179.9}};
867 double perimeter, area;
870 planimeter(&g, points, 3, &perimeter, &area);
871 result += checkEquals(perimeter, 539297, 1);
872 result += checkEquals(area, 12476152838.5, 1);
876static int Planimeter6() {
878 double pa[3][2] = {{9, -0.00000000000001}, {9, 180}, {9, 0}};
879 double pb[3][2] = {{9, 0.00000000000001}, {9, 0}, {9, 180}};
880 double pc[3][2] = {{9, 0.00000000000001}, {9, 180}, {9, 0}};
881 double pd[3][2] = {{9, -0.00000000000001}, {9, 0}, {9, 180}};
883 double perimeter, area;
887 planimeter(&g, pa, 3, &perimeter, &area);
888 result += checkEquals(perimeter, 36026861, 1);
889 result += checkEquals(area, 0, 1);
890 planimeter(&g, pb, 3, &perimeter, &area);
891 result += checkEquals(perimeter, 36026861, 1);
892 result += checkEquals(area, 0, 1);
893 planimeter(&g, pc, 3, &perimeter, &area);
894 result += checkEquals(perimeter, 36026861, 1);
895 result += checkEquals(area, 0, 1);
896 planimeter(&g, pd, 3, &perimeter, &area);
897 result += checkEquals(perimeter, 36026861, 1);
898 result += checkEquals(area, 0, 1);
902static int Planimeter12() {
904 double points[2][2] = {{66.562222222, 0}, {66.562222222, 180}};
906 double perimeter, area;
909 planimeter(&g, points, 2, &perimeter, &area);
910 result += checkEquals(perimeter, 10465729, 1);
911 result += checkEquals(area, 0, 1);
915static int Planimeter13() {
917 double points[6][2] = {{89,-360}, {89,-240}, {89,-120},
918 {89,0}, {89,120}, {89,240}};
920 double perimeter, area;
923 planimeter(&g, points, 6, &perimeter, &area);
924 result += checkEquals(perimeter, 1160741, 1);
925 result += checkEquals(area, 32415230256.0, 1);
929static int Planimeter15() {
934 double lat[] = {2, 1, 3},
lon[] = {1, 2, 3};
935 double area, s12, azi1;
936 double r = 18454562325.45119,
937 a0 = 510065621724088.5093;
944 result += checkEquals(area, r, 0.5);
946 result += checkEquals(area, r, 0.5);
948 result += checkEquals(area, -r, 0.5);
950 result += checkEquals(area, a0-r, 0.5);
953 result += checkEquals(area, r, 0.5);
955 result += checkEquals(area, r, 0.5);
957 result += checkEquals(area, -r, 0.5);
959 result += checkEquals(area, a0-r, 0.5);
962 result += checkEquals(area, r, 0.5);
964 result += checkEquals(area, r, 0.5);
966 result += checkEquals(area, -r, 0.5);
968 result += checkEquals(area, a0-r, 0.5);
970 result += checkEquals(area, r, 0.5);
974static int Planimeter19() {
984 result += area == 0 ? 0 : 1;
985 result += perim == 0 ? 0 : 1;
987 result += area == 0 ? 0 : 1;
988 result += perim == 0 ? 0 : 1;
990 result += checkNaN(area);
991 result += checkNaN(perim);
994 result += area == 0 ? 0 : 1;
995 result += perim == 0 ? 0 : 1;
998 result += perim == 0 ? 0 : 1;
1000 result += perim == 0 ? 0 : 1;
1002 result += checkNaN(perim);
1005 result += perim == 0 ? 0 : 1;
1008 result += checkEquals(perim, 1000, 1e-10);
1010 result += checkEquals(perim, 156876.149, 0.5e-3);
1014static int Planimeter21() {
1019 double area,
lat = 45,
1020 a = 39.2144607176828184218, s = 8420705.40957178156285,
1021 r = 39433884866571.4277,
1022 a0 = 510065621724088.5093;
1032 for (i = 3; i <= 4; ++i) {
1036 result += checkEquals(area, i*r, 0.5);
1038 result += checkEquals(area, i*r, 0.5);
1040 result += checkEquals(area, -i*r, 0.5);
1042 result += checkEquals(area, -i*r + a0, 0.5);
1044 result += checkEquals(area, i*r, 0.5);
1046 result += checkEquals(area, i*r, 0.5);
1048 result += checkEquals(area, -i*r, 0.5);
1050 result += checkEquals(area, -i*r + a0, 0.5);
1053 result += checkEquals(area, i*r, 0.5);
1055 result += checkEquals(area, i*r, 0.5);
1057 result += checkEquals(area, -i*r, 0.5);
1059 result += checkEquals(area, -i*r + a0, 0.5);
1064static int Planimeter29() {
1079 result += checkEquals(area, 1000000.0, 0.01);
1085 if ((i = testinverse())) {++n; printf(
"testinverse fail: %d\n", i);}
1086 if ((i = testdirect())) {++n; printf(
"testdirect fail: %d\n", i);}
1087 if ((i = testarcdirect())) {++n; printf(
"testarcdirect fail: %d\n", i);}
1088 if ((i = GeodSolve0())) {++n; printf(
"GeodSolve0 fail: %d\n", i);}
1089 if ((i = GeodSolve1())) {++n; printf(
"GeodSolve1 fail: %d\n", i);}
1090 if ((i = GeodSolve2())) {++n; printf(
"GeodSolve2 fail: %d\n", i);}
1091 if ((i = GeodSolve4())) {++n; printf(
"GeodSolve4 fail: %d\n", i);}
1092 if ((i = GeodSolve5())) {++n; printf(
"GeodSolve5 fail: %d\n", i);}
1093 if ((i = GeodSolve6())) {++n; printf(
"GeodSolve6 fail: %d\n", i);}
1094 if ((i = GeodSolve9())) {++n; printf(
"GeodSolve9 fail: %d\n", i);}
1095 if ((i = GeodSolve10())) {++n; printf(
"GeodSolve10 fail: %d\n", i);}
1096 if ((i = GeodSolve11())) {++n; printf(
"GeodSolve11 fail: %d\n", i);}
1097 if ((i = GeodSolve12())) {++n; printf(
"GeodSolve12 fail: %d\n", i);}
1098 if ((i = GeodSolve14())) {++n; printf(
"GeodSolve14 fail: %d\n", i);}
1099 if ((i = GeodSolve15())) {++n; printf(
"GeodSolve15 fail: %d\n", i);}
1100 if ((i = GeodSolve17())) {++n; printf(
"GeodSolve17 fail: %d\n", i);}
1101 if ((i = GeodSolve26())) {++n; printf(
"GeodSolve26 fail: %d\n", i);}
1102 if ((i = GeodSolve28())) {++n; printf(
"GeodSolve28 fail: %d\n", i);}
1103 if ((i = GeodSolve33())) {++n; printf(
"GeodSolve33 fail: %d\n", i);}
1104 if ((i = GeodSolve55())) {++n; printf(
"GeodSolve55 fail: %d\n", i);}
1105 if ((i = GeodSolve59())) {++n; printf(
"GeodSolve59 fail: %d\n", i);}
1106 if ((i = GeodSolve61())) {++n; printf(
"GeodSolve61 fail: %d\n", i);}
1107 if ((i = GeodSolve65())) {++n; printf(
"GeodSolve65 fail: %d\n", i);}
1108 if ((i = GeodSolve67())) {++n; printf(
"GeodSolve67 fail: %d\n", i);}
1109 if ((i = GeodSolve71())) {++n; printf(
"GeodSolve71 fail: %d\n", i);}
1110 if ((i = GeodSolve73())) {++n; printf(
"GeodSolve73 fail: %d\n", i);}
1111 if ((i = GeodSolve74())) {++n; printf(
"GeodSolve74 fail: %d\n", i);}
1112 if ((i = GeodSolve76())) {++n; printf(
"GeodSolve76 fail: %d\n", i);}
1113 if ((i = GeodSolve78())) {++n; printf(
"GeodSolve78 fail: %d\n", i);}
1114 if ((i = GeodSolve80())) {++n; printf(
"GeodSolve80 fail: %d\n", i);}
1115 if ((i = GeodSolve84())) {++n; printf(
"GeodSolve84 fail: %d\n", i);}
1116 if ((i = GeodSolve92())) {++n; printf(
"GeodSolve92 fail: %d\n", i);}
1117 if ((i = Planimeter0())) {++n; printf(
"Planimeter0 fail: %d\n", i);}
1118 if ((i = Planimeter5())) {++n; printf(
"Planimeter5 fail: %d\n", i);}
1119 if ((i = Planimeter6())) {++n; printf(
"Planimeter6 fail: %d\n", i);}
1120 if ((i = Planimeter12())) {++n; printf(
"Planimeter12 fail: %d\n", i);}
1121 if ((i = Planimeter13())) {++n; printf(
"Planimeter13 fail: %d\n", i);}
1122 if ((i = Planimeter15())) {++n; printf(
"Planimeter15 fail: %d\n", i);}
1123 if ((i = Planimeter19())) {++n; printf(
"Planimeter19 fail: %d\n", i);}
1124 if ((i = Planimeter21())) {++n; printf(
"Planimeter21 fail: %d\n", i);}
1125 if ((i = Planimeter29())) {++n; printf(
"Planimeter29 fail: %d\n", i);}
API for the geodesic routines in C.
double GEOD_DLL geod_gendirect(const struct geod_geodesic *g, double lat1, double lon1, double azi1, unsigned flags, double s12_a12, double *plat2, double *plon2, double *pazi2, double *ps12, double *pm12, double *pM12, double *pM21, double *pS12)
void GEOD_DLL geod_polygon_addedge(const struct geod_geodesic *g, struct geod_polygon *p, double azi, double s)
void GEOD_DLL geod_polygon_addpoint(const struct geod_geodesic *g, struct geod_polygon *p, double lat, double lon)
unsigned GEOD_DLL geod_polygon_testpoint(const struct geod_geodesic *g, const struct geod_polygon *p, double lat, double lon, int reverse, int sign, double *pA, double *pP)
void GEOD_DLL geod_init(struct geod_geodesic *g, double a, double f)
void GEOD_DLL geod_directline(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double azi1, double s12, unsigned caps)
void GEOD_DLL geod_inverse(const struct geod_geodesic *g, double lat1, double lon1, double lat2, double lon2, double *ps12, double *pazi1, double *pazi2)
unsigned GEOD_DLL geod_polygon_testedge(const struct geod_geodesic *g, const struct geod_polygon *p, double azi, double s, int reverse, int sign, double *pA, double *pP)
void GEOD_DLL geod_lineinit(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double azi1, unsigned caps)
unsigned GEOD_DLL geod_polygon_compute(const struct geod_geodesic *g, const struct geod_polygon *p, int reverse, int sign, double *pA, double *pP)
void GEOD_DLL geod_position(const struct geod_geodesicline *l, double s12, double *plat2, double *plon2, double *pazi2)
double GEOD_DLL geod_geninverse(const struct geod_geodesic *g, double lat1, double lon1, double lat2, double lon2, double *ps12, double *pazi1, double *pazi2, double *pm12, double *pM12, double *pM21, double *pS12)
double GEOD_DLL geod_genposition(const struct geod_geodesicline *l, unsigned flags, double s12_a12, double *plat2, double *plon2, double *pazi2, double *ps12, double *pm12, double *pM12, double *pM21, double *pS12)
void GEOD_DLL geod_direct(const struct geod_geodesic *g, double lat1, double lon1, double azi1, double s12, double *plat2, double *plon2, double *pazi2)
void GEOD_DLL geod_polygonarea(const struct geod_geodesic *g, double lats[], double lons[], int n, double *pA, double *pP)
void GEOD_DLL geod_inverseline(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double lat2, double lon2, unsigned caps)
void GEOD_DLL geod_polygon_init(struct geod_polygon *p, int polylinep)