I'm an iphone developer, but this question is about geometry.
I have a simple rectangle (maybe a photo). The user touches this photo at a point and drags their finger to a new point:
http://dl.dropbox.com/u/792862/Untitleddrawing.png
How many radians I must rotate this rectangle to simulate a rotation given by the touches?
I'm assuming that you have a fixed origin for your rotation (the crosshair in your picture would suggest so) and the touch sets the other point.
First you need a method to figure out the angle of a line. The atan2 function (available in any well-equipped math library) figures out the angle between any line and the X axis. First figure out the starting angle:
startAngle = atan2(startY - originY, startX - originX)
And then the ending angle:
endAngle = atan2(endY - originY, endX - originX)
And then just subtract the two angles from each other to figure out your rotation:
angleToRotate = endAngle - startAngle
You might need to swap things around depending on which way your rotations work.
Use atan2 to convert the starting point and the ending point to angles, after translating each to correct for a non-(0,0) origin if necessary.
Related
I've already asked this question in a different way here; Swift-Setting a physics body velocity by angle but the three attempts to answer it were unfortunately not exactly what I'm looking for, although I'm grateful for what they taught me anyway. I decided that I should simply rephrase my question with an example and further explanation instead of perpetuating a discussion via comments. So here it is.
Imagine I have an SKNode positioned in the centre of the screen. Let's say this is a ball, so any rotation action on it is not visible. I would need a way to have a random angle selected, and have said SKNode rotate to it, and then continuously move in the direction determined by the aforementioned angle from its original position in the centre of the screen, until, say, the edge of the screen.
I know how to determine the random angle, have the SKNode rotate to it, and have it stop at the edge of the screen. Hopefully with this example what I need is clearer, a way to simply have an SKNode move forward, but on an angle determined by a single variable, and not a velocity determined by two, dx and dy.
Thanks in advance.
To do this, you just need to use some trigonometry!
When zRotation is between 0 and 90, you don't need to do anything to the angle except converting it to radians. Just call tan(radianAngle). Now tan will return how much should the node move in the y axis when it moves by 1 in the x axis. If you learned trigonometry before, you should understand what I'm saying. If you have not learned trigonometry, learn it. :)
Let's say the node's zRotation is 60 degrees, which is π/3 radians. Pass that into tan and you get √3. This means your dx and dy parameters in SKAction must be in the ratio of 1 : √3 in order to make the node move in the direction of 60 degrees.
When zRotation is between 90 and 180, you need to first subtract the angle from 180, then convert it to radians. Again, pass that to tan and the return value is how much your node should move in the y direction when it moves by -1 in the x axis. The dx : dy ratio is now -1 : tan(angleInRadians).
When zRotation is between 180 and 270, subtract 180 from that angle and convert it to radians. The dx : dy ratio is -1 : -tan(angleInRadians).
Lastly, a zRotation bewteen 270 and 360, subtract the angle from 360 and convert it to radians. The dx : dy ratio is 1 : -tan(angleInRadians).
Just before you convert the angle to radians, check if the angle is 90 degrees. If it is, please hard code the dx and dy because tan(M_PI / 2) is undefined.
in my game im having one Ccsprite for arrow, and one b2body for ball... im trying to throw ball at direction which is pointed by my arrow sprite. here is my code... i'm counting rotation of arrow sprite and then applying impulse to ball at that angle...
float totalRotation = arrow.rotation ;
ballBody->ApplyLinearImpulse(b2Vec2(10.0f+cos(totalRotation)*25.0f,10.0f+sin(totalRotation)*25.0f), eggBody->GetWorldCenter());
BUt, this not working exactly...ball is getting thrown in improper direction.
The rotation property of a CCNode (and CCSprite, which inherits from CCNode) is measured in degrees, with clockwise rotation being positive. The Box2D world uses angles measured in radians, with counter-clockwise rotation being positive, which is more conventional for a cartesian coordinate system. In order to provide the correct angle to a Box2D function, you will have to convert. In Cocos2D, the conversion goes like this:
float angle = - 1 * CC_DEGREES_TO_RADIANS(totalRotation);
The macro converts the totalRotation from degrees to radians, and you multiply by -1 because Box2D measures positive angles in the counter-clockwise direction, which is opposite of the CCNode rotation.
What is the method to use to rotate an image about a point that is not the image's center point using MATLAB?
Two rotations of the same angle are equal up to a translation. So you can just do rotation around the center, and then translate the image to put your own center of rotation at its old position.
The help to 'rotate' says:
ROTATE Rotate objects about specified origin and direction.
ROTATE(H,[THETA PHI],ALPHA) rotates the objects with handles H
through angle ALPHA about an axis described by the 2-element
direction vector [THETA PHI] (spherical coordinates).
All the angles are in degrees. The handles in H must be children
of the same axes.
...
ROTATE(...,ORIGIN) uses the point ORIGIN = [x0,y0,y0] as the center
of rotation instead of the center of the plot box.
To rotate about a point other than the origin you:
Translate the point you want to rotate around to the origin. For example, if you want to rotate around (3,5), you would translate by (-3,-5).
Perform your rotation.
Undo the initial translation. So in my example you would now translate by (+3,+5).
Basically I have two 2D points and there is a line between them. A cube is placed on the midpoint of this line. I want the cube to rotate so it is facing upwards from the line as the diagram below indicates.
I've been thinking through how I can do this using trig and I still haven't come up with anything. Any ideas would be much appreciated :)
In pseudo-code:
angle = atan2(p2.y - p1.y, p2.x - p1.x)
cube.rotation = angle + PI/2
Given two points (x1, y1) and (x2, y2), the angle of the line is given by
atan2(y2-y1, x2-x1)
Then rotate the square accordingly. To do that you can use a Affine transform -- see
CGAffineTransformMakeRotation
CGPointApplyAffineTransform
Here:
http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CGAffineTransform/Reference/reference.html
I have a map of individual trees from a forest stored as x,y points in a matrix. I call it fixedPositions. It's cartesian and (0,0) is the origin.
Given a velocity and a heading, i.e. .5 m/s and 60 degrees (2 o'clock equivalent on a watch), how do I rotate the x,y points, so that the new origin is centered at (.5cos(60),.5sin(60)) and 60 degrees is now at the top of the screen?
Then if I were to give you another heading and speed, i.e. 0 degrees and 2m/s, it should calculate it from the last point, not the original fixedPositions origin.
I've wasted my day trying to figure this out. I wish I took matrix algebra but I'm at a loss.
I tried doing cos(30) and even those wouldn't compute correctly, which after an hour I realize were in radians.
I'd try the following: In your object, you already have a property heading. Now you add another property, currentPosition (an maybe rename them to heading_robot and currentPos_robot). heading as well as currentPosition should always be relative to the original coordinate system
Then you add a new method, updatePosition that takes (newHeading, distance) as input. This method will update both heading and currentPosition, by first adding the angle in newHeading to the angle in heading, after which you update currentPosition by adding [distance*cos(heading),distance*sin(heading)] (check for signs of sin/cos here!) to the old value of currentPosition.
Finally, to get the view of the landscape (i.e. apparentPositions), you run bsxfun(#minus,fixedPositions,currentPosition) to move the origin to where the robot is at this moment, and then you multiply with the 2D rotation matrix using the angle stored in heading.
You just first translate the coordinates (-0.5cos(60),-0.5sin(60)) to take the origin to your target point.
Then rotate by multiplying the coordinates by a rotation matrix.
Of course, most programming languages use radians as angle units, so that instead of 60 you must enter 60 * PI / 180