percentages deviations during sampling physical distance with "current point" on different monitors with different resolutions

1 回表示 (過去 30 日間)
I'm trying to write a code that detrmine the physical lateral distance between a press of a button to specific target on the middle of the screen.
I'm using the next code:
set(gca,'units','centimeters');
cp = get(gca,'CurrentPoint');
dist = (LinePosition - cp(1));
LinePosition is the distance in centimeters of the middle of the screen from the left edge of the primary display to the inner left edge of the monitor using "MonitorPosition" property.
My problem is that on different monitors i.e on different sizes, resolution and definitions, I get different percentages deviations.
I measured with a ruler the length from the click and compared it to the distance that the code had provided.
For example:
On DELL P2317H which is 23 inch on 1920x1080 and 100% 0n the display settings (recommended) I get no significant deviation
On the same DELL, still 1920x1080 but with 125% 0n the display settings I get deviation of 20% approx
On Lenovo Yoga 7 screen which is 14 inch on 1920x1080 and 150% 0n the display settings (recommended) I get deviation of +9% approx
On the same Lenovo screen still 1920x1080 but with 125% I get deviation of +30% approx
On the same Lenovo screen still 1920x1080 but with 175% I get deviation of -6.5% approx (lenghs are shorter)
On Asus X541U screen which is 1366x768 and 100% 0n the display settings (recommended) I get deviation of +4% approx
I will note that I read a lot of documents and searched as much as I could for questions and answers related to the topic but did not find a solution that would meet my need for the code to run on different monitors with different settings
  6 件のコメント
Adam Danz
Adam Danz 2021 年 9 月 16 日
You aren't plotting in 3D axes, are you? That's a whole other story that involves camera angle, projection geometry, and depth within the axes.
Are you using equal aspect ratio (ie, "axis equal")?
Could you provide a short example of the code you're using so I can do the same thing you're doing?
Yoav Tsoran
Yoav Tsoran 2021 年 9 月 17 日
No, I'm not using 3D axes. and I didn't try to use an equal aspect ratio, so I will read about it, thanks.
I'm attaching the part of the code that might be relevant. the first part is for enlarging the figure when opened, and decide in which monitor to open it, with priority to the second monitor. I attached this part because I set there the 'OterPosition' property, so maybe it's relevant.
Again, thank you very much for the help.
f = figure;
set(0,'units','centimeters');
f.WindowState = "maximized"; %Opens the figure in maximum size.
ax1 = axes('InnerPosition',[0 0 1 1]);
%%Check if a second monitor is plug to the computer
MP = get(0, 'MonitorPositions');
if size(MP, 1) == 1 % Single monitor
Pixels_SS = MP(1, 1:4);
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
set(gcf, 'Toolbar', 'none', 'Menu', 'none');
else %second monitor gets the priority
Pixels_SS = MP(2, 1:4);
set(0,'units','normalized');
MP = get(0, 'MonitorPositions');
set(gcf, 'Units', 'normalized', 'OuterPosition', [MP(2, 1) MP(2, 2) MP(2, 3) MP(2, 4)]);
set(gcf, 'Toolbar', 'none', 'Menu', 'none');
end
LinePosition = Pixels_SS(3)/2;
BottumLim = Pixels_SS(4)/2 - 9;
UpperLim = Pixels_SS(4)/2 + 9;
x = LinePosition*ones(10);
set(0,'units','centimeters');
y = linspace(BottumLim,UpperLim,10);
plot(x,y,'red','LineWidth', 5);
set(gca,'Color','k');
axis([0 Pixels_SS(3) 0 Pixels_SS(4)])
w = waitforbuttonpress; % Waiting for the user to click
if w == 0
set(gca,'units','centimeters');
cp = get(gca,'CurrentPoint');
dist = (LinePosition - cp(1));
end

サインインしてコメントする。

回答 (1 件)

