Hi, I really hope it is possible to rotate a MATLAB plot while dragging with the scroll button. With this I mean the foillowing:
1.) Enable rotation mode on the mouse-down event (of the middie/scroll button)
2.) When moving around the mouse, with the scroll button still down/pressed, rotation should occur
3.) Disable rotation mode again on the mouse-up event
In short, I'm just trying the mimic the rotation behaviour of a general design/model application (CAD or Animation related).
The thing is that 1.) and 3.) are rather easy. But after 1.), moving the mouse around doesn't do anything (i.e. no rotation occurs). I assume that normally, another mouse-down event needs to occur after activating the rotation mode (the ordinary way would be by clicking the "rotate" button in the plot toolbar), before you can actually rotate.
Therefore I guess the question becomes, how to "fake" a mouse-down event, such that step 2.) follows directly after step 1.).... ?
The code for 1.) and 3.) is as follows:
% -----------------------------------------------------
function ScrollButtonRotation
clear all;
close all;
clc;
figure('WindowButtonDownFcn', @MouseDown);
axis
function MouseDown(~,~)
if strcmp(get(gcf,'SelectionType'), 'extend')
disp('Enable Rotation Mode.')
rotate3d
hManager = uigetmodemanager(gcf);
set(hManager.WindowListenerHandles,'Enable','off')
set(gcf,'WindowButtonUpFcn',@MouseUp )
end
function MouseUp(~,~)
if strcmp(get(gcf,'SelectionType'), 'extend')
disp('Disable Rotation Mode.')
rotate3d
end
% -----------------------------------------------------
Save this as "ScrollButtonRotation.m" to test. In a previous topic I discussed a similar topic, how to enable/disable rotation mode with the keyboard: http://www.mathworks.com/matlabcentral/newsreader/view_thread/322438
|
|
0
|
|
|
|
Reply
|
pieter84 (10)
|
8/18/2012 9:52:09 PM |
|
I don't think you have any choice but hack the source code rotate3d.m
Bruno
|
|
0
|
|
|
|
Reply
|
b.luong5955 (6341)
|
8/19/2012 8:06:05 AM
|
|
"Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <k0q6pd$brj$1@newscl01ah.mathworks.com>...
> I don't think you have any choice but hack the source code rotate3d.m
>
> Bruno
Yep I guess you're right. Hmm, setting the "WindowButtonMotionFcn" of the figure to the subfunction "localRotateOrbitMotionFcn" of rotate3d.m might do the trick (line 885 of rotate3d.m in my case).
However, to be able to access a subfunction from a function I'd need to do something like this: http://www.mathworks.nl/support/solutions/en/data/1-Y84NJ/index.html?product=SL&solution=1-Y84NJ
And furthermore, get the arguments for this function (i.e. rotaObj and evd) right. Any help is welcome, I'll let you know if I managed to come up with something.
|
|
0
|
|
|
|
Reply
|
pieter84 (10)
|
8/19/2012 9:49:07 AM
|
|
"Pieter" wrote in message <k0qcqj$qi$1@newscl01ah.mathworks.com>...
> "Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <k0q6pd$brj$1@newscl01ah.mathworks.com>...
> > I don't think you have any choice but hack the source code rotate3d.m
> >
> > Bruno
>
> Yep I guess you're right. Hmm, setting the "WindowButtonMotionFcn" of the figure to the subfunction "localRotateOrbitMotionFcn" of rotate3d.m might do the trick (line 885 of rotate3d.m in my case).
>
> However, to be able to access a subfunction from a function I'd need to do something like this: http://www.mathworks.nl/support/solutions/en/data/1-Y84NJ/index.html?product=SL&solution=1-Y84NJ
>
> And furthermore, get the arguments for this function (i.e. rotaObj and evd) right. Any help is welcome, I'll let you know if I managed to come up with something.
This is not that hard. You can rotate by just setting the view and it'll be MUCH faster than rotate3d. Here's an example:
function buttondownfcn(src,ev)
%src is the axes to be rotated
handles=guidata(src);
[az,el]=view(src);
cp=get(0,'PointerLocation');
set(handles.fig,'windowbuttonmotionfcn',{@rotate_motion,src,cp,az,el});
set(handles.fig,'windowbuttonupfcn',{@rotate_done});
function rotate_motion(src,ev,ax,cp,az,el)
newpt=get(0,'PointerLocation');
dy=newpt(2)-cp(2);
dx=newpt(1)-cp(1);
%factors of 3 control the conversion from mouse pixels to degrees. adjust for desired rotation speed.
newel=el-dy/3;
newaz=az-dx/3;
if newel<0;newel=0;end
if newel>90;newel=90;end
view(ax,newaz,newel)
function rotate_done(src,ev)
handles=guidata(src);
set(handles.fig,'windowbuttonmotionfcn',@ravedefaultwindowbuttonmotionfcn);
set(handles.fig,'windowbuttonupfcn',[]);
|
|
0
|
|
|
|
Reply
|
n.a (510)
|
8/19/2012 9:04:07 PM
|
|
"matt dash" wrote in message <k0rkc7$63o$1@newscl01ah.mathworks.com>...
> This is not that hard. You can rotate by just setting the view and it'll be MUCH faster than rotate3d. Here's an example:
>
> function buttondownfcn(src,ev)
> %src is the axes to be rotated
>
> handles=guidata(src);
> [az,el]=view(src);
> cp=get(0,'PointerLocation');
> set(handles.fig,'windowbuttonmotionfcn',{@rotate_motion,src,cp,az,el});
> set(handles.fig,'windowbuttonupfcn',{@rotate_done});
>
> function rotate_motion(src,ev,ax,cp,az,el)
> newpt=get(0,'PointerLocation');
>
> dy=newpt(2)-cp(2);
> dx=newpt(1)-cp(1);
>
> %factors of 3 control the conversion from mouse pixels to degrees. adjust for desired rotation speed.
> newel=el-dy/3;
> newaz=az-dx/3;
>
> if newel<0;newel=0;end
> if newel>90;newel=90;end
>
> view(ax,newaz,newel)
>
> function rotate_done(src,ev)
> handles=guidata(src);
> set(handles.fig,'windowbuttonmotionfcn',@ravedefaultwindowbuttonmotionfcn);
> set(handles.fig,'windowbuttonupfcn',[]);
% --------------------------------------------------------------------------------
Hi Matt, thanks for you input! But I'm not entirely sure how to use this code? I thought that assigning this new function as the callback function would work, i.e.
figure('WindowButtonDownFcn', @buttondownfcn)
Because the Source (src) and EventData (ev) are default arguments. But it doesn't (I get some errors about the view):
Single scalar argument must be 2 or 3
For this line: [az,el]=view(src);
It would be really helpful if you could provide some more details (or copy some ready-to-use code). Thanks!
|
|
0
|
|
|
|
Reply
|
pieter84 (10)
|
8/19/2012 10:08:06 PM
|
|
On 8/19/2012 5:08 PM, Pieter wrote:
> "matt dash" wrote in message <k0rkc7$63o$1@newscl01ah.mathworks.com>...
>
>> This is not that hard. You can rotate by just setting the view and
>> it'll be MUCH faster than rotate3d. Here's an example:
>>
>> function buttondownfcn(src,ev)
>> %src is the axes to be rotated
>>
>> handles=guidata(src);
>> [az,el]=view(src);
>> cp=get(0,'PointerLocation');
>> set(handles.fig,'windowbuttonmotionfcn',{@rotate_motion,src,cp,az,el});
>> set(handles.fig,'windowbuttonupfcn',{@rotate_done});
>>
>> function rotate_motion(src,ev,ax,cp,az,el)
....
> Hi Matt, thanks for you input! But I'm not entirely sure how to use this
> code? I thought that assigning this new function as the callback
> function would work, i.e.
>
> figure('WindowButtonDownFcn', @buttondownfcn)
>
> Because the Source (src) and EventData (ev) are default arguments. But
> it doesn't (I get some errors about the view):
>
> Single scalar argument must be 2 or 3
> For this line: [az,el]=view(src);
....
I'm not sure, but it looks like overlooked an argument in the function
handle definition
set(handles.fig,'windowbuttonmotionfcn',{@rotate_motion,src,cp,az,el});
whereas the function definition is
function rotate_motion(src,ev,ax,cp,az,el)
I see where ev (I presume 'elent'?) is an argument in the
function buttondownfcn(src,ev)
so I'd try the following to make the function handle list match the
arguments in the function --
OOOhhh..., though I see there's also an 'ax' as well -- I presume that
must be an axis handle but not sure where it came from, either.
I was going to say use the following but I think it's lacking, too...
set(handles.fig,'windowbuttonmotionfcn', ...
{@rotate_motion,src, ev, cp,az,el});
I've never done any gui stuff and my version predates fully-implemented
function handles so I can't test this out but that mismatch in argument
lists is a problem I'm pretty sure.
The full/correct fix(es) I'm unsure of but maybe that'll be something
you can figure out...
--
|
|
0
|
|
|
|
Reply
|
none1568 (6639)
|
8/19/2012 10:48:43 PM
|
|
dpb <none@non.net> wrote in message <k0rqgf$jq7$1@speranza.aioe.org>...
> On 8/19/2012 5:08 PM, Pieter wrote:
> > "matt dash" wrote in message <k0rkc7$63o$1@newscl01ah.mathworks.com>...
> >
> >> This is not that hard. You can rotate by just setting the view and
> >> it'll be MUCH faster than rotate3d. Here's an example:
> >>
> >> function buttondownfcn(src,ev)
> >> %src is the axes to be rotated
> >>
> >> handles=guidata(src);
> >> [az,el]=view(src);
> >> cp=get(0,'PointerLocation');
> >> set(handles.fig,'windowbuttonmotionfcn',{@rotate_motion,src,cp,az,el});
> >> set(handles.fig,'windowbuttonupfcn',{@rotate_done});
> >>
> >> function rotate_motion(src,ev,ax,cp,az,el)
> ...
>
> > Hi Matt, thanks for you input! But I'm not entirely sure how to use this
> > code? I thought that assigning this new function as the callback
> > function would work, i.e.
> >
> > figure('WindowButtonDownFcn', @buttondownfcn)
> >
> > Because the Source (src) and EventData (ev) are default arguments. But
> > it doesn't (I get some errors about the view):
> >
> > Single scalar argument must be 2 or 3
> > For this line: [az,el]=view(src);
> ...
>
> I'm not sure, but it looks like overlooked an argument in the function
> handle definition
>
> set(handles.fig,'windowbuttonmotionfcn',{@rotate_motion,src,cp,az,el});
>
> whereas the function definition is
>
> function rotate_motion(src,ev,ax,cp,az,el)
>
> I see where ev (I presume 'elent'?) is an argument in the
>
> function buttondownfcn(src,ev)
>
> so I'd try the following to make the function handle list match the
> arguments in the function --
>
> OOOhhh..., though I see there's also an 'ax' as well -- I presume that
> must be an axis handle but not sure where it came from, either.
>
> I was going to say use the following but I think it's lacking, too...
>
> set(handles.fig,'windowbuttonmotionfcn', ...
> {@rotate_motion,src, ev, cp,az,el});
>
> I've never done any gui stuff and my version predates fully-implemented
> function handles so I can't test this out but that mismatch in argument
> lists is a problem I'm pretty sure.
>
> The full/correct fix(es) I'm unsure of but maybe that'll be something
> you can figure out...
>
> --
Here's a fully working version. You set the buttondownfcn of the axes, not the figure. I'm not sure about how to get it to work with a middle click only but I think you already figured that part out...
function rotatedemo
figure
axes('buttondownfcn',@buttondownfcn)
line(rand(10),rand(10),rand(10),'hittest','off')
view(3)
function buttondownfcn(src,ev)
%src is the axes to be rotated
fig=ancestor(src,'figure');
handles=guidata(src);
[az,el]=view(src);
cp=get(0,'PointerLocation');
set(fig,'windowbuttonmotionfcn',{@rotate_motion,src,cp,az,el});
set(fig,'windowbuttonupfcn',{@rotate_done});
function rotate_motion(src,ev,ax,cp,az,el)
newpt=get(0,'PointerLocation');
dy=newpt(2)-cp(2);
dx=newpt(1)-cp(1);
%factors of 3 control the conversion from mouse pixels to degrees. adjust for desired rotation speed.
newel=el-dy/3;
newaz=az-dx/3;
if newel<0;newel=0;end
if newel>90;newel=90;end
view(ax,newaz,newel)
function rotate_done(src,ev)
fig=ancestor(src,'figure');
set(fig,'windowbuttonmotionfcn',[]);
set(fig,'windowbuttonupfcn',[]);
|
|
0
|
|
|
|
Reply
|
n.a (510)
|
8/19/2012 11:35:06 PM
|
|
Works great, thanks for your time and effort to post this solution!
|
|
0
|
|
|
|
Reply
|
pieter84 (10)
|
8/20/2012 4:14:09 PM
|
|
|
7 Replies
28 Views
(page loaded in 0.184 seconds)
|