/*! * \file lib/gis/rhumbline.c * * \brief GIS Library - Rhumbline calculation routines. * * From "Map Projections" by Peter Richardus and Ron K. Alder, 1972
* (526.8 R39m in Map & Geography Library)
* Page 20,21, formulas 2.21, 2.22 * * Formula is the equation of a rhumbline from (lat1,lon1) to * (lat2,lon2). Input is lon, output is lat (all in degrees). * * Note: Formula only works if 0 < abs(lon2-lon1) < 180. * If lon1 == lon2 then rhumbline is the merdian lon1 (and the formula * will fail). *
* WARNING: This code is preliminary. It may not even be correct. * * (C) 2001-2014 by the GRASS Development Team * * This program is free software under the GNU General Public License * (>=v2). Read the file COPYING that comes with GRASS for details. * * \author GRASS GIS Development Team * * \date 1999-2014 */ #include #include #include "pi.h" static void adjust_lat(double *); #if 0 static void adjust_lon(double *); #endif /* unused */ static struct state { double TAN_A, TAN1, TAN2, L; int parallel; } state; static struct state *st = &state; /** * \brief Start rhumbline calculations. * * Note: This function must be called before other rhumbline * functions to initialize parameters. * * \param[in] lon1,lat1 longitude, latitude of first point * \param[in] lon2,lat2 longitude, latitude of second point * \return 1 on success * \return 0 on error */ int G_begin_rhumbline_equation(double lon1, double lat1, double lon2, double lat2) { adjust_lat(&lat1); adjust_lat(&lat2); if (lon1 == lon2) { st->parallel = 1; /* a lie */ st->L = lat1; return 0; } if (lat1 == lat2) { st->parallel = 1; st->L = lat1; return 1; } st->parallel = 0; lon1 = Radians(lon1); lon2 = Radians(lon2); lat1 = Radians(lat1); lat2 = Radians(lat2); st->TAN1 = tan(M_PI_4 + lat1 / 2.0); st->TAN2 = tan(M_PI_4 + lat2 / 2.0); st->TAN_A = (lon2 - lon1) / (log(st->TAN2) - log(st->TAN1)); st->L = lon1; return 1; } /** * \brief Calculates rhumbline latitude. * * Note: Function only works if lon1 < lon < lon2. * * \param[in] lon longitude * \return double latitude in degrees */ double G_rhumbline_lat_from_lon(double lon) { if (st->parallel) return st->L; lon = Radians(lon); return Degrees(2 * atan(exp((lon - st->L) / st->TAN_A) * st->TAN1) - M_PI_2); } #if 0 static void adjust_lon(double *lon) { while (*lon > 180.0) *lon -= 360.0; while (*lon < -180.0) *lon += 360.0; } #endif /* unused */ static void adjust_lat(double *lat) { if (*lat > 90.0) *lat = 90.0; if (*lat < -90.0) *lat = -90.0; }