Rotate plot while dragging with the scroll button?

  • Follow


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)


Reply: