Let's say that you have a stick figure. Let's say the stick figure has an elbow and a hand. What if the stick figure wants to spin his hand in a windmill without moving his elbow? If the elbow serves as the center of a circle, and the hand must always be on the circle's circumference, and I know the exact location of the elbow and hand, how do I move the hand around the circle's circumference, while preserving the radius (the length of the arm between the elbow and hand because it really shouldn't shrink or grow)?
I need to move the coordinate of the hand along the circumference of a circle, where the center of the circle is the elbow. This is in 2D.
I have the coordinates of both points. I can calculate the radius which is the length of the line between the points. Knowing the circle's center and radius, how do I rotate the hand along the circle circumference? I want it to maintain the radius, but change positions on the circumference. Basically, it must act like it's hinged.
P.S: I had a picture, but Stack Overflow said I was too new... Blame Stack Overflow.
Basic trigonometry says:
x = r * cos(a);
y = r * sin(a);
This does not take into account the rotation of the hand, just shows the point on the circle where the wrist will be. Is that what you are after?
EDIT: Sorry, that assumes the elbow is at (0, 0) and x +ve is right and y +ve is up.
Given the elbow is at (ex, ey) then wrist is at:
wx = ex + r * cos(a);
wy = ey + r * sin(a);
If, as happens in browsers, y is +ve down, then subtract instead of add.
Related
I've got a 3d sphere which I've been able to plot a point on using longitude and latitude thanks to some work of another developer I've found online. I think I understand what its doing.
What I need to do now is rotate my planet so the point is always at the top most point (ie the north pole) but I'm not sure how to do this. I'm probably missing some important fundamentals here so I'm hoping the answer can assist in my future learning.
Here's an image showing what I have - The blue line is a line coming from the longitude and latitude I have plotted and I need to rotate the planet so that line is basically pointing directly upwards.
https://ibb.co/2y24FxS
If anyone is able to advise it'd be very much appreciated.
If I'm not mistaken, Unity uses a coordinate system where the y-axis points up.
If the point on your sphere was in the xy-plane, you'd just have to determine the angle between the radius-vector (starts in the center of the sphere, ends on the point in question) and the y-axis, and than rotate by that amount around the z-axis, so that the radius vector becomes vertical. But your point is at an arbitrary location in 3D space - see the image below. So one way to go about it is to first bring the point to the xy-plane, then continue from there.
Calculate the radius vector, which is just r = x-sphereCenter. Make a copy of it, set y to zero, so that you have (x, 0, z) - which is just the projection of the vector r on the horizontal xz-plane - let's call the copy rXZ.
Determine the signed angle between the x-axis and rXZ (use Vector3.SignedAngle(xAxis, rXZ, yAxis), see docs), and create a rotation matrix M1 that rotates the sphere in the opposite direction around the vertical (negate the angle). This should place your point in the xy-plane.
Now determine the angle between r and the y-axis (Vector3.SignedAngle(r, yAxis, zAxis)), and create a new rotation matrix M2 that rotates by that angle around the zAxis. (I think for this second one, the simpler Vector3.Angle will work as well.)
So, what you want now is to combine the two matrices (by multiplying them) into a single transform (I'm assuming this is a transformation in the local coordinate system of the sphere, where (0, 0, 0) is the sphere's center). If I'm not mistaken, Unity uses column-major matrices, so the multiplication order should be M = M2 * M1 (the rightmost matrix is applied first).
Reorient your globe using M as a local transform, and it should bring your point to the top. You can also create M3 = M1.inverse, and then do M = M3 * M2 * M1, to preserve the original angular offset from the xy-plane.
Check for edge cases, such as r already being vertical (pointing straight up, or straight down).
I am more interested in the mathematics behind this problem, but am using matlab to try and solve this problem. I have an object, positioned using the world coordinate system at (Wx, Wy, Wz)
I would like to calculate the coordinates of this point using the object coordinate system (Ox, Oy, Oz)
To do this, I first need to calculate the axes of the object coordinate system.
Step 1 is to find the Normal (Nx, Ny, Nz)
(assuming that this is not the world z-axis). My object has a yaw, pitch and roll angle applied so I need to find my normal relative to this.
To do this I use a rotational matrix and perform the operations in the order stated above.
Step 2 is to calculate the arbitrary axes.
If abs(Nx < 1/64) and abs(Ny < 1/64)
(Axx, Axy, Axz) = cross product of world y-axis (0,1,0) and the Normal
else
(Axx, Axy, Axz) = cross product of world z-axis (0,0,1) and the Normal
(Ayx, Ayy, Ayz) = cross product of N and Ax
I then scale my arbitrary axes by dividing by the sqrt of the sum of the squares.
Step 3 - Transform the coordinate
To transform the coordinate you point multiply the initial coordinate by each of the axes.
Ox = Wx * Axx + Wy * Axy + Wz * Axz
Oy = Wx * Ayx + Wy * Ayy + Wz * Ayz
Oz = Wx * Nx + Wy * Ny + Wz * Nz
DXF for autocad takes the object coordinates, the Normal vector and a rotation about the normal vector.
This appears to be working reasonable well at positioning the coordinate, but with some issues:
When I use the method above, I find that sometimes my objects are rotated 180 degrees. Digging into this, sometimes the Arbitrary x-axis is negative, sometimes it is positive. This may account for some objects being rotated, but Autocad does not actually reference this Ax vector. It calculates it. This means that I may have to correct this with a rotation about the normal, but I do not what it to always apply (I cannot simply look for a negative value and rotate if negative, as sometimes the object is required to be placed in this direction).I do not know how to overcome this.
If I apply a roll angle to the object and work through this process, the roll angle is not applied correctly. Instead this appears to translate this angle as an Yaw and Site change, but not actually the intended rotation. I cannot see what I have done using the above formula.
I have point A (x,y,z) and point B (x, y, z) in ARWorld. I want to keep point A horizontally parallel to B or let's say both should be on the surface.
See the image to get a better idea.
I am planning to get Y direction height or vertical height from A to B and then I will push down A by height. But how to find the height.
I want to keep A's x and z the same as it is.
Not sure how to articulate the issue, But aY - By does not work.
NOTE: A and B both are different Anchor in ARKit. Box/Mesh is on the anchor. Seems like I need global absolute world positions.
Is there any other way to get a rounded position in the image?
You say you want to get the positionA mapped down to the same "height" (Y axis) level as positionB
positionA.y = positionB.y;
it is simple as that.
Be aware that I am talking about absolute world space positions ... the values will of course be different in the Inspector since there you see only the local positions relative to the parent.
So when we are talking about GameObjects what you want to do is
var positionA = objectA.transform.position;
var positionB = objectB.transform.position;
positionA.y = positionB.y;
objectA.transform.position = positionA;
I would make an horizontal plane in B find the closest point in that plane to A and move A to that point.
Create horizontal plane:
Taking the constructor into account Plane(Vector3 inNormal, Vector3 inPoint);.
Plane myPlane = new Plane(Vector3.up, <Bpositon>)
Then with Plane.ClosestPointOnPlane you can find the closest point to A in your horizontal plane.
Vector3 closestPoint = myPlane.ClosestPointOnPlane(<APosition>);
Then you can move A to that point.
APosition = closesPoint;
Conviniently the closest point in the plane to one point is the one perpendicular to the plane, so the one "horizontally parallel" I believe you are after.
I'd like to create a fixed size circle that will have a varying number (between 6 - 12) of rectangle sprites positioned on it. I've read about a cocos2d function called drawCircle which is great for displaying a circle. I'd like to display a circle, but I'd also like to include the rectangle sprites on top of it, spaced evenly depending on the number of sprites.
Is there a function that would layout the rectangle sprites in a circle?
I see a little bit of trigonometry in your future! Perhaps draw the circle using a drawing function, and then compute points for the center of each box?
You'll need to know the radius of your circle, obviously, but from there it should be pretty simple. It looks like you want to place them at 45 degree angles. So the first box would be placed at point (radius, 0), the second at (radius*cos(45), radius*sin(45)), third at (0, radius), etc.
The above math is assuming standard counter-clockwise rotation from 0-360 degrees. You can also use radians - you would then compute all these points with theta = 0, pi/4, pi/2, 3pi/4, pi, 5pi/4, 3pi/2, and 7pi/4
Basically is the circle center is x0, y0, your calculated points will be (x0 + radius*cos(theta), y0 + radius*sin(theta))
Should be fairly simple math at play there :)
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.