~gpredict-team/gpredict/gpredict-packaging

« back to all changes in this revision

Viewing changes to src/locator.c

  • Committer: Jan Simon
  • Date: 2011-12-04 19:31:47 UTC
  • Revision ID: jan.simon@gmx.de-20111204193147-qhwjxglv1f4i4442
rules: added autogen. Updated translation files

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
 
/**
3
 
 * \file src/locator.c
4
 
 * \ingroup hamlib
5
 
 * \brief locator and bearing conversion interface
6
 
 * \author Stephane Fillod and the Hamlib Group
7
 
 * \date 2000-2006
8
 
 *
9
 
 *  Hamlib Interface - locator, bearing, and conversion calls
10
 
 */
11
 
 
12
 
/*
13
 
 *  Hamlib Interface - locator and bearing conversion calls
14
 
 *  Copyright (c) 2001-2009 by Stephane Fillod
15
 
 *  Copyright (c) 2003 by Nate Bargmann
16
 
 *  Copyright (c) 2003 by Dave Hines
17
 
 *
18
 
 *  Code to determine bearing and range was taken from the Great Circle,
19
 
 *  by S. R. Sampson, N5OWK.
20
 
 *  Ref: "Air Navigation", Air Force Manual 51-40, 1 February 1987
21
 
 *  Ref: "ARRL Satellite Experimenters Handbook", August 1990
22
 
 *
23
 
 *  Code to calculate distance and azimuth between two Maidenhead locators,
24
 
 *  taken from wwl, by IK0ZSN Mirko Caserta.
25
 
 *
26
 
 *  New bearing code added by N0NB was found at:
27
 
 *  http://williams.best.vwh.net/avform.htm#Crs
28
 
 *
29
 
 *
30
 
 *
31
 
 *   This library is free software; you can redistribute it and/or modify
32
 
 *   it under the terms of the GNU Library General Public License as
33
 
 *   published by the Free Software Foundation; either version 2 of
34
 
 *   the License, or (at your option) any later version.
35
 
 *
36
 
 *   This program is distributed in the hope that it will be useful,
37
 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
38
 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39
 
 *   GNU Library General Public License for more details.
40
 
 *
41
 
 *   You should have received a copy of the GNU Library General Public
42
 
 *   License along with this library; if not, write to the Free Software
43
 
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
44
 
 *
45
 
 */
46
 
 
47
 
/*! \page hamlib Hamlib general purpose API
48
 
 *
49
 
 *  Here are grouped some often used functions, like locator conversion
50
 
 *  routines.
51
 
 */
52
 
 
53
 
#ifdef HAVE_CONFIG_H
54
 
#include "build-config.h"
55
 
#endif
56
 
 
57
 
#include <stdio.h>
58
 
#include <stdlib.h>
59
 
#include <string.h>
60
 
#include <ctype.h>
61
 
#include <math.h>
62
 
 
63
 
 
64
 
#include "locator.h"
65
 
 
66
 
 
67
 
#ifndef DOC_HIDDEN
68
 
 
69
 
#define RADIAN  (180.0 / M_PI)
70
 
 
71
 
/* arc length for 1 degree, 60 Nautical Miles */
72
 
#define ARC_IN_KM 111.2
73
 
 
74
 
/* The following is contributed by Dave Hines M1CXW
75
 
 *
76
 
 * begin dph
77
 
 */
78
 
/*
79
 
 * These are the constants used when converting between Maidenhead grid
80
 
 * locators and longitude/latitude values. MAX_LOCATOR_PAIRS is the maximum
81
 
 * number of locator character pairs to convert. This number MUST NOT exceed
82
 
 * the number of pairs of values in loc_char_range[].
83
 
 * Setting MAX_LOCATOR_PAIRS to 3 will convert the currently defined 6
84
 
 * character locators. A value of 4 will convert the extended 8 character
85
 
 * locators described in section 3L of "The IARU region 1 VHF managers
86
 
 * handbook". Values of 5 and 6 will extent the format even more, to the
87
 
 * longest definition I have seen for locators, see
88
 
 *     http://www.btinternet.com/~g8yoa/geog/non-ra.html
89
 
 * Beware that there seems to be no universally accepted standard for 10 & 12
90
 
 * character locators.
91
 
 *
92
 
 * The ranges of characters which will be accepted by locator2longlat, and
93
 
 * generated by longlat2locator, are specified by the loc_char_range[] array.
94
 
 * This array may be changed without requiring any other code changes.
95
 
 *
96
 
 * For the fifth pair to range from aa to xx use:
97
 
 * const static int loc_char_range[] = { 18, 10, 24, 10, 24, 10 };
98
 
 *
99
 
 * For the fifth pair to range from aa to yy use:
100
 
 * const static int loc_char_range[] = { 18, 10, 24, 10, 25, 10 };
101
 
 *
102
 
 * MAX_LOCATOR_PAIRS now sets the limit locator2longlat() will convert and
103
 
 * sets the maximum length longlat2locator() will generate.  Each function
104
 
 * properly handles any value from 1 to 6 so MAX_LOCATOR_PAIRS should be
105
 
 * left at 6.  MIN_LOCATOR_PAIRS sets a floor on the shortest locator that
106
 
 * should be handled.  -N0NB
107
 
 */
