navit-gps / navit

The open source (GPL v2) turn-by-turn navigation software for many OS
http://www.navit-project.org
Other
551 stars 173 forks source link

Improving the behaviour of country selection #676

Open lains opened 5 years ago

lains commented 5 years ago

On the internal GUI, when searching for a Town, the default country is taken from the country configuration (locale). This can be unadapted when using navit abroad (searching for a destination means continuously forcing the country selection). Shouldn't the GUI propose by default the coutry where we are located (if localization is enabled and active) then fallback on last selected country, and only the very first time use the locale?

lains commented 5 years ago

Does anyone have a hint on how I can know to which country corresponds a GPS coord on the map? This is the basic building block to implement this feature... and I am not very familiar with searches in the map data.

mvglasow commented 5 years ago

To my knowledge, while we have border_country as a line type, we have no polygon type for countries. Translating coordinates to a country may be complex.

Lower admin levels are represented as polygons (poly_town, poly_place*). Since the search feature requires a hierarchy (country–town–street), these links would have to be stored somewhere in the data. I’d recommend digging through the search code and/or maptool for some pointers to this. Unfortunately, I’m no expert on search myself—but I would really appreciate such a feature.

There’s one caveat: when Navit starts up, we have no coordinates yet (until we get the first GPS fix). One could either use the current map center, or just fall back to the last country used.

If all else fails, just defaulting to the last selected country would already be a major improvement over what we have now.

A further improvement to this would be to populate the town search field with the current town (or last selected), so the user just has to hit the check mark to find an address in the same town, rather than enter the town name over and over again.

lains commented 5 years ago

Thanks for the hint. I will look into the search functions. Maybe there is also a function that gives me the closest town, given a GPS positions, and if so, it would do the job, by then getting the country associated with this town.

mvglasow commented 5 years ago

POI search is probably your friend if you restrict the search to place types (I’d have to look up the exact types, maptool would be a good starting point).

lains commented 5 years ago

There is some code about searching around one geographic point on the map (which could thus be the current GPS location if it is known at the time the search is started). This code is located in the GTK GUI. @mvglasow, I will thus dig into this as you advised me, I think this is indeed a good starting point.

lains commented 5 years ago

No luck so far. I can get nearby towns (compared to current GPS location), but it seems this data does not contain a reference on which country a town belongs to (at least, I could not find it... I have been looking at struct item data). Search in GTK POI allows to retrieve information about various item types and their distance, but I don't know how to get the country for these items, nor to get the country matching with a specific coordinates on maps (that would have been easy!).

mdankov commented 5 years ago

If nothing has changed significantly in maptool last 3 years, situation is as following.

  1. We indeed do not have country polygons in the binfile. The whole country polygon is just too big to be stored as a whole in the map and be processed on the target device. If we put such object to the binfile, we would have to process it every time we process anything in that country and in nearby countries. For some countries, their country polygon would fall into the root tile and have to be processed when we do any map query. That's unacceptable.

  2. Country data is not attached to every map object.

3. But maybe (i'm unsure) we have country data attached to town objects, both polygons and points.

  1. Town points which are used in search by country are stored separately in the binfile in country-based indice and might be unavailable in generic map query operations used for map drawing and POI searches.

UPD: 3 seems to be not a currently available option. If it would appear impossible to query the map with option 4 too, I think we'll have to change maptool behaviour.

lains commented 5 years ago

@mdankov, I think I have an interesting track. I could manage to get the country ID for a specific location by:

Once this is done, the country ID can be used as an entry in struct country

This seems to work for the test I have performed on the sample map in Germany. I would need help to test this for other countries and other map types to be sure this solution is generic enough.

If someone is interested, I can release the code in a new PR.

mdankov commented 5 years ago

@lains , sounds interesting. Are we talking about this branch: https://github.com/lains/navit/tree/improve-country-search ? I'll try to test it.

lains commented 5 years ago

@mdankov, yes, this is the branch, but what I have currently submitted is really a work in progress with bits and pieces of debugging, I am using the GTK POI search window as a base to check the country matching with the coords of the center of the screen. Actually, the two methods above are working, so I can get the country of the nearest town, or just the country of a geographical point... I'll keep you update when I get something running properly so please hold on (I will then open a proper pull request... it's a matter of cleaning up, commenting, and chasing a segfault!)

mdankov commented 5 years ago

I have it running now. Looks like the pieces which actually query the country are not published on github. I have nearest town properly reported to the log without anything about the country it belongs to.

