Skip to content

Commit 18bb101

Browse files
committed
Added tests
1 parent 27da50e commit 18bb101

File tree

10 files changed

+75
-44
lines changed

10 files changed

+75
-44
lines changed

lib/cartopy/mpl/feature_artist.py

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,6 @@ def draw(self, renderer, *args, **kwargs):
285285
stylised_paths = OrderedDict()
286286
key = ax.projection
287287

288-
skip_geoms = ["LineString", "LinearRing", "MultiLineString"]
289-
290288
for geom in geoms:
291289
# As Shapely geometries cannot be relied upon to be
292290
# hashable, we have to use a WeakValueDictionary to manage
@@ -314,12 +312,7 @@ def draw(self, renderer, *args, **kwargs):
314312
self._styler(geom))
315313
style = _freeze(style)
316314
if geom_paths is None:
317-
# Shapely can't represent the difference between a line and a
318-
# polygon. If all geoms are lines, bypass building the polygon
319-
# containing points projecting to infinity and use different
320-
# masking method.
321-
if (ax.projection != feature_crs) & \
322-
(geom.geom_type not in skip_geoms):
315+
if ax.projection != feature_crs:
323316
if feature_crs not in ax.projection.invalid_geoms.keys():
324317
invalid_geom = self.build_invalid_geom()
325318
ax.projection.invalid_geoms[feature_crs] = invalid_geom
@@ -334,40 +327,6 @@ def draw(self, renderer, *args, **kwargs):
334327
feature_crs)
335328
geom_paths = cpatch.geos_to_path(projected_geom)
336329
mapping[key] = geom_paths
337-
338-
elif (ax.projection != feature_crs) & \
339-
(geom.geom_type in skip_geoms):
340-
if isinstance(geom, sgeom.LineString):
341-
geom = sgeom.MultiLineString([geom])
342-
elif isinstance(geom, sgeom.LinearRing):
343-
geom = [geom]
344-
for subgeom in geom:
345-
x, y = np.array(subgeom.xy)
346-
xyz = ax.projection.transform_points(feature_crs, x, y)
347-
x_proj, y_proj = xyz[:, 0], xyz[:, 1]
348-
349-
inds_x = ~np.isfinite(x_proj)
350-
inds_y = ~np.isfinite(y_proj)
351-
inds = inds_x | inds_y
352-
353-
x_proj = np.ma.masked_array(x_proj, mask=inds)
354-
clump_slices = np.ma.clump_unmasked(x_proj)
355-
geom_paths = []
356-
for clump_slice in clump_slices:
357-
if clump_slice.stop - clump_slice.start > 1:
358-
xt = x[clump_slice]
359-
yt = y[clump_slice]
360-
cleaned_geom = sgeom.LineString(zip(xt, yt))
361-
projected_geom = \
362-
ax.projection.project_geometry(
363-
cleaned_geom, feature_crs
364-
)
365-
geom_paths.extend(
366-
cpatch.geos_to_path(projected_geom))
367-
if key not in mapping.keys():
368-
mapping[key] = geom_paths
369-
else:
370-
mapping[key].extend(geom_paths)
371330
else:
372331
geom_paths = cpatch.geos_to_path(geom)
373332
mapping[key] = geom_paths
Binary file not shown.
291 KB
Loading
93 KB
Loading
112 KB
Loading
112 KB
Loading
118 KB
Loading
3.31 KB
Loading
93.4 KB
Loading

lib/cartopy/tests/mpl/test_features.py

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,41 @@ def test_wfs():
6969

7070

7171
@pytest.mark.natural_earth
72-
@ImageTesting(['UTM_all_zones'])
73-
def test_utm_all():
72+
@ImageTesting(['UTM_coastlines'])
73+
def test_utm_coastlines():
7474
# this test fails because of padding (?) differences
7575
# probably solved with an rcParam
76+
# if a feature contains points that project to infinity the plot will have
77+
# artifacts
78+
# this tests coastlines and should replace the example in the gallery
7679
zones = range(1, 61)
7780
fig = plt.figure(figsize=(18, 6))
7881
for zone in zones:
7982
ax = fig.add_subplot(1, len(zones), zone,
8083
projection=ccrs.UTM(zone=zone,
8184
southern_hemisphere=True))
8285
ax.add_feature(cfeature.LAND, facecolor="tab:blue")
86+
ax.coastlines()
87+
88+
89+
@pytest.mark.natural_earth
90+
@ImageTesting(['tmerc_oceans'])
91+
def test_tmerc_oceans():
92+
# if a feature contains points that project to infinity the plot will have
93+
# artifacts
94+
# this tests polygons
95+
fig = plt.figure(figsize=(10, 7))
96+
proj = ccrs.TransverseMercator(central_longitude=18.14159, approx=False)
97+
ax = fig.add_subplot(1, 1, 1, projection=proj)
98+
ax.add_feature(cfeature.OCEAN.with_scale("10m"), facecolor="tab:blue")
99+
ax.coastlines()
83100

