Monday, February 20, 2023

I've Got The Whole Commonwealth In My Hand | Crafting and Visualizing an Offline Map Repository

I want to create an offline library of USGS Topo maps that will serve as a navigational backup for my local area. Whether I find myself at a trail head without downloaded maps, or some cataclysmic event has disabled mobile data access, I want a reliable source of high quality maps. Using my usgsassist script and newly implemented map compression, I can easily grab and store large swaths of maps on a single SD card. So creating this repository should be a breeze.

The first question is, what's my local area? I'm located in Northern Virginia, and for this exercise I decided to cast a (very) wide net. I opted to grab all the topo maps from the northern boundary of Pennsylvania to the southern boundary of Virginia. That's almost 6 hours of driving in any direction. Surely that's overkill for my 'local area,' but having a broader area adds to the likelihood that this repository will save the day.

You can grab the latest version of usgsassist from github.

OK, let's build this!

Building the Library

# Grab a list of maps in the area of interest

$ usgsassist -a topos -l "PA, USA; VA, USA" > area.maps

# Spot check the list

# Looks like we got them all, from: Abilene to Zelienople. $ wc -l area.maps 3363 area.maps $ head -3 area.maps Abilene, VA|2022-09-14||-78.625|37.125|-78.5|37.25 Abingdon, VA|2022-09-16||-82|36.625|-81.875|36.75 Accomac, VA|2022-08-31||-75.75|37.625|-75.625|37.75 $ tail -3 area.maps Zanesville East, OH 2019|2019-12-02||-82|39.875|-81.875|40 Zanesville West, OH 2019|2019-12-03||-82.125|39.875|-82|40 Zelienople, PA 2019|2019-09-04||-80.25|40.75|-80.125|40.875

# Download and compress each map

# Download each map to map.pdf # Then store the compressed map as the name provided by the USGS $ cat area.maps | cut -d'|' -f3 | \ while read url ; do \ name=$(basename $url) ; \ echo $name ; \ curl -s $url > map.pdf ; \ pdfimages -a remove -i map.pdf -o $name ; \ done VA_Abilene_20220914_TM_geo.pdf VA_Abingdon_20220916_TM_geo.pdf ...

# Copy to an SD Card

$ sudo mount -t drvfs 'D:' /mnt/d $ cp -Rv area/ /mnt/d/ 'area/' -> '/mnt/d/area' 'area/NY_Port_Jervis_North_20190923_TM_geo.pdf' -> '/mnt/d/area/NY_Port_Jervis_North_20190923_TM_geo.pdf' 'area/WV_Porters_Falls_20191210_TM_geo.pdf' -> '/mnt/d/area/WV_Porters_Falls_20191210_TM_geo.pdf' 'area/WV_Romance_20191209_TM_geo.pdf' -> '/mnt/d/area/WV_Romance_20191209_TM_geo.pdf' ...

After a lengthy, but thankfully unattended downloading process, all 3,363 maps downloaded to my laptop. I was able to put these maps on a single 128GB SD card with space to spare. I confirmed that I can access the map files from my cell phone via an SD card reader:

So now what?

While it's comforting that I have this repository, there are issues with it. The most glaring one being: how would I actually use it? More specifically, how would I find the few maps of interest out of the 3,000+ that are on the SD card?

I'll be answering that question in a future post. For now, I want to tackle a simpler question: what area does this library cover?

I'm confident that the maps from 'northern Pennsylvania' to 'southern Virginia' has me covered, but what does that area include?

I searched for web services that would let me visualize this, and ultimately landed on a delightfully simple option: the Google Static Maps API.

This API is allows you to craft a URL that describes the map you're looking for and Google will serve up an image of said map. How have I never used this capability before?

I implemented usgsassist -a preview by creating a Static Maps URL that includes a path definition which outlines the area of interest in purple. The path coordinates are made up of the bounding box returned by usgsassist -a geobox. This sounds complex, but it turned out to be straightforward to implement.

Here's the URL generated by my map library's bounding box (minus my Google Maps key):

$ usgsassist -a preview -l "PA, USA; VA, USA" | sed 's/key=[^&]*/key=XXX/'|42.5141658,-74.6895018|42.5141658,-83.675415|36.5407589,-83.675415|36.5407589,-74.6895018|42.5141658,-74.6895018

Here's the corresponding image Google generated:

Sweet, right? This URL can be trivially passed to curl to download the image. I've stored the image on the SD card with the maps to provide additional context.

$ curl -s $(usgsassist -a preview -l "PA, USA; VA, USA") > ~/dl/area.png

In general, this preview command takes the guess work out of figuring out what area usgsassist -a topos is going to include.

Next up I'll tackle the challenge of actually using this map library.

No comments:

Post a Comment