We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
cartopy coastlines issue with shapely 1.5.13
With shapely 1.5.13 the following cartopy example generates an incomplete figure:

```
import os
import matplotlib.pyplot as plt

from cartopy import config
import cartopy.crs as ccrs


fig = plt.figure(figsize=(8, 12))

# get the path of the file. It can be found in the repo data directory.
fname = os.path.join(config["repo_data_dir"],
                     'raster', 'sample', 'Miriam.A2012270.2050.2km.jpg'
                     )
img_extent = (-120.67660000000001, -106.32104523100001, 13.2301484511245, 30.766899999999502)
img = plt.imread(fname)

ax = plt.axes(projection=ccrs.PlateCarree())
plt.title('Hurricane Miriam from the Aqua/MODIS satellite\n'
          '2012 09/26/2012 20:50 UTC')

# set a margin around the data
ax.set_xmargin(0.05)
ax.set_ymargin(0.10)

# add the image. Because this image was a tif, the "origin" of the image is in the
# upper left corner
ax.imshow(img, origin='upper', extent=img_extent, transform=ccrs.PlateCarree())
ax.coastlines(resolution='50m', color='black', linewidth=1)

# mark a known place to help us geo-locate ourselves
ax.plot(-117.1625, 32.715, 'bo', markersize=7, transform=ccrs.Geodetic())
ax.text(-117, 33, 'San Diego', transform=ccrs.Geodetic())

plt.show()
```

I think the error comes from the ax.coastlines line. The error goes away by reverting back to shapely 1.5.12. 
Otherwise I'm using cartopy 0.13.0 and matplotlib 1.4.3 on CentOS 6.
The code comes from http://scitools.org.uk/cartopy/docs/latest/matplotlib/advanced_plotting.html.

Thought this might be useful to know.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/cartopy/mpl/feature_artist.py`
Content:
```
1 # (C) British Crown Copyright 2011 - 2015, Met Office
2 #
3 # This file is part of cartopy.
4 #
5 # cartopy is free software: you can redistribute it and/or modify it under
6 # the terms of the GNU Lesser General Public License as published by the
7 # Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # cartopy is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with cartopy.  If not, see <http://www.gnu.org/licenses/>.
17 """
18 This module defines the :class:`FeatureArtist` class, for drawing
19 :class:`Feature` instances with matplotlib.
20 
21 """
22 
23 from __future__ import (absolute_import, division, print_function)
24 
25 import warnings
26 import weakref
27 
28 import matplotlib.artist
29 import matplotlib.collections
30 
31 import cartopy.mpl.patch as cpatch
32 
33 
34 class FeatureArtist(matplotlib.artist.Artist):
35     """
36     A subclass of :class:`~matplotlib.artist.Artist` capable of
37     drawing a :class:`cartopy.feature.Feature`.
38 
39     """
40     _geometry_to_path_cache = weakref.WeakKeyDictionary()
41     """
42     A nested mapping from geometry and target projection to the
43     resulting transformed matplotlib paths::
44 
45         {geom: {target_projection: list_of_paths}}
46 
47     This provides a significant boost when producing multiple maps of the
48     same projection.
49 
50     """
51     def __init__(self, feature, **kwargs):
52         """
53         Args:
54 
55         * feature:
56             an instance of :class:`cartopy.feature.Feature` to draw.
57         * kwargs:
58             keyword arguments to be used when drawing the feature. These
59             will override those shared with the feature.
60 
61         """
62         super(FeatureArtist, self).__init__()
63 
64         if kwargs is None:
65             kwargs = {}
66         self._kwargs = dict(kwargs)
67 
68         # Set default zorder so that features are drawn before
69         # lines e.g. contours but after images.
70         # Note that the zorder of Patch, PatchCollection and PathCollection
71         # are all 1 by default. Assuming equal zorder drawing takes place in
72         # the following order: collections, patches, lines (default zorder=2),
73         # text (default zorder=3), then other artists e.g. FeatureArtist.
74         if self._kwargs.get('zorder') is not None:
75             self.set_zorder(self._kwargs['zorder'])
76         elif feature.kwargs.get('zorder') is not None:
77             self.set_zorder(feature.kwargs['zorder'])
78         else:
79             # The class attribute matplotlib.collections.PathCollection.zorder
80             # was removed after mpl v1.2.0, so the hard-coded value of 1 is
81             # used instead.
82             self.set_zorder(1)
83 
84         self._feature = feature
85 
86     @matplotlib.artist.allow_rasterization
87     def draw(self, renderer, *args, **kwargs):
88         """
89         Draws the geometries of the feature that intersect with the extent of
90         the :class:`cartopy.mpl.GeoAxes` instance to which this
91         object has been added.
92 
93         """
94         if not self.get_visible():
95             return
96 
97         ax = self.get_axes()
98         feature_crs = self._feature.crs
99 
100         # Get geometries that we need to draw.
101         extent = None
102         try:
103             extent = ax.get_extent(feature_crs)
104         except ValueError:
105             warnings.warn('Unable to determine extent. Defaulting to global.')
106         geoms = self._feature.intersecting_geometries(extent)
107 
108         # Project (if necessary) and convert geometries to matplotlib paths.
109         paths = []
110         key = ax.projection
111         for geom in geoms:
112             mapping = FeatureArtist._geometry_to_path_cache.setdefault(geom,
113                                                                        {})
114             geom_paths = mapping.get(key)
115             if geom_paths is None:
116                 if ax.projection != feature_crs:
117                     projected_geom = ax.projection.project_geometry(
118                         geom, feature_crs)
119                 else:
120                     projected_geom = geom
121                 geom_paths = cpatch.geos_to_path(projected_geom)
122                 mapping[key] = geom_paths
123             paths.extend(geom_paths)
124 
125         # Build path collection and draw it.
126         transform = ax.projection._as_mpl_transform(ax)
127         # Combine all the keyword args in priority order
128         final_kwargs = dict(self._feature.kwargs)
129         final_kwargs.update(self._kwargs)
130         final_kwargs.update(kwargs)
131         c = matplotlib.collections.PathCollection(paths,
132                                                   transform=transform,
133                                                   **final_kwargs)
134         c.set_clip_path(ax.patch)
135         c.set_figure(ax.figure)
136         return c.draw(renderer)
137
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lib/cartopy/mpl/feature_artist.py b/lib/cartopy/mpl/feature_artist.py
--- a/lib/cartopy/mpl/feature_artist.py
+++ b/lib/cartopy/mpl/feature_artist.py
@@ -31,16 +31,43 @@
 import cartopy.mpl.patch as cpatch
 
 
