Map projection on a two-dimensional terminal with Go

Enhance!

If you want more detail at a higher resolution, you either need to scale down the font used by the terminal and open the window wide enough or switch the terminal to graphics mode. The latter is done by the termui package, which I have used in this column many times.

Listing 4 reads the GPX file just like in Listing 2 and then uses ui.Init() to set up the terminal UI. The display consists of two widgets, a large Canvas object at the top and a single-line Paragraph widget with a border at the bottom that outputs the name of the GPX file plotted at the top of the Canvas widget for informational purposes.

Listing 4

gpx-tui.go

 

The widgets rely on termui's built-in SetRect() function to help them take up their positions in the terminal window. The function expects the spatial boundary of the widgets as coordinates with row and column values; termui counts the columns from left to right, and the rows from top to bottom.

The call to projectSimple() in line 28 of Listing 4 returns the projected track points, which are already in the correct coordinate system. This means that, for each track point, line 30 only needs to call the c.SetPoint() method of the termui Canvas object to draw a graphical dot at the correct location on the Canvas widget.

The Render() function in line 33 throws both widgets up on the screen, and the for loop starting in line 35 uses ui.PollEvents() to check for things like keyboard events until line 37 stops the carousel if the user presses any key to halt.

To compile, again you need the three commands mentioned in Listing 3; only this time the build command is

go build gpx-tui.go gpx.go

The resulting gpx-tui binary expects a GPX file, as you can see in Figure 6, and displays the trail's track points at a relatively high resolution in the termui Canvas widget. Pressing any key closes the terminal UI and the shell returns to its prompt.

Figure 6: Listing 4 displays the GPX file in the terminal's graphic mode.

Eye Candy

All told, though, the terminal display still leaves something to be desired. Reference points such as roads are missing, as are the natural boundaries usually offered by maps, such as coastlines, rivers, and mountains. Unfortunately, map data from providers such as Google Maps is not available for free (feel free to boo at this point).

However, there is always OpenStreetMap (yay!). This community project's maps are licensed under the Open Data Commons Open Database License [3], and there is even a tile server from which arbitrary applications can download the maps as tiles free of charge, even without registering. A tile displays a small section of the world map in appropriate detail, depending on the zoom setting.

The process of finding the tile for a given latitude and longitude on Earth at a given zoom setting is well documented [4]. Applications need to put the three values into a geometric formula and then download the tile data as a PNG file from https://tile.openstreetmap.org/Z/X/Y.png (where Z, X, and Y are the zoom setting, and two calculated values based on the latitute and longitude of the location). However, there's an even easier way. The go-staticmaps Golang library – available on GitHub – elegantly abstracts both the task of fetching tiles for specific latitudes and longitudes and of inserting markers into the displayed maps.

To turn this into production, compile the source code in Listing 5 with

go build gpx-osm.go gpx.go

Listing 5

gpx-osm.go

 

which creates a Go binary named gpx osm.. When called with a GPX file as an argument, the trail comes up drawn neatly in blue on a map (Figure 7).

Figure 7: Hiking trail enriched with OpenStreetMap data.

How does this work? Line 23 in Listing 5 uses NewContext() to create a new map object. The previously called for loop iterated through all the track points in the GPX file, appending each one as a LatLng object to the array slice named edges. The call to NewPath() in line 25 turns this into the segments of a path object that AddObject() inserts into the virtual map. The path's color is set to deep blue with an RGB value 0x0000ff, and the alpha channel defines full opacity with a value of 0xff. The weight of the path is specified by the value of 10.0, which is quite thick.

The Render() function on the Context object molds the whole thing to the right shape in line 26, while SavePNG() in line 32 writes the PNG data to a file in the /tmp directory. To immediately show the new artwork on screen, line 35 calls the Eye of Gnome utility with the path of the temporary map file as a parameter – and up comes the map with the trail drawn on it. Amazing!

All done: Without further ado, you now have a handy tool that graphically displays selected trail files, which means you immediately know where you are going when you make a selection. The whole thing now cries out to be integrated into an application, perhaps with a Fyne GUI. It goes without saying that there are virtually no limits to what creative programmers can do here!

Infos

  1. "Programming Snapshot – Go Filters" by Mike Schilli, Linux Magazine, issue 269, April 2023, pp. 48-52
  2. Mercator projection: https://en.wikipedia.org/wiki/Mercator_projection
  3. OpenStreetMap data license: https://opendatacommons.org/licenses/odbl/
  4. "Slippy map tilenames": https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Lon./lat._to_tile_numbers

The Author

Mike Schilli works as a software engineer in the San Francisco Bay Area, California. Each month in his column, which has been running since 1997, he researches practical applications of various programming languages. If you email him at mailto:mschilli@perlmeister.com he will gladly answer any questions.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Wanderlust

    For running statistics on his recorded hiking trails, Mike Schilli turns to Go to extract the GPS data while relying on plotters and APIs for a bit of geoanalysis.

  • Pathfinder

    When Mike Schilli is faced with the task of choosing a hiking tour from his collection of city trails, he turns to a DIY program trained to make useful suggestions.

  • Programming Snapshot – Go

    Every photo you take with your mobile phone stores the GPS location in the Exif data. A Go program was let loose on Mike Schilli's photo collection to locate shots taken within an area around a reference image.

  • Perl: Plotting GPS Data

    Perl hackers take to the hills with a navigation system that provides a graphical rendering of a hiking tour.

  • GPS Tools

    Almost all manufacturers of GPS devices use proprietary formats to save routes, tracks, and waypoints. Vendors unfortunately rarely offer Linux software for uploading and downloading or processing the data. Four GPS editors keep Linux users on the right track.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More

News