mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
Save latitude/longitude using integer math
I hate using floating point, this tries to at least make parts of it be integer logic, and avoid the whole locale issue. This still keeps the latitude and longitude internally as a floating point value, and parses it that way, but I'm slowly moving towards less and less FP use. We're going to use micro-degrees for location information: that's sufficient to about a tenth of a meter precision, and it fits in a 32-bit integer. If you specify dive sites with more precision than that, you may have OCD. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
1e074f3fb2
commit
708df33539
1 changed files with 35 additions and 9 deletions
44
save-xml.c
44
save-xml.c
|
@ -4,6 +4,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "dive.h"
|
||||
|
||||
|
@ -177,6 +178,35 @@ static void save_salinity(FILE *f, struct dive *dive)
|
|||
fputs(" />\n", f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Format degrees to within 6 decimal places. That's about 0.1m
|
||||
* on a great circle (ie longitude at equator). And micro-degrees
|
||||
* is also enough to fit in a fixed-point 32-bit integer.
|
||||
*/
|
||||
static int format_degrees(char *buffer, double value)
|
||||
{
|
||||
int udeg = round(value * 1000000.0);
|
||||
const char *sign = "";
|
||||
|
||||
if (udeg < 0) {
|
||||
sign = "-";
|
||||
udeg = -udeg;
|
||||
}
|
||||
return sprintf(buffer, "%s%u.%06u",
|
||||
sign, udeg / 1000000, udeg % 1000000);
|
||||
}
|
||||
|
||||
static int format_location(char *buffer, double latitude, double longitude)
|
||||
{
|
||||
int len = sprintf(buffer, "gps='");
|
||||
|
||||
len += format_degrees(buffer+len, latitude);
|
||||
buffer[len++] = ' ';
|
||||
len += format_degrees(buffer+len, longitude);
|
||||
buffer[len++] = '\'';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void show_location(FILE *f, struct dive *dive)
|
||||
{
|
||||
|
@ -192,20 +222,16 @@ static void show_location(FILE *f, struct dive *dive)
|
|||
* you dove a few meters away.
|
||||
*/
|
||||
if (latitude || longitude) {
|
||||
int len = snprintf(buffer, sizeof(buffer)-4,
|
||||
" <location gps=");
|
||||
char *buf = buffer + len;
|
||||
int len = sprintf(buffer, " <location ");
|
||||
|
||||
len = strlen(g_ascii_formatd(buf, 80, "'%.12g ", latitude));
|
||||
buf += len;
|
||||
len = strlen(g_ascii_formatd(buf, 80, "%.12g'>", longitude));
|
||||
buf += len;
|
||||
len = buf - buffer;
|
||||
len += format_location(buffer+len, latitude, longitude);
|
||||
if (!dive->location) {
|
||||
memcpy(&buffer[len-1], "/>\n", 4);
|
||||
memcpy(buffer+len, "/>\n", 4);
|
||||
fputs(buffer, f);
|
||||
return;
|
||||
}
|
||||
buffer[len++] = '>';
|
||||
buffer[len] = 0;
|
||||
prefix = buffer;
|
||||
}
|
||||
show_utf8(f, dive->location, prefix,"</location>\n", 0);
|
||||
|
|
Loading…
Reference in a new issue