I need to transform (part of) a sine curve from the first frame to the second.
Is my matrix correct ?
This is a discussion on 2d Transformations : Is the following correct ? within the Tech Board forums, part of the Community Boards category; I need to transform (part of) a sine curve from the first frame to the second. Is my matrix correct ...
I need to transform (part of) a sine curve from the first frame to the second.
Is my matrix correct ?
Manasij Mukherjee | gcc-4.9.2 @Arch Linux
Slow and Steady wins the race... if and only if :
1.None of the other participants are fast and steady.
2.The fast and unsteady suddenly falls asleep while running !
Why do you have a 3x3 transformation matrix when you only have a 2-d graph? The result of your transformation should be another 1x2 matrix, representing the new x and y, x' and y'. Also, you are performing 3 transformations. You are scaling, sliding and rotating, so I would use 3 separate 2x2 matrices, one for each transformation. You can combine them later, once you get it. As for the 3 matrices, here is how they work:
- Scaling: Your old x-axis length was pi/2. The new length needs pythagoreans theorem: sqrt((c-x1)^2 + (d-y1)^2). The scaling factor is new/old. You do similar for the y scaling factor.
- Rotation: You must figure out how much you rotated by. Make a right triangle with (x1,y1), (c,y1) and (c,d). Use the lengths of the sides to figure out theta, your angle of rotation.
- Translation: You moved to the right x1 units and up y1 units. You will add this number after you scale and rotate.
Your scaling matrix is just a diagonal. You multiply the x coordinate by the x scaling factor, and the y coordinate by the y scaling factor:
Your rotation matrix looks like:Code:[x'] = [Sx 0] [x] [y'] [0 Sy] [y]
And your translation matrix is a 1x2 matrix that you add instead of multiply:Code:[x'] = [cos t -sin t] [x] where t is theta, your angle of rotation [y'] [sin t cos t] [y]
Putting it all together, you get:Code:[x'] = [x1] + [x] [y'] [y1] [y]
At least, I'm pretty sure that's how you'd do it. Try taking some points with known cooridanates both before and after, and plug them to see if they transform correctly. Some "easy" known points are (0,0)-->(x1,y1), (0,1)-->(a,b) and (pi/2,0)-->(c,d).Code:[x'] = [cos t -sin t] [Sx 0] [x] + [x1] [y'] [sin t cos t] [0 Sy] [y] [y1]
Last edited by anduril462; 05-15-2012 at 11:09 AM. Reason: Fixed rotation matrices
Last edited by manasij7479; 05-15-2012 at 10:46 AM.
Manasij Mukherjee | gcc-4.9.2 @Arch Linux
Slow and Steady wins the race... if and only if :
1.None of the other participants are fast and steady.
2.The fast and unsteady suddenly falls asleep while running !
Manasij Mukherjee | gcc-4.9.2 @Arch Linux
Slow and Steady wins the race... if and only if :
1.None of the other participants are fast and steady.
2.The fast and unsteady suddenly falls asleep while running !
Hmm...I'm pretty sure your setup doesn't work. Your vector should be [x y 1], so you multiply 1 by the translation amounts and add it to your final result. You also need to put [x1 y1 1] across the bottom, not down the right side. It would work on the right side only if you made your horizontal vector vertical and moved it to the right side of your transformation matrix for the multiplication. I'll have to do more reading before I can tell you whether the scale and rotate portion is correct.
The fact that the components of the unit vectors (i,j,k) in the new frame as represented from the old frame are the rows of the transformation matrix, in order.
(no k here, though)
EDIT:
It is actually the opposite.
It is the components of the old i and j when transformed into the new frame.
Last edited by manasij7479; 05-15-2012 at 11:26 AM.
Manasij Mukherjee | gcc-4.9.2 @Arch Linux
Slow and Steady wins the race... if and only if :
1.None of the other participants are fast and steady.
2.The fast and unsteady suddenly falls asleep while running !
I'm pretty sure what you did wont work, it seems to fail when mapping the end of your y axis, (0,1). I get (a-x1, b-y1) when I should just get (a,b).
Given the rotation, you really need some sin/cos values in there. I think you can use the scaling factor matrix and rotation matrix (now fixed -- I had a type) from my first reply, and multiply those to get the upper-left 2x2 for your final matrix. Then just put the translation factors across the bottom, something like:
EDIT: You may need to transpose just the 2x2 scale/translate matrix here, since you're using a row vector on the left instead of a column vector on the right. But you get the idea.Code:[Sx cos t -Sy sin t 0] [Sx sin t Sy cos t 0] [x1 y1 0]
Last edited by anduril462; 05-15-2012 at 11:26 AM.
Ooh, I think I get it now. The 2x2 for your first matrix appears to be correct, but your vector and translation is wrong for the reasons I mentioned in post #6. Your vector needs a 1, not a 0, and you need to move the translation values to the bottom row. That makes your 3 axis points map correctly. That should be sufficient, but if you want to double check, pick some easier points, like the midpoints of the axis and the midpoint between (0,1) and (pi/2,0) should map to the midpoint between (a,b) and (c,d).
O_oAnd the (2x2) matrix in the upper left corner is my attempt in combining and simplifying rotation and scaling.
From the example, it seems you also want translation (movement). Is that correct?
I can't follow your example; it also seems like you've updated your matrix since it was posted.
Is this what you have?
Where is 'S' is the scale factor, 'A' is the angle of rotation, and ('H', 'K') is the new origin.Code:[X'] [S*COS(A)][ -SIN(A)][H] [X] [Y']=[ SIN(A)][S*COS(A)][K]*[Y] [ 1] [ 0][ 0][1] [1]
[Edit]
If any of these transformation are actually fixed, you can simplify the partial expressions.
[/Edit]
Soma
Last edited by phantomotap; 05-15-2012 at 12:15 PM.
Yes.. that is where the 3x3 matrix comes from.
NoI can't follow your example; it also seems like you've updated your matrix since it was posted.
I think so, only the Scales on x and y being different.Is this what you have?
That is what led me to construct the simplified version, not calculating the actual angle at all. (and thus avoiding the calls to sin and cos in the inner loop)If any of these transformation are actually fixed, you can simplify the partial expressions.
I 'think', it works, when following the advice on post#6.
Not tested rigourously yet.
Manasij Mukherjee | gcc-4.9.2 @Arch Linux
Slow and Steady wins the race... if and only if :
1.None of the other participants are fast and steady.
2.The fast and unsteady suddenly falls asleep while running !
O_oYes.. that is where the 3x3 matrix comes from.
With homogeneous coordinates scaling, rotation, sheering, translation, and so in two dimensions are all represented by a "3x3" matrix.
I was specifically asking if you were trying to do translations as well because that's what it looks like despite you listing only rotation and scaling.
Right, but you don't have to do it that way. I'm not talking about doing it manually.That is what led me to construct the simplified version, not calculating the actual angle at all.
This can be done in code.
Create your translation matrix.
Create your rotation matrix.
Create your scaling matrix.
Multiple these three matrices together in an order appropriate to your target.
[Edit]
This resulting matrix can be computed before entering the tight loop to get the `x' and `y' values for the sine wave.
[/Edit]
The result is a matrix with only constant values. You can then multiple that matrix by your point vectors to get the new "position".
Soma
Obviously... (0,0) to (x1,y1) is definitely translation too.
I know that ![Edit]
This resulting matrix can be computed before entering the tight loop to get the `x' and `y' values for the sine wave.
[/Edit]
The result is a matrix with only constant values. You can then multiply that matrix by your point vectors to get the new "position".
Soma
....there is still one problem (not mentioned above).
I won't generate the whole sine wave in the same coordinates...and the matrix would have to remade for each version.. as opposed to just plugging in the 'random' numbers as with my version.
Here is a rough sketch of a possible output.
Note that the circled points are generated randomly.. under constrains (and a,b,c,d are derived with some algebra) .
Last edited by manasij7479; 05-15-2012 at 12:53 PM.
Manasij Mukherjee | gcc-4.9.2 @Arch Linux
Slow and Steady wins the race... if and only if :
1.None of the other participants are fast and steady.
2.The fast and unsteady suddenly falls asleep while running !
The "problem" you describe isn't so much of a problem as you apparently think.
If you are only dealing with one transformation each of scaling, rotation, and transformation the combined matrix I posted is sufficient.
It does have to be "baked" (the correct values inserted) but doesn't have to be simplified beyond that to be quite fast. (You only need one extra call to `sin' and `cos'.)
For each frame of reference you "bake" the combined transformation matrix and multiply normally. That's one extra call to `sin' and one extra call to `cos' per frame of reference not per "dot". Each matrix still doesn't have to be created and multiplied every time you sample to get the natural `x' and `y'.
So, to look at your example, you are transforming the sine wave over pairs of third positions. That means you'll be "baking" the transformation matrix once for each consecutive pair. (Which you've helpfully marked with a dotted line.) You'' only need to do this five times for your example. You'll be using each generation as many times as you need to get the fidelity you desire.
If you require a very high quality mapping you'll be sampling `x' and `y' using `sin' far more often than you'll be creating a transformation matrix.
If you are interpolating instead of calling `sin' a lot to get the sine wave you can "bake" the transformation into the interpolation function. Unfortunately, that is beyond my skill; you'll have to wait for VirtualAce or someone else if you want to try that.
Soma