108
 
const static int loc_char_range[] = { 18, 10, 24, 10, 24, 10 };
109
 
 
110
 
#define MAX_LOCATOR_PAIRS       6
111
 
#define MIN_LOCATOR_PAIRS       1
112
 
 
113
 
/* end dph */
114
 
 
115
 
#endif     /* !DOC_HIDDEN */
116
 
 
117
 
/**
118
 
 * \brief Convert DMS to decimal degrees
119
 
 * \param degrees     Degrees, whole degrees
120
 
 * \param minutes     Minutes, whole minutes
121
 
 * \param seconds     Seconds, decimal seconds
122
 
 * \param sw            South or West
123
 
 *
124
 
 *  Convert degree/minute/second angle to decimal degrees angle.
125
 
 *  \a degrees >360, \a minutes > 60, and \a seconds > 60.0 are allowed,
126
 
 *  but resulting angle won't be normalized.
127
 
 *
128
 
 *  When the variable sw is passed a value of 1, the returned decimal
129
 
 *  degrees value will be negative (south or west).  When passed a
130
 
 *  value of 0 the returned decimal degrees value will be positive
131
 
 *  (north or east).
132
 
 *
133
 
 * \return The angle in decimal degrees.
134
 
 *
135
 
 * \sa dec2dms()
136
 
 */
137
 
 
138
 
double dms2dec (int degrees, int minutes, double seconds, int sw) {
139
 
     double st;
140
 
 
141
 
     if (degrees < 0)
142
 
          degrees = abs(degrees);
143
 
     if (minutes < 0)
144
 
          minutes = abs(minutes);
145
 
     if (seconds < 0)
146
 
          seconds = fabs(seconds);
147
 
 
148
 
     st = (double)degrees + (double)minutes / 60. + seconds / 3600.;
149
 
 
150
 
     if (sw == 1)
151
 
          return -st;
152
 
     else
153
 
          return st;
154
 
}
155
 
 
156
 
/**
157
 
 * \brief Convert D M.MMM notation to decimal degrees
158
 
 * \param degrees     Degrees, whole degrees
159
 
 * \param minutes     Minutes, decimal minutes
160
 
 * \param sw            South or West
161
 
 *
162
 
 *  Convert a degrees, decimal minutes notation common on
163
 
 *  many GPS units to its decimal degrees value.
164
 
 *
165
 
 *  \a degrees > 360, \a minutes > 60.0 are allowed, but
166
 
 *  resulting angle won't be normalized.
167
 
 *
168
 
 *  When the variable sw is passed a value of 1, the returned decimal
169
 
 *  degrees value will be negative (south or west).  When passed a
170
 
 *  value of 0 the returned decimal degrees value will be positive
171
 
 *  (north or east).
172
 
 *
173
 
 * \return The angle in decimal degrees.
174
 
 *
175
 
 * \sa dec2dmmm()
176
 
 */
177
 
 
178
 
double dmmm2dec (int degrees, double minutes, int sw) {
179
 
     double st;
180
 
 
181
 
     if (degrees < 0)
182
 
          degrees = abs(degrees);
183
 
     if (minutes < 0)
184
 
          minutes = fabs(minutes);
185
 
 
186
 
     st = (double)degrees + minutes / 60.;
187
 
 
188
 
     if (sw == 1)
189
 
          return -st;
190
 
     else
191
 
          return st;
192
 
}
193
 
 
194
 
