A Racket GUI Widget to display maps based on Open  Street  Map tiles
1 Map Widget Concepts
1.1 Tile Servers
1.2 GPS Tracks and Groups
2 Map Widget Reference
map-widget%
new
zoom-level
show-map-layer
clear
add-track
add-marker
current-location
track-current-location
set-group-pen
set-group-zorder
delete-group
center-map
move-to
resize-to-fit
map-snip%
new
zoom-level
show-map-layer
clear
add-track
add-marker
current-location
track-current-location
set-group-pen
set-group-zorder
delete-group
center-map
move-to
resize-to-fit
get-tile-provider-names
current-tile-provider-name
set-current-tile-provider
7.7

A Racket GUI Widget to display maps based on OpenStreetMap tiles

Alex Harsányi

This module contains a widget to display a map based on OpenStreetMap data, plus additional markers and GPS tracks. The widget allows zooming and paning with the mouse, as well as programatically. Two interfaces are available, map-widget% is based on a canvas% implementation and can be added to other GUI elements, while map-snip% implements the map as a snip% object which can be inserted into a pasteboard%.

There is a tutorial on how to use this widget, it is available here.

1 Map Widget Concepts

1.1 Tile Servers

The map widget displays a map as a collection of tiles, each tile is a square bitmap 256 pixels in width and height. These tiles are downloaded from tile servers as needed and they are stored locally in a persistent cache on disk. The Open Street Map tile server is always available, and it is used by the map widget by default. In addition tiles from the Thunderforest service can also be used, but this requires an API key to be set. If you have an API key, and you can get a developer one for free, set the AL2TFAPIKEY environment variable to contain the API key. The API key is compiled into the code and the environment variable is not needed if you distribute a built application using the map widget.

You can set the tile provider to use by calling set-current-tile-provider and you can get a list of available tile providers by calling get-tile-provider-names.

1.2 GPS Tracks and Groups

The map widget can overlay GPS tracks onto the map. These are sequences of GPS points, which represent a continuous track: the map widget will draw aa single line connecting all the points. Multiple tracks can be added to the map and all would be drawn independently.

GPS tracks can form groups. A group is a number of symbol which is specified to add-track method. Groups are useful because the map widget allows specifying how the track is drawn (the pen%) as well as the Z-order at group level. A group can be used to draw a GPS track that is discontinous.

2 Map Widget Reference

 (require map-widget) package: map-widget

class

map-widget% : class?

  superclass: object%

A widget to display map plus GPS tracks and markers.

constructor

(new map-widget%    
    [parent parent]    
    [[position position]])  (is-a?/c map-widget%)
  parent : 