Adam Danz
Adam Danz 2021 年 9 月 17 日
I cleaned of your snippet of code and left comments where I've made changes.
I've also added a horizontal ruler with 1cm tick marks that perfectly align to a physical ruler on my monitor (see image below).
% Store original units % ADDED This section
clear('cleanupProps') % This line only needed if working in a script
origUnits = get(0, 'Units'); % Store original units
cleanupProps = onCleanup(@()set(0, 'Units', origUnits)); % Return original units when this var is cleared
f = figure(); % Consider renaming this varible
f.WindowState = "maximized"; %Opens the figure in maximum size.
ax1 = axes(f, 'Units','Normalized','InnerPosition',[0 0 1 1]); % ADDED UNITS and fig handle
%%Check if a second monitor is plug to the computer
set(0,'units','centimeters')
MP = get(0, 'MonitorPositions');
if size(MP, 1) == 1 % Single monitor
Pixels_SS = MP(1, :); % Simplified
else %second monitor gets the priority
Pixels_SS = MP(2, :); % Simplified
end
set(f, 'Units', 'Centimeters', 'OuterPosition', Pixels_SS, ... % Replaced gcf with fig handle; combined lines; changed to cm
'Toolbar', 'none', 'Menu', 'none')
LinePosition = Pixels_SS(3)/2;
BottumLim = Pixels_SS(4)/2 - 9;
UpperLim = Pixels_SS(4)/2 + 9;
% x = LinePosition*ones(10);
x = [LinePosition, LinePosition]; % Replaced line above
% set(0,'units','centimeters'); % Redundant with the line in the condition below
% y = linspace(BottumLim,UpperLim,10);
y = [BottumLim,UpperLim]; % Replaced the line above
plot(x,y,'red','LineWidth', 5);
set(ax1,'Color','k',... % Replaced gca with axes handle!
'xlim',[0 Pixels_SS(3)],'ylim',[0 Pixels_SS(4)]); % The replaces the line below
% axis([0 Pixels_SS(3) 0 Pixels_SS(4)])
w = waitforbuttonpress; % Waiting for the user to click
if w == 0
set(ax1,'units','centimeters'); % Use object handles instead of gca/gcf/etc
cp = get(gca,'CurrentPoint');
dist = (LinePosition - cp(1));
fprintf('Current Point = [%.3f,%.3f]; dist = %.5f\n', cp(1,1), cp(1,2), dist)
end
% ADDED THIS SECTION FOR PHYSICAL VERIFICATION
yline(range(ylim)/2,'g--') % This draws a horizontal line at the center, the red line should be 9cm on each side
% These lines below add 1 cm tick marks. Hold a ruler to your monitor for verification
xtickLines = ax1.XLim(1) : 1 : ax1.XLim(2);
ytickLines = ax1.YLim(1)+range(ax1.YLim)/2+[-1;1]*range(ax1.YLim)*.02;
hold on
plot([xtickLines;xtickLines], ytickLines, 'g-')
The slight offset is due to the thickness of the ruler offsetting it in depth from the monitor and the camera's viewing angle.
  4 件のコメント
Yoav Tsoran
Yoav Tsoran 2021 年 9 月 20 日
Hi
So I tried both links, and in both of them my monitor is scaled to the ruler and I'm using the monitor's native resolution. However, when I'm runing the code, it doesnt mach to the 1 cm ticks and the distance from the bar has precentage deviation. I also treid to run the code with any different resolutions I could and it still doesnt work.
The weird thing is that even if I just run this
set(0,'units','centimeters')
MP = get(0, 'MonitorPositions');
I still get a nonereal size of the screen. (i.e the MonitorPosition return 36.14 cm and my monitor width is 34.5 cm)
I managed to get a very accurate measurement when I did some weird manipulation: I worked with Pixels units, got the screen width in pixels, then I measured the screen width in cm with a physical ruler so I have the screen 'real' Dots Per Cm ratio. then I use the get current point property with pixels unit and convert it to cm. This one is very accurate. But of course I don't see it as a solution, because in each new monitor I need to make this measurement again to get the 'real' ratio of the monitor.
Adam Danz
Adam Danz 2021 年 9 月 20 日
I don't know what to tell ya...
This Matlab Tech Support answer indicates, " Sometimes inaccuracies creep into the results you may get. This is due to the fact that the system may return incorrect information. If you begin to notice this, you can compensate by updating the video drivers or switching the resolution of the monitor."
This thread may also be helpful.

サインインしてコメントする。

カテゴリ

Help Center および File Exchange2-D and 3-D Plots についてさらに検索

製品


リリース

R2020a

Community Treasure Hunt

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

Start Hunting!

Translated by