Harmonic Notes on MATLAB and Image Processing

Concepts, examples, new code, tutorials, tips, stories, history, etc.

« Image Processing... Improved... »

Making a Simple Two-State Map with Landmarks

Steve Eddins
September 21, 2025

image_0.png

Recently, while doing some volunteer website work for a music nonprofit, I needed to show the location of an event (Cormont Horn Camp) on a map of New Hampshire and Vermont. The image above shows what I made. In today’s post, I’ll show how I made it using MATLAB and Mapping Toolbox.

First, start with a special kind of axes called a geographic axes. In a geographic axes, data is plotted using latitude and longitude coordinates.

h_geoaxes = geoaxes

figure_0.png

h_geoaxes = 
  GeographicAxes with properties:

     Basemap: 'streets-light'
    Position: [0.1300 0.1140 0.7750 0.8110]
       Units: 'normalized'

  Show all properties

Next, read low-resolution state boundaries into a geographic data table using readgeotable. (Note: the data file usastatelo.shp is included with Mapping Toolbox.)

states = readgeotable("usastatelo.shp")
Shape Name LabelLat LabelLon PopDens2000
1 geopolyshape “Alabama” 32.2827 -86.9206 87.6000
2 geopolyshape “Alaska” 64.6097 -152.4593 1.1000
3 geopolyshape “Arizona” 34.3451 -112.0705 45.2000
4 geopolyshape “Arkansas” 34.8350 -91.8861 51.3000
5 geopolyshape “California” 36.8223 -119.6633 217.2000
6 geopolyshape “Colorado” 39.0295 -105.5440 41.5000
7 geopolyshape “Connecticut” 41.5106 -72.7627 702.9000
8 geopolyshape “Delaware” 39.1071 -75.4942 401
9 geopolyshape “Florida” 28.3914 -82.8483 296.4000
10 geopolyshape “Georgia” 32.5803 -83.0864 141.4000
11 geopolyshape “Hawaii” 21.0458 -154.5259 188.6000
12 geopolyshape “Idaho” 45.0105 -114.6199 15.6000
13 geopolyshape “Illinois” 39.7424 -89.1980 223.4000
14 geopolyshape “Indiana” 39.4482 -86.5771 169.5000

I’m specifically interested in New Hampshire and Vermont.

new_hampshire = states(states.Name == "New Hampshire", :)
Shape Name LabelLat LabelLon PopDens2000
1 geopolyshape “New Hampshire” 43.9080 -71.5591 137.8000
vermont = states(states.Name == "Vermont", :)
Shape Name LabelLat LabelLon PopDens2000
1 geopolyshape “Vermont” 44.0435 -72.5565 65.8000

The function geoplot can plot various kinds of latitude-longitude data, including the geopolyshapes in the usastatelo dataset.

geoplot(new_hampshire,"FaceColor",[0.3 1.0, 0.675])
hold on
geoplot(vermont,"FaceColor","yellow")
hold off

figure_1.png

Now I’ll mark the location of the event. I looked up the latitude and longitude coordinates.

cormont_lat = 43.675833;
cormont_lon = -72.040556;
hold on
geoplot(cormont_lat, cormont_lon, Marker = "o", ...
    MarkerEdgeColor = "black", ...
    MarkerFaceColor = "black", ...
    MarkerSize = 3)
text(cormont_lat, cormont_lon, ["  Cormont" ; "  Horn Camp"], ...
    FontSize = 6, ...
    FontAngle = "italic", ...
    HorizontalAlignment = "left", ...
    VerticalAlignment = "top");
hold off

figure_2.png

I wanted to show the Appalachian Trail on the map. I did some online searching and found a file with latitude-longitude coordinates for the trail.

s = load("at_area_shape.mat");
at_shape = s.at_area_shape;
at_geopoly = geopolyshape(at_shape.Lat, at_shape.Lon);

I used the function geoclip to clip the Appalachian Trail coordinates to the states of New Hampshire and Vermont. Then, I used geoplot once again to plot the trail. For labeling the trail, the MATLAB function text works just fine with geographic axes.

at_clipped_nh = geoclip(at_geopoly, new_hampshire.Shape);
at_clipped_vt = geoclip(at_geopoly, vermont.Shape);
trail_color = [.75 .75 .75];

hold on
geoplot(at_clipped_nh, FaceColor = trail_color, ...
    EdgeColor = trail_color)
geoplot(at_clipped_vt, FaceColor = trail_color, ...
    EdgeColor = trail_color)
hold off
at_label_lat = 44 + 20/60;
at_label_lon = -71 - 22/60;
text(at_label_lat, at_label_lon, ...
    "Appalachian Trail", ...
    FontSize = 6, ...
    Rotation = 34, ...
    HorizontalAlignment = "center", ...
    VerticalAlignment = "bottom")

figure_3.png

It’s time to fix up the background. I don’t need a basemap or visible latitude and longitude coordinates.

h_geoaxes.Basemap = "none";
h_geoaxes.Visible = "off";

figure_4.png

Finally, I wanted to place a few key landmarks, including two airports (Manchester-Boston Regional and Patrick Leahy Burlington) and the two capitol cities (Concord and Montpelier). MATLAB code files and MATLAB graphics can include Unicode characters, which made it easy to show airplane icons on the map.

mht_lat = 42.93250;
mht_lon = -71.43556;
btv_lat = 44.47194;
btv_lon = -73.15333;
concord_lat = 43.206667;
concord_lon = -71.538056;
mp_lat = 44.259444;
mp_lon = -72.575833;
plane_rotation = 30;
hold on
text(vermont.LabelLat, vermont.LabelLon, "VT", ...
    HorizontalAlignment = "center")
text(new_hampshire.LabelLat, new_hampshire.LabelLon, ...
    "NH", HorizontalAlignment = "center")
text(mht_lat, mht_lon, "✈", ...
    FontSize = 16, ...
    VerticalAlignment = "middle", ...
    HorizontalAlignment = "center", ...
    Rotation = plane_rotation);
text(btv_lat, btv_lon, "✈", ...
    FontSize = 16, ...
    VerticalAlignment = "middle", ...
    HorizontalAlignment = "center", ...
    Rotation = plane_rotation);
text(concord_lat, concord_lon, "★", ...
    HorizontalAlignment = "center", ...
    VerticalAlignment = "middle")
text(mp_lat, mp_lon, "★", ...
    HorizontalAlignment = "center", ...
    VerticalAlignment = "middle")
hold off

figure_5.png

With the map now completed, I can use exportgraphics to save the result to an image file at the desired resolution.

exportgraphics(h_geoaxes,"cormont_location.png", ...
    Resolution = 600)

figure_6.png