Skip to content

Commit

Permalink
Convinience Macro to get projection names in text
Browse files Browse the repository at this point in the history
Fix for navit-gps#1218 Crash when setting first destination
Changes to make UTM coordinates working
  • Loading branch information
OLFDB committed Jan 14, 2023
1 parent 34fcdb9 commit ca0fd3c
Showing 1 changed file with 128 additions and 126 deletions.
254 changes: 128 additions & 126 deletions navit/coord.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
* @returns the coordinate
*/

int projection_enum_size[SIZE];
#define PROJASSTRING(x) (x==0?"projection_none":x==1?"projection_mg":x==2?"projection_garmin":x==3?"projection_screen":x==4?"projection_utm":"UNKNOWN")

struct coord * coord_get(unsigned char **p) {
struct coord *ret=(struct coord *)(*p);
*p += sizeof(*ret);
Expand Down Expand Up @@ -132,11 +135,11 @@ void coord_rect_extend(struct coord_rect *r, struct coord *c) {
* Parses \c char \a *coord_input and writes back the coordinates to \c coord \a *result, using \c projection \a output_projection.
* \a *coord_input may specify its projection at the beginning.
* The format for \a *coord_input can be:
* \li [Proj:][-]0xXX.... [-]0xXX... - Mercator coordinates, hex integers (XX), Proj can be "mg" or "garmin", defaults to mg
* \li [Proj:][D][D]Dmm.mm.. N/S [D][D]DMM.mm... E/W - lat/long (WGS 84), integer degrees (DD) and minutes as decimal fraction (MM), Proj must be "geo" or absent
* \li [Proj:][-][D]D.d[d]... [-][D][D]D.d[d]... - long/lat (WGS 84, note order!), degrees as decimal fraction, Proj does not matter
* \li utm[zoneinfo]:[-][D]D.d[d]... [-][D][D]D.d[d] - UTM coordinates, as decimal fraction, with optional zone information (?)
* \li [-][D]D.d[d]...,[-][D][D]D.d[d]... - comma-separated (but without space inside the string) lat/long degrees as decimal fraction, Proj does not matter
* \li [Proj:][-]0xXX.... [-]0xXX... - Mercator coordinates, hex integers (XX), Proj can be "mg" or "garmin", defaults to mg
* \li [Proj:][D][D]Dmm.mm.. N/S [D][D]DMM.mm... E/W - lat/long (WGS 84), integer degrees (DD) and minutes as decimal fraction (MM), Proj must be "geo" or absent
* \li [Proj:][-][D]D.d[d]... [-][D][D]D.d[d]... - long/lat (WGS 84, note order!), degrees as decimal fraction, Proj does not matter
* \li utm[zoneinfo]:[-][D]D.d[d]... [-][D][D]D.d[d] - UTM coordinates, as decimal fraction, with optional zone information (?)
* \li [-][D]D.d[d]...,[-][D][D]D.d[d]... - comma-separated (but without space inside the string) lat/long degrees as decimal fraction, Proj does not matter
* Note that the spaces are relevant for parsing.
*
* @param *coord_input String to be parsed
Expand All @@ -145,126 +148,125 @@ void coord_rect_extend(struct coord_rect *r, struct coord *c) {
* @returns The lenght of the parsed string
*/

int coord_parse(const char *coord_input, enum projection output_projection, struct coord *result) {
char *proj=NULL,*s,*co;
const char *str=coord_input;
int args,ret = 0;
struct coord_geo g;
struct coord c,offset;
enum projection str_pro=projection_none;
int space_as_sep = 0;

dbg(lvl_debug,"enter('%s',%d,%p)", coord_input, output_projection, result);
s=strchr(str, ' ');
if (!s) {
space_as_sep = 1;
s=strchr(str, ',');
}
co=strchr(str,':');
if (co && co < s) {
proj=g_malloc(co-str+1);
g_strlcpy(proj, str, 1+co-str);
dbg(lvl_debug,"projection=%s", proj);
str=co+1;
s=strchr(str,space_as_sep?' ':',');
if (!strcmp(proj, "geo"))
str_pro = projection_none;
else {
str_pro = projection_from_name(proj,&offset);
if (str_pro == projection_none) {
dbg(lvl_error, "Unknown projection: %s", proj);
goto out;
}
}
}
if (! s) {
ret=0;
goto out;
}
while (*s == ' ') {
s++;
}
if (!space_as_sep && (!strncmp(s, "0x", 2) || !strncmp(s, "-0x", 3))) {
args=sscanf(str, "%i %i%n",&c.x, &c.y, &ret);
if (args < 2)
goto out;
dbg(lvl_debug,"str='%s' x=0x%x y=0x%x c=%d", str, c.x, c.y, ret);
dbg(lvl_debug,"rest='%s'", str+ret);

if (str_pro == projection_none)
str_pro=projection_mg;
if (str_pro != output_projection) {
transform_to_geo(str_pro, &c, &g);
transform_from_geo(output_projection, &g, &c);
}
*result=c;
} else if (!space_as_sep && (*s == 'N' || *s == 'n' || *s == 'S' || *s == 's')) {
double lng, lat;
char ns, ew;
dbg(lvl_debug,"str='%s'", str);
args=sscanf(str, "%lf %c %lf %c%n", &lat, &ns, &lng, &ew, &ret);
dbg(lvl_debug,"args=%d", args);
dbg(lvl_debug,"lat=%f %c lon=%f %c", lat, ns, lng, ew);
if (args < 4)
goto out;
dbg(lvl_debug,"projection=%d str_pro=%d projection_none=%d", output_projection, str_pro, projection_none);
if (str_pro == projection_none) {
g.lat=floor(lat/100);
lat-=g.lat*100;
g.lat+=lat/60;
g.lng=floor(lng/100);
lng-=g.lng*100;
g.lng+=lng/60;
if (ns == 's' || ns == 'S')
g.lat=-g.lat;
if (ew == 'w' || ew == 'W')
g.lng=-g.lng;
dbg(lvl_debug,"transform_from_geo(%f,%f)",g.lat,g.lng);
transform_from_geo(output_projection, &g, result);
dbg(lvl_debug,"result 0x%x,0x%x", result->x,result->y);
}
dbg(lvl_debug,"str='%s' x=%f ns=%c y=%f ew=%c c=%d", str, lng, ns, lat, ew, ret);
dbg(lvl_debug,"rest='%s'", str+ret);
} else if (!space_as_sep && (str_pro == projection_utm)) {
double x,y;
args=sscanf(str, "%lf %lf%n", &x, &y, &ret);
if (args < 2)
goto out;
c.x=x+offset.x;
c.y=y+offset.y;
if (str_pro != output_projection) {
transform_to_geo(str_pro, &c, &g);
transform_from_geo(output_projection, &g, &c);
}
*result=c;
} else if (space_as_sep) {
// When entering coords like google's format, we actually get strings like "52.5219,19.4127"
double lng, lat;
args=sscanf(str, "%lf,%lf%n", &lat, &lng, &ret);
if (args < 2)
goto out;
dbg(lvl_debug,"str='%s' x=%f y=%f c=%d", str, lng, lat, ret);
dbg(lvl_debug,"rest='%s'", str+ret);
g.lng=lng;
g.lat=lat;
transform_from_geo(output_projection, &g, result);
}
else {
double lng, lat;
args=sscanf(str, "%lf %lf%n", &lng, &lat, &ret);
if (args < 2)
goto out;
dbg(lvl_debug,"str='%s' x=%f y=%f c=%d", str, lng, lat, ret);
dbg(lvl_debug,"rest='%s'", str+ret);
g.lng=lng;
g.lat=lat;
transform_from_geo(output_projection, &g, result);
}
ret+=str-coord_input;
dbg(lvl_info, "ret=%d delta=%d ret_str='%s'", ret, GPOINTER_TO_INT(str-coord_input), coord_input+ret);
out:
g_free(proj);
return ret;
int coord_parse(const char *coord_input, enum projection output_projection, struct coord *result) {
char *proj = NULL, *s = NULL, *co;
const char *str = coord_input;
int args, ret = 0;
struct coord_geo g;
struct coord c, offset;
enum projection str_pro = projection_none;
int space_as_sep = 0;

dbg(lvl_debug, "enter('%s',%s,%p)\n", coord_input,
PROJASSTRING(output_projection), result);
co = strchr(str, ':');
if (co)
s = strstr(str, ": ");
if (s) {
space_as_sep = 1;
}
if (co) {
proj = g_malloc(co - str + 1);
g_strlcpy(proj, str, 1 + co - str);
dbg(lvl_debug, "projection=%s\n", proj);
str = co + 1;
if (space_as_sep)
str++;
s = (char*) str;
if (!strcmp(proj, "geo"))
str_pro = projection_none;
else {
str_pro = projection_from_name(proj, &offset);
if (str_pro == projection_none) {
dbg(lvl_debug, "Unknown projection: %s\n", proj);
goto out;
}
}
} else {
s = (char*) str;
}
if ((!strncmp(s, "0x", 2) || !strncmp(s, "-0x", 3))) {
args = sscanf(str, "%i %i%n", &c.x, &c.y, &ret);
if (args < 2)
goto out;
dbg(lvl_debug, "str='%s' x=0x%x y=0x%x c=%d\n", str, c.x, c.y, ret);
dbg(lvl_debug, "rest='%s'\n", str + ret);

if (str_pro == projection_none)
str_pro = projection_mg;
if (str_pro != output_projection) {
transform_to_geo(str_pro, &c, &g);
transform_from_geo(output_projection, &g, &c);
}
*result = c;
} else if ((*s == 'N' || *s == 'n' || *s == 'S' || *s == 's')) {
double lng, lat;
char ns, ew;
dbg(lvl_debug, "str='%s'\n", str);
args = sscanf(str, "%lf %c %lf %c%n", &lat, &ns, &lng, &ew, &ret);
dbg(lvl_debug, "args=%d\n", args);
dbg(lvl_debug, "lat=%f %c lon=%f %c\n", lat, ns, lng, ew);
if (args < 4)
goto out;
dbg(lvl_debug, "projection=%s str_pro=%d projection_none=%d\n",
PROJASSTRING(output_projection), str_pro, projection_none);
if (str_pro == projection_none) {
g.lat = floor(lat / 100);
lat -= g.lat * 100;
g.lat += lat / 60;
g.lng = floor(lng / 100);
lng -= g.lng * 100;
g.lng += lng / 60;
if (ns == 's' || ns == 'S')
g.lat = -g.lat;
if (ew == 'w' || ew == 'W')
g.lng = -g.lng;
dbg(lvl_debug, "transform_from_geo(%f,%f)\n", g.lat, g.lng);
transform_from_geo(output_projection, &g, result);
dbg(lvl_debug, "result 0x%x,0x%x\n", result->x, result->y);
}
dbg(lvl_debug, "str='%s' x=%f ns=%c y=%f ew=%c c=%d\n", str, lng, ns,
lat, ew, ret);
dbg(lvl_debug, "rest='%s'\n", str + ret);
} else if (str_pro == projection_utm) {
double x, y;
args = sscanf(str, "%lf %lf%n", &x, &y, &ret);
if (args < 2)
goto out;
c.x = x + offset.x;
c.y = y + offset.y;
if (str_pro != output_projection) {
transform_to_geo(str_pro, &c, &g);
transform_from_geo(output_projection, &g, &c);
}
*result = c;
} else if (!space_as_sep) {
// When entering coords like google's format, we actually get strings like "52.5219,19.4127"
double lng, lat;
args = sscanf(str, "%lf,%lf%n", &lat, &lng, &ret);
if (args < 2)
goto out;
dbg(lvl_debug, "str='%s' x=%f y=%f c=%d\n", str, lng, lat, ret);
dbg(lvl_debug, "rest='%s'\n", str + ret);
g.lng = lng;
g.lat = lat;
transform_from_geo(output_projection, &g, result);
} else {
double lng, lat;
args = sscanf(str, "%lf %lf%n", &lng, &lat, &ret);
if (args < 2)
goto out;
dbg(lvl_debug, "str='%s' x=%f y=%f c=%d\n", str, lng, lat, ret);
dbg(lvl_debug, "rest='%s'\n", str + ret);
g.lng = lng;
g.lat = lat;
transform_from_geo(output_projection, &g, result);
}
ret += str - coord_input;
dbg(lvl_debug, "ret=%d delta=%d ret_str='%s'\n", ret,
GPOINTER_TO_INT(str - coord_input), coord_input + ret);
out: g_free(proj);
return ret;
}

/**
Expand Down Expand Up @@ -300,7 +302,7 @@ void coord_print(enum projection pro, struct coord *c, FILE *out) {
} else {
y = c->y;
}
fprintf( out, "%s: %s0x%x %s0x%x\n",
fprintf( out, "%s:%s0x%x %s0x%x\n",
projection_to_name( pro ),
sign_x, x,
sign_y, y );
Expand Down

0 comments on commit ca0fd3c

Please sign in to comment.