Skip to content
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

Open
wants to merge 29 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
68afffb
Initial commit
OLFDB May 23, 2022
5a0288b
Merge branch 'navit-gps:trunk' into navitori
OLFDB May 23, 2022
e3cb9c2
Merge pull request #18 from navit-gps/trunk
OLFDB Jan 4, 2023
fd91e40
Fix:#1185
OLFDB Jan 5, 2023
be87cd3
Fix:#1185
OLFDB Jan 5, 2023
a2ffdea
Update after further tests
OLFDB Jan 7, 2023
31c48d4
Update navit.c
OLFDB Jan 7, 2023
90ff624
Update navit.c
OLFDB Jan 7, 2023
ae572cc
Revert "Fix:#1185"
OLFDB Jan 8, 2023
57cba4e
Revert "Fix:#1185"
OLFDB Jan 8, 2023
381e544
Merge trunk.
OLFDB Jan 11, 2023
64c5eab
merge trunk
OLFDB Jan 11, 2023
be53f3d
Merge branch 'navit-gps-trunk' into navitori
OLFDB Jan 11, 2023
34fcdb9
Taken from wiki and added UTM coordinate description
OLFDB Jan 14, 2023
ca0fd3c
Convinience Macro to get projection names in text
OLFDB Jan 14, 2023
7620dc4
Added SIZE enum member to calculate size of enum
OLFDB Jan 14, 2023
5d0bfe0
Changes to fix handling of UTM coordinates.
OLFDB Jan 14, 2023
223b8b3
Changed SIZE to projection_enumsize
OLFDB Jan 14, 2023
fb0afeb
Removed unneccessary macro PROJASSTRING
OLFDB Jan 21, 2023
90d36d7
Removed unneccessary enum value projection_enumsize
OLFDB Jan 21, 2023
7c2492a
Use dbg instead of printf again
OLFDB Jan 21, 2023
c187fda
Linked new file coordinates.rst
OLFDB Jan 21, 2023
d9c0f97
astyle
OLFDB Jan 21, 2023
4f64b74
Update after testing with all coordinate formats. Google Maps included.
OLFDB Jan 21, 2023
c3dba1b
Changed to rst format and added Google Maps coordinates description
OLFDB Jan 31, 2023
1167d94
Merge branch 'trunk' into bookmarkissue
OLFDB Dec 25, 2023
55f0c86
Revert "Merge branch 'trunk' into bookmarkissue"
OLFDB Dec 26, 2023
8a3fa0d
Fixes for testcases
OLFDB Dec 26, 2023
cf5587b
Fix for testcases
OLFDB Dec 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions docs/configuration/coordinates.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
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 decimal degrees
---------------------------------------

Longitude / latitude in degrees can be specified as signed decimal
fractions:

.. code::

-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 in degrees and minutes
-------------------------------------------

Latitude / Longitude can also be specified in degress and minutes with
compass directions (N/S, E/W):

.. code::

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:

.. code::

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:

.. code::

0x13a3d7 0x5d6d6d

or specifying a projection:

.. code::

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?)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK this is for legacy reasons: Navit was started around 2002 (source code was released later). Note that this predates OSM – the first versions used commercial map data, including Garmin. Hence there would have been a need to support their coordinate system. This probably also explains why Navit internally uses mg rather than WGS84.


This format is used internally by Navit, but is probably not very useful
for other purposes.

Google Maps Format
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes it sound like Google invented this format. Can’t we put this more nicely (e.g. decimal WGS84 lat/lon)? Also, since this is closely related to the other WGS84 formats, why not move it closer to them?

------------------

.. code::

48.137260, 11.575420
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there is another WGS84 decimal format, albeit with longitude before latitude, how does Navit know which of the two is meant (i.e. order of coordinates)? Or, what do I need to pay attention to when supplying these coordinates so Navit interprets them correctly (avoiding coordinates being swapped)?


That is again 48°8.2356' N 11°34.5252' E. The values are comma
separated. You can pick such values from Google Maps with right click on
a location and then click on the coordinate in the context menu. This is
useful when planning a route online by creating a waypoint file.

UTM coordinates
---------------

Navit can read coordinates in the `Universal Transverse Mercator
coordinate
system <http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system>`__
(UTM).

.. code::

utm32U: 674499.306 5328063.675

.. code::

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).
2 changes: 1 addition & 1 deletion docs/configuration/general.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ On Navit's very first startup, it needs a **center** to look at on the map. By d

center="11.5666 48.1333"

Coordinates can be written in different formats; see [[Coordinate_format]] for the full list.
Coordinates can be written in different formats; see :doc:`coordinates` for the full list.
To determine a specific latitude and longitude for your location you can use http://itouchmap.com/latlong.html.
Usually, changing the "center" setting is not necessary, since it is only used during the first start.
On subsequent starts, Navit will remember the last map position (stored in "center.txt") and ignore the "center" setting.
Expand Down
98 changes: 54 additions & 44 deletions navit/coord.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,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 @@ -146,50 +146,60 @@ void coord_rect_extend(struct coord_rect *r, struct coord *c) {
*/

int coord_parse(const char *coord_input, enum projection output_projection, struct coord *result) {
char *proj=NULL,*s,*co;
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;
c.x=0;
c.y=0;

dbg(lvl_debug,"enter('%s',%d,%p)", coord_input, output_projection, result);
s=strchr(str, ' ');
if (!s) {
dbg(lvl_debug,"enter('%s',%s,%p)\n", coord_input, projection_to_name(output_projection), result);
co=strchr(str,':');
if(co)
s=strstr(str, ": ");
else {
while(*str==' ') {
str++;
}
s=strstr(str, " ");
while(s && *s==' ') {
s++;
}
}


if (s && !strstr(str, ",")) {
space_as_sep = 1;
s=strchr(str, ',');
}
co=strchr(str,':');
if (co && co < s) {
if (co) {
proj=g_malloc(co-str+1);
g_strlcpy(proj, str, 1+co-str);
dbg(lvl_debug,"projection=%s", proj);
dbg(lvl_debug,"projection=%s\n", proj);
str=co+1;
s=strchr(str,space_as_sep?' ':',');
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_error, "Unknown projection: %s", proj);
dbg(lvl_error, "Unknown projection: %s\n", proj);
goto out;
}
}
} else if (!space_as_sep || strstr(str, "0x")) {
s=(char*)str;
}
if (! s) {
ret=0;
goto out;
}
while (*s == ' ') {
s++;
}
if (!space_as_sep && (!strncmp(s, "0x", 2) || !strncmp(s, "-0x", 3))) {
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", str, c.x, c.y, ret);
dbg(lvl_debug,"rest='%s'", str+ret);
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;
Expand All @@ -198,16 +208,17 @@ int coord_parse(const char *coord_input, enum projection output_projection, stru
transform_from_geo(output_projection, &g, &c);
}
*result=c;
} else if (!space_as_sep && (*s == 'N' || *s == 'n' || *s == 'S' || *s == 's')) {
} else if ((*s == 'N' || *s == 'n' || *s == 'S' || *s == 's')) {
double lng, lat;
char ns, ew;
dbg(lvl_debug,"str='%s'", str);
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", args);
dbg(lvl_debug,"lat=%f %c lon=%f %c", lat, ns, lng, ew);
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=%d str_pro=%d projection_none=%d", output_projection, str_pro, projection_none);
dbg(lvl_debug,"projection=%s str_pro=%d projection_none=%d\n", projection_to_name(output_projection), str_pro,
projection_none);
if (str_pro == projection_none) {
g.lat=floor(lat/100);
lat-=g.lat*100;
Expand All @@ -219,13 +230,13 @@ int coord_parse(const char *coord_input, enum projection output_projection, stru
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);
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", result->x,result->y);
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", str, lng, ns, lat, ew, ret);
dbg(lvl_debug,"rest='%s'", str+ret);
} else if (!space_as_sep && (str_pro == projection_utm)) {
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)
Expand All @@ -237,31 +248,30 @@ int coord_parse(const char *coord_input, enum projection output_projection, stru
transform_from_geo(output_projection, &g, &c);
}
*result=c;
} else if (space_as_sep) {
} 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);
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 {
} 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);
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_info, "ret=%d delta=%d ret_str='%s'", ret, GPOINTER_TO_INT(str-coord_input), coord_input+ret);
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 +310,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
8 changes: 7 additions & 1 deletion navit/projection.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,18 @@ enum projection projection_from_name(const char *name, struct coord *utm_offset)
return projection_names[i].projection;
}
if (utm_offset) {
if (sscanf(name,"utm%d%c",&zone,&ns) == 2 && zone > 0 && zone <= 60 && (ns == 'n' || ns == 's')) {
int scanres = sscanf(name,"utm%d%c",&zone,&ns);
ns = tolower(ns);
if (scanres == 2 && zone > 0 && zone <= 60 && (ns == 'n' || ns == 's')) {
utm_offset->x=zone*1000000;
utm_offset->y=(ns == 's' ? -10000000:0);
return projection_utm;
}
if (sscanf(name,"utmref%d%c%c%c",&zone,&zone_field,&square_x,&square_y)) {
zone=tolower(zone);
zone_field=tolower(zone_field);
square_x=tolower(square_x);
square_y=tolower(square_y);
i=utmref_letter(zone_field);
if (i < 2 || i > 21) {
dbg(lvl_error,"invalid zone field '%c' in '%s'",zone_field,name);
Expand Down
10 changes: 5 additions & 5 deletions navit/projection.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
#define NAVIT_PROJECTION_H

enum projection {
projection_none, /*!< No projection or unknown projection */
projection_mg, /*!< Mercator projection */
projection_garmin, /*!< Garmin projection */
projection_screen, /*!< Screen projection */
projection_utm /*!< UTM projection */
projection_none, /*!< No projection or unknown projection */
projection_mg, /*!< Mercator projection */
projection_garmin, /*!< Garmin projection */
projection_screen, /*!< Screen projection */
projection_utm /*!< UTM projection */
};

enum map_datum {
Expand Down