From: Phil E. <pel...@gm...> - 2013-03-06 17:06:19
|
Smart rendering of adjacent, anti-aliased patches is a question which has come up a couple of times in various guises in the past. It is my understanding that the lack of this functionality led us to disable anti-aliasing for contouring and is the reason the following image has a white stripe around the circle where there should be just a nice blend of the two colors: import matplotlib.pyplot as plt import numpy as np import matplotlib.patches as mpatches import matplotlib.path as mpath import matplotlib.collections as mcol # create two paths. One a circle, the other # a square with the same circle cut out. x = np.linspace(0, np.pi * 2, 1000) circle_coords = np.array(zip(*[np.sin(x) * 0.8, np.cos(x) * 0.8])) pth_circle = mpath.Path(circle_coords) sqr_codes = np.repeat(mpath.Path.MOVETO, len(circle_coords) + 5) sqr_codes[1:5] = mpath.Path.LINETO sqr_codes[6:] = mpath.Path.LINETO sqr_coords = np.concatenate([[[-1, -1], [-1, 1], [1, 1], [1, -1], [-1, -1]], circle_coords[::-1]], axis=0) sqr_path = mpath.Path(sqr_coords, sqr_codes) ax = plt.axes() patches = [mpatches.PathPatch(pth_circle), mpatches.PathPatch(sqr_path)] col = mcol.PatchCollection(patches, antialiaseds=True, edgecolors='none', facecolors=[(0, 0.0, 0.0, 0.9), (0.1, 0.1, 0.02, 0.9)]) ax.add_collection(col) ax.set_xlim([-1, 1]) ax.set_ylim([-1, 1]) plt.show() I know of lots of the workarounds for this (turn off AA, turn on lines, extend the path slightly, set a dark background color) all of which have down-sides, so I'm keen to find a final solution to the problem. When the two patches marry up perfectly with full anti-aliasing, the antigrain (AGG) community call this "flash" or compound rendering, and this capability was added to Agg 2.4 (which we already ship with mpl). In order to make full use of the compound rendering technique I believe the drawing pipeline in "_backend_agg.cpp" would need to change, which could be problematic. A less wide-impacting alternative would be to draw all "patches" of a single Collection in the same rasterization step (i.e. just change _draw_path_collection_generic), though this does mean that, as it stands, the result of plt.contourf would not be able to make use of this new functionality - a MEP which changes the return type of plt.contourf to a single Collection might be able to fix that. I've put together a simple example similar to this in C++ using agg (no mpl changes yet), showing the differences in the code needed between the old technique vs the "new" compound renderer (attached). Ok, so the question to those that have knowledge of the _backend_agg.cpp code (Mike, Eric, JJ + others?): - Have you already looked at doing this and determined that this is a non-starter? - Do you support adding the ability for the agg backend to draw compound artists (i.e. Collections) in this way rather than treating them as individual primitives in the canvas? - Since many of the other backends can't do flash rendering, would we even want to make this change? - SVG in Firefox 10.0.2 has the same problem, it is discussed slightly more in http://www.svgopen.org/2002/papers/sorotokin__svg_secrets/ - Acroread has the same problem with PDFs, only to a much lesser extent than in the PNG attached Thoughts? |
From: Eric F. <ef...@ha...> - 2013-03-06 18:43:08
|
On 2013/03/06 7:06 AM, Phil Elson wrote: > Smart rendering of adjacent, anti-aliased patches is a question which > has come up a couple of times in various guises in the past. > It is my understanding that the lack of this functionality led us to > disable anti-aliasing for contouring and is the reason the following > image has a white stripe around the circle where there should be just a > nice blend of the two colors: > > > import matplotlib.pyplot as plt > import numpy as np > import matplotlib.patches as mpatches > import matplotlib.path as mpath > import matplotlib.collections as mcol > > > # create two paths. One a circle, the other > # a square with the same circle cut out. > x = np.linspace(0, np.pi * 2, 1000) > > circle_coords = np.array(zip(*[np.sin(x) * 0.8, np.cos(x) * 0.8])) > pth_circle = mpath.Path(circle_coords) > > sqr_codes = np.repeat(mpath.Path.MOVETO, len(circle_coords) + 5) > sqr_codes[1:5] = mpath.Path.LINETO > sqr_codes[6:] = mpath.Path.LINETO > sqr_coords = np.concatenate([[[-1, -1], [-1, 1], [1, 1], [1, -1], [-1, > -1]], > circle_coords[::-1]], axis=0) > sqr_path = mpath.Path(sqr_coords, sqr_codes) > > > ax = plt.axes() > patches = [mpatches.PathPatch(pth_circle), mpatches.PathPatch(sqr_path)] > col = mcol.PatchCollection(patches, > antialiaseds=True, > edgecolors='none', > facecolors=[(0, 0.0, 0.0, 0.9), (0.1, 0.1, > 0.02, 0.9)]) > ax.add_collection(col) > ax.set_xlim([-1, 1]) > ax.set_ylim([-1, 1]) > plt.show() > > > > I know of lots of the workarounds for this (turn off AA, turn on lines, > extend the path slightly, set a dark background color) all of which have > down-sides, so I'm keen to find a final solution to the problem. > > When the two patches marry up perfectly with full anti-aliasing, the > antigrain (AGG) community call this "flash" or compound rendering, and > this capability was added to Agg 2.4 (which we already ship with mpl). > > In order to make full use of the compound rendering technique I believe > the drawing pipeline in "_backend_agg.cpp" would need to change, which > could be problematic. A less wide-impacting alternative would be to draw > all "patches" of a single Collection in the same rasterization step > (i.e. just change _draw_path_collection_generic), though this does mean > that, as it stands, the result of plt.contourf would not be able to make > use of this new functionality - a MEP which changes the return type of > plt.contourf to a single Collection might be able to fix that. > > I've put together a simple example similar to this in C++ using agg (no > mpl changes yet), showing the differences in the code needed between the > old technique vs the "new" compound renderer (attached). > > > Ok, so the question to those that have knowledge of the _backend_agg.cpp > code (Mike, Eric, JJ + others?): > > * Have you already looked at doing this and determined that this is a > non-starter? > * Do you support adding the ability for the agg backend to draw > compound artists (i.e. Collections) in this way rather than treating > them as individual primitives in the canvas? > * Since many of the other backends can't do flash rendering, would we > even want to make this change? > o SVG in Firefox 10.0.2 has the same problem, it is discussed > slightly more in > http://www.svgopen.org/2002/papers/sorotokin__svg_secrets/ > o Acroread has the same problem with PDFs, only to a much lesser > extent than in the PNG attached > > > Thoughts? Phil, Would this greatly slow down the rendering? Does it work with alpha < 1? I'm initially not enthusiastic about having contourf return a single Collection, but maybe in practice it would not make much difference. The drawback, apart from code brakeage, is that it would remove the ability to pick out a level for additional customization. Could this be handled at a subsequent level, by having the renderer able to treat an arbitrary collection of artists as a group? It seems that contourf is where this "flash" capability would be most important; if it can't be made to work there, I think it might not be worth the trouble to add. Eric |
From: Michael D. <md...@st...> - 2013-03-06 20:45:03
|
I'm trying to compile your examples, but it seems perhaps you forget to include a file -- pixel_formats.hpp? It's not in the agg24 source tree. Mike On 03/06/2013 12:06 PM, Phil Elson wrote: > Smart rendering of adjacent, anti-aliased patches is a question which > has come up a couple of times in various guises in the past. > It is my understanding that the lack of this functionality led us to > disable anti-aliasing for contouring and is the reason the following > image has a white stripe around the circle where there should be just > a nice blend of the two colors: > > > import matplotlib.pyplot as plt > import numpy as np > import matplotlib.patches as mpatches > import matplotlib.path as mpath > import matplotlib.collections as mcol > > > # create two paths. One a circle, the other > # a square with the same circle cut out. > x = np.linspace(0, np.pi * 2, 1000) > > circle_coords = np.array(zip(*[np.sin(x) * 0.8, np.cos(x) * 0.8])) > pth_circle = mpath.Path(circle_coords) > > sqr_codes = np.repeat(mpath.Path.MOVETO, len(circle_coords) + 5) > sqr_codes[1:5] = mpath.Path.LINETO > sqr_codes[6:] = mpath.Path.LINETO > sqr_coords = np.concatenate([[[-1, -1], [-1, 1], [1, 1], [1, -1], [-1, > -1]], > circle_coords[::-1]], axis=0) > sqr_path = mpath.Path(sqr_coords, sqr_codes) > > > ax = plt.axes() > patches = [mpatches.PathPatch(pth_circle), mpatches.PathPatch(sqr_path)] > col = mcol.PatchCollection(patches, > antialiaseds=True, > edgecolors='none', > facecolors=[(0, 0.0, 0.0, 0.9), (0.1, 0.1, 0.02, 0.9)]) > ax.add_collection(col) > ax.set_xlim([-1, 1]) > ax.set_ylim([-1, 1]) > plt.show() > > > > I know of lots of the workarounds for this (turn off AA, turn on > lines, extend the path slightly, set a dark background color) all of > which have down-sides, so I'm keen to find a final solution to the > problem. > > When the two patches marry up perfectly with full anti-aliasing, the > antigrain (AGG) community call this "flash" or compound rendering, and > this capability was added to Agg 2.4 (which we already ship with mpl). > > In order to make full use of the compound rendering technique I > believe the drawing pipeline in "_backend_agg.cpp" would need to > change, which could be problematic. A less wide-impacting alternative > would be to draw all "patches" of a single Collection in the same > rasterization step (i.e. just change _draw_path_collection_generic), > though this does mean that, as it stands, the result of plt.contourf > would not be able to make use of this new functionality - a MEP which > changes the return type of plt.contourf to a single Collection might > be able to fix that. > > I've put together a simple example similar to this in C++ using agg > (no mpl changes yet), showing the differences in the code needed > between the old technique vs the "new" compound renderer (attached). > > > Ok, so the question to those that have knowledge of the > _backend_agg.cpp code (Mike, Eric, JJ + others?): > > * Have you already looked at doing this and determined that this is > a non-starter? > * Do you support adding the ability for the agg backend to draw > compound artists (i.e. Collections) in this way rather than > treating them as individual primitives in the canvas? > * Since many of the other backends can't do flash rendering, would > we even want to make this change? > o SVG in Firefox 10.0.2 has the same problem, it is discussed > slightly more in > http://www.svgopen.org/2002/papers/sorotokin__svg_secrets/ > o Acroread has the same problem with PDFs, only to a much lesser > extent than in the PNG attached > > > Thoughts? > > > > > > > > > > > > > ------------------------------------------------------------------------------ > Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester > Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the > endpoint security space. For insight on selecting the right partner to > tackle endpoint security challenges, access the full report. > http://p.sf.net/sfu/symantec-dev2dev > > > _______________________________________________ > Matplotlib-devel mailing list > Mat...@li... > https://lists.sourceforge.net/lists/listinfo/matplotlib-devel |