We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Path <-> LineString vs Polygon conversion
Consider the following:

```
p = Path([[0, 0], [0, 2], [0, 0]])
print cpatch.path_to_geos(p)
```

In this case, the result should be a LineString, but the following should be a polygon:

```
p = Path([[0, 0], [0, 2], [2, 2], [2, 0], [0, 0]])
print cpatch.path_to_geos(p)
```

Update `cartopy.mpl_integration.patch` (possibly renaming it) to handle these cases in the best possible way (which way is, as yet, unclear). 

Add tests for these cases.


--- 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_integration/patch.py`
Content:
```
1 # (C) British Crown Copyright 2011 - 2012, 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 Provides shapely geometry <-> matplotlib path support.
19 
20 See also `Shapely Geometric Objects <http://toblerity.github.com/shapely/manual.html#geometric-objects>`_
21 and `Matplotlib Path API <http://matplotlib.org/api/path_api.html>`_.
22 
23 """
24 
25 import numpy as np
26 import matplotlib.path
27 from matplotlib.path import Path
28 from shapely.geometry.collection import GeometryCollection
29 from shapely.geometry.linestring import LineString
30 from shapely.geometry.point import Point
31 from shapely.geometry.polygon import Polygon
32 from shapely.geometry.multilinestring import MultiLineString
33 from shapely.geometry.multipoint import MultiPoint
34 from shapely.geometry.multipolygon import MultiPolygon
35 
36 
37 def geos_to_path(shape):
38     """
39     Creates a list of :class:`matplotlib.path.Path` objects that describe
40     a shape.
41 
42     Args:
43 
44     * shape
45         A list, tuple or single instance of any of the following
46         types: :class:`shapely.geometry.point.Point`,
47         :class:`shapely.geometry.linestring.LineString`,
48         :class:`shapely.geometry.polygon.Polygon`,
49         :class:`shapely.geometry.multipoint.MultiPoint`,
50         :class:`shapely.geometry.multipolygon.MultiPolygon`,
51         :class:`shapely.geometry.multilinestring.MultiLineString`,
52         :class:`shapely.geometry.collection.GeometryCollection`,
53         or any type with a _as_mpl_path() method.
54 
55     Returns:
56         A list of :class:`matplotlib.path.Path` objects.
57 
58     """
59     if isinstance(shape, (list, tuple)):
60         paths = []
61         for shp in shape:
62             paths.extend(geos_to_path(shp))
63         return paths
64 
65     if isinstance(shape, (LineString, Point)):
66         return [Path(np.vstack(shape.xy).T)]
67     elif isinstance(shape, Polygon):
68         def poly_codes(poly):
69             codes = np.ones(len(poly.xy[0])) * Path.LINETO
70             codes[0] = Path.MOVETO
71             return codes
72         
73         vertices = np.concatenate([np.array(shape.exterior.xy)] +
74                                   [np.array(ring.xy) for ring in
75                                    shape.interiors], 1).T
76         codes = np.concatenate([poly_codes(shape.exterior)] +
77                                [poly_codes(ring) for ring in shape.interiors])
78         return [Path(vertices, codes)]
79     elif isinstance(shape, (MultiPolygon, GeometryCollection, MultiLineString,
80                             MultiPoint)):
81         paths = []
82         for geom in shape.geoms:
83             paths.extend(geos_to_path(geom))
84         return paths
85     elif hasattr(shape, '_as_mpl_path'):
86         vertices, codes = shape._as_mpl_path()
87         return [Path(vertices, codes)]
88     else:
89         raise ValueError('Unsupported shape type {}.'.format(type(shape)))
90 
91 
92 def path_segments(path, transform=None, remove_nans=False, clip=None,
93                   quantize=False, simplify=False, curves=False,
94                   stroke_width=1.0, snap=False):
95     """
96     Creates an array of vertices and a corresponding array of codes from a
97     :class:`matplotlib.path.Path`.
98 
99     Args:
100 
101     * path
102         A :class:`matplotlib.path.Path` instance.
103 
104     Kwargs:
105         See :func:`matplotlib.path.iter_segments` for details of the keyword
106         arguments.
107 
108     Returns:
109         A (vertices, codes) tuple, where vertices is a numpy array of
110         coordinates, and codes is a numpy array of matplotlib path codes.
111         See :class:`matplotlib.path.Path` for information on the types of
112         codes and their meanings.
113 
114     """
115     # XXX assigned to avoid a ValueError inside the mpl C code...
116     a = transform, remove_nans, clip, quantize, simplify, curves
117 
118     # Series of cleanups and conversions to the path e.g. it
119     # can convert curved segments to line segments.
120     vertices, codes = matplotlib.path.cleanup_path(path, transform,
121                                                    remove_nans, clip,
122                                                    snap, stroke_width,
123                                                    simplify, curves)
124     
125     # Remove the final vertex (with code 0)
126     return vertices[:-1, :], codes[:-1]
127 
128 
129 def path_to_geos(path):
130     """
131     Creates a list of Shapely geometric objects from a
132     :class:`matplotlib.path.Path`.
133 
134     Args:
135 
136     * path
137         A :class:`matplotlib.path.Path` instance.
138 
139     Returns:
140         A list of :class:`shapely.geometry.polygon.Polygon`,
141         :class:`shapely.geometry.linestring.LineString` and/or
142         :class:`shapely.geometry.multilinestring.MultiLineString` instances.
143 
144     """
145     # Convert path into numpy array of vertices (and associated codes)
146     path_verts, path_codes = path_segments(path, curves=False)
147     
148     # Split into subarrays such that each subarray consists of connected
149     # line segments based on the start of each one being marked by a
150     # matplotlib MOVETO code.
151     verts_split_inds = np.where(path_codes == Path.MOVETO)[0]
152     verts_split = np.split(path_verts, verts_split_inds)
153     codes_split = np.split(path_codes, verts_split_inds)
154     
155     # Iterate through the vertices generating a list of
156     # (external_geom, [internal_polygons]) tuples.
157     collection = []
158     for path_verts, path_codes in zip(verts_split, codes_split):
159         if len(path_verts) == 0:
160             continue
161 
162         # XXX A path can be given which does not end with close poly, in that
163         # situation, we have to guess?
164         # XXX Implement a point
165                 
166         if path_verts.shape[0] > 2 and (path_codes[-1] == Path.CLOSEPOLY or
167                                         all(path_verts[0, :] == path_verts[-1, :])):
168             if path_codes[-1] == Path.CLOSEPOLY:
169                 geom = Polygon(path_verts[:-1, :])
170             else:
171                 geom = Polygon(path_verts)
172         else:
173             geom = LineString(path_verts)
174 
175         # If geom is a Polygon and is contained within the last geom in collection,
176         # add it to its list of internal polygons, otherwise simple append it as a
177         # new external geom.
178         if (len(collection) > 0 and 
179                  isinstance(collection[-1][0], Polygon) and
180                  isinstance(geom, Polygon) and
181                  collection[-1][0].contains(geom.exterior)):
182             collection[-1][1].append(geom.exterior)
183         else:
184             collection.append((geom, []))
185     
186     # Convert each (external_geom, [internal_polygons]) pair into a
187     # a shapely Polygon that encapsulates the internal polygons, if the
188     # external geom is a LineSting leave it alone.
189     geom_collection = []
190     for external_geom, internal_polys in collection:
191         if internal_polys:
192             # XXX worry about islands within lakes
193             geom = Polygon(external_geom.exterior, internal_polys)
194         else:
195             geom = external_geom
196         geom_collection.append(geom)
197     
198     # If the geom_collection only contains LineStrings combine them
199     # into a single MultiLinestring.
200     if geom_collection and all(isinstance(geom, LineString) for
201                                geom in geom_collection):
202         geom_collection = [MultiLineString(geom_collection)]
203 
204     # Remove any zero area Polygons
205     result = filter(lambda geom: (isinstance(geom, Polygon) and geom.area != 0) or
206                     not isinstance(geom, Polygon), geom_collection)
207     
208     return result
209
```
--- 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_integration/patch.py b/lib/cartopy/mpl_integration/patch.py
--- a/lib/cartopy/mpl_integration/patch.py
+++ b/lib/cartopy/mpl_integration/patch.py
@@ -202,7 +202,9 @@
         geom_collection = [MultiLineString(geom_collection)]
 
     # Remove any zero area Polygons
-    result = filter(lambda geom: (isinstance(geom, Polygon) and geom.area != 0) or
-                    not isinstance(geom, Polygon), geom_collection)
-    
+    not_zero_poly = lambda geom: ((isinstance(geom, Polygon) and
+                                   not geom._is_empty and geom.area != 0) or
+                                  not isinstance(geom, Polygon))
+    result = filter(not_zero_poly, geom_collection)
+
     return result

{"golden_diff": "diff --git a/lib/cartopy/mpl_integration/patch.py b/lib/cartopy/mpl_integration/patch.py\n--- a/lib/cartopy/mpl_integration/patch.py\n+++ b/lib/cartopy/mpl_integration/patch.py\n@@ -202,7 +202,9 @@\n         geom_collection = [MultiLineString(geom_collection)]\n \n     # Remove any zero area Polygons\n-    result = filter(lambda geom: (isinstance(geom, Polygon) and geom.area != 0) or\n-                    not isinstance(geom, Polygon), geom_collection)\n-    \n+    not_zero_poly = lambda geom: ((isinstance(geom, Polygon) and\n+                                   not geom._is_empty and geom.area != 0) or\n+                                  not isinstance(geom, Polygon))\n+    result = filter(not_zero_poly, geom_collection)\n+\n     return result\n", "issue": "Path <-> LineString vs Polygon conversion\nConsider the following:\n\n```\np = Path([[0, 0], [0, 2], [0, 0]])\nprint cpatch.path_to_geos(p)\n```\n\nIn this case, the result should be a LineString, but the following should be a polygon:\n\n```\np = Path([[0, 0], [0, 2], [2, 2], [2, 0], [0, 0]])\nprint cpatch.path_to_geos(p)\n```\n\nUpdate `cartopy.mpl_integration.patch` (possibly renaming it) to handle these cases in the best possible way (which way is, as yet, unclear). \n\nAdd tests for these cases.\n\n", "before_files": [{"content": "# (C) British Crown Copyright 2011 - 2012, 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\"\"\"\nProvides shapely geometry <-> matplotlib path support.\n\nSee also `Shapely Geometric Objects <http://toblerity.github.com/shapely/manual.html#geometric-objects>`_\nand `Matplotlib Path API <http://matplotlib.org/api/path_api.html>`_.\n\n\"\"\"\n\nimport numpy as np\nimport matplotlib.path\nfrom matplotlib.path import Path\nfrom shapely.geometry.collection import GeometryCollection\nfrom shapely.geometry.linestring import LineString\nfrom shapely.geometry.point import Point\nfrom shapely.geometry.polygon import Polygon\nfrom shapely.geometry.multilinestring import MultiLineString\nfrom shapely.geometry.multipoint import MultiPoint\nfrom shapely.geometry.multipolygon import MultiPolygon\n\n\ndef geos_to_path(shape):\n    \"\"\"\n    Creates a list of :class:`matplotlib.path.Path` objects that describe\n    a shape.\n\n    Args:\n\n    * shape\n        A list, tuple or single instance of any of the following\n        types: :class:`shapely.geometry.point.Point`,\n        :class:`shapely.geometry.linestring.LineString`,\n        :class:`shapely.geometry.polygon.Polygon`,\n        :class:`shapely.geometry.multipoint.MultiPoint`,\n        :class:`shapely.geometry.multipolygon.MultiPolygon`,\n        :class:`shapely.geometry.multilinestring.MultiLineString`,\n        :class:`shapely.geometry.collection.GeometryCollection`,\n        or any type with a _as_mpl_path() method.\n\n    Returns:\n        A list of :class:`matplotlib.path.Path` objects.\n\n    \"\"\"\n    if isinstance(shape, (list, tuple)):\n        paths = []\n        for shp in shape:\n            paths.extend(geos_to_path(shp))\n        return paths\n\n    if isinstance(shape, (LineString, Point)):\n        return [Path(np.vstack(shape.xy).T)]\n    elif isinstance(shape, Polygon):\n        def poly_codes(poly):\n            codes = np.ones(len(poly.xy[0])) * Path.LINETO\n            codes[0] = Path.MOVETO\n            return codes\n        \n        vertices = np.concatenate([np.array(shape.exterior.xy)] +\n                                  [np.array(ring.xy) for ring in\n                                   shape.interiors], 1).T\n        codes = np.concatenate([poly_codes(shape.exterior)] +\n                               [poly_codes(ring) for ring in shape.interiors])\n        return [Path(vertices, codes)]\n    elif isinstance(shape, (MultiPolygon, GeometryCollection, MultiLineString,\n                            MultiPoint)):\n        paths = []\n        for geom in shape.geoms:\n            paths.extend(geos_to_path(geom))\n        return paths\n    elif hasattr(shape, '_as_mpl_path'):\n        vertices, codes = shape._as_mpl_path()\n        return [Path(vertices, codes)]\n    else:\n        raise ValueError('Unsupported shape type {}.'.format(type(shape)))\n\n\ndef path_segments(path, transform=None, remove_nans=False, clip=None,\n                  quantize=False, simplify=False, curves=False,\n                  stroke_width=1.0, snap=False):\n    \"\"\"\n    Creates an array of vertices and a corresponding array of codes from a\n    :class:`matplotlib.path.Path`.\n\n    Args:\n\n    * path\n        A :class:`matplotlib.path.Path` instance.\n\n    Kwargs:\n        See :func:`matplotlib.path.iter_segments` for details of the keyword\n        arguments.\n\n    Returns:\n        A (vertices, codes) tuple, where vertices is a numpy array of\n        coordinates, and codes is a numpy array of matplotlib path codes.\n        See :class:`matplotlib.path.Path` for information on the types of\n        codes and their meanings.\n\n    \"\"\"\n    # XXX assigned to avoid a ValueError inside the mpl C code...\n    a = transform, remove_nans, clip, quantize, simplify, curves\n\n    # Series of cleanups and conversions to the path e.g. it\n    # can convert curved segments to line segments.\n    vertices, codes = matplotlib.path.cleanup_path(path, transform,\n                                                   remove_nans, clip,\n                                                   snap, stroke_width,\n                                                   simplify, curves)\n    \n    # Remove the final vertex (with code 0)\n    return vertices[:-1, :], codes[:-1]\n\n\ndef path_to_geos(path):\n    \"\"\"\n    Creates a list of Shapely geometric objects from a\n    :class:`matplotlib.path.Path`.\n\n    Args:\n\n    * path\n        A :class:`matplotlib.path.Path` instance.\n\n    Returns:\n        A list of :class:`shapely.geometry.polygon.Polygon`,\n        :class:`shapely.geometry.linestring.LineString` and/or\n        :class:`shapely.geometry.multilinestring.MultiLineString` instances.\n\n    \"\"\"\n    # Convert path into numpy array of vertices (and associated codes)\n    path_verts, path_codes = path_segments(path, curves=False)\n    \n    # Split into subarrays such that each subarray consists of connected\n    # line segments based on the start of each one being marked by a\n    # matplotlib MOVETO code.\n    verts_split_inds = np.where(path_codes == Path.MOVETO)[0]\n    verts_split = np.split(path_verts, verts_split_inds)\n    codes_split = np.split(path_codes, verts_split_inds)\n    \n    # Iterate through the vertices generating a list of\n    # (external_geom, [internal_polygons]) tuples.\n    collection = []\n    for path_verts, path_codes in zip(verts_split, codes_split):\n        if len(path_verts) == 0:\n            continue\n\n        # XXX A path can be given which does not end with close poly, in that\n        # situation, we have to guess?\n        # XXX Implement a point\n                \n        if path_verts.shape[0] > 2 and (path_codes[-1] == Path.CLOSEPOLY or\n                                        all(path_verts[0, :] == path_verts[-1, :])):\n            if path_codes[-1] == Path.CLOSEPOLY:\n                geom = Polygon(path_verts[:-1, :])\n            else:\n                geom = Polygon(path_verts)\n        else:\n            geom = LineString(path_verts)\n\n        # If geom is a Polygon and is contained within the last geom in collection,\n        # add it to its list of internal polygons, otherwise simple append it as a\n        # new external geom.\n        if (len(collection) > 0 and \n                 isinstance(collection[-1][0], Polygon) and\n                 isinstance(geom, Polygon) and\n                 collection[-1][0].contains(geom.exterior)):\n            collection[-1][1].append(geom.exterior)\n        else:\n            collection.append((geom, []))\n    \n    # Convert each (external_geom, [internal_polygons]) pair into a\n    # a shapely Polygon that encapsulates the internal polygons, if the\n    # external geom is a LineSting leave it alone.\n    geom_collection = []\n    for external_geom, internal_polys in collection:\n        if internal_polys:\n            # XXX worry about islands within lakes\n            geom = Polygon(external_geom.exterior, internal_polys)\n        else:\n            geom = external_geom\n        geom_collection.append(geom)\n    \n    # If the geom_collection only contains LineStrings combine them\n    # into a single MultiLinestring.\n    if geom_collection and all(isinstance(geom, LineString) for\n                               geom in geom_collection):\n        geom_collection = [MultiLineString(geom_collection)]\n\n    # Remove any zero area Polygons\n    result = filter(lambda geom: (isinstance(geom, Polygon) and geom.area != 0) or\n                    not isinstance(geom, Polygon), geom_collection)\n    \n    return result\n", "path": "lib/cartopy/mpl_integration/patch.py"}], "after_files": [{"content": "# (C) British Crown Copyright 2011 - 2012, 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\"\"\"\nProvides shapely geometry <-> matplotlib path support.\n\nSee also `Shapely Geometric Objects <http://toblerity.github.com/shapely/manual.html#geometric-objects>`_\nand `Matplotlib Path API <http://matplotlib.org/api/path_api.html>`_.\n\n\"\"\"\n\nimport numpy as np\nimport matplotlib.path\nfrom matplotlib.path import Path\nfrom shapely.geometry.collection import GeometryCollection\nfrom shapely.geometry.linestring import LineString\nfrom shapely.geometry.point import Point\nfrom shapely.geometry.polygon import Polygon\nfrom shapely.geometry.multilinestring import MultiLineString\nfrom shapely.geometry.multipoint import MultiPoint\nfrom shapely.geometry.multipolygon import MultiPolygon\n\n\ndef geos_to_path(shape):\n    \"\"\"\n    Creates a list of :class:`matplotlib.path.Path` objects that describe\n    a shape.\n\n    Args:\n\n    * shape\n        A list, tuple or single instance of any of the following\n        types: :class:`shapely.geometry.point.Point`,\n        :class:`shapely.geometry.linestring.LineString`,\n        :class:`shapely.geometry.polygon.Polygon`,\n        :class:`shapely.geometry.multipoint.MultiPoint`,\n        :class:`shapely.geometry.multipolygon.MultiPolygon`,\n        :class:`shapely.geometry.multilinestring.MultiLineString`,\n        :class:`shapely.geometry.collection.GeometryCollection`,\n        or any type with a _as_mpl_path() method.\n\n    Returns:\n        A list of :class:`matplotlib.path.Path` objects.\n\n    \"\"\"\n    if isinstance(shape, (list, tuple)):\n        paths = []\n        for shp in shape:\n            paths.extend(geos_to_path(shp))\n        return paths\n\n    if isinstance(shape, (LineString, Point)):\n        return [Path(np.vstack(shape.xy).T)]\n    elif isinstance(shape, Polygon):\n        def poly_codes(poly):\n            codes = np.ones(len(poly.xy[0])) * Path.LINETO\n            codes[0] = Path.MOVETO\n            return codes\n        \n        vertices = np.concatenate([np.array(shape.exterior.xy)] +\n                                  [np.array(ring.xy) for ring in\n                                   shape.interiors], 1).T\n        codes = np.concatenate([poly_codes(shape.exterior)] +\n                               [poly_codes(ring) for ring in shape.interiors])\n        return [Path(vertices, codes)]\n    elif isinstance(shape, (MultiPolygon, GeometryCollection, MultiLineString,\n                            MultiPoint)):\n        paths = []\n        for geom in shape.geoms:\n            paths.extend(geos_to_path(geom))\n        return paths\n    elif hasattr(shape, '_as_mpl_path'):\n        vertices, codes = shape._as_mpl_path()\n        return [Path(vertices, codes)]\n    else:\n        raise ValueError('Unsupported shape type {}.'.format(type(shape)))\n\n\ndef path_segments(path, transform=None, remove_nans=False, clip=None,\n                  quantize=False, simplify=False, curves=False,\n                  stroke_width=1.0, snap=False):\n    \"\"\"\n    Creates an array of vertices and a corresponding array of codes from a\n    :class:`matplotlib.path.Path`.\n\n    Args:\n\n    * path\n        A :class:`matplotlib.path.Path` instance.\n\n    Kwargs:\n        See :func:`matplotlib.path.iter_segments` for details of the keyword\n        arguments.\n\n    Returns:\n        A (vertices, codes) tuple, where vertices is a numpy array of\n        coordinates, and codes is a numpy array of matplotlib path codes.\n        See :class:`matplotlib.path.Path` for information on the types of\n        codes and their meanings.\n\n    \"\"\"\n    # XXX assigned to avoid a ValueError inside the mpl C code...\n    a = transform, remove_nans, clip, quantize, simplify, curves\n\n    # Series of cleanups and conversions to the path e.g. it\n    # can convert curved segments to line segments.\n    vertices, codes = matplotlib.path.cleanup_path(path, transform,\n                                                   remove_nans, clip,\n                                                   snap, stroke_width,\n                                                   simplify, curves)\n    \n    # Remove the final vertex (with code 0)\n    return vertices[:-1, :], codes[:-1]\n\n\ndef path_to_geos(path):\n    \"\"\"\n    Creates a list of Shapely geometric objects from a\n    :class:`matplotlib.path.Path`.\n\n    Args:\n\n    * path\n        A :class:`matplotlib.path.Path` instance.\n\n    Returns:\n        A list of :class:`shapely.geometry.polygon.Polygon`,\n        :class:`shapely.geometry.linestring.LineString` and/or\n        :class:`shapely.geometry.multilinestring.MultiLineString` instances.\n\n    \"\"\"\n    # Convert path into numpy array of vertices (and associated codes)\n    path_verts, path_codes = path_segments(path, curves=False)\n    \n    # Split into subarrays such that each subarray consists of connected\n    # line segments based on the start of each one being marked by a\n    # matplotlib MOVETO code.\n    verts_split_inds = np.where(path_codes == Path.MOVETO)[0]\n    verts_split = np.split(path_verts, verts_split_inds)\n    codes_split = np.split(path_codes, verts_split_inds)\n    \n    # Iterate through the vertices generating a list of\n    # (external_geom, [internal_polygons]) tuples.\n    collection = []\n    for path_verts, path_codes in zip(verts_split, codes_split):\n        if len(path_verts) == 0:\n            continue\n\n        # XXX A path can be given which does not end with close poly, in that\n        # situation, we have to guess?\n        # XXX Implement a point\n                \n        if path_verts.shape[0] > 2 and (path_codes[-1] == Path.CLOSEPOLY or\n                                        all(path_verts[0, :] == path_verts[-1, :])):\n            if path_codes[-1] == Path.CLOSEPOLY:\n                geom = Polygon(path_verts[:-1, :])\n            else:\n                geom = Polygon(path_verts)\n        else:\n            geom = LineString(path_verts)\n\n        # If geom is a Polygon and is contained within the last geom in collection,\n        # add it to its list of internal polygons, otherwise simple append it as a\n        # new external geom.\n        if (len(collection) > 0 and \n                 isinstance(collection[-1][0], Polygon) and\n                 isinstance(geom, Polygon) and\n                 collection[-1][0].contains(geom.exterior)):\n            collection[-1][1].append(geom.exterior)\n        else:\n            collection.append((geom, []))\n    \n    # Convert each (external_geom, [internal_polygons]) pair into a\n    # a shapely Polygon that encapsulates the internal polygons, if the\n    # external geom is a LineSting leave it alone.\n    geom_collection = []\n    for external_geom, internal_polys in collection:\n        if internal_polys:\n            # XXX worry about islands within lakes\n            geom = Polygon(external_geom.exterior, internal_polys)\n        else:\n            geom = external_geom\n        geom_collection.append(geom)\n    \n    # If the geom_collection only contains LineStrings combine them\n    # into a single MultiLinestring.\n    if geom_collection and all(isinstance(geom, LineString) for\n                               geom in geom_collection):\n        geom_collection = [MultiLineString(geom_collection)]\n\n    # Remove any zero area Polygons\n    not_zero_poly = lambda geom: ((isinstance(geom, Polygon) and\n                                   not geom._is_empty and geom.area != 0) or\n                                  not isinstance(geom, Polygon))\n    result = filter(not_zero_poly, geom_collection)\n\n    return result\n", "path": "lib/cartopy/mpl_integration/patch.py"}]}