0

I want to plot mileposts on a map every 100 miles along the coastline. An example is shown in the figure below: enter image description here

It is easy to plot the coastlines using Cartopy, but how to determine the locations of these mileposts and show them on a map? It would be better if the coastlines between the points were colored.

Feng Hu
  • 63
  • 6

1 Answers1

1

You can use Shapely's interpolate method to figure out the location of the mileposts. However, the tricky part of this is getting a singlepart linestring for the coastline. I messed around with a few coastline shapefiles that I downloaded, but due to the complexity and distance, getting a nice singlepart linestring was not a simple task. Therefore, I chose to digitize my own for this example (digitize.shp).

import geopandas as gpd
import numpy as np
import matplotlib
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

# hand digitized simplified version of coastline
cl_gdf = gpd.read_file("digitize.shp")


# project data from geographic crs so we have meters for interpolation below, vs degrees
cl_gdf = cl_gdf.to_crs(9311)

# get shapely ls from gdf
coastline = cl_gdf.iloc[0].geometry

interval = 160934 # approx 100 miles in meters
interval_arr = np.arange(0, coastline.length, interval )
points = [coastline.interpolate(d) for d in interval_arr] + [coastline.boundary[1]]

# create gdf from our list of interpolated Shapely points
points_gdf = gpd.GeoDataFrame(geometry=points, crs=9311)

# transform crs to wgs84 for plotting
points_gdf = points_gdf.to_crs(4326)

# add Lat and Long cols from geometry for plotting
points_gdf['Lat'] = (points_gdf['geometry'].apply(lambda geom: np.max([coord[1] for coord in geom.coords])))
points_gdf['Long'] = (points_gdf['geometry'].apply(lambda geom: np.max([coord[0] for coord in geom.coords])))

ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines()

ax.set_extent([points_gdf['Long'].min() - 1,
               points_gdf['Long'].max() + 1,
               points_gdf['Lat'].min() - 1,
               points_gdf['Lat'].max() + 1], 
              crs=ccrs.PlateCarree())
              
# add our interpolated points to the Cartopy coastline
ax.scatter(points_gdf['Long'], points_gdf['Lat'], color='red', s=10)

fig = matplotlib.pyplot.gcf()
fig.set_size_inches(18.5, 10.5)

plt.show()

enter image description here

EDIT:

Here is a replacement for "digitize.shp" for a full working example. You can use gpd's to_file() if you want to save cl_gdf to a shapefile.

from shapely.geometry import LineString

ls_coords = [(-84.35698841221803, 29.95854398344339),
 (-84.05368623055452, 30.09279249008134),
 (-83.96252983715839, 30.0613020996354),
 (-83.7586709937452, 29.908822314318225),
 (-83.44376708928581, 29.68673219222582),
 (-83.40854757365547, 29.657727885236138),
 (-83.16946921461201, 29.28191493609843),
 (-82.7551219719023, 28.99684403311415),
 (-82.66893774541866, 28.698514018363166),
 (-82.68219685718537, 28.439961338912305),
 (-82.79489930720241, 28.158205213869703),
 (-82.63910474394356, 27.94937420354401),
 (-82.54629096157659, 27.641099854967987),
 (-82.63578996600191, 27.392491509342157),
 (-82.26122005859231, 26.72290636512327),
 (-81.52533935553987, 25.88095276793714),
 (-80.85243943337927, 25.168275510476434),
 (-80.7596256510123, 25.14175728694301),
 (-80.65355275687861, 25.150044231797207),
 (-80.59222936495757, 25.176562455330625),
 (-80.49278602670725, 25.206395456805726),
 (-80.65355275687864, 24.90143588617138),
 (-80.53587813994908, 25.03236961486765),
 (-80.23920551416893, 25.340643963443675),
 (-80.27069590461487, 25.353903075210386),
 (-80.37345402080688, 25.312468350939415),
 (-80.104957007531, 25.963822216479077),
 (-80.07180922811422, 26.91847826368225),
 (-80.66846925761622, 28.60238545805451),
 (-80.72150570468307, 28.86756769338872),
 (-81.19883372828465, 29.663114399391368),
 (-81.43749774008545, 30.392365546560455),
 (-81.47727507538558, 31.095098470196124),
 (-81.26512928711821, 31.406687596713834),
 (-81.09276083415097, 31.844238285015287),
 (-80.7612830399832, 32.175716079183054),
 (-80.48947124876561, 32.48067564981741),
 (-80.07180922811422, 32.61326676748452),
 (-79.32929896917841, 33.07070612343603),
 (-79.20996696327803, 33.22981546463656),
 (-78.9779325073606, 33.61432970587117),
 (-78.55364093082585, 33.8331050500219),
 (-77.93046267779044, 33.919289276505516),
 (-77.71831688952308, 34.28391485009006),
 (-77.45976421007221, 34.469542414824005),
 (-75.76259790393324, 35.20542311787645),
 (-75.76259790393324, 36.21974516802982),
 (-75.84215257453349, 36.58437074161438),
 (-76.17031559075959, 36.939051981373886),
 (-76.29959193048501, 36.96722759387815),
 (-76.2946197635725, 37.12136476816616),
 (-76.41726654741457, 37.16942904832049),
 (-76.50179338492735, 37.23738199612488),
 (-76.3377118768143, 37.5108511763133),
 (-76.72885567393226, 37.79923685723926),
 (-76.76200345334904, 37.878791527839525),
 (-76.31119365328087, 37.68653440722222),
 (-76.23163898268061, 37.89205063960623),
 (-76.35428576652268, 37.951716642556434),
 (-76.38411876799778, 37.95668880946896),
 (-76.50676555183985, 38.02298436830251),
 (-76.52665421948991, 38.05613214771928),
 (-76.6028941121485, 38.10253903890277),
 (-76.60952366803185, 38.12905726243619),
 (-76.85978940262852, 38.16717720876549),
 (-76.90785368278284, 38.19203804332807),
 (-76.94265885117046, 38.2102693220073),
 (-77.01724135485821, 38.313027438199306),
 (-77.01724135485821, 38.31799960511182),
 (-77.26916447842571, 38.3428604396744),
 (-77.30396964681333, 38.38263777497453),
 (-77.29568270195914, 38.52517322646668),
 (-77.23270192106726, 38.60804267500862),
 (-77.21612803135888, 38.63953306545456),
 (-77.17966547400042, 38.613014841921135),
 (-76.96254751882053, 38.4108133874788),
 (-76.81338251144503, 38.27987965878253),
 (-76.41063699153119, 38.311370049228465),
 (-76.53825594228582, 38.710800791200626),
 (-76.53494116434413, 39.2047027045106),
 (-76.0808165863343, 39.532865720736694),
 (-76.02446536132577, 39.370441601594486),
 (-76.06755747456758, 39.254424373635764),
 (-76.14048258928449, 39.101944588318595),
 (-76.1835747025263, 38.956094358884776),
 (-76.196833814293, 38.88316924416787),
 (-76.18688948046797, 38.76383723826747),
 (-76.17031559075959, 38.64782001030875),
 (-76.094075698101, 38.51854367058332),
 (-75.98468802602564, 38.33291610584937),
 (-75.89850379954201, 38.24341710142407),
 (-75.84546735247517, 38.190380654357234),
 (-75.77917179364162, 38.10419642787361),
 (-75.69961712304135, 38.011382645506636),
 (-75.65652500979955, 37.95171664255644),
 (-75.66978412156625, 37.91525408519799),
 (-75.92502202307544, 37.54068417778841),
 (-75.76591268187491, 37.481018174838205),
 (-75.67972845539128, 37.46112950718814),
 (-75.62337723038277, 37.48433295277989),
 (-75.58359989508264, 37.59703540279693),
 (-75.2189743214981, 38.051159980806766),
 (-75.05655020235588, 38.37600821909118),
 (-75.03666153470581, 38.44893333380809),
 (-75.39465755240701, 39.1450367015604),
 (-75.50404522448237, 39.39033026924455),
 (-75.54713733772417, 39.536180498678355),
 (-75.5438225597825, 39.60413344648275),
 (-75.50901739139488, 39.57595783397849),
 (-75.51896172521991, 39.48977360749487),
 (-75.50073044654069, 39.45331105013641),
 (-75.45100877741551, 39.41684849277796),
 (-75.3996297193195, 39.38701549130286),
 (-75.33333416048596, 39.34889554497357),
 (-75.2753255465066, 39.31409037658595),
 (-75.17588220825627, 39.27431304128582),
 (-75.07146670309342, 39.23453570598569),
 (-74.95710686410554, 39.19144359274388),
 (-74.8957834721845, 39.169897536122974),
 (-74.53778745448334, 39.270998263344154),
 (-74.29249388679919, 39.46325538396146),
 (-74.10023676618188, 39.89417651637956),
 (-74.02731165146497, 40.046656301696736),
 (-74.13338454559866, 40.32509764879766),
 (-74.23945743973235, 40.4974661017649),
 (-74.07371854264846, 40.550502548831744),
 (-73.80853630731424, 40.56376166059845),
 (-73.60302007493023, 40.550502548831744),
 (-73.4439107337297, 40.61016855178194),
 (-73.39750384254621, 40.70298233414891),
 (-73.41739251019628, 40.88198034299951),
 (-73.42070728813798, 40.935016790066356),
 (-73.62953829846366, 40.8985542327079),
 (-73.77207374995581, 40.83225867387435),
 (-73.7588146381891, 40.931702012124674),
 (-73.53672451609668, 41.031145350375006),
 (-73.15552505280375, 41.1504773562754),
 (-72.96658271012812, 41.17368080186715),
 (-71.70033753640726, 41.35930836660109),
 (-71.04401150395508, 41.50515859603491),
 (-70.70590415390394, 41.65100882546872),
 (-70.68601548625388, 41.670897493118794),
 (-70.67938593037053, 41.51178815191826),
 (-70.61309037153697, 41.53830637545168),
 (-70.5070174774033, 41.76371127548577),
 (-70.54016525682006, 41.86978416961945),
 (-70.6528677068371, 42.00237528728656),
 (-70.77882926862085, 42.247668854970726),
 (-70.93130905393804, 42.41340775205461),
 (-70.91142038628796, 42.5924057609052),
 (-70.86501349510448, 42.65870131973875),
 (-70.54679481270341, 43.32165690807428),
 (-70.19542835088558, 43.63987559047534),
 (-69.74461855081742, 43.81887359932593),
 (-69.53910231843341, 43.885169158159485),
 (-68.96233095658148, 44.289572067044155),
 (-68.81648072714766, 44.44868140824468),
 (-68.41207781826299, 44.48845874354482),
 (-67.91486112701133, 44.42216318471126),
 (-67.61653111226035, 44.52823607884495),
 (-67.09942575335863, 44.70723408769554),
 (-67.02650063864172, 44.760270534762384)]

ls = LineString(ls_coords)
cl_gdf = gpd.GeoDataFrame(geometry=[ls], crs=4326) 
Matthew Borish
  • 3,016
  • 2
  • 13
  • 25
  • Thanks for your answer, Matthew. Another question is how to make this customized shapefile within a particular region. Otherwise I cannot compute the locations of these points. – Feng Hu Jan 08 '23 at 11:55
  • It took about 3 minutes to trace the coast and make a simple singlepart polyline shapefile in QGIS. If you want to show your map at a finer scale, you may want to spend more time digitizing or experiment with other files you may be able to find online. The challenge with most of what's already available to download is that the they are made of of complex multipart geometries with many parts less than 100 miles in length, So it is not easy to add points at 100 mile intervals. You would either need to simplify it through dissolving or come up with a much more complicated way to add points. – Matthew Borish Jan 08 '23 at 18:34
  • @FengHu please see my edit to give you a better idea of my hand-digitized coastline, digitize.shp, that I used in my original answer. – Matthew Borish Jan 08 '23 at 22:52
  • Thanks for your further work. It helps. I gave you the answer. – Feng Hu Jan 09 '23 at 15:29