/**
195
 
 * \brief Convert decimal degrees angle into DMS notation
196
 
 * \param dec          Decimal degrees
197
 
 * \param degrees     Pointer for the calculated whole Degrees
198
 
 * \param minutes     Pointer for the calculated whole Minutes
199
 
 * \param seconds     Pointer for the calculated decimal Seconds
200
 
 * \param sw            Pointer for the calculated SW flag
201
 
 *
202
 
 *  Convert decimal degrees angle into its degree/minute/second
203
 
 *  notation.
204
 
 *
205
 
 *  When \a dec < -180 or \a dec > 180, the angle will be normalized
206
 
 *  within these limits and the sign set appropriately.
207
 
 *
208
 
 *  Upon return dec2dms guarantees 0 >= \a degrees <= 180,
209
 
 *  0 >= \a minutes < 60, and 0.0 >= \a seconds < 60.0.
210
 
 *
211
 
 *  When \a dec is < 0.0 \a sw will be set to 1.  When \a dec is
212
 
 *  >= 0.0 \a sw will be set to 0.  This flag allows the application
213
 
 *  to determine whether the DMS angle should be treated as negative
214
 
 *  (south or west).
215
 
 *
216
 
 * \retval -RIG_EINVAL if any of the pointers are NULL.
217
 
 * \retval RIG_OK if conversion went OK.
218
 
 *
219
 
 * \sa dms2dec()
220
 
 */
221
 
 
222
 
int dec2dms (double dec, int *degrees, int *minutes, double *seconds, int *sw) {
223
 
     int deg, min;
224
 
     double st;
225
 
 
226
 
     /* bail if NULL pointers passed */
227
 
     if (!degrees || !minutes || !seconds || !sw)
228
 
          return -RIG_EINVAL;
229
 
 
230
 
     /* reverse the sign if dec has a magnitude greater
231
 
      * than 180 and factor out multiples of 360.
232
 
      * e.g. when passed 270 st will be set to -90
233
 
      * and when passed -270 st will be set to 90.  If
234
 
      * passed 361 st will be set to 1, etc.  If passed
235
 
      * a value > -180 || < 180, value will be unchanged.
236
 
      */
237
 
     if (dec >= 0.0)
238
 
          st = fmod(dec + 180, 360) - 180;
239
 
     else
240
 
          st = fmod(dec - 180, 360) + 180;
241
 
 
242
 
     /* if after all of that st is negative, we want deg
243
 
      * to be negative as well except for 180 which we want
244
 
      * to be positive.
245
 
      */
246
 
     if (st < 0.0 && st != -180)
247
 
          *sw = 1;
248
 
     else
249
 
          *sw = 0;
250
 
 
251
 
     /* work on st as a positive value to remove a
252
 
      * bug introduced by the effect of floor() when
253
 
      * passed a negative value.  e.g. when passed
254
 
      * -96.8333 floor() returns -95!  Also avoids
255
 
      * a rounding error introduced on negative values.
256
 
      */
257
 
     st = fabs(st);
258
 
 
259
 
     deg = (int)floor(st);
260
 
     st  = 60. * (st - (double)deg);
261
 
     min = (int)floor(st);
262
 
     st  = 60. * (st - (double)min);
263
 
 
264
 
     *degrees = deg;
265
 
     *minutes = min;
266
 
     *seconds = st;
267
 
 
268
 
     return RIG_OK;
269
 
}
270
 
 
271
 
/**
272
 
 * \brief Convert a decimal angle into D M.MMM notation
273
 
 * \param dec          Decimal degrees
274
 
 * \param degrees     Pointer for the calculated whole Degrees
275
 
 * \param minutes     Pointer for the calculated decimal Minutes
276
 
 * \param sw            Pointer for the calculated SW flag
277
 
 *
278
 
 *  Convert a decimal angle into its degree, decimal minute
279
 
 *  notation common on many GPS units.
280
 
 *
281
 
 *  When passed a value < -180 or > 180, the value will be normalized
282
 
 *  within these limits and the sign set apropriately.
283
 
 *
284
 
 *  Upon return dec2dmmm guarantees 0 >= \a degrees <= 180,
285
 
 *  0.0 >= \a minutes < 60.0.
286
 
 *
287
 
 *  When \a dec is < 0.0 \a sw will be set to 1.  When \a dec is
288
 
 *  >= 0.0 \a sw will be set to 0.  This flag allows the application
289
 
 *  to determine whether the D M.MMM angle should be treated as negative
290
 
 *  (south or west).
291
 
 *
292
 
 * \retval -RIG_EINVAL if any of the pointers are NULL.
293
 
 * \retval RIG_OK if conversion went OK.
294
 
 *
295
 
 * \sa dmmm2dec()
296
 
 */
297
 
int dec2dmmm (double dec, int *degrees, double *minutes, int *sw) {
298
 
     int r, min;
299
 
     double sec;
300
 
 
301
 
     /* bail if NULL pointers passed */
302
 
     if (!degrees || !minutes || !sw)
303
 
          return -RIG_EINVAL;
304
 
 
305
 
     r = dec2dms(dec, degrees, &min, &sec, sw);
306
 
     if (r != RIG_OK)
307
 
          return r;
308
 
 
309
 
     *minutes = (double)min + sec / 60;
310
 
 
311
 
     return RIG_OK;
312
 
}
313
 
 
314
 
/**
315
 
 * \brief Convert Maidenhead grid locator to Longitude/Latitude
316
 
 * \param longitude     Pointer for the calculated Longitude
317
 
 * \param latitude     Pointer for the calculated Latitude
318
 
 * \param locator     The Maidenhead grid locator--2 through 12 char + nul string
319
 
 *
320
 
 *  Convert Maidenhead grid locator to Longitude/Latitude (decimal degrees).
321
 
 *  The locator should be in 2 through 12 chars long format.
322
 
 *  \a locator2longlat is case insensitive, however it checks for
323
 
 *  locator validity.
324
 
 *
325
 
 *  Decimal long/lat is computed to center of grid square, i.e. given
326
 
 *  EM19 will return coordinates equivalent to the southwest corner
327
 
 *  of EM19mm.
328
 
 *
329
 
 * \retval -RIG_EINVAL if locator exceeds RR99xx99xx99 or exceeds length
330
 
 *  limit--currently 1 to 6 lon/lat pairs.
331
 
 * \retval RIG_OK if conversion went OK.
332
 
 *
333
 
 * \bug The fifth pair ranges from aa to xx, there is another convention
334
 
 *  that ranges from aa to yy.  At some point both conventions should be
335
 
 *  supported.
336
 
 *
337
 
 * \sa longlat2locator()
338
 
 */
339
 
 
340
 
/* begin dph */
341
 
 
342
 
int locator2longlat (double *longitude, double *latitude, const char *locator) {
343
 
     int x_or_y, paircount;
344
 
     int locvalue, pair;
345
 
     int divisions;
346
 
     double xy[2], ordinate;
347
 
 
348
 
     /* bail if NULL pointers passed */
349
 
     if (!longitude || !latitude)
350
 
          return -RIG_EINVAL;
351
 
 
352
 
     paircount = strlen(locator) / 2;
353
 
 
354
 
     /* verify paircount is within limits */
355
 
     if (paircount > MAX_LOCATOR_PAIRS)
356
 
          paircount = MAX_LOCATOR_PAIRS;
357
 
     else if (paircount < MIN_LOCATOR_PAIRS)
358
 
          return -RIG_EINVAL;
359
 
 
360
 
     /* For x(=longitude) and y(=latitude) */
361
 
     for (x_or_y = 0;  x_or_y < 2;  ++x_or_y) {
362
 
          ordinate = -90.0;
363
 
          divisions = 1;
364
 
 
365
 
          for (pair = 0;  pair < paircount;  ++pair) {
366
 
               locvalue = locator[pair*2 + x_or_y];
367
 
 
368
 
               /* Value of digit or letter */
369
 
               locvalue -= (loc_char_range[pair] == 10) ? '0' :
370
 
                    (isupper(locvalue)) ? 'A' : 'a';
371
 
 
372
 
               /* Check range for non-letter/digit or out of range */
373
 
               if ((locvalue < 0) || (locvalue >= loc_char_range[pair]))
374
 
                    return -RIG_EINVAL;
375
 
 
376
 
               divisions *= loc_char_range[pair];
377
 
               ordinate += locvalue * 180.0 / divisions;
378
 
          }
379
 
          /* Center ordinate in the Maidenhead "square" or "subsquare" */
380
 
          ordinate += 90.0 / divisions;
381
 
 
382
 
          xy[x_or_y] = ordinate;
383
 
     }
384
 
 
385
 
     *longitude = xy[0] * 2.0;
386
 
     *latitude = xy[1];
387
 
 
388
 
     return RIG_OK;
389
 
}
390
 
/* end dph */
391
 
 
392
 
/**
393
 
 * \brief Convert longitude/latitude to Maidenhead grid locator
394
 
 * \param longitude     Longitude, decimal degrees
395
 
 * \param latitude     Latitude, decimal degrees
396
 
 * \param locator     Pointer for the Maidenhead Locator
397
 
 * \param pair_count     Precision expressed as lon/lat pairs in the locator
398
 
 *
399
 
 *  Convert longitude/latitude (decimal degrees) to Maidenhead grid locator.
400
 
 *  \a locator must point to an array at least \a pair_count * 2 char + '\\0'.
401
 
 *
402
 
 * \retval -RIG_EINVAL if \a locator is NULL or \a pair_count exceeds
403
 
 *  length limit.  Currently 1 to 6 lon/lat pairs.
404
 
 * \retval RIG_OK if conversion went OK.
405
 
 *
406
 
 * \bug \a locator is not tested for overflow.
407
 
 * \bug The fifth pair ranges from aa to yy, there is another convention
408
 
 *  that ranges from aa to xx.  At some point both conventions should be
409
 
 *  supported.
410
 
 *
411
 
 * \sa locator2longlat()
412
 
 */
413
 
 
414
 
/* begin dph */
415
 
int longlat2locator(double longitude, double latitude, char *locator, int pair_count) {
416
 
     int x_or_y, pair, locvalue, divisions;
417
 
     double square_size, ordinate;
418
 
 
419
 
     if (!locator)
420
 
          return -RIG_EINVAL;
421
 
 
422
 
     if (pair_count < MIN_LOCATOR_PAIRS || pair_count > MAX_LOCATOR_PAIRS)
423
 
          return -RIG_EINVAL;
424
 
 
425
 
     for (x_or_y = 0;  x_or_y < 2;  ++x_or_y) {
426
 
          ordinate = (x_or_y == 0) ? longitude / 2.0 : latitude;
427
 
          divisions = 1;
428
 
 
429
 
          /* The 1e-6 here guards against floating point rounding errors */
430
 
          ordinate = fmod(ordinate + 270.000001, 180.0);
431
 
          for (pair = 0;  pair < pair_count;  ++pair) {
432
 
               divisions *= loc_char_range[pair];
433
 
               square_size = 180.0 / divisions;
434
 
 
435
 
               locvalue = (int) (ordinate / square_size);
436
 
               ordinate -= square_size * locvalue;
437
 
               locvalue += (loc_char_range[pair] == 10) ? '0':'A';
438
 
               locator[pair * 2 + x_or_y] = locvalue;
439
 
          }
440
 
     }
441
 
     locator[pair_count * 2] = '\0';
442
 
 
443
 
     return RIG_OK;
444
 
}
445
 
 
446
 
/* end dph */
447
 
 
448
 
/**
449
 
 * \brief Calculate the distance and bearing between two points.
450
 
 * \param lon1          The local Longitude, decimal degrees
451
 
 * \param lat1          The local Latitude, decimal degrees
452
 
 * \param lon2          The remote Longitude, decimal degrees
453
 
 * \param lat2          The remote Latitude, decimal degrees
454
 
 * \param distance     Pointer for the distance, km
455
 
 * \param azimuth     Pointer for the bearing, decimal degrees
456
 
 *
457
 
 *  Calculate the QRB between \a lon1, \a lat1 and \a lon2, \a lat2.
458
 
 *
459
 
 *     This version will calculate the QRB to a precision sufficient
460
 
 *     for 12 character locators.  Antipodal points, which are easily
461
 
 *     calculated, are considered equidistant and the bearing is
462
 
 *     simply resolved to be true north (0.0).
463
 
 *
464
 
 * \retval -RIG_EINVAL if NULL pointer passed or lat and lon values
465
 
 * exceed -90 to 90 or -180 to 180.
466
 
 * \retval RIG_OK if calculations are successful.
467
 
 *
468
 
 * \return The distance in kilometers and azimuth in decimal degrees
469
 
 *  for the short path are stored in \a distance and \a azimuth.
470
 
 *
471
 
 * \sa distance_long_path(), azimuth_long_path()
472
 
 */
473
 
int  qrb (double lon1, double lat1, double lon2, double lat2,
474
 
       double *distance, double *azimuth) 
475
 
