diff --git a/include/hamlib/rotator.h b/include/hamlib/rotator.h index 34df86ec6..3b6943294 100644 --- a/include/hamlib/rotator.h +++ b/include/hamlib/rotator.h @@ -2,7 +2,7 @@ * Hamlib Interface - Rotator API header * Copyright (c) 2000-2003 by Stephane Fillod * - * $Id: rotator.h,v 1.10 2003-09-12 03:15:18 n0nb Exp $ + * $Id: rotator.h,v 1.11 2003-11-03 04:26:37 n0nb Exp $ * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -339,15 +339,15 @@ extern HAMLIB_EXPORT(int) longlat2locator HAMLIB_PARAMS((double longitude, extern HAMLIB_EXPORT(int) locator2longlat HAMLIB_PARAMS((double *longitude, double *latitude, const char *locator)); -extern HAMLIB_EXPORT(double) dms2dec HAMLIB_PARAMS((float degrees, double minutes, - double seconds)); -extern HAMLIB_EXPORT(int) dec2dms HAMLIB_PARAMS((double dec, float *degrees, - double *minutes, double *seconds)); +extern HAMLIB_EXPORT(double) dms2dec HAMLIB_PARAMS((int degrees, int minutes, + double seconds, int sw)); +extern HAMLIB_EXPORT(int) dec2dms HAMLIB_PARAMS((double dec, int *degrees, + int *minutes, double *seconds, int *sw)); -extern HAMLIB_EXPORT(int) dec2dmmm HAMLIB_PARAMS((double dec, float *degrees, - double *minutes)); -extern HAMLIB_EXPORT(double) dmmm2dec HAMLIB_PARAMS((float degrees, - double minutes)); +extern HAMLIB_EXPORT(int) dec2dmmm HAMLIB_PARAMS((double dec, int *degrees, + double *minutes, int *sw)); +extern HAMLIB_EXPORT(double) dmmm2dec HAMLIB_PARAMS((int degrees, + double minutes, int sw)); /*! \def rot_debug * \brief Convenience definition for debug level. diff --git a/src/locator.c b/src/locator.c index f43bb4485..12a0d63fd 100644 --- a/src/locator.c +++ b/src/locator.c @@ -14,7 +14,7 @@ * Copyright (c) 2003 by Nate Bargmann * Copyright (c) 2003 by Dave Hines * - * $Id: locator.c,v 1.12 2003-10-28 01:01:05 n0nb Exp $ + * $Id: locator.c,v 1.13 2003-11-03 04:26:37 n0nb Exp $ * * Code to determine bearing and range was taken from the Great Circle, * by S. R. Sampson, N5OWK. @@ -110,29 +110,48 @@ const static int loc_char_range[] = { 18, 10, 24, 10, 25, 10 }; * \param degrees Degrees * \param minutes Minutes * \param seconds Seconds + * \param sw South or West * * Convert degree/minute/second angle to decimal degrees angle. * \a degrees >360, \a minutes > 60, and \a seconds > 60 are allowed, * but resulting angle won't be normalized. * + * When the variable sw is passed a value of 1, the returned decimal + * degrees value will be negative (south or west). When passed a + * value of 0 the returned decimal degrees value will be positive + * (north or east). + * * \return The angle in decimal degrees. * * \sa dec2dms() */ -double dms2dec(float degrees, double minutes, double seconds) { - double s, st; +double dms2dec(int degrees, int minutes, double seconds, int sw) { + double st; - s = copysign(1.0, (double)degrees); - st = fabs((double)degrees); +// s = copysign(1.0, (double)degrees); +// st = fabs((double)degrees); - return copysign((st + minutes / 60. + seconds / 3600.), s); + if (degrees < 0) + degrees = abs(degrees); + if (minutes < 0) + minutes = abs(minutes); + if (seconds < 0) + seconds = fabs(seconds); + + st = (double)degrees + (double)minutes / 60. + seconds / 3600.; + + if (sw == 1) + return -st; + else + return st; } /** * \brief Convert D M.MMM notation to decimal degrees * \param degrees Degrees * \param minutes Minutes + * \param sw South or West * * Convert a degrees, decimal minutes notation common on * many GPS units to its decimal degrees value. @@ -140,21 +159,39 @@ double dms2dec(float degrees, double minutes, double seconds) { * \a degrees > 360, \a minutes > 60 are allowed, but * resulting angle won't be normalized. * + * When the variable sw is passed a value of 1, the returned decimal + * degrees value will be negative (south or west). When passed a + * value of 0 the returned decimal degrees value will be positive + * (north or east). + * * \return The angle in decimal degrees. * * \sa dec2dmmm() */ -double dmmm2dec(float degrees, double minutes) { - return dms2dec(degrees, minutes, 0.0); +double dmmm2dec(int degrees, double minutes, int sw) { + double st; + + if (degrees < 0) + degrees = abs(degrees); + if (minutes < 0) + minutes = fabs(minutes); + + st = (double)degrees + minutes / 60.; + + if (sw == 1) + return -st; + else + return st; } /** * \brief Convert decimal degrees angle into DMS notation * \param dec Decimal angle - * \param degrees The location where to store the degrees - * \param minutes The location where to store the minutes - * \param seconds The location where to store the seconds + * \param degrees The address of the degrees + * \param minutes The address of the minutes + * \param seconds The address of the seconds + * \param sw The address of the sw flag * * Convert decimal degrees angle into its degree/minute/second * notation. @@ -162,6 +199,9 @@ double dmmm2dec(float degrees, double minutes) { * When \a dec < -180 or \a dec > 180, the angle will be normalized * within these limits and the sign set appropriately. * + * When \a dec is < 0 \a sw will be set to 1. When \a dec is + * >= 0 \a sw will be set to 0. + * * Upon return dec2dms guarantees -180 <= \a degrees < 180, * 0 <= \a minutes < 60, and 0 <= \a seconds < 60. * @@ -171,13 +211,13 @@ double dmmm2dec(float degrees, double minutes) { * \sa dms2dec() */ -int dec2dms(double dec, float *degrees, double *minutes, double *seconds) { - int s = 0; - float deg; - double st, min; +int dec2dms(double dec, int *degrees, int *minutes, double *seconds, int *sw) { +// int s = 0; + int deg, min; + double st; /* bail if NULL pointers passed */ - if (!degrees || !minutes || !seconds) + if (!degrees || !minutes || !seconds || !sw) return -RIG_EINVAL; /* reverse the sign if dec has a magnitude greater @@ -197,7 +237,9 @@ int dec2dms(double dec, float *degrees, double *minutes, double *seconds) { * to be positive. */ if (st < 0.0 && st != -180) - s = 1; + *sw = 1; + else + *sw = 0; /* work on st as a positive value to remove a * bug introduced by the effect of floor() when @@ -207,14 +249,15 @@ int dec2dms(double dec, float *degrees, double *minutes, double *seconds) { */ st = fabs(st); - deg = (float)floor(st); + deg = (int)floor(st); st = 60. * (st - (double)deg); - min = floor(st); - st = 60. * (st - min); + min = (int)floor(st); + st = 60. * (st - (double)min); /* set *degrees to sign determined by fmod() */ - (s == 1) ? (*degrees = -deg) : (*degrees = deg); +// (s == 1) ? (*degrees = -deg) : (*degrees = deg); + *degrees = deg; *minutes = min; *seconds = st; @@ -224,8 +267,9 @@ int dec2dms(double dec, float *degrees, double *minutes, double *seconds) { /** * \brief Convert a decimal angle into D M.MMM notation * \param dec Decimal angle - * \param degrees The location where to store the degrees - * \param minutes The location where to store the minutes + * \param degrees The address of the degrees + * \param minutes The address of the minutes + * \param sw The address of the sw flag * * Convert a decimal angle into its degree, decimal minute * notation common on many GPS units. @@ -233,6 +277,9 @@ int dec2dms(double dec, float *degrees, double *minutes, double *seconds) { * When passed a value < -180 or > 180, the value will be normalized * within these limits and the sign set apropriately. * + * When \a dec is < 0 \a sw will be set to 1. When \a dec is + * >= 0 \a sw will be set to 0. + * * Upon return dec2dmmm guarantees -180 <= \a degrees < 180, * 0 <= \a minutes < 60. * @@ -242,19 +289,19 @@ int dec2dms(double dec, float *degrees, double *minutes, double *seconds) { * \sa dmmm2dec() */ -int dec2dmmm(double dec, float *degrees, double *minutes) { - int r; - double min, sec; +int dec2dmmm(double dec, int *degrees, double *minutes, int *sw) { + int r, min; + double sec; /* bail if NULL pointers passed */ - if (!degrees || !minutes) + if (!degrees || !minutes || !sw) return -RIG_EINVAL; - r = dec2dms(dec, degrees, &min, &sec); + r = dec2dms(dec, degrees, &min, &sec, sw); if (r != RIG_OK) return r; - *minutes = min + sec / 60; + *minutes = (double)min + sec / 60; return RIG_OK; } @@ -419,8 +466,8 @@ int longlat2locator(double longitude, double latitude, int qrb(double lon1, double lat1, double lon2, double lat2, double *distance, double *azimuth) { - double delta_long, tmp, arc, cosaz, az; - double a, c, dlon, dlat; + double delta_long, tmp, arc, az; +// double cosaz, a, c, dlon, dlat; /* bail if NULL pointers passed */ if (!distance || !azimuth) @@ -531,11 +578,14 @@ int qrb(double lon1, double lat1, double lon2, double lat2, az = RADIAN * fmod(atan2(sin(lon1 - lon2) * cos(lat2), cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon1 - lon2)), 2 * M_PI); if (lon1 > lon2) { - az -= 360; + az -= 360.; *azimuth = -az; - } else - *azimuth = -az; - + } else { + if (az >= 0.0) + *azimuth = az; + else + *azimuth = -az; + } return RIG_OK; } diff --git a/tests/testloc.c b/tests/testloc.c index 6084f4bc4..aec83045d 100644 --- a/tests/testloc.c +++ b/tests/testloc.c @@ -8,7 +8,7 @@ * to >= 1 or <= 6. If two locators are given, then the qrb is also * calculated. * - * $Id: testloc.c,v 1.10 2003-10-28 01:01:06 n0nb Exp $ + * $Id: testloc.c,v 1.11 2003-11-03 04:26:37 n0nb Exp $ * */ @@ -18,11 +18,10 @@ int main (int argc, char *argv[]) { - char recodedloc[13], *loc1, *loc2; + char recodedloc[13], *loc1, *loc2, sign; double lon1, lat1, lon2, lat2; - double distance, az, min, sec; - float deg; - int retcode, loc_len; + double distance, az, mmm, sec; + int deg, min, retcode, loc_len, nesw = 0; if (argc < 3) { fprintf(stderr, "Usage: %s []\n", argv[0]); @@ -43,51 +42,67 @@ int main (int argc, char *argv[]) { } /* hamlib function to convert decimal degrees to deg, min, sec */ - retcode = dec2dms(lon1, °, &min, &sec); + retcode = dec2dms(lon1, °, &min, &sec, &nesw); if (retcode != RIG_OK) { fprintf(stderr, "dec2dms() failed, invalid paramter address.\n"); exit(2); } - printf(" Longitude:\t%f\t%.0f° %.0f' %.2f\"\n", lon1, deg, min, sec); + if (nesw == 1) + sign = '-'; + else + sign = '\0'; + printf(" Longitude:\t%f\t%c%d° %d' %.2f\"\n", lon1, sign, deg, min, sec); /* hamlib function to convert deg, min, sec to decimal degrees */ - lon1 = dms2dec(deg, min, sec); + lon1 = dms2dec(deg, min, sec, nesw); printf(" Recoded lon:\t%f\n", lon1); /* hamlib function to convert decimal degrees to deg decimal minutes */ - retcode = dec2dmmm(lon1, °, &min); + retcode = dec2dmmm(lon1, °, &mmm, &nesw); if (retcode != RIG_OK) { fprintf(stderr, "dec2dmmm() failed, invalid paramter address.\n"); exit(2); } - printf(" GPS lon:\t%f\t%.0f° %.3f'\n", lon1, deg, min); + if (nesw == 1) + sign = '-'; + else + sign = '\0'; + printf(" GPS lon:\t%f\t%c%d° %.3f'\n", lon1, sign, deg, mmm); /* hamlib function to convert deg, decimal min to decimal degrees */ - lon1 = dmmm2dec(deg, min); + lon1 = dmmm2dec(deg, mmm, nesw); printf(" Recoded GPS:\t%f\n", lon1); /* hamlib function to convert decimal degrees to deg, min, sec */ - retcode = dec2dms(lat1, °, &min, &sec); + retcode = dec2dms(lat1, °, &min, &sec, &nesw); if (retcode != RIG_OK) { fprintf(stderr, "dec2dms() failed, invalid paramter address.\n"); exit(2); } - printf(" Latitude:\t%f\t%.0f° %.0f' %.2f\"\n", lat1, deg, min, sec); + if (nesw == 1) + sign = '-'; + else + sign = '\0'; + printf(" Latitude:\t%f\t%c%d° %d' %.2f\"\n", lat1, sign, deg, min, sec); /* hamlib function to convert deg, min, sec to decimal degrees */ - lat1 = dms2dec(deg, min, sec); + lat1 = dms2dec(deg, min, sec, nesw); printf(" Recoded lat:\t%f\n", lat1); /* hamlib function to convert decimal degrees to deg decimal minutes */ - retcode = dec2dmmm(lat1, °, &min); + retcode = dec2dmmm(lat1, °, &mmm, &nesw); if (retcode != RIG_OK) { fprintf(stderr, "dec2dmmm() failed, invalid paramter address.\n"); exit(2); } - printf(" GPS lat:\t%f\t%.0f° %.3f'\n", lat1, deg, min); + if (nesw == 1) + sign = '-'; + else + sign = '\0'; + printf(" GPS lat:\t%f\t%c%d° %.3f'\n", lat1, sign, deg, mmm); /* hamlib function to convert deg, decimal min to decimal degrees */ - lat1 = dmmm2dec(deg, min); + lat1 = dmmm2dec(deg, mmm, nesw); printf(" Recoded GPS:\t%f\n", lat1); /* hamlib function to convert decimal degrees to maidenhead */ @@ -111,51 +126,67 @@ int main (int argc, char *argv[]) { } /* hamlib function to convert decimal degrees to deg, min, sec */ - retcode = dec2dms(lon2, °, &min, &sec); + retcode = dec2dms(lon2, °, &min, &sec, &nesw); if (retcode != RIG_OK) { fprintf(stderr, "dec2dms() failed, invalid paramter address.\n"); exit(2); } - printf(" Longitude:\t%f\t%.0f° %.0f' %.2f\"\n", lon2, deg, min, sec); + if (nesw == 1) + sign = '-'; + else + sign = '\0'; + printf(" Longitude:\t%f\t%c%d° %d' %.2f\"\n", lon2, sign, deg, min, sec); /* hamlib function to convert deg, min, sec to decimal degrees */ - lon2 = dms2dec(deg, min, sec); + lon2 = dms2dec(deg, min, sec, nesw); printf(" Recoded lon:\t%f\n", lon2); /* hamlib function to convert decimal degrees to deg decimal minutes */ - retcode = dec2dmmm(lon2, °, &min); + retcode = dec2dmmm(lon2, °, &mmm, &nesw); if (retcode != RIG_OK) { fprintf(stderr, "dec2dmmm() failed, invalid paramter address.\n"); exit(2); } - printf(" GPS lon:\t%f\t%.0f° %.3f'\n", lon2, deg, min); + if (nesw == 1) + sign = '-'; + else + sign = '\0'; + printf(" GPS lon:\t%f\t%c%d° %.3f'\n", lon2, sign, deg, mmm); /* hamlib function to convert deg, decimal min to decimal degrees */ - lon2 = dmmm2dec(deg, min); + lon2 = dmmm2dec(deg, mmm, nesw); printf(" Recoded GPS:\t%f\n", lon2); /* hamlib function to convert decimal degrees to deg, min, sec */ - retcode = dec2dms(lat2, °, &min, &sec); + retcode = dec2dms(lat2, °, &min, &sec, &nesw); if (retcode != RIG_OK) { fprintf(stderr, "dec2dms() failed, invalid paramter address.\n"); exit(2); } - printf(" Latitude:\t%f\t%.0f° %.0f' %.2f\"\n", lat2, deg, min, sec); + if (nesw == 1) + sign = '-'; + else + sign = '\0'; + printf(" Latitude:\t%f\t%c%d° %d' %.2f\"\n", lat2, sign, deg, min, sec); /* hamlib function to convert deg, min, sec to decimal degrees */ - lat2 = dms2dec(deg, min, sec); + lat2 = dms2dec(deg, min, sec, nesw); printf(" Recoded lat:\t%f\n", lat2); /* hamlib function to convert decimal degrees to deg decimal minutes */ - retcode = dec2dmmm(lat2, °, &min); + retcode = dec2dmmm(lat2, °, &mmm, &nesw); if (retcode != RIG_OK) { fprintf(stderr, "dec2dmmm() failed, invalid paramter address.\n"); exit(2); } - printf(" GPS lat:\t%f\t%.0f° %.3f'\n", lat2, deg, min); + if (nesw == 1) + sign = '-'; + else + sign = '\0'; + printf(" GPS lat:\t%f\t%c%d° %.3f'\n", lat2, sign, deg, mmm); /* hamlib function to convert deg, decimal min to decimal degrees */ - lat2 = dmmm2dec(deg, min); + lat2 = dmmm2dec(deg, mmm, nesw); printf(" Recoded GPS:\t%f\n", lat2); /* hamlib function to convert decimal degrees to maidenhead */ @@ -167,14 +198,19 @@ int main (int argc, char *argv[]) { printf(" Recoded:\t%s\n", recodedloc); retcode = qrb(lon1, lat1, lon2, lat2, &distance, &az); - if (retcode != 0) { + if (retcode != RIG_OK) { fprintf(stderr, "QRB error: %d\n", retcode); exit(2); } - dec2dms(az, °, &min, &sec); + dec2dms(az, °, &min, &sec, &nesw); printf("\nDistance: %.6fkm\n", distance); - printf("Bearing: %f, %.0f° %.0f' %.2f\"\n", az, deg, min, sec); + if (nesw == 1) + sign = '-'; + else + sign = '\0'; + /* Beware printf() rounding error! */ + printf("Bearing: %.2f, %c%d° %d' %.2f\"\n", az, sign, deg, min, sec); exit(0); }