I'm trying math.sin and math.cos to do a moving edge line in my program. I get all the math and it seems to add up properly (I use mouse location from a click and a moving mouse variable to determine the draw areas. I then use a width value to give it the edge offset.
I use math.cos to find how far in to offset the points in the X and Y locations. While doing this, the value of cos(Angle) seems to go absolutely crazy, from +1 to -1. Here's an example.
Angle = 29.153788462442
Cos as per window calculator = 0.8733152733324487151754721490934
Cos as per Math.Cos(Angle) = -0.637571130025255
I tried converting Angle to a float and an int in case the decimal place was causing it an issue, no avail.
This is the code I am using to bring up those answers.
lblInOpts.Text = Math.Cos(Angle).ToString() + " " + Angle.ToString();
The document is in degrees, switched over from radians and being use the same way MSDN seems to suggest.
You need to convert from degrees to radians:
Math.Cos(Angle * Math.PI / 180.0)
You are passing the angle in degrees, Math.Cos expects an angle in radians
The result from the Windows Calculator is the cosine of the angle interpreted as degrees.
The result from your C# code is the cosine of the angle interpreted as radians, which is the equivalent of 1670.389... degrees.
To convert degrees to radians in your code, use
public static double ToRadians(double x) {
return x * Math.PI / 180.0;
}
-0.637571130025255 is the cosine of 29.153788462442 radians (1670.38903571 degrees). Check the documentation of Math.Cos() - does it take an argument in radians or degrees?
Related
I am trying to code Canny edge detection in C#. I am confused about finding the Direction of the edge. I know The Direction is the angle between the gradient vector and the x-axis. When finding the gradient vector's Direction (D), you do inverse tan of the y/x ratio.
I understand that part. The part that I am lost at is some examples online seem to add PI out of nowhere, and I do not understand. So is it :
` double angle = X/ Y;
double radians = angle * (180/Math.PI);
Angle = Math.Tan(radians) + Math.PI;`
or this:
double angle = X/ Y;
double radians = angle * (180/Math.PI);
Angle = Math.Tan(radians);
I have also seen :
orientation[index] = Math.Atan2(dy, dx) + Math.PI;
but this is not even inverse tan or is it ?
Both your first examples don't make any sense. X / Y is surely not an angle but the tangens of an angle.
To get the angle from the tangens you must use the one of the two inverse functions Math.Atan or Math.Atan2.
Always prefer Math.Atan2 over Math.Atan if you have got both components (X and Y) of the direction vector because Math.Atan2 returns an unambiguous angle in the range for -Pi to +Pi, while Math.Tan only gives you a result in the range form -Pi/2 to +Pi/2. Then you have to decide if in a certain case you have to add or subtract Pi (ATan doesn't "know" whether the angle is in the first or in the third quadrant if the result is positive or whether it is in the second or fourth quadrant if the result is negative).
Try to learn how to work with trigonometric functions and when you understand how to apply them and the corresponding inverse trigonometric functions come back to your programme.
And read the Microsoft documentation concerning the trigonometric functions.
I am currently using Atan2 to calculate the player heading angle.
however after some trial and error I discovered that the in-game angle's are rather different to that of a "normal" lay out :
ReturnedAngle = Math.Atan2(Y2 - Y1, X2 - X1); /// ArcTan2 the difference in our Y axis is always passed first followed by X
ReturnedAngle = (180 / Math.PI) * ReturnedAngle; /// Converting our radians to Degrees the convervion ends at 358 not the full 360 degrees.
ReturnedAngle = Math.Round(ReturnedAngle + 360, MidpointRounding.AwayFromZero) % 360; /// MOD and round our angle.
Above is the C# code I am using to calc the heading angle. My questions is how would I go about converting this angle from the "normal" angle system to the in-game one.
I think this is your situation. You have a right-hand coordinate system, but you are measuring a clock-wise angle, which is inconsistent.
In any case, draw a small positive angle from 360 (red below) to form a right triangle (purple below) with positive sides.
To measure the angle θ of the triangle, measure the short side Δx and the long side Δy and compute.
var θ = Math.Atan2(Δx, Δy);
This would work for any positive or negative values for the two sides. For example, if the angle goes above 90° then Δy would flip signs, as your target point is going to be below the origin. But the beauty of Atan2() is that you don't need to worry about these cases as it works on all four quadrants if you make it work for a small positive angle.
In reverse you have
var Δx = R*Math.Sin(Θ);
var Δy = R*Math.Cos(Θ);
where R is the distance between the target and the reference point.
Math.Atan2(Y2 - Y1, X2 - X1) computes the angle anticlockwise from the x axis. Math.Atan2(X2 - X1, Y2 - Y1) computes the angle clockwise from the y axis, which is what you want.
The 'clockwise from north' convention is used in navigation and mapping. Over the years I've found that it easiest to think in terms of vectors having components north, east. This means that atan2 is called the same way, that is, to get the direction of q from p:
dirn = atan2( q[1]-p[1], q[0]-p[0]);
If you are thinking of p and q as x,y vectors this gives you the angle anti-clockwise from the x axis. If you are thinking of p and q as n,e vectors it gives you the angle clockwise from north.
It also means that the formulae for a rotation matrix is the same. To rotate through an angle a, you use the matrix
R = ( cos(a) -sin(a) )
( sin(a) cos(a) )
Again, if you are thinking of the vectors as being x,y then applying R rotates through and angle a, anti-clockwise from the axis, while if you think of vectors as being n,e applying R rotates through an angle a, clockwise from north.
I made a speedometer control My controller has a property called Angle that changes the shape of my speedometer (180 for Complete Circul, and so on...)
With the help of a converter, I can move the speedometer correctly
// values[0] = Angle
// values[1] = Value
var startAngle = System.Convert.ToDouble(values[0]) * -1;
var endAngle = startAngle + (((double)values[1]) * 2);
return endAngle;
Now I want to have a property called Maximum, And if the user sets it to 50, even if my circle is 360 degrees, the whole circle will be full with 50 values.
I used the following code but unfortunately it does not work properly
return value * angle / maximum;
also this is my arc
<x:Arc StartAngle="{Binding Angle, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource Positive2Nagative}}" EndAngle="{Binding Angle, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
UPDATE:
this code:
//a = s * A / max
value * angle / maximum;
Compile to this:
<loc:speedometer Angle="120" MaximumValue="50" Value="{Binding ElementName=sld, Path=Value}"
/>
UPDATE 2:
i fixed problem with this code
return ((value * angle / maximumValue * 2) - angle);
You're using a very strange notation for this.
Let's call a change in value of 1 a step. So 50 km/h maximum means 50 steps.
You want 50 steps between the start and end.
Your first task is to work out angle per step.
For that you need to know the angle the entire arc will go through.
If the start is always over there on the left of the vertical line then it's always negative.
Hence you want -1 * start for the left number of degrees offset from vertical.
The right is easy it's just end.
Hence (-1 * start) + end = totalArc degrees
That gives you how many degrees the 0 to max covers.
Let's call the thing you're representing speed. Because angle is a very very bad name for a variable in a calculation which is all about angles.
totalArc / maximum gives the value in degrees of each step in our speed.
Hence you want (totalArc / maximum) * speed.
That gives you the angle between the start and where the speed indicator should go to.
You will then have to work out what that means in terms of your display.
I would suggest the simplest is to rotatetransform whatever does the red stuff so 0 angle matches the start. Maybe you're already doing that though.
I think you are looking for the following:
Given an angle a, the equivalent value s, considering A degrees repesents the maximum value max, is:
s = a * max / A
Or what is pobably more useful, the angle a which reprenets a given speed s in a A degree speedometer with a maximum speed max is:
a = s * A / max
That said, I'm not really sure how your speedometer works. At first you talk about a 180º gauge and then you start talking about a full 360º one. Either way, A is either 180 or 360.
I am creating an XNA game but am a little bit confuse working differently from the standard Cartesian coordinate when it comes to angle rotation.
Let say I have the following and I want to find the angle between those vectors
Vector2 p1 = new Vector2(111, 0);
Vector2 p2 = new Vector2(223, 110);
float angle = (float)Math.Atan2(p2.Y - p1.Y, p2.X - p1.X);
Debug.WriteLine(MathHelper.ToDegrees(angle).ToString());
I would imagine that angle should be close to 90 degree but it gives 44.48384.
Come to think of it, am I correct to assume that it's the angle between the horizontal line i.e Vector2(0,0) and Vector2(111, 0) and Vector2(0,0) and Vector2(223, 110)?
However if I calculate the angle using tan x = 110 / 223 the angle I get is 26.25. What am I missing?
The angle is 44.48384°, if you are measuring the angle around the origin (as you would expect, since "angle between two vectors").
Maybe you have your definition of which angle you wish to calculate envisioned incorrectly as I'm struggling to see how these two points could form the angle of 90°.
Here's a quick sketch I did on paper of these two points (please excuse the scruffiness!):
I have the Y coordinates going in the wrong direction but the problem is the same.
I have no Idea what is wrong. I have converted my sin answer to degrees but It will not give me the correct answer but instead gave me a 4.18......
The correct output should have been around 2.8.
Input 1 = 4.9 and Input 2 = 35
On my calculator Sin(35) * 4.9 = 2.8....
output = Convert.ToDouble(Input1.Text)
* Math.Sin(Convert.ToDouble(Input2.Text)*180/Math.PI);
Math.Sin() takes the angle in radians.
What you do are doing here
Math.Sin(Convert.ToDouble(Input2.Text)*180/Math.PI)
is converting input2 to degrees.
You need to multiply by Math.PI/180 to convert degrees to radians.
Edit:
So you should use
Math.Sin(Convert.ToDouble(Input2.Text)*Math.PI/180)
As has been stated in other answers, your operator precedence is backwards, you need to divide Math.PI by 180 rather than dividing 180 by Math.PI. So, your function should be:
output = Convert.ToDouble(Input1.Text) * Math.Sin(
Convert.ToDouble(Input2.Text)*(Math.PI/180));