84101

85102
@pytest.mark.natural_earth
86103
@ImageTesting(['nonplatecarree_with_projected_hole'])
87104
def test_nonpc_hole():
105+
# tests the difference algo if a feature in a non-Plate Carree CRS is
106+
# passed
88107
lamaz_box = Polygon(((8.5e5, 1.1e6), (-8.5e5, 1.1e6),
89108
(-5.6e5, -1.2e6), (5.6e5, -1.2e6),
90109
(8.5e5, 1.1e6)))
@@ -99,3 +118,56 @@ def test_nonpc_hole():
99118
central_latitude=50.)
100119
ax2 = fig.add_subplot(1, 2, 2, projection=proj2)
101120
ax2.add_geometries([lamaz_box], crs=proj1, color="tab:blue")
121+
122+
123+
@pytest.mark.natural_earth
124+
@ImageTesting(['azimuthal_interior_rings'])
125+
def test_azi_interior_rings():
126+
# in cartopy <= 0.18 the following test produces an entirely blue plot
127+
# because the algo inverts ~6800 interior rings wrt the boundary instead of
128+
# treating them as holes
129+
fig = plt.figure(figsize=(10, 7))
130+
proj = ccrs.AzimuthalEquidistant(central_longitude=15, central_latitude=62)
131+
ax = fig.add_subplot(1, 1, 1, projection=proj)
132+
ax.add_feature(cfeature.OCEAN.with_scale("10m"), facecolor="tab:blue")
133+
ax.coastlines()
134+
135+
136+
@pytest.mark.natural_earth
137+
@ImageTesting(['lambert_equalarea_oceans'])
138+
def test_lam_eq_oceans():
139+
# Note: this test doesn't crash in 0.18 and does in 7e077e589d2a
140+
# in 0.18 it produces an entirely blue plot
141+
fig = plt.figure(figsize=(10, 7))
142+
proj = ccrs.LambertAzimuthalEqualArea(central_longitude=-62,
143+
central_latitude=-15)
144+
ax = fig.add_subplot(1, 1, 1, projection=proj)
145+
ax.add_feature(cfeature.OCEAN.with_scale("10m"), facecolor="tab:blue")
146+
ax.coastlines()
147+
148+
149+
@pytest.mark.natural_earth
150+
@ImageTesting(['lambert_exterior_rings'])
151+
def test_azi_exterior_rings():
152+
# in cartopy <= 0.18 the following test produces an entirely blue plot
153+
# because the algo doesn't subtract all interior rings from multiple
154+
# exterior rings that span the entire domain
155+
fig = plt.figure(figsize=(10, 7))
156+
proj = ccrs.LambertAzimuthalEqualArea(central_longitude=-62,
157+
central_latitude=15)
158+
ax = fig.add_subplot(1, 1, 1, projection=proj)
159+
ax.add_feature(cfeature.OCEAN.with_scale("10m"), facecolor="tab:blue")
160+
ax.coastlines()
161+
162+
163+
@pytest.mark.natural_earth
164+
@ImageTesting(['lambert_ring_flip'])
165+
def test_lam_ring_flip():
166+
# sometimes interior rings become exterior rings; test the containment
167+
# logic
168+
fig = plt.figure(figsize=(10, 7))
169+
proj = ccrs.LambertAzimuthalEqualArea(central_longitude=62,
170+
central_latitude=-50)
171+
ax = fig.add_subplot(1, 1, 1, projection=proj)
172+
ax.add_feature(cfeature.OCEAN.with_scale("10m"), facecolor="tab:blue")
173+
ax.coastlines()

0 commit comments

Comments
 (0)