(or/c (is-a?/c frame%)
      (is-a?/c dialog%)
      (is-a?/c panel%)
      (is-a?/c pane%))
  position : (or/c #f (vector/c flonum? flonum?)) = #f
Construct a new widget. position specifies the initial position shown in the center of the map, it is a vector containing the latitude and longitude. If position is #f, a defatult position will be used.

method

(send a-map-widget zoom-level level)  any/c

  level : exact-nonnegative-integer?
(send a-map-widget zoom-level)  exact-nonnegative-integer?
Set or get the zoom level for the displayed map. The zoom level is a value between 1 (zoomed out) and 16 (zoomed in). The zoom level can also be changed by the user using the mousewheel, so once set, it is not guaranteed to remain at the same value.

method

(send a-map-widget show-map-layer show?)  any/c

  show? : boolean?
(send a-map-widget show-map-layer)  boolean?
Set or get whether to show the map tile layer not not. If the map tile layer is hidden, only the traks and markers will be visible.

method

(send a-map-widget clear)  any/c

Remove all overlay items (tracks and markers) from the widget

method

(send a-map-widget add-track track group)  any/c

  track : sequence?
  group : (or/c symbol? integer? #f)
Add a new GPS track to the map. The GPS track is a sequence of points, each point is a vector of at least two elements: the latitude and longitude of the point.

A track can be addded to a group, which is a symbol used to identify related tracks. The pen% and z-order can be specified for a group.

method

(send a-map-widget add-marker position    
  name    
  direction    
  color)  any/c
  position : (vector/c flonum? flonum?)
  name : string?
  direction : (or/c -1 1)
  color : (is-a?/c color%)
Add a marker to the map at the specified position. "name" will be used for the label.

method

(send a-map-widget current-location location)  any/c

  location : (or/c (vector/c flonum? flonum?) #f)
Display a cicle marker at the specified GPS point. The marker can be moved around by calling this method with a new position or it can be cleared by specifying #f as the location.

method

(send a-map-widget track-current-location flag)  any/c

  flag : boolean?
If flag is #t, the map will be automatically panned so that the location speficied by set-current-location is always in the middle of the map, when flag is #f, this functionality is disabled

method

(send a-map-widget set-group-pen group pen)  any/c

  group : (or/c #f integer? symbol?)
  pen : (is-a?/c pen%)
Set the pen used to draw tracks in the specified track group. When the track group is #f, the default pen is updated, this is used for tracks that have no group defined (i.e. the group is #f)

method

(send a-map-widget set-group-zorder group    
  zorder)  any/c
  group : (or/c #f integer? symbol?)
  zorder : positive?
Set the order in which tracks in the specified trackgroup will be drawn. Tracks with a smaller Z-order will be drawn before tracks with a larger Z-order. The draw order for tracks with the same Z-order value is unspecified.

method

(send a-map-widget delete-group group)  any/c

  group : (or/c #f integer? symbol?)
Delete all GPS tracks within the specified group

method

(send a-map-widget center-map group)  any/c

  group : (or/c #f integer? symbol?)
Center the map around the specified track group, or around all tracks if group is #f

method

(send a-map-widget move-to position)  any/c

  position : (vector/c flonum? flonum?)
Center the map around the specified position, a vector containing the latitude and longitude.

method

(send a-map-widget resize-to-fit group)  any/c

  group : (or/c #f symbol?)
Center and set the zoom level of the map such that the specified track group fits on the visible part of the map canvas. If group is #f, all the tracks will fit on the map canvas.

class

map-snip% : class?

  superclass: snip%

A snip% to display map plus GPS tracks and markers, which can be inserted in a pasteboard%.

constructor

(new map-snip%    
    [[position position]    
    [track track]    
    [width width]    
    [height height]])  (is-a?/c map-snip%)
  position : (or/c #f (vector/c flonum? flonum?)) = #f
  track : sequence? = #f
  width : positive? = 600
  height : positive? = 300
Construct a new map snip. position specifies the initial position shown in the center of the map, it is a vector containing the latitude and longitude. If position is #f, a defatult position will be used.

track specifies an initial track to add to the map, if #f, no tracks will be added.

width and height represent the initial dimensions for the snip%.

method

(send a-map-snip zoom-level level)  any/c

  level : exact-nonnegative-integer?
(send a-map-snip zoom-level)  exact-nonnegative-integer?
Set or get the zoom level for the displayed map. The zoom level is a value between 1 (zoomed out) and 16 (zoomed in). The zoom level can also be changed by the user using the mousewheel, so once set, it is not guaranteed to remain at the same value.

method

(send a-map-snip show-map-layer show?)  any/c

  show? : boolean?
(send a-map-snip show-map-layer)  boolean?
Set or get whether to show the map tile layer not not. If the map tile layer is hidden, only the traks and markers will be visible.

method

(send a-map-snip clear)  any/c

Remove all overlay items (tracks and markers) from the widget

method

(send a-map-snip add-track track group)  any/c

  track : sequence?
  group : (or/c symbol? integer? #f)
Add a new GPS track to the map. The GPS track is a sequence of points, each point is a vector of at least two elements: the latitude and longitude of the point.

A track can be addded to a group, which is a symbol used to identify related tracks. The pen% and z-order can be specified for a group.

method

(send a-map-snip add-marker position    
  name    
  direction    
  color)  any/c
  position : (vector/c flonum? flonum?)
  name : string?
  direction : (or/c -1 1)
  color : (is-a?/c color%)
Add a marker to the map at the specified position. "name" will be used for the label.

method

(send a-map-snip current-location location)  any/c

  location : (or/c (vector/c flonum? flonum?) #f)
Display a cicle marker at the specified GPS point. The marker can be moved around by calling this method with a new position or it can be cleared by specifying #f as the location.

method

(send a-map-snip track-current-location flag)  any/c

  flag : boolean?
If flag is #t, the map will be automatically panned so that the location speficied by set-current-location is always in the middle of the map, when flag is #f, this functionality is disabled

method

(send a-map-snip set-group-pen group pen)  any/c

  group : (or/c #f integer? symbol?)
  pen : (is-a?/c pen%)
Set the pen used to draw tracks in the specified track group. When the track group is #f, the default pen is updated, this is used for tracks that have no group defined (i.e. the group is #f)

method

(send a-map-snip set-group-zorder group    
  zorder)  any/c
  group : (or/c #f integer? symbol?)
  zorder : positive?
Set the order in which tracks in the specified trackgroup will be drawn. Tracks with a smaller Z-order will be drawn before tracks with a larger Z-order. The draw order for tracks with the same Z-order value is unspecified.

method

(send a-map-snip delete-group group)  any/c

  group : (or/c #f integer? symbol?)
Delete all GPS tracks within the specified group

method

(send a-map-snip center-map group)  any/c

  group : (or/c #f integer? symbol?)
Center the map around the specified track group, or around all tracks if group is #f

method

(send a-map-snip move-to position)  any/c

  position : (vector/c flonum? flonum?)
Center the map around the specified position, a vector containing the latitude and longitude.

method

(send a-map-snip resize-to-fit group)  any/c

  group : (or/c #f symbol?)
Center and set the zoom level of the map such that the specified track group fits on the visible part of the map canvas. If group is #f, all the tracks will fit on the map canvas.

Returns a list of available tile providers.

By default only the Open Street Map tile server is available. To use Thunderforest tiles, you will need to obtain an API key and set the AL2TFAPIKEY environment variable with that API key.

Return the name of the current tile provider

procedure

(set-current-tile-provider name)  any/c

  name : string?
Set the name of the tile provider to use. All instances of map-widget% will use the same tile provider.

When this function is called, the selected tile provider is also stored int the racket preference file and this tile provider will be used each time the application is run, util this function is called with a different tile provider name