Coverage for pyguymer3/geo/_add_railroads.py: 3%
37 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-16 08:31 +0000
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-16 08:31 +0000
1#!/usr/bin/env python3
3# Define function ...
4def _add_railroads(
5 ax,
6 /,
7 *,
8 debug = __debug__,
9 fov = None,
10 linestyle = "solid",
11 linewidth = 0.5,
12 onlyValid = False,
13 resolution = "10m",
14):
15 """Add railroads to a Cartopy axis.
17 Parameters
18 ----------
19 axis : cartopy.mpl.geoaxes.GeoAxesSubplot
20 the axis to add the railroads to
21 debug : bool, optional
22 print debug messages
23 fov : None or shapely.geometry.polygon.Polygon, optional
24 clip the plotted shapes to the provided field-of-view to work around
25 occaisional MatPlotLib or Cartopy plotting errors when shapes much
26 larger than the field-of-view are plotted
27 linestyle : str, optional
28 the style of the railroads
29 linewidth : float, optional
30 the width of the railroads
31 onlyValid : bool, optional
32 only add valid LinearRings and LineStrings (checks for validity can take
33 a while, if being being called often)
34 resolution : str, optional
35 the resolution of the railroads
37 Notes
38 -----
39 This function uses `CSS4 named colours
40 <https://matplotlib.org/stable/gallery/color/named_colors.html>`_ .
42 Copyright 2017 Thomas Guymer [1]_
44 References
45 ----------
46 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
47 """
49 # Import standard modules ...
50 import pathlib
51 import urllib
53 # Import special modules ...
54 try:
55 import cartopy
56 cartopy.config.update(
57 {
58 "cache_dir" : pathlib.PosixPath("~/.local/share/cartopy_cache").expanduser(),
59 }
60 )
61 except:
62 raise Exception("\"cartopy\" is not installed; run \"pip install --user Cartopy\"") from None
63 try:
64 import matplotlib
65 matplotlib.rcParams.update(
66 {
67 "backend" : "Agg", # NOTE: See https://matplotlib.org/stable/gallery/user_interfaces/canvasagg.html
68 "figure.dpi" : 300,
69 "figure.figsize" : (9.6, 7.2), # NOTE: See https://github.com/Guymer/misc/blob/main/README.md#matplotlib-figure-sizes
70 "font.size" : 8,
71 }
72 )
73 except:
74 raise Exception("\"matplotlib\" is not installed; run \"pip install --user matplotlib\"") from None
76 # Import sub-functions ...
77 from .extract_lines import extract_lines
79 # **************************************************************************
81 # Create suitable colour ...
82 edgecolor = matplotlib.colors.to_rgba(matplotlib.colors.CSS4_COLORS["black"])
83 if debug:
84 print(f"INFO: \"railroads\" is ({edgecolor[0]:.6f},{edgecolor[1]:.6f},{edgecolor[2]:.6f},{edgecolor[3]:.6f}).")
86 # Define names ...
87 names = [
88 "railroads",
89 "railroads_north_america",
90 ]
92 # Loop over names ...
93 for name in names:
94 # Find file containing the shapes ...
95 try:
96 sfile = cartopy.io.shapereader.natural_earth(
97 resolution = resolution,
98 category = "cultural",
99 name = name,
100 )
101 except urllib.error.HTTPError:
102 continue
103 if debug:
104 print(f"INFO: \"{name}\" is \"{sfile}\".")
106 # Loop over records ...
107 for record in cartopy.io.shapereader.Reader(sfile).records():
108 # Skip bad records ...
109 if not hasattr(record, "geometry"):
110 continue
112 # Create a list of LineStrings to plot (taking in to account if the
113 # user provided a field-of-view to clip them by) ...
114 lines = []
115 for line in extract_lines(
116 record.geometry,
117 onlyValid = onlyValid,
118 ):
119 if fov is None:
120 lines.append(line)
121 continue
122 if line.disjoint(fov):
123 continue
124 lines.append(line.intersection(fov))
126 # Plot geometry ...
127 ax.add_geometries(
128 lines,
129 cartopy.crs.PlateCarree(),
130 edgecolor = edgecolor,
131 facecolor = "none",
132 linestyle = linestyle,
133 linewidth = linewidth,
134 )