+class _GeomKey(object):
+    """
+    Provide id() based equality and hashing for geometries.
+
+    Instances of this class must be treated as immutable for the caching
+    to operate correctly.
+
+    A workaround for Shapely polygons no longer being hashable as of 1.5.13.
+
+    """
+    def __init__(self, geom):
+        self._id = id(geom)
+
+    def __eq__(self, other):
+        return self._id == other._id
+
+    def __hash__(self):
+        return hash(self._id)
+
+
 class FeatureArtist(matplotlib.artist.Artist):
     """
     A subclass of :class:`~matplotlib.artist.Artist` capable of
     drawing a :class:`cartopy.feature.Feature`.
 
     """
-    _geometry_to_path_cache = weakref.WeakKeyDictionary()
+
+    _geom_key_to_geometry_cache = weakref.WeakValueDictionary()
     """
-    A nested mapping from geometry and target projection to the
-    resulting transformed matplotlib paths::
+    A mapping from _GeomKey to geometry to assist with the caching of
+    transformed matplotlib paths.
+
+    """
+    _geom_key_to_path_cache = weakref.WeakKeyDictionary()
+    """
+    A nested mapping from geometry (converted to a _GeomKey) and target
+    projection to the resulting transformed matplotlib paths::
 
         {geom: {target_projection: list_of_paths}}
 
@@ -48,6 +75,7 @@
     same projection.
 
     """