{
476
 
 
477
 
     double delta_long, tmp, arc, az;
478
 
 
479
 
     /* bail if NULL pointers passed */
480
 
     if (!distance || !azimuth)
481
 
          return -RIG_EINVAL;
482
 
 
483
 
     if ((lat1 > 90.0 || lat1 < -90.0) || (lat2 > 90.0 || lat2 < -90.0))
484
 
          return -RIG_EINVAL;
485
 
 
486
 
     if ((lon1 > 180.0 || lon1 < -180.0) || (lon2 > 180.0 || lon2 < -180.0))
487
 
          return -RIG_EINVAL;
488
 
 
489
 
     /* Prevent ACOS() Domain Error */
490
 
     if (lat1 == 90.0)
491
 
          lat1 = 89.999999999;
492
 
     else if (lat1 == -90.0)
493
 
          lat1 = -89.999999999;
494
 
 
495
 
     if (lat2 == 90.0)
496
 
          lat2 = 89.999999999;
497
 
     else if (lat2 == -90.0)
498
 
          lat2 = -89.999999999;
499
 
 
500
 
     /* Convert variables to Radians */
501
 
     lat1     /= RADIAN;
502
 
     lon1     /= RADIAN;
503
 
     lat2     /= RADIAN;
504
 
     lon2     /= RADIAN;
505
 
 
506
 
     delta_long = lon2 - lon1;
507
 
 
508
 
     tmp = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(delta_long);
509
 
 
510
 
     if (tmp > .999999999999999) {
511
 
          /* Station points coincide, use an Omni! */
512
 
          *distance = 0.0;
513
 
          *azimuth = 0.0;
514
 
          return RIG_OK;
515
 
     }
516
 
 
517
 
     if (tmp < -.999999) {
518
 
          /*
519
 
           * points are antipodal, it's straight down.
520
 
           * Station is equal distance in all Azimuths.
521
 
           * So take 180 Degrees of arc times 60 nm,
522
 
           * and you get 10800 nm, or whatever units...
523
 
           */
524
 
          *distance = 180.0 * ARC_IN_KM;
525
 
          *azimuth = 0.0;
526
 
          return RIG_OK;
527
 
     }
528
 
 
529
 
     arc = acos(tmp);
530
 
 
531
 
     /*
532
 
      * One degree of arc is 60 Nautical miles
533
 
      * at the surface of the earth, 111.2 km, or 69.1 sm
534
 
      * This method is easier than the one in the handbook
535
 
      */
536
 
 
537
 
     /* Short Path */
538
 
     *distance = ARC_IN_KM * RADIAN * arc;
539
 
 
540
 
     /* This formula seems to work with very small distances
541
 
      *
542
 
      * I found it on the Web at:
543
 
      * http://williams.best.vwh.net/avform.htm#Crs
544
 
      *
545
 
      * Strangely, all the computed values were negative thus the
546
 
      * sign reversal below.
547
 
      * - N0NB
548
 
      */
549
 
     az = RADIAN * fmod(atan2(sin(lon1 - lon2) * cos(lat2),
550
 
                     cos(lat1) * sin(lat2) - sin(lat1) *
551
 
                     cos(lat2) * cos(lon1 - lon2)), 2 * M_PI);
552
 
 
553
 
     if (lon1 > lon2) {
554
 
          az -= 360.;
555
 
          *azimuth = -az;
556
 
     } else {
557
 
          if (az >= 0.0)
558
 
               *azimuth = az;
559
 
          else
560
 
               *azimuth = -az;
561
 
     }
562
 
 
563
 
     return RIG_OK;
564
 
}
565
 
 
566
 
/**
567
 
 * \brief Calculate the long path distance between two points.
568
 
 * \param distance     The shortpath distance
569
 
 *
570
 
 *  Calculate the long path (respective of the short path)
571
 
 *  of a given distance.
572
 
 *
573
 
 * \return the distance in kilometers for the opposite path.
574
 
 *
575
 
 * \sa qrb()
576
 
 */
577
 
 
578
 
double distance_long_path (double distance) {
579
 
     return (ARC_IN_KM * 360.0) - distance;
580
 
}
581
 
 
582
 
/**
583
 
 * \brief Calculate the long path bearing between two points.
584
 
 * \param azimuth     The shortpath bearing
585
 
 *
586
 
 *  Calculate the long path (respective of the short path)
587
 
 *  of a given bearing.
588
 
 *
589
 
 * \return the azimuth in decimal degrees for the opposite path.
590
 
 *
591
 
 * \sa qrb()
592
 
 */
593
 
 
594
 
double azimuth_long_path (double azimuth) {
595
 
     return 360.0 - azimuth;
596
 
}