Repository: SciTools/cartopy

Issue:
Rotated pole badly filled contour
I've managed to get hold of a contour which failed to transform from rotated pole to rotated pole (i.e. self to self + mod 360). This path comes from contouring the data using matplotlib:

```
from matplotlib.path import Path
import numpy as np

bad_path = Path(np.array([[ 345.72000122, 20.11333402],
       [ 345.76000977, 20.11000061],
       [ 345.77799988, 20.1400013 ],
       [ 345.77067057, 20.1799984 ],
       [ 345.76000977, 20.19523684],
       [ 345.73524257, 20.21999931],
       [ 345.72923396, 20.26000023],
       [ 345.72000122, 20.27714348],
       [ 345.69999695, 20.30000114],
       [ 345.6909041 , 20.34000206],
       [ 345.68841553, 20.37999916],
       [ 345.72000122, 20.41750002],
       [ 345.72125149, 20.42000008],
       [ 345.72625256, 20.46000099],
       [ 345.72000122, 20.48857307],
       [ 345.71750069, 20.50000191],
       [ 345.69555155, 20.53999901],
       [ 345.68713706, 20.57999992],
       [ 345.67999268, 20.58666674],
       [ 345.64667765, 20.62000084],
       [ 345.64001465, 20.62000084],
       [ 345.63601379, 20.62000084],
       [ 345.64001465, 20.61707394],
       [ 345.67706745, 20.57999992],
       [ 345.67999268, 20.56666629],
       [ 345.68666077, 20.53999901],
       [ 345.70749855, 20.50000191],
       [ 345.7152002 , 20.46000099],
       [ 345.70249748, 20.42000008],
       [ 345.67999268, 20.39230713],
       [ 345.66769174, 20.37999916],
       [ 345.65500641, 20.34000206],
       [ 345.66222466, 20.30000114],
       [ 345.67332967, 20.26000023],
       [ 345.67999268, 20.25200005],
       [ 345.72000122, 20.21999931],
       [ 345.67999268, 20.20857048],
       [ 345.64001465, 20.21058733],
       [ 345.6000061 , 20.21199913],
       [ 345.55999756, 20.18285561],
       [ 345.51998901, 20.18533185],
       [ 345.50074033, 20.21999931],
       [ 345.49750137, 20.26000023],
       [ 345.50843981, 20.30000114],
       [ 345.50843981, 20.34000206],
       [ 345.50893126, 20.37999916],
       [ 345.51998901, 20.4105881 ],
       [ 345.52841187, 20.42000008],
       [ 345.52841187, 20.46000099],
       [ 345.51998901, 20.47777918],
       [ 345.51739304, 20.50000191],
       [ 345.48688221, 20.53999901],
       [ 345.48001099, 20.54956444],
       [ 345.46028846, 20.57999992],
       [ 345.48001099, 20.62000084],
       [ 345.51998901, 20.62000084],
       [ 345.55999756, 20.62000084],
       [ 345.55999756, 20.62000084],
       [ 345.55999756, 20.62000084],
       [ 345.51998901, 20.62000084],
       [ 345.48001099, 20.62000084],
       [ 345.4711202 , 20.62000084],
       [ 345.45578046, 20.57999992],
       [ 345.48001099, 20.54260776],
       [ 345.48188496, 20.53999901],
       [ 345.51323948, 20.50000191],
       [ 345.51763737, 20.46000099],
       [ 345.51702768, 20.42000008],
       [ 345.50212649, 20.37999916],
       [ 345.5013326 , 20.34000206],
       [ 345.5013326 , 20.30000114],
       [ 345.48750687, 20.26000023],
       [ 345.48889499, 20.21999931],
       [ 345.51199341, 20.1799984 ],
       [ 345.51998901, 20.17225702],
       [ 345.55999756, 20.17124903],
       [ 345.57473755, 20.1799984 ],
       [ 345.6000061 , 20.19919884],
       [ 345.64001465, 20.19176337],
       [ 345.67999268, 20.18571281],
       [ 345.68570818, 20.1799984 ],
       [ 345.69332886, 20.1400013 ],
       [ 345.72000122, 20.11333402],
       [ 345.72000122, 20.1311122 ],
       [ 345.71111043, 20.1400013 ],
       [ 345.70857021, 20.1799984 ],
       [ 345.72000122, 20.21999931],
       [ 345.76000977, 20.1799984 ],
       [ 345.76000977, 20.1799984 ],
       [ 345.77000427, 20.1400013 ],
       [ 345.76000977, 20.12333425],
       [ 345.72000122, 20.1311122 ]]),
                codes=np.array([1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2], dtype=np.uint8))



import cartopy.crs as ccrs
crs = ccrs.RotatedPole(193.0, 41.0)

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

ax = plt.axes(projection=crs)
ax.add_patch(mpatches.PathPatch(bad_path, transform=crs))
ax.set_global()
ax.coastlines()
plt.show()
```

