matplotlib/matplotlib — pull request #3874 by ianthomas23 (2014-12-02 21:42:32+00:00)
Title: New C++ contour code with corner_mask kwarg

This is a new C++ extension module that calculates contours to add support for different ways of dealing with masked arrays using a new `corner_mask` keyword argument. It was originally suggested by @efiring a number of years (!) ago. The current behaviour, which is now obtained using `corner_mask=False`, was for a single masked point to completely mask out all 4 quads touching that point. The new behaviour, obtained using `corner_mask=True`, masks the corners of those quads touching the point but any triangular corners comprising three unmasked points on the opposite sides of those quads are contoured as usual. The diagram below should make this clearer; red circles indicate masked points.
![contour_corner_mask](https://cloud.githubusercontent.com/assets/580326/5270690/456d2508-7a65-11e4-8f13-cb503f4d9ea2.png)
I intend this code to eventually replace the existing C contouring module (cntr.c), if/when it is proven to be robust enough. I did not attempt to add the new functionality to cntr.c as it is a little too cryptic for my taste and I could not see how to shoehorn the new functionality into it. I have kept the existing code, however, and it can be accessed using `corner_mask='legacy'`. This allows the results of the old and new codes to be compared, and allows us to easily fall back to the old code if I have messed up.

If the `corner_mask` is not specified in a `contour` or `contourf` call, then new rcParam `contour.corner_mask` is used instead. This defaults to `True`, on the basis that if we have improved functionality it should be the default, and is therefore an API change.

I have modified the chunking behaviour (obtained using the kwarg `nchunk`). Previously it only applied to `contourf`, in the new extension if applies to `contour` as well. Also, previously it divided the domain into roughly nchunk-by-nchunk quads, now it is exactly nchunk-by-nchunk quads. I prefer this as the chunks are at predictable, regularly-spaced intervals making it easier to e.g. align them with grid lines to minimise the effects of rendering artifacts that chunking can give you. This is another API change, although not a significant one as I believe chunking is rarely used.

In the absence of chunking I have tried to make the outputs of `corner_mask=False` and `corner_mask='legacy'` as similar as possible. I've been mostly successful as image diffs of standard situations usually turn out completely black. But this does not always work as (1) the contoured polygons occur in a different order, and (2) the polygons' points are determined using floating-point math so will not necessarily be exactly the same.

What I would like is for other developers/users who regularly generate contour plots (especially of masked arrays) to try out the new functionality. Code of this complexity will invariable have some bugs in it, i.e. I won't have done a perfect job! As well as picking holes in the implementation, there are a few obvious decisions I have made that others may question:

1. Name of the `corner_mask` keyword argument.
2. Default rcParam of `contour.corner_mask=True`.
3. Chunking changes.

Finally, I've added a couple of image tests and an example. I have made the minimum number of changes to the python code, although I have added code to `contour.py` to remove a mask that is all `False`. I have had to change the images generated by test_patheffects.test_collection as some default label positions have changed, presumably because the contoured polygons are in a different order. And I've fixed a couple of typos in `_tri_wrapper.cpp` that I put in as part of the CXX removal.