Standalone OSM.PBF files and Runtime Loading Different Files for iOS

My understanding is that following shell command will create the offline file for germany using germany-latest.osm.pbf from graphhoper-ios-sample.

FILE=germany-latest.osm.pbf JAVA_OPTS="-Xmx4096m -Xms1000m -server" ./graphhopper-ios-sample/import-sample.sh
# if a large file is imported, JAVA_OPTS may need to be changed

When I run

 ./graphhopper-ios-sample/import-sample.sh

This created default romanian graph-data.osm-gh and corresponding actual map file at graph-data.osm.pbf.

How do I make import different country files to standalone zip files with graph-data.osm-gh folder and corresponding osm.pbf? Above germany command did not create a germany-data.osm.pbf file and germany-data.osm-gh folder. Can graphhoper support switching between different maps at runtime? If so, can someone show the code for it?

Take a look at ./graphhopper-ios-sample/import-sample.sh (doesn’t let me post links for some reason). Basically this script downloads the files from http://download.geofabrik.de/europe/$FILE.

To import files from a different source you can do a git checkout 0.6.0 (or a different branch), run the ./graphhopper.sh import $GRAPH_FILE command and bring back graphhopper with git checkout ios-compat.

However you can import the graph from the main GraphHopper repo, the import script is just a sample to give you a starting point.

Here is the script import-sample.sh:

#!/usr/bin/env bash

cd graphhopper
if [ -z ${FILE+x} ]; then
  FILE="romania-latest.osm.pbf"
fi
#graphhopper GRAPH_FILE="graph-data.osm.pbf"
if [ ! -e $FILE ] && [ ! -e $GRAPH_FILE ]; then
  echo "Downloading http://download.geofabrik.de/europe/$FILE"
  curl -O http://download.geofabrik.de/europe/$FILE
fi
if [ ! -e $GRAPH_FILE ]; then
  mv $FILE $GRAPH_FILE
fi
rm -rf $(expr $GRAPH_FILE : '\([^\.]*\)\.')".osm-gh"
git checkout 0.6.0-RC1
./graphhopper.sh import $GRAPH_FILE
git checkout ios-compat
cd ..
touch class.list

Do I use $GRAPH_FILE to match filename of http://download.geofabrik.de/europe/$FILE

./graphhopper.sh import $GRAPH_FILE

Does this script create the $GRAPH_FILE.osm-gh folder? How do I specify it in Xcode? How about code in runtime changing .osm.pbf and graph files?

The graph folder gets created in ./graphhopper/graph-data.osm-gh, from where it is included in the Xcode project of the sample app, if you look.

The import-sample.sh it’s just a sample script, you can (and should) create your own to do the import. Just remember to checkout a different branch if you use the ./graphhopper/ project since it’s checked out on ios-compat branch, which doesn’t allow you to do imports.

1 Like

I am assuming you meant using following command:

FILE=albenia-latest.osm.pbf JAVA_OPTS="-Xmx4096m -Xms1000m -server" ./graphhopper-ios-sample/import-sample.sh

Here is my import-sample.sh

#!/usr/bin/env bash

cd graphhopper
if [ -z ${FILE+x} ]; then
  FILE="romania-latest.osm.pbf"
fi
GRAPH_FILE="graph-data.osm.pbf"
if [ ! -e $FILE ] && [ ! -e $GRAPH_FILE ]; then
  echo "Downloading http://download.geofabrik.de/europe/$FILE"
  curl -O http://download.geofabrik.de/europe/$FILE
fi
if [ ! -e $GRAPH_FILE ]; then
  mv $FILE $GRAPH_FILE
fi
rm -rf $(expr $GRAPH_FILE : '\([^\.]*\)\.')".osm-gh"
git checkout 0.6.0-RC1
./graphhopper.sh import $GRAPH_FILE
git checkout alternate_route2
cd ..
touch class.list

I use above code with alternate_route2 instead of ios-compat branch as you recommended. However this does not download the default albenia file graph-data.osm.pbf but it updates graph-data.osm-gh folder. Can I zip those two files into a folder and make standalone map by each different country?

By the way this is the only place I found out refering to the both folder graph-data.osm-gh and graph-data.osm.pdf file in Directions.m code:

