Plot elements of specific size

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 个评论

It sounds like you want the result from functions like patch, but want to use line objects to achieve that. There is probably a way to get that to work, but I question the underlying assumption.
You could probably use a listener to increase the MarkerSize etc as a response to zooming in or out.
Zohar
Zohar 2021-10-23
编辑:Zohar 2021-10-23
Then, I would need to ad hoc address and tweak each element size.
First, I don't care about interactive zooming. I'd like to save a pdf.
Then, even if I increase or change the marker size, it is still limited by the screen resolution. That is, the minimum marker size is bounded by a screen pixel. The 1000 polygon can't fit the screen.
So the rescaling on zoom should happen in the pdf?
It still sounds as if you want line art to behave like patches. That sounds like an XY problem to me. Can you confirm that is what you want? Or am I not understanding you correctly?
Zohar
Zohar 2021-10-23
编辑:Zohar 2021-10-23
I'm not fully clear on your definition, but I would say yes.
A pdf is a pdf: a static image, which you can't control (ignoring the elaborate features). Same as a rastarized image such as a png. Everyone is familiar with the behavior of a common viewer of these formats. Everything is written on a canvas, and the viewer is just a tool to explor the canvas. Not unlike a camera viewing a 3D scene. When you dolly or zoom on objects, they become bigger. When I design a 3D scene, I put objects inside the scene. Matlab, for some reason, draws on the camera lens instead of the convas. Then, when you walk, everything looks the same. Also, you don't have a scene or a world. The camear lens, or the screen in our case, is all you have to populate.
I can't imagine anyone sees these things differently: give me one example of a 2D or 3D app, file format, real life, or whatever that is designed differently. A very poor design on matlab's part. You simply can't control your drawing (what you see is definitely not what you want), or otherwise it's extremely limited.
If you look around a bit you can find some functions for creating UDF, which is interactive PDF.
Drawing of lines and of the dot marker (specifically) are "primitives" handled by OpenGL. MATLAB did not invent this behaviour.
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 :)

请先登录,再进行评论。

 采纳的回答

Matt J
Matt J 2021-10-23
编辑:Matt J 2021-10-23
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 个评论

"One option is to scale their size according to the zoom level. However, then the large polygon wouldn't necessarily fit the screen."
Meaning, if I have a large drawing and I need to zoom in to the right scale, then not everything would fit in the screen--specifically, the figure window. For this to be applicable, I need the second way (2) that I referred to. Matlab saves to a pdf only what you see on the screen, right?
Matt J
Matt J 2021-10-23
编辑:Matt J 2021-10-24
if I have a large drawing and I need to zoom in to the right scale, then not everything would fit in the screen--specifically, the figure window
Again, you sometimes speak as if you intend to be zooming in Matlab and elsewhere say that you only plan to be zooming a pdf print of the figure. Which is it?
Matlab saves to a pdf only what you see on the screen, right?
Yes, but you would print only after zooming out so that the full figure is in view. You would also set the MarkerSize and LineWidth when the full figure is in view. I don't see how the selection of the MarkerSize and LineWidth requires any zooming. Aren't you pre-selecting them in proportion to the dimensions of your polygon?
Is the issue that you want to be able to zoom the Matlab figure to verify the proportions of the LineWidths and MarkerSizes? If so, it is not an ad hoc matter to rescale the Markers to keep them in the same proportion. The code I proposed above systematically calculates the proportionality factor that you need given the current axes limits. You could put it in a function and re-execute it every time you zoom in and zoom out. As Rik pointed out, this could be further automated with listeners or, if you have R2021a, with a LimitsChangedFcn:
One of us is missing something.
For simplicity, forget about zooming in matlab, I'm not iterested in that at all, and I don't need to check anything. I'm working with a pdf instead.
When I render the figure, I'm using the default zoom, where the whole polygon is on screen. Now, it's a big polygon with a lot of tiny details which can't be captured using the screen pixel resolution: either nothing would be drawn, or elements would be scaled (out of proportion) to be the size of at least one pixel (the latter is matlab's behavior).
A pdf, unlike the screen, isn't rasterized, it's vectorized. Thus, it has infinite resolution, and it has no issue with any detail size. Therefore, I would like to render everything in a selected paper resolution (DPI)--not limiting myself to the screen resolution.
To do that, according to your method, I'll need to scale down the markers and edges of fine details below matlab's threshold (1 pixel).
Matt J
Matt J 2021-10-24
编辑:Matt J 2021-10-24
Now, it's a big polygon with a lot of tiny details which can't be captured using the screen pixel resolution: either nothing would be drawn, or elements would be scaled (out of proportion) to be the size of at least one pixel (the latter is matlab's behavior).
That may be true of how Matlab renders line objects on the screen, but I think internally, they are vectorized and, when exporting to PDF, are also sent in vectorized format by default. As a simple test, I generated a plot with MarkerSize=0.1. I can't see the marker in the Matlab figure no matter how much I zoom, but when I export the same figure to PDF, I can zoom down by a factor 6400 and see a very sharp, well-defined circular marker.
Further evidence of this is in the documentation for the new exportgraphics() command, which has specific options to let you export to PDF in vectorized format.
Zohar
Zohar 2021-10-24
编辑:Zohar 2021-10-24
I also think that internally they use vectorized format. I tried to play with hgexport(), which has specific parameters for font and line only--and not for the marker (that's what I meant by I don't want ad hoc solution for each specific element type.)
I've stumbled across exportgraphics(), but I haven't tried it (I have matlab 2019b--but I'll try to upgrade if you confirm). Are you saying that this new function allows me to render off-screen and save in any resolution?
(By the way, it's not so hard to devise a specific example. Say, the screen is 1000-pixel high. Draw a straight vertical polyline of 10,000 vertices, where the radius of each vertex marker is tenth of a segment edge. You won't be able to view it on screen but a pdf could accommodate it. But sounded like you got the idea and tested it with a .1 marker).
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().
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).

请先登录,再进行评论。

更多回答(1 个)

Matt J
Matt J 2021-10-24
编辑:Matt J 2021-10-24
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

类别

帮助中心File Exchange 中查找有关 Graphics Performance 的更多信息

标签

Community Treasure Hunt

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

Start Hunting!

Translated by