Skip to content

Instantly share code, notes, and snippets.

@wjx
Last active March 7, 2017 03:08
Show Gist options
  • Save wjx/cb6fc7ae0189ab4f8ba3171ca8207a0d to your computer and use it in GitHub Desktop.
Save wjx/cb6fc7ae0189ab4f8ba3171ca8207a0d to your computer and use it in GitHub Desktop.

#Create your own map with OpenStreetMap

This is some note of me playing with OpenStreetMap and creating an Android app that renders the map drawn.

##Draw a map

###Get GPS trace

If you want to draw your own map, OpenStreetMap is a good choice because it's an open project with many tools and resources available.

To draw a map, the first thing to do is to get GPS trace, there are many Android apps to do this. The one I used is OSMTracker. You can recording tracks with this app and take some note and photos along the way. After the survey, the gps data can be exported as gpx file.

###Edit the map

With the surveyed gps data, we can draw the map. The best tool I think is JOSM, in which we can import the gpx file and then download from the internet the map data surrounding the surveyed area that is already in OpenStreetMap as a starting point of our edit. The OpenStreetMap's basic data structures are Nodes, Ways and Relations, these can easily be drawn using the tools in JOSM. Usually we draw these elements alongside our GPS data as guidance. JOSM also have some presets for us to set to the elements we draw, they in fact set the tags to the data structures and make them have the corresponding visual effects when rendered.

After we finished the editing of the map, we can save the data to an .osm file, these are xml files containing map data with osm data strutures.

##Using the drawn map in an Android app ###Convert it to mapsforge format The generated osm file cannot be used directly, they first need to be rendered. The best library to use on Android I find is MapsForge. But before the OSM data can be used with mapsforge, it must be converted to mapsforege's format, .map file and the tool to do this is Mapsforge Map-Writer. It's an osmosis plugin and after installed, It's simply a matter of going to osmosis's install directory and run the command:

/osmosis --read-xml file="/[osm file path]/file.osm" --mapfile-writer file="/[out put path]/dest.map"

Osmosis may complain invalid osm file format that's because the JOSM file format saved by JOSM is not exactly the same as the osm file download from openstreetmap server, it have action='modify' and don't have timestamp and some other xml attributes. This can be easily solved by opening the osm file in vim and substitute the attributes with a command like the following:

:%s/action='modify' visible='true'/timestamp='2008-06-27T03:38:51Z' uid='13721' user='wangchun' visible='true' version='1' /

###Using it in android To use the map in android with mapsfore, it's best to start from mapsfore's sample project, which is in the 'mapsforge-samples-androd' folder in mapsforge's source code.

There are several 'Viewer' classes such as SimplestMapViewer and StackedLayersMapViewer that inherits from MapViewerTemplate and implements different styles of map. MapViewerTemplate extends from Activity and deals with some dirty works to setup mapsforge. So all we have to do is extending from MapViewerTemplate and overriding some of its method to change the configurations as we like. For example by overriding getMapViewId() and getMapFileName() we can specify the map view id and the map data file.

One important method to override is createLayers(), in which we create 'layers' and add them to the map view, such as TileRendererLayer and Marker. As its name suggests, with Marker class we can add markers which is usually a bitmap on top of the map, one thing to remember is we need to call setDisplayModel() before a layer is added to a map view.

Now that the map is setup, we need to set the position to be displayed at the center of the view as the map may be larger than the view port. The initial position can be set by overriding method initializePosition() from MapViewerTemplate. The view port location and zoom level can be updated afterwards(such as in LocationListener) with mapView.getModel().mapViewPosition.setCenter() and mapView.getModel().mapViewPosition.setZoomLevel() respectively. The markers location can be set with setLatLong() method of the marker class.

One last thing to note is mapsforge expects a map file in some directory(default is /sdcard/), while in Android we often store data in an app's asset folder. So in onCreate(), we need to open the map data file in asset and write it to a file in /sdcard directory , if it doesn't exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment