-
Notifications
You must be signed in to change notification settings - Fork 174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix:#1218 #1219
base: trunk
Are you sure you want to change the base?
Fix:#1218 #1219
Changes from 18 commits
68afffb
5a0288b
e3cb9c2
fd91e40
be87cd3
a2ffdea
31c48d4
90ff624
ae572cc
57cba4e
381e544
64c5eab
be53f3d
34fcdb9
ca0fd3c
7620dc4
5d0bfe0
223b8b3
fb0afeb
90d36d7
7c2492a
c187fda
d9c0f97
4f64b74
c3dba1b
1167d94
55f0c86
8a3fa0d
cf5587b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
## Coordinates in Navit | ||
|
||
Various parts of Navit will read geographical coordinates provided as text: | ||
|
||
- the [textfile](https://wiki.navit-project.org/index.php/Textfile) map format | ||
- the "center=" attribute in the configuration file | ||
- some Navit commands (e.g. set_position), which can be invoked via the [internal GUI](https://wiki.navit-project.org/index.php/Internal_GUI) or the [Dbus](https://wiki.navit-project.org/index.php/Dbus) bindings | ||
- the files for bookmarks and last map position (bookmarks.txt and center.txt) | ||
|
||
This page documents the coordinate systems and formats that Navit will accept. | ||
|
||
## Supported coordinate systems and formats | ||
|
||
### Longitude / Latitude in decimal degrees | ||
|
||
Longitude / latitude in degrees can be specified as signed decimal fractions: | ||
|
||
``` | ||
-33.3553 6.334 | ||
``` | ||
|
||
That would be about 33° West, 6° North. Note that in this format longitude comes first. The coordinates are assumed to be based on WGS84 (the coordinate system used by the GPS system, and by practically all common navigation systems). | ||
|
||
### Latitude / Longitude in degrees and minutes | ||
|
||
Latitude / Longitude can also be specified in degress and minutes with compass directions (N/S, E/W): | ||
|
||
``` | ||
4808 N 1134 E | ||
``` | ||
|
||
Latitude and longitude are multiplied by 100, so the position above corresponds to 48°8' N, 11°34' (Munich). | ||
|
||
For greater precision you can write the minutes as decimal fractions: | ||
|
||
``` | ||
4808.2356 N 1134.5252 E | ||
``` | ||
|
||
That is 48°8.2356' N 11°34.5252' E, the center of the Marienplatz in Munich. | ||
|
||
Notes: | ||
|
||
- This format is rather unusual (because it uses arcminutes, but not arcseconds). It is probably easier to just use decimal fractions of degrees. | ||
- The spaces are relevant for parsing. Use exactly one space between the number and the letter N/S/E/W. | ||
|
||
### Cartesian coordinates | ||
|
||
Internally, Navit uses a cartesian coordinate system induced by a Mercator projection. Coordinates are written as hexadecimal integers: | ||
|
||
``` | ||
0x13a3d7 0x5d6d6d | ||
``` | ||
|
||
or specifying a projection: | ||
|
||
``` | ||
mg: 0x13a3d7 0x5d6d6d | ||
``` | ||
|
||
That is again 48°8.2356' N 11°34.5252' E. The part up to and including the colon is optional, it names the projection to use. Possible values: | ||
|
||
- mg - the projection used by Map&Guide (the default) | ||
- garmin - "Garmin" projection (TODO: When would it be useful?) | ||
|
||
This format is used internally by Navit, but is probably not very useful for other purposes. | ||
|
||
### UTM coordinates | ||
|
||
Navit can read coordinates in the [Universal Transverse Mercator coordinate system](http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system) (UTM). | ||
|
||
``` | ||
utm32U: 674499.306 5328063.675 | ||
``` | ||
|
||
``` | ||
utmref32UPU:74499.306 28063.675 | ||
``` | ||
|
||
|
||
|
||
## Development notes | ||
|
||
The coordinates are parsed in function coord_parse() in coord.c. This code is used everywhere where Navit parses coordinates, except for the manual coordinate input in the Internal GUI (which uses its own format and parsing function). |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,9 @@ | |
* @returns the coordinate | ||
*/ | ||
|
||
int projection_enum_size[projection_enumsize]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed. |
||
#define PROJASSTRING(x) (x==0?"projection_none":x==1?"projection_mg":x==2?"projection_garmin":x==3?"projection_screen":x==4?"projection_utm":"UNKNOWN") | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this what projection_to_name is doing already? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. Removed the macro and used projection_to_name. |
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why change from error to debug? error seems to be fitting here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed to error again. |
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why all the line returns? dbg should add those itself? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is original code. It is shown here as there were spaces inserted by eclipse formatter. |
||
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 ); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just happen now to see that you used markdown instead of reStructuredText which results in no headline found here and not format here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just updated coordinates.rst to be in rst format (at least I choose export reStructuredText in Typora to create it). Added some lines for Google Maps coordinates as well.