I'll simplify down the full geometry shortly (and provide some pictures), but I wanted to preserve the full geometry here first in-case my simplification removes key topological features.

Ocean being filled
Ocean polygon causing issue in #492.

Hopefully you can see that this is a cut down version of a polygon which comes from a Natural Earth 110m ocean shapefile. I'll reduce the path down to as few vertices as possible in this ticket.

```
target = ccrs.Orthographic(0, -75)
source = ccrs.PlateCarree()

codes = np.array([1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2], dtype=np.uint8)
verts = np.array([[ 180.        ,   71.5157143 ],
       [ 178.7253    ,   71.0988    ],
       [ -20.09778884,   26.39232361],
       [  47.7409058 ,    4.21948242],
       [  48.5944824 ,    5.33911133],
       [  49.4526978 ,    6.8046875 ],
       [  50.0709229 ,    8.08172607],
       [  50.5524902 ,    9.19873047],
       [  50.8342896 ,   10.2797241 ],
       [  51.0452881 ,   10.6409302 ],
       [  51.0415039 ,   11.1665039 ],
       [  51.1339111 ,   11.748291  ],
       [  51.1113281 ,   12.0247192 ],
       [  50.7321167 ,   12.0219116 ],
       [  50.2589111 ,   11.6796875 ],
       [  49.7286987 ,   11.5789185 ],
       [  49.2678833 ,   11.430481  ],
       [  48.9483032 ,   11.4107056 ],
       [  48.3789063 ,   11.3754883 ],
       [  48.0217285 ,   11.1931152 ],
       [  47.5256958 ,   11.1273193 ],
       [  46.6455078 ,   10.8165283 ],
       [  45.5568848 ,   10.6981201 ],
       [  44.6143188 ,   10.4423218 ],
       [  44.1179199 ,   10.4456787 ],
       [  43.666687  ,   10.8643188 ],
       [  43.4707031 ,   11.27771   ],
       [  43.1453247 ,   11.4620972 ],
       [  42.7158813 ,   11.7357178 ],
       [  43.286499  ,   11.9749146 ],
       [  43.3178711 ,   12.3900757 ],
       [  43.0812988 ,   12.699707  ],
       [  42.5897217 ,   13.0004883 ],
       [  42.2769165 ,   13.3441162 ],
       [  41.7349243 ,   13.9210815 ],
       [  41.1793213 ,   14.4910889 ],
       [  39.81427   ,   15.43573   ],
       [  39.2661133 ,   15.9227295 ],
       [  38.9907227 ,   16.8406982 ],
       [  38.4100952 ,   17.998291  ],
       [  37.8626709 ,   18.3679199 ],
       [  37.4818726 ,   18.6140747 ],
       [  37.1146851 ,   19.8081055 ],
       [  36.9694824 ,   20.8375244 ],
       [  37.1887207 ,   21.0189209 ],
       [  36.866272  ,   22.0001221 ],
       [  36.6906738 ,   22.204895  ],
       [  35.526123  ,   23.102478  ],
       [  54.2393188 ,   17.045105  ],
       [  54.7910767 ,   16.9506836 ],
       [  55.2749023 ,   17.2282715 ],
       [  55.2700806 ,   17.6323242 ],
       [  55.661499  ,   17.8842773 ],
       [  56.2835083 ,   17.8760986 ],
       [  56.5123291 ,   18.0870972 ],
       [  56.6096802 ,   18.5742798 ],
       [  57.234314  ,   18.9481201 ],
       [  57.694519  ,   18.9447021 ],
       [  57.7886963 ,   19.067688  ],
       [  57.6658936 ,   19.736084  ],
       [  57.8264771 ,   20.243103  ],
       [  58.0343018 ,   20.4815063 ],
       [  58.4880981 ,   20.4290771 ],
       [  58.861084  ,   21.1140747 ],
       [  59.2824707 ,   21.4338989 ],
       [  59.4423218 ,   21.7144775 ],
       [  59.8062744 ,   22.3104858 ],
       [  59.8081055 ,   22.5336914 ],
       [  59.4500732 ,   22.6602783 ],
       [  59.180481  ,   22.9924927 ],
       [  58.7293091 ,   23.5656738 ],
       [  58.137085  ,   23.7479248 ],
       [  57.4035034 ,   23.8787231 ],
       [  56.8452759 ,   24.2416992 ],
       [  56.3969116 ,   24.9246826 ],
       [  56.2611084 ,   25.7147217 ],
       [  56.3914795 ,   25.8961182 ],
       [  56.4857178 ,   26.309082  ],
       [  56.3621216 ,   26.395874  ],
       [  56.0709229 ,   26.055481  ],
       [  55.4390869 ,   25.4390869 ],
       [  54.6931152 ,   24.7979126 ],
       [  54.0081177 ,   24.1218872 ],
       [  53.4041138 ,   24.1513062 ],
       [  52.5770874 ,   24.1774902 ],
       [  51.7944946 ,   24.0198975 ],
       [  51.7575073 ,   24.2941284 ],
       [  51.5795288 ,   24.2454834 ],
       [  51.3897095 ,   24.6275024 ],
       [  51.6066895 ,   25.2156982 ],
       [  51.5891113 ,   25.8010864 ],
       [  51.286499  ,   26.1146851 ],
       [  51.0134888 ,   26.0070801 ],
       [  50.7438965 ,   25.4824829 ],
       [  50.8101196 ,   24.7548828 ],
       [  50.6607056 ,   24.9998779 ],
       [  50.5275269 ,   25.3278809 ],
       [  50.2399292 ,   25.6080933 ],
       [  50.1132813 ,   25.9440918 ],
       [  50.2130737 ,   26.2770996 ],
       [  50.1525269 ,   26.6896973 ],
       [  49.4708862 ,   27.1101074 ],
       [  49.2996826 ,   27.4613037 ],
       [  48.8076782 ,   27.6896973 ],
       [  48.4160767 ,   28.552124  ],
       [  48.0938721 ,   29.3062744 ],
       [  48.1832886 ,   29.5344849 ],
       [  47.9744873 ,   29.9758911 ],
       [  48.5681152 ,   29.9268799 ],
       [  48.9412842 ,   30.3170776 ],
       [  49.5769043 ,   29.9857178 ],
       [  50.1151123 ,   30.1478882 ],
       [  50.8530884 ,   28.8145142 ],
       [  51.520874  ,   27.8657227 ],
       [  52.4837036 ,   27.5808716 ],
       [  53.493103  ,   26.8125    ],
       [  54.7150879 ,   26.4807129 ],
       [  55.7236938 ,   26.9647217 ],
       [  56.4921265 ,   27.1433105 ],
       [  56.9708862 ,   26.9661255 ],
       [  57.3972778 ,   25.7399292 ],
       [  58.5258789 ,   25.6101074 ],
       [  59.6160889 ,   25.380127  ],
       [  61.4974976 ,   25.0783081 ],
       [  62.9057007 ,   25.2185059 ],
       [  64.5305176 ,   25.2371216 ],
       [  66.3729248 ,   25.425293  ],
       [  67.1455078 ,   24.6636963 ],
       [ 167.22314599,  -71.53846154],
       [ -11.5100671 ,  -72.0100738 ],
       [ -12.2935077 ,  -72.4019361 ],
       [ -13.3119726 ,  -72.7154571 ],
       [ -14.4088049 ,  -72.9505848 ],
       [ -15.4468552 ,  -73.1465418 ],
       [ -16.1127836 ,  -73.4601144 ],
       [ -16.4653202 ,  -73.8716139 ],
       [ -15.4077103 ,  -74.1067416 ],
       [ -15.7014909 ,  -74.498604  ],
       [ -16.6415885 ,  -74.7925396 ],
       [ -17.5229817 ,  -75.1256975 ],
       [ -18.9135429 ,  -75.4392184 ],
       [ -20.0103751 ,  -75.6743462 ],
       [ -21.2246938 ,  -75.909474  ],
       [ -22.4585978 ,  -76.105431  ],
       [ -23.927552  ,  -76.2425803 ],
       [ -25.4748219 ,  -76.2818027 ],
       [ -26.1603357 ,  -76.3601441 ],
       [ -27.5117519 ,  -76.4973451 ],
       [ -28.8827793 ,  -76.6736651 ],
       [ -29.7837321 ,  -77.0655791 ],
       [ -30.9980507 ,  -77.3595147 ],
       [ -32.2123694 ,  -77.6534502 ],
       [ -33.8967627 ,  -77.8885263 ],
       [ -35.3265462 ,  -78.1236541 ],
       [ -35.7770097 ,  -78.3392481 ],
       [ -35.9141072 ,  -79.0838547 ],
       [ -35.6399121 ,  -79.4561317 ],
       [ -33.6813236 ,  -79.4561317 ],
       [ -31.6248083 ,  -79.2993971 ],
       [ -29.6858052 ,  -79.2602263 ],
       [ -29.6858052 ,  -79.6325034 ],
       [ -29.2549013 ,  -79.985195  ],
       [ -28.5498022 ,  -80.3379383 ],
       [ -30.0970979 ,  -80.5926515 ],
       [ -32.3102962 ,  -80.7690231 ],
       [ -34.3863969 ,  -80.9061724 ],
       [ -36.2666697 ,  -81.1217148 ],
       [ -38.2448177 ,  -81.3373089 ],
       [ -40.7714335 ,  -81.3568942 ],
       [ -42.1620204 ,  -81.6508298 ],
       [ -42.8083634 ,  -82.0819146 ],
       [ -44.825708  ,  -81.8467351 ],
       [ -47.2739306 ,  -81.7095859 ],
       [ -49.7613499 ,  -81.7291712 ],
       [ -51.5436442 ,  -82.0035214 ],
       [ -53.6197707 ,  -82.2582346 ],
       [ -55.3628943 ,  -82.5717555 ],
       [ -57.0081168 ,  -82.865691  ],
       [ -58.2224871 ,  -83.2184343 ],
       [ -58.7121213 ,  -82.8461056 ],
       [ -59.6914156 ,  -82.3758501 ],
       [ -61.5520255 ,  -82.0426922 ],
       [ -63.25603   ,  -81.7487566 ],
       [ -65.7042785 ,  -81.4744581 ],
       [ -68.1916461 ,  -81.3176718 ],
       [ -70.0131628 ,  -81.0041509 ],
       [-167.022099  ,  -84.5704965 ],
       [-168.530199  ,  -84.2373902 ],
       [-168.999989  ,  -84.1179143 ],
       [-169.951223  ,  -83.8846469 ],
       [ -59.54613556,   49.1531784 ],
       [ 180.        ,   73.125     ],
       [ 180.        ,   71.5157143 ]])
```

