diff -ur hamlib-1.1.5cvs-030622/src/locator.c hamlib-1.1.5cvs-030622-mqk/src/locator.c --- hamlib-1.1.5cvs-030622/src/locator.c Tue Nov 5 00:37:53 2002 +++ hamlib-1.1.5cvs-030622-mqk/src/locator.c Mon Aug 11 20:39:04 2003 @@ -130,90 +130,143 @@ /** * \brief Convert Maidenhead grid locator to longitude/latitude - * \param longitude The location where to store longitude, decimal - * \param latitude The location where to store latitude, decimal + * \param longitude The location where to store longitude, degrees, east positive + * \param latitude The location where to store latitude, degrees, north positive * \param locator The locator * - * Convert Maidenhead grid locator to longitude/latitude (decimal). + * Convert Maidenhead grid locator to longitude/latitude (degrees). * The locator be either in 4 or 6 chars long format. locator2longlat * is case insensitive, however it checks for locator validity. * - * \todo: give center coordinate of locator - * * \return 0 to indicate conversion went ok, otherwise a negative value. * * \sa longlat2locator() + * + * The code in here is adapted from PHP script at: + * http://www.viestikallio.fi/tools/maidenheadfuncs.php?source=1 */ int locator2longlat(double *longitude, double *latitude, const char *locator) { - char loc[6]; + char loc[14]; + int i; + double lat = 0.0, lon = 0.0; + double delta = 1.0; /* One full value range is 0.0 thru 1.0 */ - if (locator[4] != '\0' && locator[6] != '\0') - return -1; + for (i = 0; i < 13 && locator[i]; ++i) + loc[i] = toupper(locator[i]); + loc[i] = 0; - loc[0] = toupper(locator[0]); - loc[1] = toupper(locator[1]); - loc[2] = locator[2]; - loc[3] = locator[3]; - if (locator[4] != '\0') { - loc[4] = toupper(locator[4]); - loc[5] = toupper(locator[5]); - } else { - loc[4] = 'A'; - loc[5] = 'A'; - } - if (loc[0] < 'A' || loc[0] > 'R' || - loc[1] < 'A' || loc[1] > 'R' || - loc[2] < '0' || loc[2] > '9' || - loc[3] < '0' || loc[3] > '9' || - loc[4] < 'A' || loc[4] > 'X' || - loc[5] < 'A' || loc[5] > 'X' ) { - return -1; + while (1) { + char la = loc[0]; + char lo = loc[1]; + + if ('A' < la || la > 'R' || + 'A' < lo || lo > 'R') return -1; /* BAD INPUT! */ + + delta /= 18.0; /* First pair base is 18 */ + + lat += delta * (double)(la - 'A'); + lon += delta * (double)(lo - 'A'); + + for (i = 0; i < 13; i += 4) { + /* 2nd/4th/.. pair: digits, base 10 */ + la = loc[i+0]; + lo = loc[i+1]; + if (la == 0) break; /* End of input */ + + + if ('0' < la || la > '9' || + '0' < lo || lo > '9') return -1; /* BAD INPUT! */ + + delta /= 10.0; /* base is 10 */ + + lat += delta * (double)(la - '0'); + lon += delta * (double)(lo - '0'); + + + /* 3rd/5th/.. pair: alphabets, base 24 */ + la = loc[i+2]; + lo = loc[i+3]; + if (la == 0) break; /* End of input */ + + if ('A' < la || la > 'X' || + 'A' < lo || lo > 'X') return -1; /* BAD INPUT! */ + + delta /= 24.0; /* base is 24 */ + + lat += delta * (double)(la - 'A'); + lon += delta * (double)(lo - 'A'); + + } + break; } - *longitude = 20.0 * (loc[0]-'A') - 180.0 + 2.0 * (loc[2]-'0') + - (loc[4]-'A')/12.0; - if (loc[0] <= 'I' && (loc[2] != '0' || loc[4] != 'A')) - *longitude += 1; + /* Converting result to square midpoint: */ + + lat += delta * 0.5; + lon += delta * 0.5; + + /* Converting result to DEGREES */ + + lat = (lat - 0.5) * 180.0; + lon = (lon - 0.5) * 360.0; + + /* Return the result */ + + *latitude = lat; + *longitude = lon; - *latitude = 10.0 * (loc[1]-'A') - 90.0 + (loc[3]-'0') + - (loc[5]-'A')/24.0; return 0; } /** * \brief Convert longitude/latitude to Maidenhead grid locator - * \param longitude The longitude, decimal - * \param latitude The latitude, decimal + * \param longitude The longitude, degrees, east positive + * \param latitude The latitude, degrees, north positive * \param locator The location where to store the locator * * Convert longitude/latitude (decimal) to Maidenhead grid locator. * \a locator must point to an array at least 6 char long. * - * \todo: give center coordinate of locator - * * \sa locator2longlat() + * + * This is modelled after the code at: + * http://www.viestikallio.fi/tools/maidenheadfuncs.php?source=1 */ void longlat2locator(double longitude, double latitude, char *locator) { - double tmp; + double la, lo; + + /* Convert at first the lat and long into 0.0 thru 1.0 ranges + from their nominal degree scales. */ + + la = (latitude + 90.0) / 180.0; + lo = (longitude + 180.0) / 360.0; + if (lo < 0.0) lo += 1.0; + if (lo > 1.0) lo -= 1.0; + + la += 1.0E-10; + lo += 1.0E-10; + + la = 18.0 * (la - floor(la)); + lo = 18.0 * (lo - floor(lo)); + + locator[0] = 'A' + (int)floor(lo); + locator[1] = 'A' + (int)floor(la); + + la = 10.0 * (la - floor(la)); + lo = 10.0 * (lo - floor(lo)); + + locator[2] = '0' + (int)floor(lo); + locator[3] = '0' + (int)floor(la); + - tmp = fmod(longitude, 360) + 180.; + la = 24.0 * (la - floor(la)); + lo = 24.0 * (lo - floor(lo)); - locator[0] = 'A' + (int)floor(tmp/20.); - tmp = fmod(tmp, 20.); - locator[2] = '0' + (int)floor(tmp/2.); - tmp = 12.*fabs(floor(longitude)-longitude); - locator[4] = 'A' + (int)floor(tmp); - - tmp = fmod(latitude, 360) + 90.; - - locator[1] = 'A' + (int)floor(tmp/10.); - tmp = fmod(tmp, 10.); - locator[3] = '0' + (int)floor(tmp); - tmp = 25. * fabs(floor(latitude)-latitude); - locator[5] = 'A' + (int)floor(tmp); + locator[4] = 'A' + (int)floor(lo); + locator[5] = 'A' + (int)floor(la); }