+
     def __init__(self, feature, **kwargs):
         """
         Args:
@@ -109,8 +137,22 @@
         paths = []
         key = ax.projection
         for geom in geoms:
-            mapping = FeatureArtist._geometry_to_path_cache.setdefault(geom,
-                                                                       {})
+            # As Shapely geometries cannot be relied upon to be
+            # hashable, we have to use a WeakValueDictionary to manage
+            # their weak references. The key can then be a simple,
+            # "disposable", hashable geom-key object that just uses the
+            # id() of a geometry to determine equality and hash value.
+            # The only persistent, strong reference to the geom-key is
+            # in the WeakValueDictionary, so when the geometry is
+            # garbage collected so is the geom-key.
+            # The geom-key is also used to access the WeakKeyDictionary
+            # cache of transformed geometries. So when the geom-key is
+            # garbage collected so are the transformed geometries.
+            geom_key = _GeomKey(geom)
+            FeatureArtist._geom_key_to_geometry_cache.setdefault(
+                geom_key, geom)
+            mapping = FeatureArtist._geom_key_to_path_cache.setdefault(
+                geom_key, {})
             geom_paths = mapping.get(key)
             if geom_paths is None:
                 if ax.projection != feature_crs:

{"golden_diff": "diff --git a/lib/cartopy/mpl/feature_artist.py b/lib/cartopy/mpl/feature_artist.py\n--- a/lib/cartopy/mpl/feature_artist.py\n+++ b/lib/cartopy/mpl/feature_artist.py\n@@ -31,16 +31,43 @@\n import cartopy.mpl.patch as cpatch\n \n \n+class _GeomKey(object):\n+    \"\"\"\n+    Provide id() based equality and hashing for geometries.\n+\n+    Instances of this class must be treated as immutable for the caching\n+    to operate correctly.\n+\n+    A workaround for Shapely polygons no longer being hashable as of 1.5.13.\n+\n+    \"\"\"\n+    def __init__(self, geom):\n+        self._id = id(geom)\n+\n+    def __eq__(self, other):\n+        return self._id == other._id\n+\n+    def __hash__(self):\n+        return hash(self._id)\n+\n+\n class FeatureArtist(matplotlib.artist.Artist):\n     \"\"\"\n     A subclass of :class:`~matplotlib.artist.Artist` capable of\n     drawing a :class:`cartopy.feature.Feature`.\n \n     \"\"\"\n-    _geometry_to_path_cache = weakref.WeakKeyDictionary()\n+\n+    _geom_key_to_geometry_cache = weakref.WeakValueDictionary()\n     \"\"\"\n-    A nested mapping from geometry and target projection to the\n-    resulting transformed matplotlib paths::\n+    A mapping from _GeomKey to geometry to assist with the caching of\n+    transformed matplotlib paths.\n+\n+    \"\"\"\n+    _geom_key_to_path_cache = weakref.WeakKeyDictionary()\n+    \"\"\"\n+    A nested mapping from geometry (converted to a _GeomKey) and target\n+    projection to the resulting transformed matplotlib paths::\n \n         {geom: {target_projection: list_of_paths}}\n \n@@ -48,6 +75,7 @@\n     same projection.\n \n     \"\"\"\n+\n     def __init__(self, feature, **kwargs):\n         \"\"\"\n         Args:\n@@ -109,8 +137,22 @@\n         paths = []\n         key = ax.projection\n         for geom in geoms:\n-            mapping = FeatureArtist._geometry_to_path_cache.setdefault(geom,\n-                                                                       {})\n+            # As Shapely geometries cannot be relied upon to be\n+            # hashable, we have to use a WeakValueDictionary to manage\n+            # their weak references. The key can then be a simple,\n+            # \"disposable\", hashable geom-key object that just uses the\n+            # id() of a geometry to determine equality and hash value.\n+            # The only persistent, strong reference to the geom-key is\n+            # in the WeakValueDictionary, so when the geometry is\n+            # garbage collected so is the geom-key.\n+            # The geom-key is also used to access the WeakKeyDictionary\n+            # cache of transformed geometries. So when the geom-key is\n+            # garbage collected so are the transformed geometries.\n+            geom_key = _GeomKey(geom)\n+            FeatureArtist._geom_key_to_geometry_cache.setdefault(\n+                geom_key, geom)\n+            mapping = FeatureArtist._geom_key_to_path_cache.setdefault(\n+                geom_key, {})\n             geom_paths = mapping.get(key)\n             if geom_paths is None:\n                 if ax.projection != feature_crs:\n", "issue": "cartopy coastlines issue with shapely 1.5.13\nWith shapely 1.5.13 the following cartopy example generates an incomplete figure:\n\n```\nimport os\nimport matplotlib.pyplot as plt\n\nfrom cartopy import config\nimport cartopy.crs as ccrs\n\n\nfig = plt.figure(figsize=(8, 12))\n\n# get the path of the file. It can be found in the repo data directory.\nfname = os.path.join(config[\"repo_data_dir\"],\n                     'raster', 'sample', 'Miriam.A2012270.2050.2km.jpg'\n                     )\nimg_extent = (-120.67660000000001, -106.32104523100001, 13.2301484511245, 30.766899999999502)\nimg = plt.imread(fname)\n\nax = plt.axes(projection=ccrs.PlateCarree())\nplt.title('Hurricane Miriam from the Aqua/MODIS satellite\\n'\n          '2012 09/26/2012 20:50 UTC')\n\n# set a margin around the data\nax.set_xmargin(0.05)\nax.set_ymargin(0.10)\n\n# add the image. Because this image was a tif, the \"origin\" of the image is in the\n# upper left corner\nax.imshow(img, origin='upper', extent=img_extent, transform=ccrs.PlateCarree())\nax.coastlines(resolution='50m', color='black', linewidth=1)\n\n# mark a known place to help us geo-locate ourselves\nax.plot(-117.1625, 32.715, 'bo', markersize=7, transform=ccrs.Geodetic())\nax.text(-117, 33, 'San Diego', transform=ccrs.Geodetic())\n\nplt.show()\n```\n\nI think the error comes from the ax.coastlines line. The error goes away by reverting back to shapely 1.5.12. \nOtherwise I'm using cartopy 0.13.0 and matplotlib 1.4.3 on CentOS 6.\nThe code comes from http://scitools.org.uk/cartopy/docs/latest/matplotlib/advanced_plotting.html.\n\nThought this might be useful to know.\n\n", "before_files": [{"content": "# (C) British Crown Copyright 2011 - 2015, Met Office\n#\n# This file is part of cartopy.\n#\n# cartopy is free software: you can redistribute it and/or modify it under\n# the terms of the GNU Lesser General Public License as published by the\n# Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# cartopy is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with cartopy.  If not, see <http://www.gnu.org/licenses/>.\n\"\"\"\nThis module defines the :class:`FeatureArtist` class, for drawing\n:class:`Feature` instances with matplotlib.\n\n\"\"\"\n\nfrom __future__ import (absolute_import, division, print_function)\n\nimport warnings\nimport weakref\n\nimport matplotlib.artist\nimport matplotlib.collections\n\nimport cartopy.mpl.patch as cpatch\n\n\nclass FeatureArtist(matplotlib.artist.Artist):\n    \"\"\"\n    A subclass of :class:`~matplotlib.artist.Artist` capable of\n    drawing a :class:`cartopy.feature.Feature`.\n\n    \"\"\"\n    _geometry_to_path_cache = weakref.WeakKeyDictionary()\n    \"\"\"\n    A nested mapping from geometry and target projection to the\n    resulting transformed matplotlib paths::\n\n        {geom: {target_projection: list_of_paths}}\n\n    This provides a significant boost when producing multiple maps of the\n    same projection.\n\n    \"\"\"\n    def __init__(self, feature, **kwargs):\n        \"\"\"\n        Args:\n\n        * feature:\n            an instance of :class:`cartopy.feature.Feature` to draw.\n        * kwargs:\n            keyword arguments to be used when drawing the feature. These\n            will override those shared with the feature.\n\n        \"\"\"\n        super(FeatureArtist, self).__init__()\n\n        if kwargs is None:\n            kwargs = {}\n        self._kwargs = dict(kwargs)\n\n        # Set default zorder so that features are drawn before\n        # lines e.g. contours but after images.\n        # Note that the zorder of Patch, PatchCollection and PathCollection\n        # are all 1 by default. Assuming equal zorder drawing takes place in\n        # the following order: collections, patches, lines (default zorder=2),\n        # text (default zorder=3), then other artists e.g. FeatureArtist.\n        if self._kwargs.get('zorder') is not None:\n            self.set_zorder(self._kwargs['zorder'])\n        elif feature.kwargs.get('zorder') is not None:\n            self.set_zorder(feature.kwargs['zorder'])\n        else:\n            # The class attribute matplotlib.collections.PathCollection.zorder\n            # was removed after mpl v1.2.0, so the hard-coded value of 1 is\n            # used instead.\n            self.set_zorder(1)\n\n        self._feature = feature\n\n    @matplotlib.artist.allow_rasterization\n    def draw(self, renderer, *args, **kwargs):\n        \"\"\"\n        Draws the geometries of the feature that intersect with the extent of\n        the :class:`cartopy.mpl.GeoAxes` instance to which this\n        object has been added.\n\n        \"\"\"\n        if not self.get_visible():\n            return\n\n        ax = self.get_axes()\n        feature_crs = self._feature.crs\n\n        # Get geometries that we need to draw.\n        extent = None\n        try:\n            extent = ax.get_extent(feature_crs)\n        except ValueError:\n            warnings.warn('Unable to determine extent. Defaulting to global.')\n        geoms = self._feature.intersecting_geometries(extent)\n\n        # Project (if necessary) and convert geometries to matplotlib paths.\n        paths = []\n        key = ax.projection\n        for geom in geoms:\n            mapping = FeatureArtist._geometry_to_path_cache.setdefault(geom,\n                                                                       {})\n            geom_paths = mapping.get(key)\n            if geom_paths is None:\n                if ax.projection != feature_crs:\n                    projected_geom = ax.projection.project_geometry(\n                        geom, feature_crs)\n                else:\n                    projected_geom = geom\n                geom_paths = cpatch.geos_to_path(projected_geom)\n                mapping[key] = geom_paths\n            paths.extend(geom_paths)\n\n        # Build path collection and draw it.\n        transform = ax.projection._as_mpl_transform(ax)\n        # Combine all the keyword args in priority order\n        final_kwargs = dict(self._feature.kwargs)\n        final_kwargs.update(self._kwargs)\n        final_kwargs.update(kwargs)\n        c = matplotlib.collections.PathCollection(paths,\n                                                  transform=transform,\n                                                  **final_kwargs)\n        c.set_clip_path(ax.patch)\n        c.set_figure(ax.figure)\n        return c.draw(renderer)\n", "path": "lib/cartopy/mpl/feature_artist.py"}], "after_files": [{"content": "# (C) British Crown Copyright 2011 - 2015, Met Office\n#\n# This file is part of cartopy.\n#\n# cartopy is free software: you can redistribute it and/or modify it under\n# the terms of the GNU Lesser General Public License as published by the\n# Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# cartopy is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with cartopy.  If not, see <http://www.gnu.org/licenses/>.\n\"\"\"\nThis module defines the :class:`FeatureArtist` class, for drawing\n:class:`Feature` instances with matplotlib.\n\n\"\"\"\n\nfrom __future__ import (absolute_import, division, print_function)\n\nimport warnings\nimport weakref\n\nimport matplotlib.artist\nimport matplotlib.collections\n\nimport cartopy.mpl.patch as cpatch\n\n\nclass _GeomKey(object):\n    \"\"\"\n    Provide id() based equality and hashing for geometries.\n\n    Instances of this class must be treated as immutable for the caching\n    to operate correctly.\n\n    A workaround for Shapely polygons no longer being hashable as of 1.5.13.\n\n    \"\"\"\n    def __init__(self, geom):\n        self._id = id(geom)\n\n    def __eq__(self, other):\n        return self._id == other._id\n\n    def __hash__(self):\n        return hash(self._id)\n\n\nclass FeatureArtist(matplotlib.artist.Artist):\n    \"\"\"\n    A subclass of :class:`~matplotlib.artist.Artist` capable of\n    drawing a :class:`cartopy.feature.Feature`.\n\n    \"\"\"\n\n    _geom_key_to_geometry_cache = weakref.WeakValueDictionary()\n    \"\"\"\n    A mapping from _GeomKey to geometry to assist with the caching of\n    transformed matplotlib paths.\n\n    \"\"\"\n    _geom_key_to_path_cache = weakref.WeakKeyDictionary()\n    \"\"\"\n    A nested mapping from geometry (converted to a _GeomKey) and target\n    projection to the resulting transformed matplotlib paths::\n\n        {geom: {target_projection: list_of_paths}}\n\n    This provides a significant boost when producing multiple maps of the\n    same projection.\n\n    \"\"\"\n\n    def __init__(self, feature, **kwargs):\n        \"\"\"\n        Args:\n\n        * feature:\n            an instance of :class:`cartopy.feature.Feature` to draw.\n        * kwargs:\n            keyword arguments to be used when drawing the feature. These\n            will override those shared with the feature.\n\n        \"\"\"\n        super(FeatureArtist, self).__init__()\n\n        if kwargs is None:\n            kwargs = {}\n        self._kwargs = dict(kwargs)\n\n        # Set default zorder so that features are drawn before\n        # lines e.g. contours but after images.\n        # Note that the zorder of Patch, PatchCollection and PathCollection\n        # are all 1 by default. Assuming equal zorder drawing takes place in\n        # the following order: collections, patches, lines (default zorder=2),\n        # text (default zorder=3), then other artists e.g. FeatureArtist.\n        if self._kwargs.get('zorder') is not None:\n            self.set_zorder(self._kwargs['zorder'])\n        elif feature.kwargs.get('zorder') is not None:\n            self.set_zorder(feature.kwargs['zorder'])\n        else:\n            # The class attribute matplotlib.collections.PathCollection.zorder\n            # was removed after mpl v1.2.0, so the hard-coded value of 1 is\n            # used instead.\n            self.set_zorder(1)\n\n        self._feature = feature\n\n    @matplotlib.artist.allow_rasterization\n    def draw(self, renderer, *args, **kwargs):\n        \"\"\"\n        Draws the geometries of the feature that intersect with the extent of\n        the :class:`cartopy.mpl.GeoAxes` instance to which this\n        object has been added.\n\n        \"\"\"\n        if not self.get_visible():\n            return\n\n        ax = self.get_axes()\n        feature_crs = self._feature.crs\n\n        # Get geometries that we need to draw.\n        extent = None\n        try:\n            extent = ax.get_extent(feature_crs)\n        except ValueError:\n            warnings.warn('Unable to determine extent. Defaulting to global.')\n        geoms = self._feature.intersecting_geometries(extent)\n\n        # Project (if necessary) and convert geometries to matplotlib paths.\n        paths = []\n        key = ax.projection\n        for geom in geoms:\n            # As Shapely geometries cannot be relied upon to be\n            # hashable, we have to use a WeakValueDictionary to manage\n            # their weak references. The key can then be a simple,\n            # \"disposable\", hashable geom-key object that just uses the\n            # id() of a geometry to determine equality and hash value.\n            # The only persistent, strong reference to the geom-key is\n            # in the WeakValueDictionary, so when the geometry is\n            # garbage collected so is the geom-key.\n            # The geom-key is also used to access the WeakKeyDictionary\n            # cache of transformed geometries. So when the geom-key is\n            # garbage collected so are the transformed geometries.\n            geom_key = _GeomKey(geom)\n            FeatureArtist._geom_key_to_geometry_cache.setdefault(\n                geom_key, geom)\n            mapping = FeatureArtist._geom_key_to_path_cache.setdefault(\n                geom_key, {})\n            geom_paths = mapping.get(key)\n            if geom_paths is None:\n                if ax.projection != feature_crs:\n                    projected_geom = ax.projection.project_geometry(\n                        geom, feature_crs)\n                else:\n                    projected_geom = geom\n                geom_paths = cpatch.geos_to_path(projected_geom)\n                mapping[key] = geom_paths\n            paths.extend(geom_paths)\n\n        # Build path collection and draw it.\n        transform = ax.projection._as_mpl_transform(ax)\n        # Combine all the keyword args in priority order\n        final_kwargs = dict(self._feature.kwargs)\n        final_kwargs.update(self._kwargs)\n        final_kwargs.update(kwargs)\n        c = matplotlib.collections.PathCollection(paths,\n                                                  transform=transform,\n                                                  **final_kwargs)\n        c.set_clip_path(ax.patch)\n        c.set_figure(ax.figure)\n        return c.draw(renderer)\n", "path": "lib/cartopy/mpl/feature_artist.py"}]}