Issues with CurrentPoint in R2021b
Show older comments
I am trying to track some user clicks within an axes that lives within a uifigure.
I was originally using CurrentPoint from the axes object, but I started to notice that in certain scenarios, the coordinates of CurrentPoint did not seem to be correct for where the mouse event happened. I did as much investigating as I could and found a possible solution in looking at the event IntersectionPoint property.
I can effectively use the IntersectionPoint property of the event for mouse down and up events and I get coordiantes that very closely match where I was trying to click.
I need something like IntersectionPoint that can be used withn mouse motion callbacks because CurrentPoint is off by a significant amount.
Here is what I have in all of my callbacks:
cp = get(obj.Axes,'CurrentPoint');
ip = evt.IntersectionPoint;
fprintf('Current Point: (%g,%g)\nIntersection Point: (%g,%g)\n\n',cp(1,1),cp(1,2),ip(1,1),ip(1,2));
Then when I execute clicks, attempting to click near (11,1200) on the axes, I get the follwing:
Current Point: (10.9365,1376.74)
Intersection Point: (10.9782,1196.9)
8 Comments
Bruno Luong
on 15 Dec 2021
If you have a Minimum Working Example; it would be helpful to post it here.
I have an application using CurrentPoint and it works fine with R2021b.
May be your mouse is lagging for whatever reason, this might be another cause.
Matt Butts
on 15 Dec 2021
Bruno Luong
on 15 Dec 2021
Edited: Bruno Luong
on 15 Dec 2021
Here is my code:
clc
close all
fig = figure;
ax = axes('Parent',fig);
set(ax,'ButtonDownFcn',@chekerrorcb);
text(ax,0.5,0.5,'click on the axes')
function chekerrorcb(ax, event)
p1 = event.IntersectionPoint(1,1:2);
p2 = ax.CurrentPoint(1,1:2);
d = p1-p2;
fprintf('%g\n',norm(d));
end
Run it then click randomly on the axes, I get this errors printed out
0.00362364
0.00362361
0.00362362
0.00362364
0.00362362
0.00362362
0.00362363
0.00362361
0.00362361
0.00362363
0.00362365
0.00362361
0.00362364
0.0036236
0.00362364
0.00362361
0.00362361
0.00362361
0.00362363
0.00362364
0.00362364
0.00362363
0.00158108
0.00362361
0.00362361
0.00362363
0.00362362
0.00362364
0.00362362
Consistently 3.6e-3 for a small windows of (0,1)x(0,1). That about one pixel.
Matt Butts
on 15 Dec 2021
Bruno Luong
on 16 Dec 2021
Edited: Bruno Luong
on 16 Dec 2021
What is obj in your case?
In my code the callback object is the axe handle. Your code doesn't clearly show that.
A snipet of code won't show exactly what you did.
Matt Butts
on 16 Dec 2021
Bruno Luong
on 16 Dec 2021
What if you call drawnow on top of your callback function? Also make sure the axes handle is the one you see on the screen, and not some hidden axes.
Matt Butts
on 16 Dec 2021
Answers (1)
Benjamin Kraus
on 16 Dec 2021
1 vote
We've seen issues in the past with CurrentPoint being slightly off, and we are investigating them. Can you provide a little more information about your particular setup and I'll add it to our internal report about this issue? Specifically:
- You said "CurrentPoint is off by a significant amount" but your reproduction steps show off by ~1 pixel. Have you experienced errors that are larger than 1 pixel before?
- In the code you posted you have an axes directly in a uifigure. Are you using anything else in the figure, like tabs, panels, uigridlayout, etc.? Is the axes always directly in the uifigure, or is it in another container inside the uifigure?
- Any reproduction code you have, with as much detail as you can include, will be helpful.
- Are you using the "Scrollable" feature of the uifigures?
- What platform are you using? Windows? Mac? Linux?
- What is the output from rendererinfo run on your axes?
- What is your screen resolution and pixel density?
7 Comments
Bruno Luong
on 16 Dec 2021
I change my script to be able to display error for figure and uifigure, and obviously the problem lies on uifigure
function checkcperror(uiflag)
% uiflag: true to check uifigure; false old figure
close all
if uiflag
fig = uifigure('Name','uifigure');
ax = uiaxes('Parent',fig);
fprintf('Check for uifigure\n')
else
fig = figure('Name','figure');
ax = axes('Parent',fig);
fprintf('Check for figure\n')
end
set(ax, 'Units','normalize', 'innerposition',[0 0 1 1]);
set(ax,'ButtonDownFcn',@chekerrorcb);
text(ax,0.5,0.5,'click on the axes','HorizontalAlignment','center');
set(ax,'Unit','pixel');
end
function chekerrorcb(ax, event)
p1 = event.IntersectionPoint(1,1:2);
p2 = ax.CurrentPoint(1,1:2);
d = p1-p2;
ax.Units = 'pixel';
pos = get(ax,'Position');
dx = pos(3);
dy = pos(4);
fprintf('error = %g pixel\n',norm(d.*[dx dy]));
end
Results (R2021b, Windows 8 run on Remote Desktop):
>> checkcperror(false)
Check for figure
error = 0.58519 pixel
error = 0.585183 pixel
error = 0.585197 pixel
error = 0.5852 pixel
error = 0.585196 pixel
error = 0.585185 pixel
>> checkcperror(true)
Check for uifigure
error = 14.5491 pixel
error = 15.43 pixel
error = 14.549 pixel
error = 14.5491 pixel
error = 15.43 pixel
error = 16.3111 pixel
error = 15.43 pixel
error = 16.3111 pixel
error = 14.549 pixel
error = 14.5491 pixel
Bruno Luong
on 16 Dec 2021
Also the error of 0.58 pixels seems odd even for figure. May be the rounding methods used or size of the axes are different for CurrentPoint and IntersectionPoint (not seems to be documented).
Matt Butts
on 16 Dec 2021
Benjamin Kraus
on 16 Dec 2021
@Matt Butts: The issue with uigridlayout is a known bug in R2021b. Unfortunately, the only workaround I can suggest is to use IntersectionPoint (which is technically undocumented).
@Bruno Luong: You are correct, IntersectionPoint is undocumented, and your comment "Maybe the rounding methods used or size of the axes are different for CurrentPoint and IntersectionPoint" is exactly correct, but it is more than the rounding methods that are different, the method for calculating the CurrentPoint and IntersectionPoint are almost completely different.
At a very high level, CurrentPoint on the axes is derived by starting with the CurrentPoint on the figure (which may be rounded to the nearest pixel) and then applying transformations to the value to translate it into the axes data space. This is why it can sometimes have an error of roughly a pixel, due to rounding. In the case of uigridlayout, the wrong transformation is being applied in some cases, which can lead to the bigger errors that @Matt Butts is seeing. This is also why CurrentPoint works when you click outside the axes, and it is why the CurrentPoint doesn't know where you clicked in 3D space (for a 3D axes) but instead gives you the "front" and "back" coordinates.
IntersectionPoint on the other hand is being computed directly by the renderer based on where you clicked, which is why it doesn't work outside the axes, why it gives you a specific point in 3D, and why it can give different values from CurrentPoint (and why it isn't impacted by containers like uigridlayout).
Matt Butts
on 16 Dec 2021
Bruno Luong
on 17 Dec 2021
Edited: Bruno Luong
on 17 Dec 2021
FWIW, I test to plot both coordinates returned by CurrentPoint and IntersectionPoint on the same axes and in all the cases CurrentPoint can correctly follow the mouse and IntersectionPoint cannnot. That is fine with me as I use CurrentPoint currently. I'm in the opposite situation than you Matt.
Here is the function with plot. In my case the difference is 3 pixels for uifigure and 0.7 pixel for figure. CurrentPoint returns correct values as stated ealier.
function checkcperror(uiflag)
% uiflag: true to check uifigure; false old figure
if nargin < 1
uiflag = true;
end
close all
if uiflag
name = 'uifigure';
fig = uifigure('Name', name);
ax = uiaxes('Parent',fig);
else
name = 'figure';
fig = figure('Name', name);
ax = axes('Parent',fig);
end
fprintf('*** Check for %s ***\n', name)
h = plot(ax,nan(3,2),nan(3,2));
legend(h, 'IntersectionPoint', 'CurrentPoint');
axis(ax,[0 1 0 1]);
set(ax, 'Units','normalize', 'innerposition',[0 0 1 1]);
set(ax,'ButtonDownFcn',@(ax,event) chekerrorcb(ax,event,h));
text(ax,0.5,0.5,sprintf('%s click on the axes', name), ...
'HorizontalAlignment','center');
end
function chekerrorcb(ax, event, h)
drawnow
ip = event.IntersectionPoint(1,1:2);
cp = ax.CurrentPoint(1,1:2);
d = ip-cp;
ax.Units = 'pixel';
pos = get(ax,'innerposition');
dx = pos(3);
dy = pos(4);
dpxl = d.*[dx dy];
fprintf('error = %g pixel\n',norm(dpxl));
set(h(1),'XData',[get(h(1),'XData') ip(1)]);
set(h(1),'YData',[get(h(1),'YData') ip(2)]);
set(h(2),'XData',[get(h(2),'XData') cp(1)]);
set(h(2),'YData',[get(h(2),'YData') cp(2)]);
set(ax, 'Units','normalize', 'innerposition', [0 0 1 1]);
axis(ax,[0 1 0 1]);
drawnow
end
Stephane Lagace
on 12 Jul 2023
Hello I have the same problem only when the uiaxes is in a couple nested gridlayouts
Categories
Find more on Color in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!