Update:
		locator.c -- added argument int pair_count to
		longlat2locator() and changed longlat2locator() from
		void to type int return.  Changed *seconds argument in
		dms2dec() and dec2dms() from type int to type double.

		rotator.h -- function prototypes to match above.

		testloc.c -- modified to support changes in locator.c
		Added additional command line parameter, locator-length
		which is expected after the first locator and before the
		optional second locator.


git-svn-id: https://hamlib.svn.sourceforge.net/svnroot/hamlib/trunk@1517 7ae35d74-ebe9-4afe-98af-79ac388436b8
Hamlib-1.2.0
Nate Bargmann, N0NB 2003-08-21 20:22:06 +00:00
rodzic 9efbb5e911
commit da8d2e4b41
3 zmienionych plików z 82 dodań i 77 usunięć

Wyświetl plik

@ -2,7 +2,7 @@
* Hamlib Interface - Rotator API header * Hamlib Interface - Rotator API header
* Copyright (c) 2000-2003 by Stephane Fillod * Copyright (c) 2000-2003 by Stephane Fillod
* *
* $Id: rotator.h,v 1.7 2003-04-27 22:14:40 fillods Exp $ * $Id: rotator.h,v 1.8 2003-08-21 20:22:06 n0nb Exp $
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as * it under the terms of the GNU Library General Public License as
@ -334,15 +334,15 @@ extern HAMLIB_EXPORT(int) qrb HAMLIB_PARAMS((double lon1, double lat1,
extern HAMLIB_EXPORT(double) distance_long_path HAMLIB_PARAMS((double distance)); extern HAMLIB_EXPORT(double) distance_long_path HAMLIB_PARAMS((double distance));
extern HAMLIB_EXPORT(double) azimuth_long_path HAMLIB_PARAMS((double azimuth)); extern HAMLIB_EXPORT(double) azimuth_long_path HAMLIB_PARAMS((double azimuth));
extern HAMLIB_EXPORT(void) longlat2locator HAMLIB_PARAMS((double longitude, extern HAMLIB_EXPORT(int) longlat2locator HAMLIB_PARAMS((double longitude,
double latitude, char *locator)); double latitude, char *locator, int pair_count));
extern HAMLIB_EXPORT(int) locator2longlat HAMLIB_PARAMS((double *longitude, extern HAMLIB_EXPORT(int) locator2longlat HAMLIB_PARAMS((double *longitude,
double *latitude, const char *locator)); double *latitude, const char *locator));
extern HAMLIB_EXPORT(double) dms2dec HAMLIB_PARAMS((int degs, int minutes, extern HAMLIB_EXPORT(double) dms2dec HAMLIB_PARAMS((int degs, int minutes,
int seconds)); double seconds));
extern HAMLIB_EXPORT(void) dec2dms HAMLIB_PARAMS((double dec, int *degrees, extern HAMLIB_EXPORT(void) dec2dms HAMLIB_PARAMS((double dec, int *degrees,
int *minutes, int *seconds)); int *minutes, double *seconds));
/*! \def rot_debug /*! \def rot_debug

Wyświetl plik

@ -14,7 +14,7 @@
* Copyright (c) 2003 by Nate Bargmann * Copyright (c) 2003 by Nate Bargmann
* Copyright (c) 2003 by Dave Hines * Copyright (c) 2003 by Dave Hines
* *
* $Id: locator.c,v 1.8 2003-08-21 03:11:27 n0nb Exp $ * $Id: locator.c,v 1.9 2003-08-21 20:22:06 n0nb Exp $
* *
* Code to determine bearing and range was taken from the Great Circle, * Code to determine bearing and range was taken from the Great Circle,
* by S. R. Sampson, N5OWK. * by S. R. Sampson, N5OWK.
@ -68,6 +68,38 @@
/* arc length for 1 degree, 60 Nautical Miles */ /* arc length for 1 degree, 60 Nautical Miles */
#define ARC_IN_KM 111.2 #define ARC_IN_KM 111.2
/* The following is contributed by Dave Hines
*
* begin dph
*/
/*
* These are the constants used when converting between Maidenhead grid
* locators and longitude/latitude values. MAX_LOCATOR_PAIRS is the maximum
* number of locator character pairs to convert. This number MUST NOT exceed
* the number of pairs of values in range[] & weight[].
* Setting MAX_LOCATOR_PAIRS to 3 will convert the currently defined 6
* character locators. A value of 4 will convert the extended 8 character
* locators described in section 3L of "The IARU region 1 VHF managers
* handbook". Values of 5 and 6 will extent the format even more, to the
* longest definition I have seen for locators. Beware that there seems to be
* no universally accepted standard for 10 & 12 character locators.
* Note that the loc_char_weight values are in minutes of arc, to avoid
* constants which can't be represented precisely in either binary or decimal.
*
* MAX_LOCATOR_PAIRS now sets the limit locator2longlat() will convert and
* sets the maximum length longlat2locator() will generate. Each function
* properly handles any value from 1 to 6 so MAX_LOCATOR_PAIRS should be
* left at 6. MIN_LOCATOR_PAIRS sets a floor on the shortest locator that
* should be handled. -N0NB
*
*/
const static double loc_char_weight[] = { 600.0, 60.0, 2.5, 0.25, 0.01, 0.001 };
const static int loc_char_range[] = { 18, 10, 24, 10, 25, 10 };
#define MAX_LOCATOR_PAIRS 6
#define MIN_LOCATOR_PAIRS 1
/* end dph */
#endif /* !DOC_HIDDEN */ #endif /* !DOC_HIDDEN */
/** /**
@ -84,11 +116,11 @@
* *
* \sa dec2dms() * \sa dec2dms()
*/ */
double dms2dec(int degrees, int minutes, int seconds) { double dms2dec(int degrees, int minutes, double seconds) {
if (degrees >= 0) if (degrees >= 0)
return (double)degrees + (double)minutes/60. + (double)seconds/3600.; return (double)degrees + (double)minutes/60. + seconds/3600.;
else else
return (double)degrees - (double)minutes/60. - (double)seconds/3600.; return (double)degrees - (double)minutes/60. - seconds/3600.;
} }
/** /**
@ -108,8 +140,8 @@ double dms2dec(int degrees, int minutes, int seconds) {
* *
* \sa dms2dec() * \sa dms2dec()
*/ */
void dec2dms(double dec, int *degrees, int *minutes, int *seconds) { void dec2dms(double dec, int *degrees, int *minutes, double *seconds) {
int deg, min, sec, is_neg = 0; int deg, min, is_neg = 0;
double st; double st;
if (!degrees || !minutes || !seconds) if (!degrees || !minutes || !seconds)
@ -147,54 +179,14 @@ void dec2dms(double dec, int *degrees, int *minutes, int *seconds) {
st = 60. * (st-(double)deg); st = 60. * (st-(double)deg);
min = (int)floor(st); min = (int)floor(st);
st = 60. * (st-(double)min); st = 60. * (st-(double)min);
sec = (int)floor(st);
/* round fractional seconds up if greater than sec.5
* round up min and deg if warranted.
*/
if (fmod(st, sec) >= 0.5) {
sec++;
if (sec == 60) {
sec = 0;
min++;
if (min == 60) {
min = 0;
deg++;
}
}
}
/* set *degrees to original sign passed to dec */ /* set *degrees to original sign passed to dec */
(is_neg == 1) ? (*degrees = deg * -1) : (*degrees = deg); (is_neg == 1) ? (*degrees = deg * -1) : (*degrees = deg);
*minutes = min; *minutes = min;
*seconds = sec; *seconds = st;
} }
/* The following is contributed by Dave Hines
*
* begin dph
*/
/*
* These are the constants used when converting between Maidenhead grid
* locators and longitude/latitude values. MAX_LOCATOR_PAIRS is the maximum
* number of locator character pairs to convert. This number MUST NOT exceed
* the number of pairs of values in range[] & weight[].
* Setting MAX_LOCATOR_PAIRS to 3 will convert the currently defined 6
* character locators. A value of 4 will convert the extended 8 character
* locators described in section 3L of "The IARU region 1 VHF managers
* handbook". Values of 5 and 6 will extent the format even more, to the
* longest definition I have seen for locators. Beware that there seems to be
* no universally accepted standard for 10 & 12 character locators.
* Note that the loc_char_weight values are in minutes of arc, to avoid
* constants which can't be represented precisely in either binary or decimal.
*/
const static double loc_char_weight[] = { 600.0, 60.0, 2.5, 0.25, 0.01, 0.001 };
const static int loc_char_range[] = { 18, 10, 24, 10, 25, 10 };
#define MAX_LOCATOR_PAIRS 6
/* end dph */
/** /**
* \brief Convert Maidenhead grid locator to longitude/latitude * \brief Convert Maidenhead grid locator to longitude/latitude
* \param longitude The location where to store longitude, decimal * \param longitude The location where to store longitude, decimal
@ -212,7 +204,7 @@ const static int loc_char_range[] = { 18, 10, 24, 10, 25, 10 };
* and 1' 15" from south boundary. * and 1' 15" from south boundary.
* *
* \return RIG_OK to indicate conversion went ok, -RIG_EINVAL if locator * \return RIG_OK to indicate conversion went ok, -RIG_EINVAL if locator
* exceeds RR99xx or is malformed (not of 2 through 12 character format). * exceeds RR99xx or exceeds length limit. Currently 1 to 6 lon/lat pairs.
* *
* \sa longlat2locator() * \sa longlat2locator()
*/ */
@ -220,12 +212,16 @@ const static int loc_char_range[] = { 18, 10, 24, 10, 25, 10 };
/* begin dph */ /* begin dph */
int locator2longlat(double *longitude, double *latitude, const char *locator) { int locator2longlat(double *longitude, double *latitude, const char *locator) {
int x_or_y, paircount = strlen(locator) / 2; int x_or_y, paircount;
int locvalue, pair; int locvalue, pair;
double xy[2], minutes; double xy[2], minutes;
paircount = strlen(locator) / 2;
if (paircount > MAX_LOCATOR_PAIRS) /* Max. locator length to allow */ if (paircount > MAX_LOCATOR_PAIRS) /* Max. locator length to allow */
paircount = MAX_LOCATOR_PAIRS; paircount = MAX_LOCATOR_PAIRS;
else if (paircount < MIN_LOCATOR_PAIRS)
return -RIG_EINVAL;
for (x_or_y = 0; x_or_y < 2; ++x_or_y) { /* For x(=long) and y(=lat) */ for (x_or_y = 0; x_or_y < 2; ++x_or_y) { /* For x(=long) and y(=lat) */
minutes = 0.0; minutes = 0.0;
@ -241,7 +237,7 @@ int locator2longlat(double *longitude, double *latitude, const char *locator) {
minutes += locvalue * loc_char_weight[pair]; minutes += locvalue * loc_char_weight[pair];
} }
minutes += loc_char_weight[paircount-1] / 2.0; /* Center coordinate */ minutes += loc_char_weight[paircount - 1] / 2.0; /* Center coordinate */
xy[x_or_y] = minutes / 60.0 - 90.0; xy[x_or_y] = minutes / 60.0 - 90.0;
} }
@ -259,34 +255,44 @@ int locator2longlat(double *longitude, double *latitude, const char *locator) {
* \param longitude The longitude, decimal * \param longitude The longitude, decimal
* \param latitude The latitude, decimal * \param latitude The latitude, decimal
* \param locator The location where to store the locator * \param locator The location where to store the locator
* \param pair_count The desired precision expressed as lon/lat pairs in the locator
* *
* Convert longitude/latitude (decimal) to Maidenhead grid locator. * Convert longitude/latitude (decimal) to Maidenhead grid locator.
* \a locator must point to an array at least MAX_LOCATOR_PAIRS*2 char plus nul long. * \a locator must point to an array at least pair_count * 2 char plus '\0'.
*
* \return RIG_OK if locator was successfully computed. -RIG_EINVAL if
* pair_count exceeds length limit. Currently 1 to 6 lon/lat pairs.
* *
* \sa locator2longlat() * \sa locator2longlat()
*/ */
/* begin dph */ /* begin dph */
void longlat2locator(double longitude, double latitude, char *locator) { int longlat2locator(double longitude, double latitude,
char *locator, int pair_count) {
int x_or_y, pair, locvalue; int x_or_y, pair, locvalue;
double tmp; double tmp;
if (pair_count < MIN_LOCATOR_PAIRS || pair_count > MAX_LOCATOR_PAIRS)
return -RIG_EINVAL;
for (x_or_y = 0; x_or_y < 2; ++x_or_y) { for (x_or_y = 0; x_or_y < 2; ++x_or_y) {
tmp = ((x_or_y == 0) ? longitude / 2. : latitude); tmp = ((x_or_y == 0) ? longitude / 2. : latitude);
/* The 1e-6 here guards against floating point rounding errors */ /* The 1e-6 here guards against floating point rounding errors */
tmp = fmod(tmp + 270., 180.) * 60. + 1e-6; tmp = fmod(tmp + 270., 180.) * 60. + 1e-6;
for (pair = 0; pair < MAX_LOCATOR_PAIRS; ++pair) { for (pair = 0; pair < pair_count; ++pair) {
locvalue = (int) (tmp / loc_char_weight[pair]); locvalue = (int) (tmp / loc_char_weight[pair]);
/* assert(locvalue < loc_char_range[pair]); */ /* assert(locvalue < loc_char_range[pair]); */
tmp -= loc_char_weight[pair] * locvalue; tmp -= loc_char_weight[pair] * locvalue;
locvalue += (loc_char_range[pair] == 10) ? '0':'A'; locvalue += (loc_char_range[pair] == 10) ? '0':'A';
locator[pair*2 + x_or_y] = locvalue; locator[pair * 2 + x_or_y] = locvalue;
} }
} }
locator[MAX_LOCATOR_PAIRS * 2] = '\0'; locator[pair_count * 2] = '\0';
return RIG_OK;
} }
/* end dph */ /* end dph */

Wyświetl plik

@ -15,17 +15,18 @@
int main (int argc, char *argv[]) { int main (int argc, char *argv[]) {
char recodedloc[13], *loc1, *loc2; char recodedloc[13], *loc1, *loc2;
double lon1 = 0, lat1, lon2, lat2; double lon1 = 0, lat1, lon2, lat2;
double distance, az; double distance, az, sec;
int deg, min, sec; int deg, min;
int retcode; int retcode, locator_length;
if (argc < 2) { if (argc < 3) {
fprintf(stderr, "Usage: %s <locator1> [<locator2>]\n", argv[0]); fprintf(stderr, "Usage: %s <locator1> <precision> [<locator2>]\n", argv[0]);
exit(1); exit(1);
} }
loc1 = argv[1]; loc1 = argv[1];
loc2 = argc > 2 ? argv[2] : NULL; locator_length = atoi(argv[2]);
loc2 = argc > 3 ? argv[3] : NULL;
printf("Locator1: %s\n", loc1); printf("Locator1: %s\n", loc1);
retcode = locator2longlat(&lon1, &lat1, loc1); retcode = locator2longlat(&lon1, &lat1, loc1);
@ -35,21 +36,20 @@ int main (int argc, char *argv[]) {
} }
dec2dms(lon1, &deg, &min, &sec); dec2dms(lon1, &deg, &min, &sec);
printf(" Longitude: %f, %d° %d' %d\"\n", lon1, deg, min, sec); printf(" Longitude: %f, %d° %d' %.2f\"\n", lon1, deg, min, sec);
lon1 = dms2dec(deg, min, sec); lon1 = dms2dec(deg, min, sec);
printf(" Recoded lon: %f\n", lon1); printf(" Recoded lon: %f\n", lon1);
dec2dms(lat1, &deg, &min, &sec); dec2dms(lat1, &deg, &min, &sec);
printf(" Latitude: %f, %d° %d' %d\"\n", lat1, deg, min, sec); printf(" Latitude: %f, %d° %d' %.2f\"\n", lat1, deg, min, sec);
lat1 = dms2dec(deg, min, sec); lat1 = dms2dec(deg, min, sec);
printf(" Recoded lat: %f\n", lat1); printf(" Recoded lat: %f\n", lat1);
longlat2locator(lon1, lat1, recodedloc); longlat2locator(lon1, lat1, recodedloc, locator_length);
// recodedloc[6] = '\0';
printf(" Recoded: %s\n", recodedloc); printf(" Recoded: %s\n", recodedloc);
if (loc2 == NULL) if (loc2 == NULL)
exit(0); exit(0);
printf("\nLocator2: %s\n", loc2); printf("\nLocator2: %s\n", loc2);
retcode = locator2longlat(&lon2, &lat2, loc2); retcode = locator2longlat(&lon2, &lat2, loc2);
@ -59,17 +59,16 @@ int main (int argc, char *argv[]) {
} }
dec2dms(lon2, &deg, &min, &sec); dec2dms(lon2, &deg, &min, &sec);
printf(" Longitude: %f, %d° %d' %d\"\n", lon2, deg, min, sec); printf(" Longitude: %f, %d° %d' %.2f\"\n", lon2, deg, min, sec);
lon2 = dms2dec(deg, min, sec); lon2 = dms2dec(deg, min, sec);
printf(" Recoded lon: %f\n", lon2); printf(" Recoded lon: %f\n", lon2);
dec2dms(lat2, &deg, &min, &sec); dec2dms(lat2, &deg, &min, &sec);
printf(" Latitude: %f, %d° %d' %d\"\n", lat2, deg, min, sec); printf(" Latitude: %f, %d° %d' %.2f\"\n", lat2, deg, min, sec);
lat2 = dms2dec(deg, min, sec); lat2 = dms2dec(deg, min, sec);
printf(" Recoded lat: %f\n", lat2); printf(" Recoded lat: %f\n", lat2);
longlat2locator(lon2, lat2, recodedloc); longlat2locator(lon2, lat2, recodedloc, locator_length);
// recodedloc[6] = '\0';
printf(" Recoded: %s\n", recodedloc); printf(" Recoded: %s\n", recodedloc);
retcode = qrb(lon1, lat1, lon2, lat2, &distance, &az); retcode = qrb(lon1, lat1, lon2, lat2, &distance, &az);
@ -79,7 +78,7 @@ int main (int argc, char *argv[]) {
} }
dec2dms(az, &deg, &min, &sec); dec2dms(az, &deg, &min, &sec);
printf("\nDistance: %.2fkm\n", distance); printf("\nDistance: %.2fkm\n", distance);
printf("Bearing: %f, %d° %d' %d\"\n", az, deg, min, sec); printf("Bearing: %f, %d° %d' %.2f\"\n", az, deg, min, sec);
return 0; return 0;
} }