![figure_1](https://cloud.githubusercontent.com/assets/810663/6081985/775380b0-ae15-11e4-9201-8c17ca296b56.png)



Discussion:
I decided not to simplify the geometry, and instead visualise it:
![Numbered geometry](https://cloud.githubusercontent.com/assets/810663/4882125/e0875dc2-6351-11e4-9a88-6e2c35f98455.png)

![Top](https://cloud.githubusercontent.com/assets/810663/4882144/1545a05a-6352-11e4-9e40-c812c80faac9.png)

Note that the degenerate line at the top is not visible with the images above.

With a bit of investigation, it turns out that either:
- removing the top degenerate vertices
- removing the single point of intersection between the two geometries
  Fixes the problem.

FWIW, the geometry _should_ look like:

![expected image](https://cloud.githubusercontent.com/assets/810663/4882231/540f0f3c-6353-11e4-8ea7-4b2dde9aaf34.png)

Interestingly, when visualisaed with matplotlib alone, whilst there exist degenerate contourf points, the visualisation does not show it. I suspect there is a simplification going on at some point which allows the degeneracies to be removed. I will look into that as a workaround for contour related problems like this.

Reduced the problem down to the following path:

```
codes = np.array([1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2], dtype=np.uint8)
verts = np.array([[ 345.72000122,   20.11333402],
       [ 345.77067057,   20.1799984 ],
       [ 345.64667765,   20.62000084],
       [ 345.63601379,   20.62000084],
       [ 345.72000122,   20.21999931],
       [ 345.48001099,   20.62000084],
       [ 345.51998901,   20.62000084],
       [ 345.51998901,   20.62000084],
       [ 345.48001099,   20.62000084],
       [ 345.72000122,   20.11333402],
       [ 345.72000122,   20.1311122 ],
       [ 345.72000122,   20.21999931],
       [ 345.76000977,   20.1799984 ],
       [ 345.76000977,   20.1799984 ],
       [ 345.72000122,   20.1311122 ]])
```

![figure_1](https://cloud.githubusercontent.com/assets/810663/6080346/31fbd9ac-ae08-11e4-8afb-a0cbb959c2a2.png)

I should have written it years ago, but I've made a path editor (based on http://matplotlib.org/examples/event_handling/path_editor.html) which allows me to move and remove vertices to see what effect they are having.

~200 lines of code follow:

```
import numpy as np
import matplotlib.path as mpath
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt

class PathInteractor:
    """
    An path editor.

    Key-bindings

      't' toggle vertex markers on and off.  When vertex markers are on,
          you can move them, delete them


    """
    showverts = True
    epsilon = 5  # max pixel distance to count as a vertex hit

    def __init__(self, pathpatch):
        self.ax = pathpatch.axes
        canvas = self.ax.figure.canvas
        self.pathpatch = pathpatch
        self.pathpatch.set_animated(True)

        x, y = zip(*self.pathpatch.get_path().vertices)

        self.line, = self.ax.plot(x,y,marker='o', markerfacecolor='r', animated=True)

        self._ind = None # the active vert

        canvas.mpl_connect('draw_event', self.draw_callback)
        canvas.mpl_connect('button_press_event', self.button_press_callback)
        canvas.mpl_connect('key_press_event', self.key_press_callback)
        canvas.mpl_connect('key_release_event', self.key_release_callback)
        canvas.mpl_connect('button_release_event', self.button_release_callback)
        canvas.mpl_connect('motion_notify_event', self.motion_notify_callback)
        self.canvas = canvas

        self.keys_down = []

    def draw_callback(self, event):
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        self.ax.draw_artist(self.pathpatch)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)

    def pathpatch_changed(self, pathpatch):
        'this method is called whenever the pathpatchgon object is called'
        # only copy the artist props to the line (except visibility)
        vis = self.line.get_visible()
        plt.Artist.update_from(self.line, pathpatch)
        self.line.set_visible(vis)  # don't use the pathpatch visibility state

    def get_ind_under_point(self, event):
        'get the index of the vertex under point if within epsilon tolerance'

        # display coords
        xy = np.asarray(self.pathpatch.get_path().vertices)
        xyt = self.pathpatch.get_transform().transform(xy)
        xt, yt = xyt[:, 0], xyt[:, 1]
        d = np.sqrt((xt-event.x)**2 + (yt-event.y)**2)
        ind = d.argmin()

        if d[ind]>=self.epsilon:
            ind = None

        return ind

    def button_press_callback(self, event):
        if not self.showverts:
            return
        if event.button in [1, 3] and event.inaxes is not None:
            if 'n' in self.keys_down:
                print 'Would like to create a node here...'
            else:
                self._ind = self.get_ind_under_point(event)

        if event.button == 3 and self._ind is not None:
            path = self.pathpatch.get_path()
            remove_inds_from_path(path, [self._ind])
            self.update_line()
            self.blit()

    def button_release_callback(self, event):
        self._ind = None

    def key_press_callback(self, event):
        if event.key=='t' and event.inaxes:
            self.showverts = not self.showverts
            self.line.set_visible(self.showverts)
            if not self.showverts:
                self._ind = None

        self.keys_down.append(event.key)

        self.canvas.draw()

    def key_release_callback(self, event):
        self.keys_down.remove(event.key)

    def motion_notify_callback(self, event):
        'on mouse movement'
        if not self.showverts: return
        if self._ind is None: return
        if event.inaxes is None: return
        if event.button not in [1, 3]:
            return
        x,y = event.xdata, event.ydata

        vertices = self.pathpatch.get_path().vertices

        vertices[self._ind] = x,y
        self.update_line()
        self.blit()

    def update_line(self):
        self.line.set_data(zip(*self.pathpatch.get_path().vertices))

    def blit(self):
        self.canvas.restore_region(self.background)
        self.ax.draw_artist(self.pathpatch)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)


def remove_inds_from_path(path, indices):
    """
    Remove the given indices from the :class:`matplotlib.path.Path` instance.

    Note: This algorithm is updating the vertices and codes *in-place*.

    """
    good = np.ones([path.codes.size, 2], dtype=np.bool)
    good[indices, :] = False
    path.vertices = path.vertices[good].reshape([-1, 2])
    path.codes = path.codes[good[:, 0]]


class MapPathEditor(object):
    def __init__(self, src_crs, target_crs, path, patch_kwargs=None):
        self.ax1 = plt.subplot(1, 2, 1, projection=target_crs)
        self.ax2 = plt.subplot(1, 2, 2)

        self.ax1.coastlines()

        self.patch1 = mpatches.PathPatch(path, transform=src_crs, **(patch_kwargs or {}))
        self.patch2 = mpatches.PathPatch(path, **(patch_kwargs or {}))

        self.ax1.add_patch(self.patch1)
        self.ax2.add_patch(self.patch2)

        self.interactor = PathInteractor(self.patch2)

        self.ax1.autoscale_view()
        self.ax2.autoscale_view()

        self.interactor.canvas.mpl_connect('button_release_event', self.update_patch1)

    def update_patch1(self, event=None):
        import cartopy.mpl.geoaxes
        new_path = self.patch2.get_path()
        print('Codes:', new_path.codes)
        print('Verts:', new_path.vertices)
        self.patch1._path = new_path
        # Remove from the cache!
        cartopy.mpl.geoaxes._PATH_TRANSFORM_CACHE.pop(new_path)
        plt.draw()
```

This can be used with:

```
import matplotlib.pyplot as plt
import cartopy.crs as ccrs

crs = ccrs.RotatedPole(193.0, 41.0)
r = MapPathEditor(crs, crs, bad_path, patch_kwargs=dict(facecolor='red', edgecolor='none'))
```

Simplified to integer form (still a problem):

```
codes = np.array([1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2], dtype=np.uint8)
verts = np.array([[ 343,   20],
                  [ 345,   23],
                  [ 342,   25],
                  [ 343,   22],
                  [ 340,   25],
                  [ 341,   25],
                  [ 340,   25],
                  [ 343,   20],
                  [ 343,   21 ],
                  [ 343,   22],
                  [ 344,   23],
                  [ 343,   21 ]])
```



Resolving patch:
diff --git a/lib/cartopy/crs.py b/lib/cartopy/crs.py
--- a/lib/cartopy/crs.py
+++ b/lib/cartopy/crs.py
@@ -459,6 +459,11 @@ def _rings_to_multi_polygon(self, rings, is_ccw):
                 if prep_polygon.contains(interior_ring):
                     holes.append(interior_ring)
                     interior_rings.remove(interior_ring)
+                elif polygon.crosses(interior_ring):
+                    # Likely that we have an invalid geometry such as
+                    # that from #509 or #537.
+                    holes.append(interior_ring)
+                    interior_rings.remove(interior_ring)
             polygon_bits.append((exterior_ring.coords,
                                  [ring.coords for ring in holes]))
 


Test patch:
diff --git a/lib/cartopy/tests/test_polygon.py b/lib/cartopy/tests/test_polygon.py
--- a/lib/cartopy/tests/test_polygon.py
+++ b/lib/cartopy/tests/test_polygon.py
@@ -151,6 +151,37 @@ def test_3pt_poly(self):
         self.assertEqual(len(multi_polygon), 1)
         self.assertEqual(len(multi_polygon[0].exterior.coords), 4)
 
+    def test_self_intersecting_1(self):
+        # Geometry comes from a matplotlib contourf (see #537)
+        wkt = ('POLYGON ((366.22000122 -9.71489298, '
+               '366.73212393 -9.679999349999999, '
+               '366.77412634 -8.767753000000001, '
+               '366.17762962 -9.679999349999999, '
+               '366.22000122 -9.71489298), '
+               '(366.22000122 -9.692636309999999, '
+               '366.32998657 -9.603356099999999, '
+               '366.74765799 -9.019999500000001, '
+               '366.5094086 -9.63175386, '
+               '366.22000122 -9.692636309999999))')
+        geom = shapely.wkt.loads(wkt)
+        source, target = ccrs.RotatedPole(198.0, 39.25), ccrs.EuroPP()
+        projected = target.project_geometry(geom, source)
+        # Before handling self intersecting interiors, the area would be
+        # approximately 13262233761329.
+        self.assertTrue(2.2e9 < projected.area < 2.3e9)
+
+    def test_self_intersecting_2(self):
+        # Geometry comes from a matplotlib contourf (see #509)
+        wkt = ('POLYGON ((343 20, 345 23, 342 25, 343 22, '
+               '340 25, 341 25, 340 25, 343 20), (343 21, '
+               '343 22, 344 23, 343 21))')
+        geom = shapely.wkt.loads(wkt)
+        source = target = ccrs.RotatedPole(193.0, 41.0)
+        projected = target.project_geometry(geom, source)
+        # Before handling self intersecting interiors, the area would be
+        # approximately 64808.
+        self.assertTrue(7.9 < projected.area < 8.1)
+
 
 class TestQuality(unittest.TestCase):
     def setUp(self):