Sorry about this but I need some conformation about this function and calculation
I currently have these Vectors:
Vector3D ElbowLeft = new Vector3D(body.Joints[JointType.ElbowLeft].Position.X, body.Joints[JointType.ElbowLeft].Position.Y, body.Joints[JointType.ElbowLeft].Position.Z);
Vector3D WristLeft = new Vector3D(body.Joints[JointType.WristLeft].Position.X, body.Joints[JointType.WristLeft].Position.Y, body.Joints[JointType.WristLeft].Position.Z);
Vector3D ShoulderLeft = new Vector3D(body.Joints[JointType.ShoulderLeft].Position.X, body.Joints[JointType.ShoulderLeft].Position.Y, body.Joints[JointType.ShoulderLeft].Position.Z);
Vector3D Head = new Vector3D(body.Joints[JointType.Head].Position.X, body.Joints[JointType.Head].Position.Y, body.Joints[JointType.Head].Position.Z);
Vector3D Neck = new Vector3D(body.Joints[JointType.Neck].Position.X, body.Joints[JointType.Neck].Position.Y, body.Joints[JointType.Neck].Position.Z);
Vector3D SpineShoulder = new Vector3D(body.Joints[JointType.SpineShoulder].Position.X, body.Joints[JointType.SpineShoulder].Position.Y, body.Joints[JointType.SpineShoulder].Position.Z);
I am calculating the angle between the two vectors using this function
public double AngleBetweenTwoVectors(Vector3D vectorA, Vector3D vectorB)
{
double dotProduct = 0.0;
vectorA.Normalize();
vectorB.Normalize();
dotProduct = Vector3D.DotProduct(vectorA, vectorB);
return (double)Math.Acos(dotProduct) / Math.PI * 180;
}
And I am calling it like this:
double LeftElbowAngle = AngleBetweenTwoVectors(ElbowLeft - ShoulderLeft, ElbowLeft - WristLeft);
double NeckAngle = AngleBetweenTwoVectors(Neck - Head, Neck - SpineBase);
Is this correct? Im just doubting myself because When i put my arm straight or stand up straight it detects an angle of about 170 - 175 rather than 180. on both my neck and my elbow joint
I have confirmed that the above Algorithim is correct mathematically, however the accuracy of the device may be a bit off due to the hardware, and individual human bones may prevent from perfect joint extension which is 180.
correct me If I'm wrong but I think instead of this
return (double)Math.Acos(dotProduct) / Math.PI * 180
it should be
return (double)Math.Acos(dotProduct) * (180.0/Math.PI);
since angle returned by Math.Acos is in radian and to convert it into degrees you should be multiplying it to 180/pi
Related
I am trying to code for a game I am working on a specific curve with a specific rotation. I am not a great mathematician... At all... Tried searching for solutions for a few hours, but I'm affraid I do not find any solution.
So, a small picture to illustrate first:
This is an eighth of a circle, radius of 9, beggining is (0,0)
The end is now at about 6.364, -2.636. But I need this same curve, with a 45° direction at the end, but ending at aexactly 6.0,-3.0.
Could any of you show me how to do this? I need to be able to calculate precisly any point on this curve & its exact length. I would suppose using some kind of eliptical math could be a solution? I admit my math class are reaaaly far now and have now good clue for now...
Thank for any possible help
I think I found a quadratic curve which sastisfies your requirement:
f(x) = -1/12 x^2 + 9
Copy the following into https://www.desmos.com/calculator to see it:
-\frac{1}{12}x^2+9
f'(x) would be -1/6x, so when x=6, the derivative would be -1, which corresponds to a -45° inclination. There are probably infinite curves that satisfy your requirement but if my calculus isn't too rusty this is one of them.
I tried to fit an ellipse with foci starting at y=6 here and starting at y=9 here to your points but the slope doesn't look like 45°.
Also starting at any height k, here doesn't seem to work.
I don't think you've fully understood the question I asked in the comments about the "inclination" angle. So I will give a general case solution, where you have an explicit tangent vector for the end of the curve. (You can calculate this using the inclination angle; if we clarify what you mean by it then I will be happy to edit with a formula to calculate the tangent vector if necessary)
Let's draw a diagram of how the setup can look:
(Not 100% accurate)
A and B are your fixed points. T is the unit tangent vector. r and C are the radius and center of the arc we need to calculate.
The angle θ is given by the angle between BA and T minus π/2 radians (90 degrees). We can calculate it using the dot product:
The (signed) distance from the center of AB to C is given by:
Note that this is negative for the case on the right, and positive for the left. The radius is given by:
(You can simplify by substituting and using a cosine addition rule, but I prefer to keep things in terms of variables in the diagram). To obtain the point C, we need the perpendicular vector to AB (call it n):
Now that we have the radius and center of the circular arc, we still need to determine which direction we are moving in, i.e. whether we are moving clockwise or anti-clockwise when going from A to B. This is a simple test, using the cross-product:
If this is negative, then T is as in the diagram, and we need to move clockwise, and vice versa. The length of the arc l, and the angular displacement γ when we move by a distance x along the arc:
Nearly there! Just one more step - we need to work out how to rotate the point A by angle γ around point C, to get the point we want (call it D):
(Adapted from this Wikipedia page)
Now for some code, in case the above was confusing (it probably was!):
public Vector2 getPointOnArc(Vector2 A, Vector2 B, Vector2 T, double x)
{
// calculate preliminaries
Vector2 BA = B - A;
double d = BA.Length();
double theta = Math.Acos(Vector2.DotProduct(BA, T) / d) - Math.PI * 0.5;
// calculate radius
double r = d / (2.0 * Math.Cos(theta));
// calculate center
Vector2 n = new Vector2(BA.y, -BA.x);
Vector2 C = 0.5 * (A + B + n * Math.Tan(theta));
// calculate displacement angle from point A
double l = (Math.PI - 2.0 * theta) * r;
double gamma = (2.0 * Math.PI * x) / l;
// sign change as discussed
double cross = T.x * BA.y - T.y * BA.x;
if (cross < 0.0) gamma = -gamma;
// finally return the point we want
Vector2 disp = A - C;
double c_g = Math.Cos(gamma), s_g = Math.Sin(gamma);
return new Vector2(disp.X * c_g + disp.Y * s_g + C.X,
disp.Y * c_g - disp.X * s_g + C.Y);
}
I'm trying to calculate distance of cannon shot using velocity and angle. I'm testing results using utility tests. The formula for range should be someting like v^2 * sin2a aka velocity squared * sin2alpha . As far as i know, sin2a is supposed to be 2*sina*cosa, but i may be wrong.
Anyway, whatever i do, i get wrong results, because it doesn't seem to be calculating sin.
Here's the code
Cannon.cs
public int CalculateDistance(int angle, int velocity)
{
int distance = 0;
double radian_angle = (Math.PI / 180) * angle;
distance_of_shot = (Math.Pow(velocity, 2)) * (2 * Math.Sin(radian_angle) * Math.Cos(radian_angle));
distance = (int)distance_of_shot;
return distance;
}
CannonAttackTest.cs
[TestMethod]
public void Calculations()
{
Canon new_canon = new Canon();
var data = new_canon.CalculateDistance(45, 450);
Assert.AreEqual(20682, data);
}
The results is suppose to be 20682, but i get 202500, which is exactly a number of squared 450...whichs points to sin not being calculated.
Any help is appreciated!
Thank you!
Check your units, you need to divide by the value of "g" because velocity is m/s and your "distance of shot" is in m^2/s^2.
distance_of_shot = (Math.Pow(velocity, 2)) * (2 * Math.Sin(radian_angle) * Math.Cos(radian_angle))/9.81;
You have a mistake sin 0.70710678118654746 and cos 0.70710678118654757 but after
(2 * Math.Sin(radian_angle) * Math.Cos(radian_angle)) result coming 1
Maths is not my strong suit and I think I have something mixed up here but I cannot figure out what.
I'm just trying to populate 2 new coordinates given a number of variables and constants.
if I make Origin coordinate 5,5 and Destination coordinate 10,5, I can work out that distance =5 and that the bearing from Origin to Destination is 90 using these two functions:
private static double GetDistance(PointF point1, PointF point2)
{
double a = (double)(point2.X - point1.X);
double b = (double)(point2.Y - point1.Y);
return Math.Sqrt(a * a + b * b);
}
public static double GetBearing(PointF coord1, PointF coord2)
{
double result = 0.0;
result = Math.Atan2(coord2.X - coord1.X, coord2.Y - coord1.Y) * (180 / Math.PI); //- Math.Atan2(coord4.y - coord3.y, coord4.x - coord3.x))
if (result < 0)
{
result = result + 360;
}
return result;
}
What I want to be able to do given an offset Distance of xd=1 and an offset bearing of 180(ie directly opposite direction to the destination) is plot the location 4,5. I'd also like to be able to feed a different offset bearing in of say 90 and plot 5,6.
Here's what I've tried but I get completely nonsensical values.
public static PointF CalculateCoordinate(double Angle, double Distance)
{
PointF coord = new PointF(Convert.ToSingle(Distance * Math.Cos(Angle)), Convert.ToSingle(Distance * Math.Sin(Angle)));
return coord;
}
and CalculateCoordinate(GetBearing(Destination, Origin),1) to reverse the bearing directly 180. I've tried this CalculateCoordinate(90,1) to calculate an offset to the side but that's not working either.
Where have I gone wrong, I'm sure it's something pretty stupid and simple.
There's two mistakes that I can see. First, Atan2 takes the Y value for the first parameter and the X value for the second:
Math.Atan2(coord2.Y - coord1.Y, coord2.X - coord1.X) * (180 / Math.PI);
Secondly, you're converting from radians to degrees in GetBearing, but you're not converting Angle from degrees to radians inside CalculateCoordinate e.g:
Math.Cos(Angle * (Math.PI / 180))
I have the following code:
double x = sw.bonePos[0, (int)Bones.HipCenter].x;
double z = sw.bonePos[0, (int)Bones.HipCenter].z;
double hypotenusePower2 = Math.Pow(x, 2) + Math.Pow(z, 2);
double hypotenuse = Math.Sqrt(hypotenusePower2);
double angle = Math.Asin(z / hypotenuse);
I know that x,z, hypotenuse are correct and z / hypotenuse is correct because its always between -1 and 1. So I want to find the angle using the ArcSin like this but when I am printing for example Math.Asin(1) the result is 1.5707...
Am I using the wrong function? Is there any function in C# that returns the angle?
Example of input/output:
x: -0.000844396417960525
z: 0.857428431510925
hypotenuse: 0.857428847292063
angle: 1.5698115260652
x: 0.0198930986225605
z: 0.849016189575195
hypotenus: 0.849249212854266
angle: 1.54736984845028
The result you get is correct - asin of 1 is half of π, or approximately 1.5707 radians.
Functions returning angles usually return the results in radians. If you need the result in degrees, you need to convert the result as follows:
double degrees = angle * ( 180 / Math.Pi );
That's the right answer. The resulting angle is measured in radians. Math.Asin(1) should therefore be equal to π/2 ≈ 1.5707 radians, which matches your result.
If you wanted the value in degrees, multiply by 180/π. In this case, π/2 * 180/π would give you 90 degrees:
double degrees = radians * (180 / Math.Pi);
I currently have this code in my game:
Vector2 pixelpos = new Vector2(x, y);
Vector2 center = new Vector2(t.Width / 2, t.Height / 2);
Vector2 pixelposWorld = (pixelpos - center);
float rotation = (float)Math.Atan2(pixelposWorld.Y, pixelposWorld.X);
float rotationPercent = (MathHelper.ToDegrees(rotation) / 360);
My goal is to end up with rotationPercent to be a value between 0.0 and 1.0, 0 degrees being 0.0, 180 being 0.5 and 360 being 1.0.
Currently, rotationPercent only comes out as 1.0.
What can I do to fix this?
First of all, in your case, there is no need to convert it to degrees, since Math.aTan2 returns the angle in radians, just divide your rotation variable by (2*Pi).
Secondly, check what you are doing at "t.Width / 2, t.Height / 2", as you haven't specified in your question what 't' is, make sure it's members are not integers.
Now as far as your problem itself, there is not enough information supplied. Where does this contain your rotation information? Is the 'pixelpos' vector your world space position, or do you also use that as rotation?
Brought back to a minimum, the following code works roughly like like you described?
Vector2 pixelpos = new Vector2(0, 1);
float rotation = (float)(Math.Atan2(pixelpos.Y, pixelpos.X) / (2 * Math.PI));
Which results 0.25, or 90 degrees.
The best way to calculate this would be through the use of dot products though:
Vector2 pixelposWorld = Vector2.Normalize(pixelpos - center);
float dot = Vector2.Dot(Vector2.UnitX, pixelposWorld);
float rotation = (pixelposWorld.Y >= 0)
? (1f - dot) / 4f
: (dot + 3f) / 4f;
Just saying, it is on average 120% faster (I ran the tests).
I think you forgot to use float in 360, it should be 360f.