Треугольные сплит патчи с рендером художников в 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*n
f1.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, чтобы сгенерировать векторизованную фигуру, и он перезапишет (или создаст другой файл) с удалением этих белых линий.