From ca0fd3c218c3636c07c4f9507b8bf8ed8c00a688 Mon Sep 17 00:00:00 2001 From: OLFDB Date: Sat, 14 Jan 2023 19:02:18 +0100 Subject: [PATCH] Convinience Macro to get projection names in text Fix for #1218 Crash when setting first destination Changes to make UTM coordinates working --- navit/coord.c | 254 +++++++++++++++++++++++++------------------------- 1 file changed, 128 insertions(+), 126 deletions(-) diff --git a/navit/coord.c b/navit/coord.c index 03dec06b9b..ede1b0a451 100644 --- a/navit/coord.c +++ b/navit/coord.c @@ -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); @@ -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 @@ -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; } /** @@ -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 );