Repository: SciTools/cartopy

Issue:
Admin 1 features incompletely drawn in some cases
### Description
<!-- Please provide a general introduction to the issue/proposal. -->
Admin level 1 Natural Earth features are incompletely drawn in some cases - the script below creates a map showing the border between Illinois and Indiana, but that ends before the bottom of the map where Illinois, Indiana, and Kentucky all meet.  Attached is a map of the same data from Natural Earth plotted in QGIS, with the junction of the three states being shown.
![screen shot 2018-10-24 at 4 21 38 pm](https://user-images.githubusercontent.com/303058/47465311-a7d50300-d7a9-11e8-8470-a72f349e95f7.png)


<!--
If you are reporting a bug, attach the *entire* traceback from Python.

If you are proposing an enhancement/new feature, provide links to related articles, reference examples, etc.

If you are asking a question, please ask on StackOverflow and use the cartopy tag. All cartopy
questions on StackOverflow can be found at https://stackoverflow.com/questions/tagged/cartopy
-->

#### Code to reproduce

```
#!/usr/bin/env python


import cartopy.crs as ccrs  # projections
import cartopy.feature as cfeature
import matplotlib.pyplot as plt

BORDER_ZORDER = 1110

if __name__ == '__main__':
    bounds = (-88.76666666666667, -86.93333333333334,
              37.73333333333333, 39.18333333333333)
    figsize = (10.0, 9.947416426343834)
    xmin, xmax, ymin, ymax = bounds
    clon = (xmin + xmax) / 2
    if xmax < 0 and xmax < xmin:
        clon = (xmin + (xmax+360))/2

    clat = (ymin + ymax) / 2
    proj = ccrs.Mercator(central_longitude=clon,
                         min_latitude=ymin,
                         max_latitude=ymax,
                         globe=None)
    geoproj = ccrs.PlateCarree()
    figure = plt.figure(figsize=figsize)

    aspect = 0.9941078696774519

    # Note: dimensions are: [left, bottom, width, height]
    dim_left = 0.1
    dim_bottom = 0.19
    dim_width = 0.8
    dim_height = dim_width/aspect

    dimensions = [dim_left, dim_bottom, dim_width, dim_height]

    ax = figure.add_axes(dimensions, projection=proj)
    ax.set_extent([xmin, xmax, ymin, ymax], crs=geoproj)
    states_provinces = cfeature.NaturalEarthFeature(
        category='cultural',
        name='admin_1_states_provinces_lines',
        scale='10m',
        facecolor='none')

    ax.add_feature(states_provinces, edgecolor='black', zorder=BORDER_ZORDER)
    plt.savefig('maptest.png')

```

#### Traceback 

```

```

<details>
 <summary>Full environment definition</summary>

<!-- fill in the following information as appropriate -->

### Operating system


### Cartopy version


### conda list

```
```

### pip list

```
```

</details>



Discussion:
This seems to have something to do with the thresholding; you can get it to work by patching it with `proj._threshold /= 6`.

The threshold is determined by the x limits, but should probably check the y limits as well. I don't really know how the threshold calculation was chosen though, so I'm not sure what the best calculation should be there (just doing the same thing would produce a threshold much much smaller than 1/6).
I think it also works fine if you take out `min_latitude` because then it's not clipping that close to the map border.

Resolving patch:
diff --git a/lib/cartopy/crs.py b/lib/cartopy/crs.py
--- a/lib/cartopy/crs.py
+++ b/lib/cartopy/crs.py
@@ -1013,7 +1013,8 @@ def __init__(self, central_longitude=0.0,
                                        np.array([min_latitude, max_latitude]))
         self._xlimits = tuple(limits[..., 0])
         self._ylimits = tuple(limits[..., 1])
-        self._threshold = np.diff(self.x_limits)[0] / 720
+        self._threshold = min(np.diff(self.x_limits)[0] / 720,
+                              np.diff(self.y_limits)[0] / 360)
 
     def __eq__(self, other):
         res = super(Mercator, self).__eq__(other)


Test patch:
diff --git a/lib/cartopy/tests/mpl/test_set_extent.py b/lib/cartopy/tests/mpl/test_set_extent.py
--- a/lib/cartopy/tests/mpl/test_set_extent.py
+++ b/lib/cartopy/tests/mpl/test_set_extent.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2011 - 2017, Met Office
+# (C) British Crown Copyright 2011 - 2018, Met Office
 #
 # This file is part of cartopy.
 #
@@ -61,6 +61,26 @@ def test_extents():
                               )
 
 
+@cleanup
+def test_get_extent():
+    # tests that getting the extents of a map produces something reasonable.
+    uk = [-12.5, 4, 49, 60]
+    uk_crs = ccrs.PlateCarree()
+
+    ax = plt.axes(projection=ccrs.PlateCarree())
+    ax.set_extent(uk, crs=uk_crs)
+    assert_array_almost_equal(ax.get_extent(uk_crs), uk)
+
+    ax = plt.axes(projection=ccrs.Mercator())
+    ax.set_extent(uk, crs=uk_crs)
+    assert_array_almost_equal(ax.get_extent(uk_crs), uk)
+
+    ax = plt.axes(projection=ccrs.Mercator(min_latitude=uk[2],
+                                           max_latitude=uk[3]))
+    ax.set_extent(uk, crs=uk_crs)
+    assert_array_almost_equal(ax.get_extent(uk_crs), uk, decimal=1)
+
+
 @cleanup
 def test_domain_extents():
     # Setting the extent to global or the domain limits.