Plot elements of specific size

10 views (last 30 days)
Zohar
Zohar on 23 Oct 2021
Commented: Zohar on 24 Oct 2021
I'm plotting a polygon made of edges and vertices. I'd like to plot these elements at a specific size or proportion: whether the polygon has 10 or 1000 vertices, I'd like the elements to be drawn at the same size. When zooming in and out of the vector image, element size would remain static. For example, define a canvas of 100inx100in and draw lines .1in thick (and save to a pdf).
Currently, it seems impossible since, e.g., the LineWidth and MarkerSize are relative to the screen instead of the canvas. This means that when you zoom into the figure, the elements keep their size wrt screen. One option is to scale their size according to the zoom level. However, then the large polygon wouldn't necessarily fit the screen.
There are two ways that I see to resolve this, both seem impossible:
  1. Define the size properties wrt the canvas and not the screen.
  2. Go to the proper zoom level, and draw all elements even if they aren't in the figure clip region (save to a pdf).
Questions on the subject asked about specific elements such as lines or markers. The suggested solutions were to draw with alternative functions such as patch() and rectangle().
In that case, I'll forsake matlab's clanky drawing mechanism altogether, export the data, and draw in svg. But it would be a shame since matlab has powerful tools such as different marker shapes or a force graph.
Am I missing something fundamental or is this the worst design I've seen lately?
Edit by @Rik:
Since stackoverflow uses CC-BY-SA 4.0 and Answers uses CC-BY-SA 3.0, I took the liberty of copying the actual content of the question from the originally posted link.
Original question:
See
  7 Comments
Walter Roberson
Walter Roberson on 23 Oct 2021
Drawing of lines and of the dot marker (specifically) are "primitives" handled by OpenGL. MATLAB did not invent this behaviour.
Zohar
Zohar on 23 Oct 2021
True. And in opengl the line thickness is limited, and it's a whole can of worms. Not something I'd take an example from :)

Sign in to comment.

Accepted Answer

Matt J
Matt J on 23 Oct 2021
Edited: Matt J on 23 Oct 2021
First, I don't care about interactive zooming. I'd like to save a pdf.
If the zooming is happening only after the pdf conversion, I don't see why you can't just set the LineWidth and MarkerSize to your preference when the whole drawing is in view, and then convert.
If it's a problem of calculating the conversion factor from data units to points (the units that LineWidth and MarkerSize are measured in, 1 point = 1/72 inch), that can be done as follows:
set(gcf,'Units','points'); %change this back later, if needed
DU=diff(xlim); %width of figure in data units
P=hfig.Position(3); %width of figure in points
conversionFactor=P/DU; %conversion factor, data units to points
  7 Comments
Matt J
Matt J on 24 Oct 2021
Are you saying that this new function allows me to draw in any resolution, and even though I won't be able to render it to a figure, I'll be able to save it to an offline pdf?
I think you should try it. I'm not sure you need to upgrade to a Matlab version which has exportgraphics(). I just used saveas().
Zohar
Zohar on 24 Oct 2021
Damn, you are right!
Full details:
One issue is multi-line text. The only way to change the line spacing is breaking the text into single lines:
But it won't work with the post scale since need to account for a new row spacing. One solution is to first render the image, work out the scaling, then draw the image with that scaling (instead of post scaling after the image is drawn).

Sign in to comment.

More Answers (1)

Matt J
Matt J on 24 Oct 2021
Edited: Matt J on 24 Oct 2021
You could probably use a listener to increase the MarkerSize etc as a response to zooming in or out.
The code below is an implementation of @Rik's suggestion. All line objects in the specified axis will have their MarkerSize and LineWidth properties auto-zoomed in proportion to changes in the axis x-limits.
plot(exp(1:3),'-o');
lockSizes(gca)
function updateSize(ax)
if ~nargin
ax=gca;
end
h=findobj(ax,'Type','line','-or','Type','functionline');
DU=diff(xlim);
factor=h(1).UserData.DU./DU;
for i=1:numel(h)
h(i).MarkerSize=h(i).MarkerSize*factor;
h(i).LineWidth=h(i).LineWidth*factor;
h(i).UserData.refSize=h(i).MarkerSize;
h(i).UserData.refWidth=h(i).LineWidth;
h(i).UserData.DU=DU;
end
end
function lockSizes(ax)
if ~nargin
ax=gca;
end
h=findobj(ax,'Type','line','-or','Type','functionline');
DU=diff(xlim);
for i=1:numel(h)
h(i).UserData.refSize=h(i).MarkerSize;
h(i).UserData.refWidth=h(i).LineWidth;
h(i).UserData.DU=DU;
end
addlistener(ax.XRuler,'MarkedClean',@(~,~) updateSize(ax));
end

Categories

Find more on Printing and Saving in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!