Repository: SciTools/cartopy

Issue:
OSNI Projection Grid Lines seem to fail on version 0.17.0
Directly from pip
![image](https://user-images.githubusercontent.com/15331990/49490512-4458df00-f805-11e8-96b3-f2fc8ffa92c5.png)

cartopy==0.17.0
![image](https://user-images.githubusercontent.com/15331990/49490506-399e4a00-f805-11e8-898a-299a5a73cfee.png)

cartopy==0.16.0
![image](https://user-images.githubusercontent.com/15331990/49490540-618dad80-f805-11e8-9d6f-cb2ef74d9d96.png)



Discussion:
Bisect says 7d348d92694a079e861b5950790aa90040d384f2, which is a bit unexpected.

Resolving patch:
diff --git a/lib/cartopy/crs.py b/lib/cartopy/crs.py
--- a/lib/cartopy/crs.py
+++ b/lib/cartopy/crs.py
@@ -663,9 +663,8 @@ def __init__(self, proj4_params, half_width, half_height, globe=None):
 
     @property
     def boundary(self):
-        # XXX Should this be a LinearRing?
         w, h = self._half_width, self._half_height
-        return sgeom.LineString([(-w, -h), (-w, h), (w, h), (w, -h), (-w, -h)])
+        return sgeom.LinearRing([(-w, -h), (-w, h), (w, h), (w, -h), (-w, -h)])
 
     @property
     def x_limits(self):
@@ -838,7 +837,7 @@ def threshold(self):
     def boundary(self):
         x0, x1 = self.x_limits
         y0, y1 = self.y_limits
-        return sgeom.LineString([(x0, y0), (x0, y1),
+        return sgeom.LinearRing([(x0, y0), (x0, y1),
                                  (x1, y1), (x1, y0),
                                  (x0, y0)])
 
@@ -863,7 +862,7 @@ def __init__(self):
     def boundary(self):
         w = self.x_limits[1] - self.x_limits[0]
         h = self.y_limits[1] - self.y_limits[0]
-        return sgeom.LineString([(0, 0), (0, h), (w, h), (w, 0), (0, 0)])
+        return sgeom.LinearRing([(0, 0), (0, h), (w, h), (w, 0), (0, 0)])
 
     @property
     def x_limits(self):
@@ -889,7 +888,7 @@ def __init__(self):
     def boundary(self):
         w = self.x_limits[1] - self.x_limits[0]
         h = self.y_limits[1] - self.y_limits[0]
-        return sgeom.LineString([(0, 0), (0, h), (w, h), (w, 0), (0, 0)])
+        return sgeom.LinearRing([(0, 0), (0, h), (w, h), (w, 0), (0, 0)])
 
     @property
     def x_limits(self):
@@ -930,7 +929,7 @@ def __init__(self, zone, southern_hemisphere=False, globe=None):
     def boundary(self):
         x0, x1 = self.x_limits
         y0, y1 = self.y_limits
-        return sgeom.LineString([(x0, y0), (x0, y1),
+        return sgeom.LinearRing([(x0, y0), (x0, y1),
                                  (x1, y1), (x1, y0),
                                  (x0, y0)])
 
@@ -1059,7 +1058,7 @@ def threshold(self):
     def boundary(self):
         x0, x1 = self.x_limits
         y0, y1 = self.y_limits
-        return sgeom.LineString([(x0, y0), (x0, y1),
+        return sgeom.LinearRing([(x0, y0), (x0, y1),
                                  (x1, y1), (x1, y0),
                                  (x0, y0)])
 
diff --git a/lib/cartopy/mpl/patch.py b/lib/cartopy/mpl/patch.py
--- a/lib/cartopy/mpl/patch.py
+++ b/lib/cartopy/mpl/patch.py
@@ -45,6 +45,7 @@ def geos_to_path(shape):
         A list, tuple or single instance of any of the following
         types: :class:`shapely.geometry.point.Point`,
         :class:`shapely.geometry.linestring.LineString`,
+        :class:`shapely.geometry.linestring.LinearRing`,
         :class:`shapely.geometry.polygon.Polygon`,
         :class:`shapely.geometry.multipoint.MultiPoint`,
         :class:`shapely.geometry.multipolygon.MultiPolygon`,
@@ -64,7 +65,9 @@ def geos_to_path(shape):
             paths.extend(geos_to_path(shp))
         return paths
 
-    if isinstance(shape, (sgeom.LineString, sgeom.Point)):
+    if isinstance(shape, sgeom.LinearRing):
+        return [Path(np.column_stack(shape.xy), closed=True)]
+    elif isinstance(shape, (sgeom.LineString, sgeom.Point)):
         return [Path(np.column_stack(shape.xy))]
     elif isinstance(shape, sgeom.Polygon):
         def poly_codes(poly):


Test patch: