Triangular split patches with painters renderer in MATLAB 2014b and above

无人久伴 提交于 2019-12-03 13:34:13

问题


MATLABs new graphics engine, HG2, fails to properly print patches using the painters renderer:

hist(randn(1,1000)); 
colorbar('Location','SouthOutside');
print('test.pdf','-dpdf');

The resulting patches, whether generated by hist or colorbar, have triangular splits:

The issue has been discussed on MATLAB Central here and here, where it was suggested that disabling the "smooth line art" option in the pdf-viewer should solve it. This conceals the problem in some readers (e.g. in Adobe Reader but not in Apple Preview), but it is hardly a solution to ask collaborators and readers to use a specific pdf-viewer with non-default settings for graphics to appear correctly. Looking at the resulting file in Inkscape, it is clear that the split is present in the output vector graphics. Here, I moved one half of the colorbar, proving that it is in fact split in half, and not just misinterpreted by the pdf-viewer:

The problem is not present using the OpenGL renderer (print('test.pdf','-opengl'), but then the output is not vectorized). The problem persists in MATLAB 2015a.

Is there a way to export artifact-free vector graphics in MATLAB 2014b or later?


回答1:


Here's a questionable work-around until the actual problem is solved:

The diagonal lines are simply the empty space between the triangles, so what we are seeing is the white space behind the patches peek through. Silly idea: Let's fill that space with matching colors instead of white.

To do so, we'll copy all objects and offset the new ones by just a tiiiiny bit.

Code:

hist(randn(1,1000));
colorbar('Location','SouthOutside');
print('test.pdf','-dpdf');               %// print original for comparison

f1 = gcf;
g  = get(f1,'children');
n  = length(g);
copyobj(g,f1);                           %// copy all figure children

The copied objects are now the first n elements in the 2*n f1.Children array. They are exactly on top of the old objects.

g=get(f1,'children');
for i=1:n;
    if strcmpi(g(i).Type,'axes');
        set(g(i),'color','none','position',g(i).Position+[0.0001 0 0 0]);
        set(g(i+n),'position',g(i+n).Position);                            %// important!
    end;
end;
print('test2.pdf','-dpdf');

Explanation:

g = get(f1,'children'); gets all axes, colorbars, etc., within the current figure.

colorbar objects are linked to an axes, which is why we'll only have to move the axes type children.

Setting the color to none makes the background of the new axes transparent (since they are on top of the old ones).

g(i).Position+[0.0001 0 0 0] shifts the new axes by 0.0001 normalized units to the right.

set(g(i+n),'position',g(i+n).Position); This line seems unnecessary, but the last image below shows what happens when printing if you don't include it.

Depending on the types of graphics objects you have plotted, you may need to tweak this to fit your own needs, but this code should work if you have only colorbar and axes objects.

Original:

With hack:

Without %// important! line:




回答2:


In R2015b, histogram seemed to not show the white lines, but fill did.

For simple plots just paste the data again:

x = 0:pi/100:pi;
y = sin(x);
f = fill(x,y,'r');
hold on;
f2 = fill(x,y,'r'); %// Worked like magic

If the magic fails try similar to Geoff's answer: f2 = fill(x+0.0001,y,'r');




回答3:


Depending on what version of Matlab you are using, you might try to use epsclean. It doesn’t seem to work with very recent versions of Matlab like 2017a.

Otherwise, epsclean can be run on an existing eps file (not pdf) exported with the -painters option to generate a vectorized figure, and it will rewrite (or create another file) with those white lines removed.



来源:https://stackoverflow.com/questions/30870613/triangular-split-patches-with-painters-renderer-in-matlab-2014b-and-above

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!