Rotation
-
I would ask this question on the algorithms/maths board, but I feel it is more appropriate here. Lets say I have 2 points, { X1,Y1 } and { X2,Y2 }, I want to calculate the rotation of #2 around #1 given a number of degrees. What is the fasted possible way to do this in C++? Here is my method, which I find to be too slow.
X2 = X1 * cosf(rotate) - Y1 * sinf(rotate); Y2 = X1 * sinf(rotate) + Y1 * cosf(rotate);
-
I would ask this question on the algorithms/maths board, but I feel it is more appropriate here. Lets say I have 2 points, { X1,Y1 } and { X2,Y2 }, I want to calculate the rotation of #2 around #1 given a number of degrees. What is the fasted possible way to do this in C++? Here is my method, which I find to be too slow.
X2 = X1 * cosf(rotate) - Y1 * sinf(rotate); Y2 = X1 * sinf(rotate) + Y1 * cosf(rotate);
You code calculates cosf() and sinf() twice - you could probably speed things up by almost 2 x by only calculating cosf(rotate) and sinf(rotate) once and assigning the values to local variables. Hope this helps Tony
-
You code calculates cosf() and sinf() twice - you could probably speed things up by almost 2 x by only calculating cosf(rotate) and sinf(rotate) once and assigning the values to local variables. Hope this helps Tony
As calculating cosines and sines is expensive, another optimization could be to just calculate them once and make a table for the values ( may in application startup ) this will considerably increase the speed :). If you are rotating these values multiple times. A question you might ask is but the value for the angle could be infinte and hence the table size. The catch here is every angle's cosine/sine is equal to an angle b/w 0-180 (0-pie).. so pratically you need only a table of 180 entries :). I hope this help! enjoy
-
As calculating cosines and sines is expensive, another optimization could be to just calculate them once and make a table for the values ( may in application startup ) this will considerably increase the speed :). If you are rotating these values multiple times. A question you might ask is but the value for the angle could be infinte and hence the table size. The catch here is every angle's cosine/sine is equal to an angle b/w 0-180 (0-pie).. so pratically you need only a table of 180 entries :). I hope this help! enjoy
Thats an excellent idea, thanks for that.
-
As calculating cosines and sines is expensive, another optimization could be to just calculate them once and make a table for the values ( may in application startup ) this will considerably increase the speed :). If you are rotating these values multiple times. A question you might ask is but the value for the angle could be infinte and hence the table size. The catch here is every angle's cosine/sine is equal to an angle b/w 0-180 (0-pie).. so pratically you need only a table of 180 entries :). I hope this help! enjoy
Nutkase is right, this method can dramatically improve performance but is only suitable if you can live with integer angle values (every degree) since these will be used directly as indexes into the look-up tables. If you need finer resolution than 1 degree you could consider having table entries every 0.1 degree but you would need to scale the angles to ensure that you have integral values e.g. 15. degrees would be index 15 in the table. Naturally the tables would be 10 times bigger i.e. 1800 entries (actually you could get a way with storing values for only 90 degrees ;)
-
Thats an excellent idea, thanks for that.
-
Nutkase is right, this method can dramatically improve performance but is only suitable if you can live with integer angle values (every degree) since these will be used directly as indexes into the look-up tables. If you need finer resolution than 1 degree you could consider having table entries every 0.1 degree but you would need to scale the angles to ensure that you have integral values e.g. 15. degrees would be index 15 in the table. Naturally the tables would be 10 times bigger i.e. 1800 entries (actually you could get a way with storing values for only 90 degrees ;)
softwaremonkey wrote:
only suitable if you can live with integer angle values (every degree)
Thats no problem in this instance. The major problem I am having at the moment is when placing the rotation code inside a loop, where the point being rotated is constantly being refreshed. Here is a slightly faster method I have tried to adapt.
FPOINT Rotate( float px, float py, float ox, float oy, int a )
{
//////////////////////////////////////////////////////////////////////////
// Rotate point 'p' about point 'o' given 'a' degrees
//////////////////////////////////////////////////////////////////////////float s = ( PI \* a ) / 180; // radians FPOINT q = { px, py }; if ( px == ox && py == oy ) { return q; } float r; if ( px == ox ) { if ( py > oy ) { r = PI / 2; } else { r = - PI / 2; } } else { if ( py == oy ) { if ( px < ox ) { r = PI; } else { r = 0; } } else { // finally the general case if ( px < ox ) { r = atan( (float)( py - oy ) / ( px - ox ) ) + PI; } else { r = atan( (float)( py - oy ) / ( px - ox ) ); } } } float hyp = sqrt( (float)( (px - ox) \* (px - ox) ) + ( ( py - oy ) \* ( py - oy ) ) ); q.x = ( ox + cos(s+r) \* hyp ); q.y = ( oy + sin(s+r) \* hyp ); return q;
}
It's faster, but doesn't work correctly. I have 4 points denoted by the corners of a rectangle. I calc the center of the mass and pass it is as point 'o', then for each of the 4 points 'p' A calc their new positions. The resulting rectangle appears to rotate about the top-right corner ( which itself is traveling up and down a 45 degree line ). I can't for the life of me see where it is going wrong.
-
softwaremonkey wrote:
only suitable if you can live with integer angle values (every degree)
Thats no problem in this instance. The major problem I am having at the moment is when placing the rotation code inside a loop, where the point being rotated is constantly being refreshed. Here is a slightly faster method I have tried to adapt.
FPOINT Rotate( float px, float py, float ox, float oy, int a )
{
//////////////////////////////////////////////////////////////////////////
// Rotate point 'p' about point 'o' given 'a' degrees
//////////////////////////////////////////////////////////////////////////float s = ( PI \* a ) / 180; // radians FPOINT q = { px, py }; if ( px == ox && py == oy ) { return q; } float r; if ( px == ox ) { if ( py > oy ) { r = PI / 2; } else { r = - PI / 2; } } else { if ( py == oy ) { if ( px < ox ) { r = PI; } else { r = 0; } } else { // finally the general case if ( px < ox ) { r = atan( (float)( py - oy ) / ( px - ox ) ) + PI; } else { r = atan( (float)( py - oy ) / ( px - ox ) ); } } } float hyp = sqrt( (float)( (px - ox) \* (px - ox) ) + ( ( py - oy ) \* ( py - oy ) ) ); q.x = ( ox + cos(s+r) \* hyp ); q.y = ( oy + sin(s+r) \* hyp ); return q;
}
It's faster, but doesn't work correctly. I have 4 points denoted by the corners of a rectangle. I calc the center of the mass and pass it is as point 'o', then for each of the 4 points 'p' A calc their new positions. The resulting rectangle appears to rotate about the top-right corner ( which itself is traveling up and down a 45 degree line ). I can't for the life of me see where it is going wrong.
NM... It was a stupid error in calculating the center of the mass.