MATLAB Answers

How to Output Accurate PDF from Matlab figure

조회 수: 13(최근 30일)
Frank 2014년 3월 18일
댓글: Frank 2014년 3월 20일
Hi everyone:
For some reason, I need to plot the mask of a microfluid device in Matlab, which consists of many posts separated by certain distance The plotting process is easy but when I tried to 'print' it into PDF file, the image was distorted (circles are not round, and they have obvious defect on them), and the spacing was not right(shortened).
I've tried function 'rectangle', code like:
function drawFilledCircle (center_x, center_y, radius)
%%Draw a filled circle
xc = center_x; yc = center_y;
r = radius;
x = r*sin(-pi:0.01*pi:pi) + xc;
y = r*cos(-pi:0.01*pi:pi) + yc;
fill(x, y, [0,0,0]);
and even a function called 'filledCircle' which I found on fileexchange.
But I always got the wrong thing. I don't know what I can do to fix it.
Please help.
P.S. I attached the original matlab figure and the printed PDF for references.
P.S.2 I've also tried to output them into other formats like EPS, but even EPS doesn't look right.
  댓글 수: 4
Frank 2014년 3월 19일
No problem. Here you go, thanks. (Please let me know how to do it if you manage to do so)
%%Hexagon in Hexagons
%%if we want to do size of 7 (hexagon in a hexagon array)
x_num = 30;
y_num = 30;
diameter = 100*7 + 100*6;
distance = diameter;
margin = 100;
% Define the long distance in the hexagonal lattice
long_distance = sqrt(3)*(distance + diameter) - diameter;
xlimit = 2*margin + diameter*x_num + (x_num-1)*(distance - diameter)/2;
ylimit = 2*margin + diameter*y_num + (y_num-1)*(sqrt(3)*(diameter + distance)/2 - distance);
figure;set(gca,'position',[0 0 1 1]);
% set(gca,'XColor',[1,1,1],'YColor',[1,1,1]);
box on;
% for x = 0:x_num-1
% for y = 0:y_num-1
% rectangle('position',[margin+(x*(diameter+distance)),margin+(y*(diameter+distance)),diameter,diameter],'curvature',[1,1],'FaceColor',[0,0,0]);
% end
% end
%Try to plot the posts by even and odd
if mod(x_num,2) == 0
odd_num_x = x_num/2;
even_num_x = x_num/2;
odd_num_x = (x_num - 1)/2 + 1;
even_num_x = (x_num - 1)/2;
if mod(y_num,2) == 0
odd_num_y = y_num/2;
even_num_y = y_num/2;
odd_num_y = (y_num - 1)/2 + 1;
even_num_y = (y_num - 1)/2;
for x = 0:odd_num_x-1
for y =0:odd_num_y-1
% rectangle('position',[margin+ x*(diameter + distance) , margin+(y*(diameter+long_distance)),diameter,diameter],'curvature',[1,1],'FaceColor',[0,0,0]);
draw_hexagon (margin+ x*(diameter + distance) + 250, margin + (y*(diameter+long_distance)),7,100,100);
for x = 0:even_num_x-1
for y = 0:even_num_y-1
% rectangle('position',[margin+ (distance + diameter)/2 + x*(diameter + distance) , margin + sqrt(3)*(diameter + distance)/2 + (y*(diameter+long_distance)),diameter,diameter],'curvature',[1,1],'FaceColor',[0,0,0]);
draw_hexagon (margin+ (distance + diameter)/2 + x*(diameter + distance) + 250, margin + sqrt(3)*(diameter + distance)/2 + (y*(diameter+long_distance)),7,100,100);
The function draw_hexagon I use above is:
%%Function to print hexagonal shaped island in a blank area
function draw_hexagon (position_x, position_y, size, diameter, distance)
% Size must be odd.
% Size is the number of posts on the longest diagonal of the hexagon.
if mode(size,2) == 0
error('Please input an odd number for the size parameter!');
side_num = (size - 1)/2 + 1;
% The strategy is to plot the lower half of hexagon, and then plot the top
% half of the hexagon.
% define a distance parameter that can switch between top and bottom
up_down = (side_num - 1)*sqrt(3)*(distance + diameter);
while side_num <= size
for index = 0:side_num - 1
rectangle('position',[position_x + index*(diameter + distance), position_y, diameter, diameter],'curvature',[1,1],'FaceColor',[0,0,0]);
rectangle('position',[position_x + index*(diameter + distance), position_y + up_down, diameter, diameter],'curvature',[1,1],'FaceColor',[0,0,0]);
side_num = side_num + 1;
up_down = up_down - sqrt(3)*(diameter + distance);
position_x = position_x - (distance + diameter)/2;
position_y = position_y + sqrt(3)*(distance + diameter)/2;
% positions are the lower left corner of the hexagon
Sorry It's not well commented. I was not intended to be distributed. Please let me know if you have any problem reading it.

댓글을 달려면 로그인하십시오.

채택된 답변

lvn 2014년 3월 20일
The problem with the spacing is in fact a problem of the line around the circle. Because you work on such small scales, it determines the size of the circle! This solves it I think. In your code change the rectangle functions to
rectangle('position',[position_x + index*(diameter + distance), position_y, diameter, diameter],'curvature',[1,1],'FaceColor',[0,0,0],'LineStyle','none');
and then Jan Simon's export print(gcf, 'test.eps', '-dpsc2', '-r1200', '-noui').
After conversion to pdf, the result looks ok to me (see attached).
  댓글 수: 3
Frank 2014년 3월 20일
Add one thing to whom may concern:
In my case, I want to output nearly 10^5 posts on one figure, it's important to set the resolution to at least '-r1600' to obtain undistorted image.

댓글을 달려면 로그인하십시오.

추가 답변(4개)

Chad Greene
Chad Greene 2014년 3월 18일
I highly recommend switching to export_fig instead of using print. Here's export_fig:
Oliver Woodford, the author of export_fig has a quite helpful and succinct site with plenty of picture examples and troubleshooting tips here:
Does the attached pdf look correct?
  댓글 수: 4
Frank 2014년 3월 18일
Let me put it in a clear way. In my matlab figure file attached above, the diameter of the post is 100um, and the spacing between two posts are 100um as well. Did any of the output file (PDF,PNG) has perfect round posts and right spacing?

댓글을 달려면 로그인하십시오.

Chad Greene
Chad Greene 2014년 3월 18일
Oh, interesting. I see the problem now, but is this a pdf issue, or an issue with the filled circle function? Perhaps simply creating a scatter plot and setting the size of the markers would fix it?
  댓글 수: 2
Frank 2014년 3월 19일
I tried to output by scatter. The result is better since the circles are round. But the problem is the marker size on figure doesn't match the size on pdf. It seems that matlab automatically scale it when you output figure into pdf. Here are the figure and pdf I got.

댓글을 달려면 로그인하십시오.

Chad Greene
Chad Greene 2014년 3월 19일
Follow the circles command with axis equal to ensure the circles don't get squashed.
  댓글 수: 2
Frank 2014년 3월 19일
Hi Chad, the results of scatter plot is very promising except i don't know how to control the size of the marker.
According to the link you send to me,I use:
s = 100; %Marker width in units of X
currentunits = get(gca,'Units');
set(gca, 'Units', 'Points');
axpos = get(gca,'Position');
set(gca, 'Units', currentunits);
markerWidth = s/diff(xlim)*axpos(3); % Calculate Marker width in points
to get the size of the marker, and then use:
to plot. The circles are not distorted on the output pdf, however, the size is apparently wrong. Do you have any idea on size control?

댓글을 달려면 로그인하십시오.

Jan 2014년 3월 19일
This creates a perfectly looking EPS and after a conversion the resulting PDF is fine also:
print(gcf, 'test.eps', '-dpsc2', '-r1200', '-noui')
Increasing the resolution to 1200 makes the difference.
  댓글 수: 1
Frank 2014년 3월 20일
Hi Jan,
Thanks for your effort. The circles look perfectly round. But the other issue still exist : the spacing between posts are definitely not right. (if you look at my code, then you can see spacing = diameter)
I don't know if it has something to do with rendering. But I'm happy to discuss with you anytime if you are willing to do so.

댓글을 달려면 로그인하십시오.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by