This course teaches how to install and configure Windows Server 2012 R2. It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

I am trying to rotate a box on screen in the same way it is done in many applications like powerpoint etc, by clicking and dragging around the object in the direction i want it to rotate.

Using the code below i have managed to make it rotate, by working out the angle between the three points; current mouse position, center of shape to be rotated and the old mouse position. Unfortunatly since i am working out the lengths of the sides with Pythagoras, i only get a positive result, wich leads to my box rotating in one direction only, regardless of the direction i move my mouse

I'm not sure if i'm going about this in completely the wrong way ( i am using a matrix to actually rotate the points, but i don't know if its possible to reverse the operation ), or whether i'm just bing a idiot and forgetting somthing simple i could do, but any help will be appreciated

Thanks in advance

Using the code below i have managed to make it rotate, by working out the angle between the three points; current mouse position, center of shape to be rotated and the old mouse position. Unfortunatly since i am working out the lengths of the sides with Pythagoras, i only get a positive result, wich leads to my box rotating in one direction only, regardless of the direction i move my mouse

I'm not sure if i'm going about this in completely the wrong way ( i am using a matrix to actually rotate the points, but i don't know if its possible to reverse the operation ), or whether i'm just bing a idiot and forgetting somthing simple i could do, but any help will be appreciated

Thanks in advance

```
public void Rotate(PointF p)
{
// Center
float cx = Center.X;
float cy = Center.Y;
// New Position
float nx = p.X;
float ny = p.Y;
// Old Position
float ox = m_pnt_MouseTrack.X;
float oy = m_pnt_MouseTrack.Y;
// Work Out the Lengths of the Sides.
// a == new -> old , b == center -> new , c == center -> old
float a = (float)(Math.Sqrt(Math.Pow((nx - ox), 2) + Math.Pow((ny - oy), 2)));
float b = (float)(Math.Sqrt(Math.Pow((nx - cx), 2) + Math.Pow((ny - cy), 2)));
float c = (float)(Math.Sqrt(Math.Pow((cx - ox), 2) + Math.Pow((cy - oy), 2)));
// Work out the Direction of the rotation
// This is the bit i don't know how to do ...
// Cos-1(( a^2 - b^2 - c^2 ) / -4bc) == A
float A = (a * a) - (b * b) - (c * c);
A /= (-2) * b * c;
A = (float)Math.Acos(A);
// Rotate the shape using a method i have written elsewhere
Rotate(A - (float)Math.PI);
}
```

If you only want to rotate around (say) the y-axis, then just use (x_new - x_old) to calculate the angle of rotation.

If you wish to rotate around an arbitrary axis, I'd recommend using quaternions rather than matrices.

In the case of matrices, you need to calculate the Euler angles around each axis (and perform them in the right order so as to avoid Gimbal lock etc) - it's quite tedious.

Quaternions are much easier to implement (although a little more abstract). This method of rotating with quaternions is sometimes called 'Arc ball'.

The idea is that you define the axis u to be the line from the centre of rotation, to the 'old' mouse position. Then use the difference in the old and new mouse positions to compute the angle of rotation (one method is to find u x (p_new-p_old)).

See here:

http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

http://cgmath.blogspot.com/2009/03/arc-ball-rotation-using-quaternion.html

and equation (30) onwards, here:

http://mathworld.wolfram.com/Quaternion.html

Ask if you have further questions.

To start with i'm only dealing in 2d here, so i'm not sure if that makes a difference, and i'm rotating around a fixed point, but thats all working fine

Its not that i'm having any trouble rotateing the box, that works fine, i'm having trouble working out wich way to rotate it

your final paragraph looks like it might be what i'm looking for, but i'll just have to read about quaternions before i can be sure

```
// Rotate the shape using a method i have written elsewhere
Rotate(A);
```

I think what i really need is a way of finding the angle formed between the three points, but using a method that either gives me results within the range -180>ang>180 or 0>ang>360

```
public void Rotate(PointF p)
{
// Center
float cx = Center.X;
float cy = Center.Y;
// New Position
float nx = p.X;
float ny = p.Y;
// Old Position
float ox = m_pnt_MouseTrack.X;
float oy = m_pnt_MouseTrack.Y;
float dx_o = ox - cx;
float dy_o = oy - cy;
float dx_n = nx - cx;
float dy_n = ny - cy;
float cross = (dx_o * dy_n) - (dx_n * dy_o);
float dot = dx_o * dx_n + dy_o * dy_n;
// when vecs a and b are at angle theta,
// a cross b = |a| * |b| * sin(theta)
// a dot b = |a| * |b| * cos(theta)
float angle;
if (cross == 0 && dot == 0) {
// either old == center or new == center, so rotation
// is undefined
angle = 0;
} else {
angle = atan2(cross, dot);
}
// now use "angle" to rotate your shape
}
```

A messy way is to transform box to coordinate system with center of box at (0,0) and mouse down at (ox,0) x>0. Now identify quadrant in which mouse up takes place. Cos(t) = absolute value (ny/nx). Rotate through angle tr.

IF quad 1 tr = t

quad 2 tr = t + 90

quad 3 tr = 180 t

quad 4 tr = -t

Transform box to original cord system.

Draw

I thought i'd managed to solve it with a really messy hack, involving using i statements to work out what qudrent the mouse was in reletive to the center, and then work out the direction of the mouse relitive to that quadrent, however after a bit more testing this morning, i broke it again ( and it's so messy and awful i'm ashamed of it ).

Your solution looks a lot better, so i'll try implement that and un close this question ( its the first time i've actually asked anything on here so if i do somthing wrong i apologize! ) so that i can award points properly.

Just one question, which points are A and B? I've assumed that they are the old and new mouse positions.

Or if you don't quite follow the cross and dot product stuff, you could just use atan2 twice, once on the old vector and once on the new vector, then subtract to get the angle. At this point the difference will be in the range (-2pi, +2pi) so you might want to normalize the angle.

Or you could use the old and new vectors to come up with the transform without ever going through any trig.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.

What was your solution?

Now that I know you're working in 2D, I see what you're doing with your code.

In your case, Pythagoras' is only an approximation for the lengths, as there's no guarantee the user is going to form a right-angled triangle. Furthermore (as was the problem) the cosine law does not give an idea for the direction of the angle.

I'd suggest using the cross product. Try,

A = arcsin[(a_x*b_y - b_x*a_y) / sqrt{(a_x*a_x+a_y*a_y)*(b_

where

a = mouse_old - centre

b = mouse_new - centre