1
\$\begingroup\$

I currently have an editor that creates shapes out of (X, Y) coordinates and then triangulate that to make up a shape of those points.

What will I have to do to rotate all of those points simultaneously? Say I click the screen in my editor, it locates the point where I've clicked and if I move the mouse up or down from that point it calculates rotation on X and Y axis depending on new position relevant to first position, say I move up 10 on the Y axis it rotates that way and the same way for X. Or simply, somehow to enter rotation degree: 90, 180, 270, 360, for example.

I use VertexPositionColor at the moment.

What are the best algorithms or methods that I can look at to rotate multiple points in 2D at once?

Also:

Since this is an editor I do now want to rotate it on the Matrix, so if I want to rotate the whole shape 180 degree that's the new "position" of all the points, so that's the new rotation = 0 for example. Later on I probably will use World Matrix rotation for this, but not now.

Example

\$\endgroup\$
17
  • 1
    \$\begingroup\$ What do you mean by "rotation on X axis"? In 2D, you can only rotate anything around a point, not around a line. \$\endgroup\$ Commented Oct 25, 2012 at 10:44
  • \$\begingroup\$ @MartinSojka You have to specify the rotation axis in 2D as well. For example: Matrix worldMatrix = Matrix.CreateRotationY(angle); \$\endgroup\$
    – Marton
    Commented Oct 25, 2012 at 10:50
  • \$\begingroup\$ @Marton: What would a rotation by, say, 30 degrees around the Y axis in 2D exactly mean - where would the points end up? Remember that neither the points nor the axis can be located outside those two dimensions, neither pre nor post rotation. \$\endgroup\$ Commented Oct 25, 2012 at 10:52
  • 1
    \$\begingroup\$ @Marton: There is no Z axis in 2D. And if you change just the X coordinate, that's either scaling or movement, or a combination thereof. \$\endgroup\$ Commented Oct 25, 2012 at 11:01
  • 1
    \$\begingroup\$ I think you're overcomplicating things. For a rotation in 2D, you need a point (the point around which the rotation happens) and some way to specify the angle of rotation - examples would be an angle value, a complex number describing the rotation, or two directional vectors - one for the direction pre rotation, one for the direction post rotation. So far, I don't even see where your origin point is supposed to be located. On the one hand, you write something about clicking on the screen to locate the point; on the other hand, you bring Blender as an example, which doesn't do that. \$\endgroup\$ Commented Oct 25, 2012 at 12:07

2 Answers 2

2
\$\begingroup\$

You need to define a center for rotation... in this case the box center..

then when you detect the mouse down you store vector (A) from the center to the mouse coords... this is your initial vector.... ans should store your shape rotation as initial rotation.

then while you move the mouse and it continues being down you calculate the second vector (B) from the center to the current mouse coords...

now you can calculate the angle between to vectors... as you should know it can be calculated normalizing the two vectors and calcultaing the dot product... so you get the cosine... now you get the angle with an arccosine function...

this angle should be added to the initial rotation of your shape... ans set the new rotation for your shape.

so you only have to build your transform matrix for your shape...

the easiest way is to store your vertex coords relative to the center of the shape, if you don't store that way you should get that points relative to it...

Your transform matrix should similar to this...

// Supposing your coords are absolute 
Matrix transform = Matrix.CreateTranslation( -Center )                       
                 * Matrix.CreateRotationZ(rotation)
                 * Matrix.CreateTranslation (Center );

// Supposing your coords are relative, center is (0,0)
Matrix transform = Matrix.CreateRotationZ(rotation)

You should realize that usually the right way is the easy way... you should use matrix transforms... I'd do something similar to this:

  class Bone2D {
      Vector2 Translation;
      float Rotation;
      float Scale;
      Bone Parent;
      Matrix Local { get { return Matrix.CreateScale(scale) 
                                * Matrix.CreateRotationZ(rotation)
                                * Matrix.CreateTranslation(translation); } }
      Matrix Absolute { get{ return (Parent == null) 
                                       ?  Local 
                                       : Parent.Absolute * Local; }}
  }

  class Shape : Bone2D {

      Vector2[] RelativeCoords;  // Relative to your shape center
      Vector2[] AbsoluteCoords { 
           get{ 
             return RelativeCoords.Select(r => Vector2.Transform(r, Absolute)
                                  .ToArray();
           } }
  }

This way the shape you show in your example, would have two bones...

1) the parent bone that translates the shape,

2) the shape that is a bone itself and can be rotated easily... or scaled or translated again relative to the parent bone of course... ;)

This editor is quite old... I have a new version... but the video shows what you can achieve doing it right... http://www.youtube.com/watch?feature=player_detailpage&v=K9R5v5Va4CI#t=28s

I hope this to be useful... ;)

\$\endgroup\$
1
\$\begingroup\$

Generic and math-heavy answer ahead.

We have the following points:

Origin O = (xO, yO), the origin (or centre) of the object and the origin point for our rotation.

Starting point S = (xS, yS), the point at which the mouse was pressed down and/or the mouse was when the rotation was initiated.

Current (mouse) point M = (xM, yM), the point the mouse is at right now during the rotational operation.

Your rotation can then be expressed as 2x2 matrix calculated from the unit vectors pointing from the origin to the starting point and to the current mouse point respectively.

DS = (xDS, yDS) = (S - O) / ||S - O||

DM = (xDM, yDM) = (M - O) / ||M - O||

enter image description here

Warning

We can calculate the inverse of the second matrix so easily because we know that the matrix is made out of an unit vector - and thus the determinant has the value of exactly 1. This is not a generic formula for calculating such.

The resulting matrix can again be expressed as a unit vector of direction, in case you ever need it:

DR = (xDM xDS + yDM yDS, - xDM yDS + yDM xDS)

The rotation matrix describes a rotation about the origin (0, 0) - not about your origin. For this, the points first have to be moved so that the object origin is the same as world origin, rotated, then moved back to their original position. In other words:

Protated = R x (Poriginal - O) + O

You can express the translations as 3x3 matrices if you first extend your 2D vectors by an anonymous dimension with the constant value of 1 for all of them; the three transformations can then be pre-calculated into one single matrix by simple matrix multiplication.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ An example in C#/XNA would be nice, not sure whether to (S - O) / (S-O) which is 0, or ((S-O) / S) - O or if it's just a variation of the first, still confused. \$\endgroup\$
    – Deukalion
    Commented Oct 26, 2012 at 14:37
  • \$\begingroup\$ @Deukalion ||v|| is the mathematical notation for "length of vector v". In other words, calculate (S-O) (a vector), sum the squares of its elements, then calculate the square root of the sum. \$\endgroup\$ Commented Oct 26, 2012 at 14:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .