Coverage for pyguymer3/geo/_add_roads.py: 2%

42 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-08 18:47 +0000

1#!/usr/bin/env python3 

2 

3# Define function ... 

4def _add_roads( 

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 roads to a Cartopy axis. 

16 

17 Parameters 

18 ---------- 

19 axis : cartopy.mpl.geoaxes.GeoAxesSubplot 

20 the axis to add the roads 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 roads 

29 linewidth : float, optional 

30 the width of the roads 

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 roads 

36 

37 Notes 

38 ----- 

39 This function uses `CSS4 named colours 

40 <https://matplotlib.org/stable/gallery/color/named_colors.html>`_ . 

41 

42 Copyright 2017 Thomas Guymer [1]_ 

43 

44 References 

45 ---------- 

46 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3 

47 """ 

48 

49 # Import standard modules ... 

50 import os 

51 import urllib 

52 

53 # Import special modules ... 

54 try: 

55 import cartopy 

56 cartopy.config.update( 

57 { 

58 "cache_dir" : os.path.expanduser("~/.local/share/cartopy_cache"), 

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 

75 try: 

76 import shapely 

77 import shapely.geometry 

78 except: 

79 raise Exception("\"shapely\" is not installed; run \"pip install --user Shapely\"") from None 

80 

81 # Import sub-functions ... 

82 from .extract_lines import extract_lines 

83 

84 # ************************************************************************** 

85 

86 # Create suitable colour ... 

87 edgecolor = matplotlib.colors.to_rgba(matplotlib.colors.CSS4_COLORS["red"]) 

88 if debug: 

89 print(f"INFO: \"roads\" is ({edgecolor[0]:.6f},{edgecolor[1]:.6f},{edgecolor[2]:.6f},{edgecolor[3]:.6f}).") 

90 

91 # Define names ... 

92 names = [ 

93 "roads", 

94 "roads_north_america", 

95 ] 

96 

97 # Loop over names ... 

98 for name in names: 

99 # Find file containing the shapes ... 

100 try: 

101 sfile = cartopy.io.shapereader.natural_earth( 

102 resolution = resolution, 

103 category = "cultural", 

104 name = name, 

105 ) 

106 except urllib.error.HTTPError: 

107 continue 

108 if debug: 

109 print(f"INFO: \"{name}\" is \"{sfile}\".") 

110 

111 # Loop over records ... 

112 for record in cartopy.io.shapereader.Reader(sfile).records(): 

113 # Skip bad records ... 

114 if not hasattr(record, "geometry"): 

115 continue 

116 

117 # Create a list of LineStrings to plot (taking in to account if the 

118 # user provided a field-of-view to clip them by) ... 

119 lines = [] 

120 for line in extract_lines( 

121 record.geometry, 

122 onlyValid = onlyValid, 

123 ): 

124 if fov is None: 

125 lines.append(line) 

126 continue 

127 if line.disjoint(fov): 

128 continue 

129 lines.append(line.intersection(fov)) 

130 

131 # Plot geometry ... 

132 ax.add_geometries( 

133 lines, 

134 cartopy.crs.PlateCarree(), 

135 edgecolor = edgecolor, 

136 facecolor = "none", 

137 linestyle = linestyle, 

138 linewidth = linewidth, 

139 )