Coverage for pyguymer3/geo/_add_urbanAreas.py: 3%
35 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_urbanAreas(
5 ax,
6 /,
7 *,
8 debug = __debug__,
9 fov = None,
10 onlyValid = False,
11 repair = False,
12 resolution = "10m",
13):
14 """Add urban areas to a Cartopy axis.
16 Parameters
17 ----------
18 axis : cartopy.mpl.geoaxes.GeoAxesSubplot
19 the axis to add the urban areas to
20 debug : bool, optional
21 print debug messages
22 fov : None or shapely.geometry.polygon.Polygon, optional
23 clip the plotted shapes to the provided field-of-view to work around
24 occaisional MatPlotLib or Cartopy plotting errors when shapes much
25 larger than the field-of-view are plotted
26 onlyValid : bool, optional
27 only add valid Polygons (checks for validity can take a while, if being
28 being called often)
29 repair : bool, optional
30 attempt to repair invalid Polygons
31 resolution : str, optional
32 the resolution of the urban areas
34 Notes
35 -----
36 This function uses `CSS4 named colours
37 <https://matplotlib.org/stable/gallery/color/named_colors.html>`_ .
39 Copyright 2017 Thomas Guymer [1]_
41 References
42 ----------
43 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
44 """
46 # Import standard modules ...
47 import pathlib
48 import urllib
50 # Import special modules ...
51 try:
52 import cartopy
53 cartopy.config.update(
54 {
55 "cache_dir" : pathlib.PosixPath("~/.local/share/cartopy_cache").expanduser(),
56 }
57 )
58 except:
59 raise Exception("\"cartopy\" is not installed; run \"pip install --user Cartopy\"") from None
60 try:
61 import matplotlib
62 matplotlib.rcParams.update(
63 {
64 "backend" : "Agg", # NOTE: See https://matplotlib.org/stable/gallery/user_interfaces/canvasagg.html
65 "figure.dpi" : 300,
66 "figure.figsize" : (9.6, 7.2), # NOTE: See https://github.com/Guymer/misc/blob/main/README.md#matplotlib-figure-sizes
67 "font.size" : 8,
68 }
69 )
70 except:
71 raise Exception("\"matplotlib\" is not installed; run \"pip install --user matplotlib\"") from None
73 # Import sub-functions ...
74 from .extract_polys import extract_polys
76 # **************************************************************************
78 # Create suitable colour ...
79 facecolor = matplotlib.colors.to_rgba(matplotlib.colors.CSS4_COLORS["gold"])
80 if debug:
81 print(f"INFO: \"urban_areas\" is ({facecolor[0]:.6f},{facecolor[1]:.6f},{facecolor[2]:.6f},{facecolor[3]:.6f}).")
83 # Find file containing the shapes ...
84 try:
85 sfile = cartopy.io.shapereader.natural_earth(
86 resolution = resolution,
87 category = "cultural",
88 name = "urban_areas",
89 )
90 except urllib.error.HTTPError:
91 return
92 if debug:
93 print(f"INFO: \"urban_areas\" is \"{sfile}\".")
95 # Loop over records ...
96 for record in cartopy.io.shapereader.Reader(sfile).records():
97 # Skip bad records ...
98 if not hasattr(record, "geometry"):
99 continue
101 # Create a list of Polygons to plot (taking in to account if the user
102 # provided a field-of-view to clip them by) ...
103 polys = []
104 for poly in extract_polys(
105 record.geometry,
106 onlyValid = onlyValid,
107 repair = repair,
108 ):
109 if fov is None:
110 polys.append(poly)
111 continue
112 if poly.disjoint(fov):
113 continue
114 polys.append(poly.intersection(fov))
116 # Plot geometry ...
117 ax.add_geometries(
118 polys,
119 cartopy.crs.PlateCarree(),
120 edgecolor = "none",
121 facecolor = facecolor,
122 )