** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
+#ifdef HAVE_MATH_H
#include <math.h>
+#endif
+#include "coords.h"
+#ifdef HAVE_VIKING
#include "viking.h"
+#include "globals.h"
+#else
+#define DEG2RAD(x) ((x)*(M_PI/180))
+#define RAD2DEG(x) ((x)*(180/M_PI))
+#endif
+#include "degrees_converters.h"
/**
* Convert a double to a string WITHOUT LOCALE.
*/
char *a_coords_dtostr ( double d )
{
- /* In order to ignore locale, we do all the stuff manually */
- double integer, decimal;
- integer = trunc(d);
-
- /* 6 decimals are sufficient (~0,1m) */
- /* Cf. http://www.tbs-sct.gc.ca/rpm-gbi/guides/Latlong_f.asp */
- decimal = d - integer;
- decimal = decimal * 1000000;
- decimal = trunc ( decimal );
- decimal = fabs ( decimal );
-
- /* Format */
- return g_strdup_printf ( "%g.%06g", integer, decimal );
+ gchar *buffer = g_malloc(G_ASCII_DTOSTR_BUF_SIZE*sizeof(gchar));
+ g_ascii_dtostr (buffer, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) d);
+ return buffer;
}
#define PIOVER180 0.01745329252
double a_coords_latlon_diff ( const struct LatLon *ll1, const struct LatLon *ll2 )
{
static struct LatLon tmp1, tmp2;
+ gdouble tmp3;
tmp1.lat = ll1->lat * PIOVER180;
tmp1.lon = ll1->lon * PIOVER180;
tmp2.lat = ll2->lat * PIOVER180;
tmp2.lon = ll2->lon * PIOVER180;
- return EquatorialRadius * acos(sin(tmp1.lat)*sin(tmp2.lat)+cos(tmp1.lat)*cos(tmp2.lat)*cos(tmp1.lon-tmp2.lon));
+ tmp3 = EquatorialRadius * acos(sin(tmp1.lat)*sin(tmp2.lat)+cos(tmp1.lat)*cos(tmp2.lat)*cos(tmp1.lon-tmp2.lon));
+ // For very small differences we can sometimes get NaN returned
+ return isnan(tmp3)?0:tmp3;
}
void a_coords_latlon_to_utm( const struct LatLon *latlon, struct UTM *utm )
longitude -= 360.0;
/* Now convert. */
- lat_rad = latitude * M_PI / 180.0;
- long_rad = longitude * M_PI / 180.0;
+ lat_rad = DEG2RAD(latitude);
+ long_rad = DEG2RAD(longitude);
zone = (int) ( ( longitude + 180 ) / 6 ) + 1;
if ( latitude >= 56.0 && latitude < 64.0 &&
longitude >= 3.0 && longitude < 12.0 )
else if ( longitude >= 33.0 && longitude < 42.0 ) zone = 37;
}
long_origin = ( zone - 1 ) * 6 - 180 + 3; /* +3 puts origin in middle of zone */
- long_origin_rad = long_origin * M_PI / 180.0;
+ long_origin_rad = DEG2RAD(long_origin);
eccPrimeSquared = EccentricitySquared / ( 1.0 - EccentricitySquared );
N = EquatorialRadius / sqrt( 1.0 - EccentricitySquared * sin( lat_rad ) * sin( lat_rad ) );
T = tan( lat_rad ) * tan( lat_rad );
R1 = EquatorialRadius * ( 1.0 - EccentricitySquared ) / pow( 1.0 - EccentricitySquared * sin( phi1_rad ) * sin( phi1_rad ), 1.5 );
D = x / ( N1 * K0 );
latitude = phi1_rad - ( N1 * tan( phi1_rad ) / R1 ) * ( D * D / 2 -( 5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * eccPrimeSquared ) * D * D * D * D / 24 + ( 61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * eccPrimeSquared - 3 * C1 * C1 ) * D * D * D * D * D * D / 720 );
- latitude = latitude * 180.0 / M_PI;
+ latitude = RAD2DEG(latitude);
longitude = ( D - ( 1 + 2 * T1 + C1 ) * D * D * D / 6 + ( 5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * eccPrimeSquared + 24 * T1 * T1 ) * D * D * D * D * D / 120 ) / cos( phi1_rad );
- longitude = long_origin + longitude * 180.0 / M_PI;
+ longitude = long_origin + RAD2DEG(longitude);
/* Show results. */
latlon->lon = longitude;
}
+
+void a_coords_latlon_to_string ( const struct LatLon *latlon,
+ gchar **lat,
+ gchar **lon )
+{
+ g_return_if_fail ( latlon != NULL );
+#ifdef HAVE_VIKING
+ vik_degree_format_t format = a_vik_get_degree_format ();
+
+ switch (format) {
+ case VIK_DEGREE_FORMAT_DDD:
+ *lat = convert_lat_dec_to_ddd ( latlon->lat );
+ *lon = convert_lon_dec_to_ddd ( latlon->lon );
+ break;
+ case VIK_DEGREE_FORMAT_DMM:
+ *lat = convert_lat_dec_to_dmm ( latlon->lat );
+ *lon = convert_lon_dec_to_dmm ( latlon->lon );
+ break;
+ case VIK_DEGREE_FORMAT_DMS:
+ *lat = convert_lat_dec_to_dms ( latlon->lat );
+ *lon = convert_lon_dec_to_dms ( latlon->lon );
+ break;
+ case VIK_DEGREE_FORMAT_RAW:
+ *lat = g_strdup_printf ( "%.6f", latlon->lat );
+ *lon = g_strdup_printf ( "%.6f", latlon->lon );
+ break;
+ default:
+ g_critical("Houston, we've had a problem. format=%d", format);
+ }
+#else
+ *lat = convert_lat_dec_to_ddd ( latlon->lat );
+ *lon = convert_lon_dec_to_ddd ( latlon->lon );
+#endif
+}