Треугольные сплит патчи с рендером художников в MATLAB 2014b и выше

Новый графический движок MATLAB, HG2, не может правильно печатать патчи с помощью средства визуализации:

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

Полученные патчи, генерируемые ли hist или же colorbar, имеют треугольные расщепления:

Треугольные расколы в заплатах

Эта проблема обсуждалась в MATLAB Central здесь и здесь, где было предложено решить эту проблему, отключив параметр "плавные линии" в программе просмотра PDF. Это скрывает проблему у некоторых читателей (например, в Adobe Reader, но не в Apple Preview), но вряд ли можно попросить соавторов и читателей использовать определенный просмотрщик PDF с настройками, отличными от настроек по умолчанию, чтобы графика отображалась правильно. Глядя на полученный файл в Inkscape, становится ясно, что в выходной векторной графике присутствует разделение. Здесь я переместил половину цветовой шкалы, доказав, что она на самом деле разделена на две части, а не просто неправильно интерпретирована программой просмотра PDF:

Проблема отсутствует при использовании рендерера OpenGL (print('test.pdf','-opengl'), но тогда выход не векторизован). Проблема сохраняется в MATLAB 2015a.

Есть ли способ экспортировать векторную графику без артефактов в MATLAB 2014b или новее?

3 ответа

Вот сомнительный обходной путь, пока реальная проблема не будет решена:

Диагональные линии - это просто пустое пространство между треугольниками, поэтому то, что мы видим, - это белое пространство за патчами, через которые можно заглянуть. Глупая идея: давайте заполним это пространство соответствующими цветами вместо белого.

Для этого мы скопируем все объекты и сместим новые только на один бит.

Код:

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

Скопированные объекты теперь являются первыми n элементы в 2*nf1.Children массив. Они точно на вершине старых предметов.

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');

Объяснение:

g = get(f1,'children'); получает все оси, цветные полосы и т. д. в пределах текущей фигуры.

colorbar объекты связаны с осями, поэтому нам нужно только переместить axes типа детей.

Настройка color в none делает фон новых осей прозрачным (так как они располагаются поверх старых).

g(i).Position+[0.0001 0 0 0] сдвигает новые оси на 0,0001 нормализованных единиц вправо.

set(g(i+n),'position',g(i+n).Position); Эта строка кажется ненужной, но последнее изображение ниже показывает, что происходит при печати, если вы ее не включаете.

В зависимости от типов графических объектов, которые вы изобразили, вам может потребоваться настроить его под свои нужды, но этот код должен работать, если у вас есть только объекты цветовой шкалы и оси.

Оригинал:

оригинал

С хаком:

Без %// important! линия:

В R2015b, histogram казалось, не показывают белые линии, но fill сделал.

Для простых графиков просто вставьте данные снова:

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

Если магия не удалась, попробуйте аналогично ответу Джеффа: f2 = fill(x+0.0001,y,'r');

В зависимости от того, какую версию Matlab вы используете, вы можете попробовать использовать epsclean. Кажется, он не работает с самыми последними версиями Matlab, такими как 2017a.

В противном случае epsclean можно запустить на существующем eps-файле (не в формате pdf), экспортированном с параметром -painters, чтобы сгенерировать векторизованную фигуру, и он перезапишет (или создаст другой файл) с удалением этих белых линий.

Другие вопросы по тегам