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
Related
Background: I am creating an AR treasure hunt app. It is simple, it has a locator that tells you where the treasure is relative to you. I have the camera being the origin and the treasure being an object in AR world.
Question: I would like to rotate my arrow according to where in space the treasure is at. but in 2d. Basically, I would ignore the relative forward plane that is camera.forward.
Example: If the camera rotation is default, the angle can be calculated as atan2(dy,dx). If the camera is looking straight down, the angle is atan2(dz,dx).
What I have tried:
Quaternion lookRot = Quaternion.LookRotation(target.transform.position - origin.transform.position);
Quaternion relativeRot = Quaternion.Inverse(origin.transform.rotation) * lookRot;
Relative rotation is correct in 3d space but I would like to convert that into 2d ignoring the camera.forward plane. So even if the treasure is in front or behind the camera, it should not change the angle.
Okay so I’m hoping this makes sense. You’re going to need some sort of if statement to determine if your character is looking along the x, y or z plane. Hopefully the diagram is clear as to what those parameters are but if not. To be looking in the “x” plane for example, the y rotation would have to be between 45° and -45° or 135° and -135° AND the z rotation would have to be between 45° and -45° or between 135° and -135°.
Essentially what you’ve got is a sphere split into six parts, two parts for each plane along which the character could look. Once you’ve determined which plane the character is looking in you can determine the direction by finding the difference in position between the character and the treasure along the two planes the character isn’t looking along. Then use trig to calculate the angle
Replying to an old thread, but I was struggling with the same problem and found a relatively simple solution:
Project the position of the target (relative to the origin) on a plane defined by the forward vector of the camera. Then just rotate towards the projected point:
Vector3 diff = target.transform.position - origin.transform.position;
Vector3 projected = Vector3.ProjectOnPlane(diff, Camera.main.transform.forward);
origin.transform.rotation = Quaternion.LookRotation(projected);
Calculate the difference in x and y coordinates simply by subtracting transform.x for one object by transform.x of another object and the same process for y coordinates and then use Mathf.atan(difference in y/difference in x) to calculate the angle. Then put the z rotation to this angle and assign the x and y rotation to what they already were.
Turns out there is a very simple way to get relative X and Y of the target.
Vector2 ExtractRelativeXY(Transform origin, Transform target) {
// Get the absolute look rotation from origin to target.
Quaternion lookRot = Quaternion.LookRotation(target.transform.position - origin.transform.position);
// Create a relative look rotation with respect to origin's forward.
Quaternion relativeRot = Quaternion.Inverse(origin.transform.rotation) * lookRot;
// Obtain Matrix 4x4 from the rotation.
Matrix4x4 m = Matrix4x4.Rotate(relativeRot);
// Get the 3rd column (which is the forward vector of the rotation).
Vector4 mForward = m.GetColumn(2);
// Simply extract the x and y.
return new Vector2(mForward.x, mForward.y);
}
Once obtained x and y, turn it into angle using angle = atan2(y,x) as suggested by both MBo and Tom.
This works because of the matrix components of the quaternion can be demonstrated in multiple vectors. Better illustration is found here https://stackoverflow.com/a/26724912.
I have images of faces in different positions. I want to rotate them, to make the line connecting the eyes always be horizontal. But I don't know how to do this in MATLAB.
And how can I calculate the angle of rotation?
Descriptive drawing of problem:
If you already have the locations of the eyes, then it's easy :) Here's an outline:
%// left eye - right eye
pos = [ 30 90 %// X
80 40]; %// Y
%// The angle equals the arctangent of dy/dx
angle = atan2(diff(pos(2,:)), diff(pos(1,:)));
%// Rotate in the opposite direction
img = imrotate(img, -angle);
Since you seem to have the Image Processing Toolbox, you can also look into the built-in landmark-based registration functions (especially if your transform is not limited to pure rotation), in particular cpselect with a syntax like:
cpselect(moving,fixed)
And then use fitgeotrans to construct the geometrical transform and imwarp to warp the moving image.
I drew Globe object using OpenGL and i can rotate it with finger touch , but it doesn't work well in some cases because i am rotating using the difference between x and y
Rotation3D rot = sphere.currentRotation;
rot.x += diffX ;
rot.y += diffY ;
rot.z += 10 ;
sphere.currentRotation = rot;
when you move your finger from Top Right to bottom Left it isn't work good.
Any ideas ?
Thanks
Peter Gabra
To arbitrarily rotate objects, it's easiest to store their current orientation as a transformation matrix and manipulate the elements. I explain this in detail here.
The only difference is that in that other question, the OP wanted to apply rotations from two controls (horizontal and vertical), whereas you are after drag-based rotation. The technique is basically the same, but instead of rotating around either the X or Y axis, you need to compute an arbitrary axis of rotation from the touch's delta vector as follows:
axis = [0, 0, 1] ⨯ [diffX, diffY, 0]
(⨯ = "cross product")
Then you rotate the U, V and W vectors (as described in my other answer) around the axis by some angle in proportion to the length of the delta vector:
M = rotation(k * length([diffX, diffY, 0]), axis)
U = M * U
V = M * V
W = M * W
If you find the object rotating in the opposite direction to what you expect, there are three possibilities:
If it's only the vertical rotation that goes the wrong way, you need to negate diffY. This is a common mistake I make due to inconsistencies between OpenGL and UIKit coordinate systems.
If it's all rotation, you can either swap the arguments in the cross-product or use [0, 0, -1]. This is usually because of confusion between left- and right-handed coordinate systems.
If it's just the horizontal rotation, make both adjustments. (Don't negate diffX, no one uses left-to-right X-coordinates.)
In case you're using Euler angles: I recommend not using Euler angles to model rotations. Use Quaternions instead. It might seem like it makes your code more complicated, but rotations work well when you use Quaternions. Here's some advantages:
it's very straightforward to apply user interaction to current rotation state
no gimbal lock problems
no need for matrix drift adjustments after repeated rotations
you can interpolate rotations easily
Note that Apple give you a Quaternion type to use: GLKQuaternion. No need to write your own Quaternion class.
See also:
http://www.ogre3d.org/tikiwiki/Quaternion+and+Rotation+Primer
Euler angles vs. Quaternions - problems caused by the tension between internal storage and presentation to the user?
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.
I am trying to solve a tricky math problem, in a cocos2d for iphone context.
Basically I have a roullette wheel which is rotating over time.
I want to have a Sprite latch onto the wheel at certain points (like compass ordinal points N, S, E, W) and bounce off at all other points.
I have the image of the wheel rotating, and just need to solve the part where I can test for whether a sprite has intersected with the circle at the right point on the circle as it is rotating.
I think this question is going in the right direction, but I can't get my head around it. Can anyone help explain?
Best way to find a point on a circle closest to a given point
If I understand correctly:
First check the distance between the sprite and the centre of the roulette wheel. This will tell you if the sprite is at the edge of the wheel. (If not, nothing happens, right?)
Then, find the angle that the sprite makes from the "x-axis" of the roulette wheel.
spriteAngle = atan2(sprite.x - rouletteCentre.x, sprite.y - rouletteCentre.y)
You'll need to find the equivalent of the atan2() function. It usually returns an answer in radians; you may want to convert it to degrees or quarter-turns or something if you prefer.
Then, subtract the angle that the roulette wheel itself is rotated by (if the wheel itself is rotating, if not then you're already done). Make sure your angle measurement is consistent.
actualAngle = spriteAngle - rouletteRotationAngle
Note that actualAngle may be outside the range 0-360 degrees, and you will need to make it "wrap around".
Lastly, you will want to allow a small range of values as acceptable (e.g. 98 degrees to 102 might count as "North").
So you have a circle of radius r, with center (x0,y0).
A point lies outside of the circle, at coordinates (x,y). Your question is to find the closest point on the circle itself to the point (x,y).
The solution is simple. The closest projection of a point onto a circle is accomplished by a simple scaling. Thus,
d = sqrt((x-x0)^2 + (y-y0)^2)
xp = x0 + (x - x0)*r/d
yp = y0 + (y - y0)*r/d
The new point (xp,yp) will lie on the circle itself. To be honest, you would be better off to work in polar coordinates, with the origin at the center of the circle. Then everything gets much easier.
Your next question will be where did it hit on the circle? Don't forget the points of the compass on the circle are rotating with time. An atan2 function will give you the angle that the point (xp-x0,yp-y0) lies at. Most toolsets will have that functionality. See that I've subtracted off the origin here.