I'm afraid that query to the town index could appear resource hungry. For smaller countries you could finish by reading all towns and town districts in the country to find the nearest one, and each such object would be multiplied by the number of words it has in its name. "York" would be counted once, "New York" twice and so on. We have planned that index to support fast search by town name, not by coordinates.

Maybe maptool modification to store country data on key objects (like town labels or town boundaries) would be an option.

lains commented 5 years ago

Yes, the code was not in there (yet). I have been working on something different from town search, I have just submitted that code. You will see it in my branch, implemented as function pcoord_to_country().

This is still ongoing work and there are bits that are not strictly related to this feature but to nearest town search as you could see...

lains commented 5 years ago

OK, I tried it on a real map (not on the sample map), but using countryindex does not seem to be a reliable solution, so I'm probably going to head back to detection of the nearest town, and then getting the associated country_id. This is not very light on CPU cycles though, but I don't search for names, rather by distance using the same code as what is used for nearby POI search in the GTK GUI code.

I think this search closest town code could also be used to better name selected points when clicking on the map using Android. Today, these points are given a numeric value name (as can be seen in previous destination), they could be named like "Point close to " instead, it would be easier to get a rough idea about where was a specific point in the history.

lains commented 5 years ago

The trick now is, as you mentionned, @mdankov, to get the information about country_id to be stored in town elements in the map, which is noy the case for now. I don't know how to do this. I had a quick look at the maptool code, it looks like this data is accessible in function osm_process_town_by_boundary(). At that line, I guess, we have the country id available as tc->country->countryid, and maybe it has to be stored in tc->attrs but I have no clue. This might also add a lot of data to the map bin file. I also though it would be better to just get the current country out of the current position + geographical data but you said there are no country polygons in the bin data...

You also wrote:

country data is not attached to every map object.

Maybe I can find another type of object that does store the country ID, and search the closest one...

mdankov commented 5 years ago

I guess, we do not use town items from town_country_list to display them directly on the map. These are rather used for text based search.

But polygonal items at osm_town_relations_to_poly() go directly to the map. I guess these items do not have country info, but at that moment are stored in the form suitable for coordinate based search with boundary_find_matches(), so you can find matching countries for first coordinate of each town boundary and assign values found to item attribute. I say "countries" because there are some cases when a town in osm data belongs to more than one country, I think we would better keep this info.

Also we can make another pass on "nodes" temporary file which (I think) contain at that time all node items to be placed on the map. I do not suggest to assign country id to each node item we have on the map, but adding that attribute to each town node shouldn't hurt.

To test these features (if you decide to experiment with them) you'll need a map which has at least one full country boundary and a few towns inside it.

I was using Overpass Turbo to extract country boundaries for my experiments and some osm processing software to merge a few files into single one (probably, osmconvert).

Don't worry if you have no resources to process the whole planet.osm yourself (it takes above 300G of fast disk space, and conversion would take a few days on a server with 32Gb of RAM). Once you have something which needs testing on the whole global dataset, we can give it a try on our server, posting the result on a separate web server, so it won't immediately affect all Navit users, but you'll be able to download map extracts in the usual way.

lains commented 5 years ago

Hello @mdankov, thanks for your help. If I understood well your proposal, the current attribute country_id cannot be used so far (it is not available anywhere useful for geographical searches).

Just to make sure... do I reformulate your proposal correctly below?

During map conversion (on server), each town polygon is geographically matched to the country/countries it spreads over (there could be more than one) using boundary_find_matches(). Once this is done, the country/countries need to be stored in the map file for each town. In runtime (on the device), an algorithm will search for the nearest town as started to implement in my tests above, then gets a country_id (list) for this town item, thus getting a sense of which country we are close to.

mdankov commented 5 years ago

@lains, you're right.

lains commented 5 years ago

I've been doing some more testing on this, especially on maptool code (that I'm not familiar with) I think I can know get the country ID for each town when processing maps, however, I have no clue about how to add this new attribute to towns when stored in the bin files, and it seems it is even more complicated to have a list of country IDs - instead of just one - attached to towns. If somesone has a clue...

lains commented 4 years ago

Getting the current country a GPS coord belongs to seems to be quite complicated to implement.

As a first improvement, I think I am just going to propose in a future PR, the implementation of a cache of the last country used during search (instead of using a country based on the device's locale).

This will already improve substancially the usability of the search feature in the internal GUI The user will only need to go through manual country selection after physically moving to a different country (or maybe when searching for a location outside of the last used country).