- (GraphHopper *)hopper
{
    if (!_hopper) {
        
        NSString *location = [[NSBundle mainBundle] pathForResource:@"graph-data" ofType:@"osm-gh"];

In ViewController.m:

For Offline predownloaded maps mode, should I concentrate only on the Offline Map Viewer code? What I am not understanding is where offlineMapDatabases points to above graph-data folder and osm-gh file?

case 7:
        {
            // Offline Map Viewer
            [self resetMapViewAndRasterOverlayDefaults];
            _currentlyViewingAnOfflineMap = YES;
            MBXOfflineMapDatabase *offlineMap = [[[MBXOfflineMapDownloader sharedOfflineMapDownloader] offlineMapDatabases] lastObject];
            if (offlineMap)
            {
                _rasterOverlay = [[MBXRasterTileOverlay alloc] initWithOfflineMapDatabase:offlineMap];
                _rasterOverlay.delegate = self;
                _removeOfflineMapsView.hidden = NO;
                
                [_mapView addOverlay:_rasterOverlay];
            }
            else
            {
                [[[UIAlertView alloc] initWithTitle:@"No Offline Maps"
                                            message:@"No offline maps have been downloaded."
                                           delegate:nil
                                  cancelButtonTitle:nil
                                  otherButtonTitlesf:@"OK", nil] show];
            }
            break;
        }

I am looking code to dynamically change the map file.

Two maps is currently not supported (although you could merge two areas) or was your intend to switch between two GraphHopper instances? (That should work)

Hi, Karussell,
How would I merge two areas to support switching between different maps at run-time? Can please explain to us what is the difference between case 7 in ViewController.m and case 6 ?

           case 6:
           {
            // Offline Map Downloader
            [self resetMapViewAndRasterOverlayDefaults];
            [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
            _rasterOverlay = [[MBXRasterTileOverlay alloc] initWithMapID:@"examples.map-pgygbwdm" includeMetadata:YES includeMarkers:YES];
            _rasterOverlay.delegate = self;
            [_mapView addOverlay:_rasterOverlay];
            _offlineMapDownloadControlsView.hidden = NO;
            [self offlineMapDownloader:[MBXOfflineMapDownloader sharedOfflineMapDownloader] stateChangedTo:[[MBXOfflineMapDownloader sharedOfflineMapDownloader] state]];
            break;
            }

And also what is the difference between pathForResource of hopper object in Directions.m?

Can you update the docs to explain this?

Hi, Karussell,
How do I switch between two GraphHopper instances?

Create two GraphHopper instances e.g. load from two maps and then decide per request which to query. There is no inbuilt mechanism or something. Still I recommend to merge while import as with two separate areas you cannot search across boundaries. Also see: https://github.com/graphhopper/graphhopper/issues/293

Are you referring in Directions.m where:

- (GraphHopper *)hopper
        {
            if (!_hopper) {
                NSString *location = [[NSBundle mainBundle] pathForResource:@"graph-data" ofType:@"osm-gh"];
                _hopper = [[GraphHopper alloc] init];
                [_hopper setCHEnableWithBoolean:YES];
                [_hopper setAllowWritesWithBoolean:NO];
                [_hopper setMemoryMapped];
                [_hopper setEncodingManagerWithEncodingManager:[[EncodingManager alloc] initWithNSString:@"car"]];
                [_hopper load__WithNSString:location];

Are you refering to graph-data.osm-gh folder where the routing query database reside which this hopper uses? By the way, does the .map file just used for getting lat long coordinates that is passed via annotation in route method:

- (void)route
{
    self.textView.text = @"Calculating route...";
    
    MKPointAnnotation *point1 = [[_mapView annotations] objectAtIndex:0],
    *point2 = [[_mapView annotations] objectAtIndex:1];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        GHRequest *request = [[GHRequest alloc] initWithDouble:point1.coordinate.latitude
                                                    withDouble:point1.coordinate.longitude
                                                    withDouble:point2.coordinate.latitude
                                                    withDouble:point2.coordinate.longitude];

Yes, this is where you would init multiple instances of GraphHopper.

Note that _mapView is an instance of mbxmapkit used only for allowing the sample app to display a map easily. In the sample app description, it says that the only interesting code related to GraphHopper is in Directions.m.

hi, calin,
Where do you specify the specific .map file in mbxmapkit?

The map load happens here https://github.com/graphhopper/graphhopper-ios/blob/master/graphhopper-ios-sample/graphhopper-ios-sample/ViewController.m#L90

But I don’t think this will be of much help for you. You should probably consider using Apple Maps and overlay GraphHopper on top.

Map display and GraphHopper are two separate things. The sample app focuses on GraphHopper and how it can be used to calculate routes.

The file it is referring to:

_rasterOverlay = [[MBXRasterTileOverlay alloc] initWithMapID:@"examples.map-pgygbwdm"];

where is it located? I cannot find it when running the sample.