Results 1 to 14 of 14

Thread: [RESOLVED] Rise/Run to Angle

  1. #1

    Thread Starter
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Resolved [RESOLVED] Rise/Run to Angle

    For a number of years I've been using a simple rise/run vector to represent the direction of a moving object onscreen. For example, if I wanted to represent the trajectory of an object moving from somewhere in the upper left on the screen to the lower right at an exact angle of 45 degrees, I'd use a value of (5,5). The values themselves aren't important, only their ratio to one another so (5,5) is the exact same direction as (1,1) or (23,23). If I wanted to represent movement along the Y axis with no movement along the X axis, I can use say, (0,10) which is downward movement or (0,-10) which is upward movement.

    This works really well for me. Its simple and makes certain calculations like plotting an intercept course quite easy. But I've always been curious: Is there anyway to convert this to an angle. How can I convert (5,5) to 45 degrees or 315 depending on how you want to interpret the angles.

    [EDIT]

    I forgot to mention that the signs of the numbers in the vector represents the direction on the specific axis. So a vector of say (12,3) represents movement in a downward right direction. (-12,3) is downward left. (-12,-3) is upward left. (12,-3) is upward right. The absolute value of the larger number is what I use to represent speed. But for the purposes of converting to an angle, speed is not important.
    Last edited by Niya; Apr 7th, 2014 at 07:19 AM.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  2. #2
    Only Slightly Obsessive jemidiah's Avatar
    Join Date
    Apr 2002
    Posts
    2,431

    Re: Rise/Run to Angle

    Converting a 2D vector to an angle is precisely the job of the atan2 function. There's a lengthy Wikipedia page about it and it's in a large number of libraries. Note there are a couple of common conventions in use that differ in the order of the two arguments. Also, to compute speed, you should probably use sqrt(x^2 + y^2) rather than max(|x|, |y|), though to each their own. (A lot of games get into trouble and use |x|+|y| for speed, which means if you move diagonally you can move twice as fast as usual.)

    It occurred to me, I could "math on" for a little bit comprehensibly at this stage. The atan2 function is perhaps surprisingly closely related to complex number arithmetic, specifically multiplication. You can represent complex numbers as vectors in the plane starting at the origin and vice-versa, so I'll use them interchangeably. It turns out complex multiplication is precisely given by the following: given two complex numbers/vectors, multiply the lengths of the two vectors; add their angles, measured from the +x-axis counterclockwise; interpret the result as a complex number.

    The exponential function can be defined on complex numbers in a cute way--given R+Ti, *define* e^(R+Ti) to be the vector of length e^R and which makes an angle T with the +x-axis measured counterclockwise (in radians). We see if R=0, T=pi, then e^(pi i) is the vector of length e^0 = 1 which makes an angle pi with the +x-axis, i.e. it's the vector (-1, 0), which is the complex number -1. This gives Euler's formula, e^(pi i) + 1 = 0.

    (Well, usually the exponential function is defined in terms of its Taylor series, but this is way more intuitive and makes it a simple matter to show e^(w+z) = e^w e^z, for instance.)

    What about atan2? Well, this comes into play when we try to invert the exponential function. That is, given some complex number z, we want to find a+bi such that e^(a+bi) = z. Finding "a" is easy enough: the length of e^(a+bi) is e^a, so we need e^a to be the length of z, denoted |z|. Hence we need a = ln|z|, using the natural log function. What about b? It's precisely atan2(z).

    But, there's some ugliness. The "illustrations" section of the Wikipedia article I linked shows that atan2 is discontinuous. This is an "essential" problem, in some sense. It can be used to compute algebraic invariants of the circle, which leads to the study of algebraic topology. And this is where I have no hope of being understood, so I stop.
    Last edited by jemidiah; Apr 8th, 2014 at 01:50 AM.
    The time you enjoy wasting is not wasted time.
    Bertrand Russell

    <- Remember to rate posts you find helpful.

  3. #3

    Thread Starter
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Rise/Run to Angle

    I have to admit, a lot of that flies over my head but not so much so that it hasn't helped me to figure it out. The Atan2 function works as you said:-
    vbnet Code:
    1. '
    2.     Public Function GetAngleOfTrajectoryInDegrees(ByVal trajectory As PointF) As Integer
    3.         Dim radians As Double = Math.Atan2(trajectory.Y, trajectory.X)
    4.         Dim degrees As Integer = radians * (180 / Math.PI)
    5.  
    6.         If degrees < 0 Then
    7.             degrees = 360 + degrees
    8.         End If
    9.  
    10.         Return degrees
    11.     End Function

    I also punched in a couple values with your suggested formula for calculating speed and the result was intriguing. With a vector of say (5,5), I get a speed value of 7.07106781186548 whereas I measure a speed of 5 with my method. I'm not sure how this will affect my engines if this is applied but its certainly warrants further investigation.

    Only thing left now is for me to figure out how to convert degrees back into a trajectory vector. These operations would enable me to accomplish a couple neat tricks. For example I can use these conversions to target projectiles to random points within narrow angle, something that would be clumsy to implement using strictly rise/run vectors. It could be done very easily with using degrees to represent direction instead of rise/run, assuming I figure out how to convert degrees back into rise/run.

    Now, the part of your post about complex numbers really flew over my head. I browsed over the topic briefly to get an idea of what its about and I kinda get it but I'm going to have to study this in detail and do some exercises to really begin to grasp what you're describing from your second paragraph and onwards.

    Nonetheless, thanks for you help. Really appreciate this man.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  4. #4

    Thread Starter
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Rise/Run to Angle

    Ok, I've figured out how to convert degrees back into rise/run vector. I altered the other function slightly so I'll repost that one as well:-
    vbnet Code:
    1. '
    2.     Public Function GetAngleInDegrees(ByVal trajectory As PointF) As Double
    3.         Dim radians As Double = Math.Atan2(trajectory.Y, trajectory.X)
    4.         Dim degrees As Double = radians * (180 / Math.PI)
    5.  
    6.         'Anything less than zero means a trajectory above
    7.         'the X axis. -45 would be upper right but I want
    8.         '315 instead so I subtract 45 from 360 via addition since
    9.         'addition of a large positive and small negative is
    10.         'the same as subtracting the absolute of the small value
    11.         'from the big value.
    12.         If degrees < 0 Then
    13.             degrees = 360 + degrees
    14.         End If
    15.  
    16.         Return degrees
    17.     End Function
    18.  
    19.     Public Function GetRiseRunFromAngle(ByVal angleDegrees As Double) As PointF
    20.  
    21.         'Needs to convert back to the angle Atan2 would have
    22.         'produced
    23.         If angleDegrees > 180 Then
    24.             angleDegrees -= 360
    25.         End If
    26.  
    27.         Dim radians As Double = angleDegrees * (Math.PI / 180)
    28.         Dim tangent As Double = Math.Tan(radians)
    29.  
    30.         Return New PointF(1, tangent)
    31.     End Function
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  5. #5

    Thread Starter
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Rise/Run to Angle

    Thank you very much for your help Jemidiah. I'll now consider this resolved.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  6. #6
    Only Slightly Obsessive jemidiah's Avatar
    Join Date
    Apr 2002
    Posts
    2,431

    Re: [RESOLVED] Rise/Run to Angle

    A relatively minor point: it's probably best to use "New PointF(Math.Cos(radians), Math.Sin(radians))" instead of "New PointF(1, tangent)". The direction will be unaffected, but the benefits are: (1) the speed is always 1, rather than something that varies from 1 to infinity; (2) you don't get errors at special values like when radians = pi/2; (3) it's conceptually cleaner. Indeed, this operation is precisely computing the exponential e^(0 + radians * i) that I defined in the first post. So the operations you wanted, which are close to inverses of each other, have been recognized as (super) important and given quite a lot of attention by mathematicians.

    Some notes on speed functions: sqrt(x^2 + y^2) is the same even if you rotate the point (x, y) around the origin, whereas max{|x|,|y|} is not; sqrt(x^2 + y^2) has a simple interpretation using the Pythagorean theorem--it is precisely the distance from the origin to the point (x, y)--whereas max{|x|,|y|} is constant on squares centered at the origin, which is a bit strange. It's the "supremum norm", which certainly has applications, but it's not really what you want when making most games.
    The time you enjoy wasting is not wasted time.
    Bertrand Russell

    <- Remember to rate posts you find helpful.

  7. #7

    Thread Starter
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: [RESOLVED] Rise/Run to Angle

    Quote Originally Posted by jemidiah View Post
    A relatively minor point: it's probably best to use "New PointF(Math.Cos(radians), Math.Sin(radians))" instead of "New PointF(1, tangent)". The direction will be unaffected....
    Wow so simple! I had to write a whole other function which did a bunch of angle measurements to correct the direction. Can't believe the solution was so simple....well not simple since I never had a firm grasp of what Sine, Cosine and Tangent really mean so I certainly wasn't gonna figure out that on my own. Its amazing how much you understand all this.

    Quote Originally Posted by jemidiah View Post
    Some notes on speed functions: sqrt(x^2 + y^2) is the same even if you rotate the point (x, y) around the origin, whereas max{|x|,|y|} is not; sqrt(x^2 + y^2) has a simple interpretation using the Pythagorean theorem--it is precisely the distance from the origin to the point (x, y)--whereas max{|x|,|y|} is constant on squares centered at the origin, which is a bit strange. It's the "supremum norm", which certainly has applications, but it's not really what you want when making most games.
    I think I get what you're saying. I found a formula for calculating the distances between two points which is very similar:-
    vbnet Code:
    1. '
    2.     Public Shared Function CalculateDistance(ByVal pt1 As PointF, ByVal pt2 As PointF) As Double
    3.         Return Math.Sqrt(((pt1.X - pt2.X) ^ 2) + ((pt1.Y - pt2.Y) ^ 2))
    4.     End Function

    This is actually starting to make sense speed is just distance over time. I hadn't really looked at it so until now.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  8. #8
    Only Slightly Obsessive jemidiah's Avatar
    Join Date
    Apr 2002
    Posts
    2,431

    Re: [RESOLVED] Rise/Run to Angle

    Roughly speaking, you can define sin and cos to be the correct functions to use in your GetRiseRunFromAngle function, subject to the constraint that the resulting vector has length 1. That is, (cos(t), sin(t)) is precisely the vector of length 1 making angle t with the +x-axis measured counterclockwise (well, clockwise in environments where the y-axis is flipped; IIRC VB uses this silly convention). The usual interpretation in terms of right triangles follows quickly from this definition, and this makes the signs make sense. How to calculate these quantities from this definition is another matter.

    The distance function code you wrote is precisely the Pythagorean theorem in vector component form. If pt2 is (0, 0), you get my assertion. When the vector (x, y) is thought of as giving the direction of movement, the length sqrt(x^2 + y^2) is typically thought of as giving the speed. This is precisely true eg. if x and y are in units of, say, miles/hour.

    I noticed at this point I'm sort of just babbling basic properties of vectors, so I'll stop.
    The time you enjoy wasting is not wasted time.
    Bertrand Russell

    <- Remember to rate posts you find helpful.

  9. #9

    Thread Starter
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: [RESOLVED] Rise/Run to Angle

    Quote Originally Posted by jemidiah View Post
    I noticed at this point I'm sort of just babbling basic properties of vectors, so I'll stop.
    Well you've certainly given some useful insight even though I don't fully understand all of it. I'm going to make some time and hit Khan Acedemy on Youtube to see if he has any explanation for some of these concepts. In particular, Sine, Cosine, Tangent and Pythagoras Theorem. This is all very intriguing. They taught all these things at secondary school but I never imagined I would have use for them one day. Wished I paid more attention.
    Last edited by Niya; Apr 8th, 2014 at 05:12 PM. Reason: Corrected spelling. Changed "thought" to "taught"
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  10. #10

    Thread Starter
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: [RESOLVED] Rise/Run to Angle

    OMG, I just read up on Pythagorean theorem on Wikipedia and by God it makes sense. The reason the distance calculation works is because the sum of the squares of the two sides of a right angle triangle is equal to the square of the hypotenuse. Calculating the distance between two points is exactly the same as solving for the length of the hypotenuse of a right angle triangle when you know the length of the other two sides(rise and run). Your speed calculation is the same thing as well. Never thought I'd come to understand this.
    Last edited by Niya; Apr 9th, 2014 at 01:22 PM.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  11. #11
    Only Slightly Obsessive jemidiah's Avatar
    Join Date
    Apr 2002
    Posts
    2,431

    Re: [RESOLVED] Rise/Run to Angle

    Heh, glad some of it is clicking.
    The time you enjoy wasting is not wasted time.
    Bertrand Russell

    <- Remember to rate posts you find helpful.

  12. #12

    Thread Starter
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: [RESOLVED] Rise/Run to Angle

    Quote Originally Posted by jemidiah View Post
    A relatively minor point: it's probably best to use "New PointF(Math.Cos(radians), Math.Sin(radians))" instead of "New PointF(1, tangent)". The direction will be unaffected, but the benefits are: (1) the speed is always 1, rather than something that varies from 1 to infinity; (2) you don't get errors at special values like when radians = pi/2; (3) it's conceptually cleaner.
    After watching a video on unit circles for the umpteenth time I now understand why this works. With a tangent of 1, the Cosine of an angle can be interpreted as a simple X co-ordinate and the Sine can be interpreted as the Y. Its also why you said the speed would always be 1. The way I'm using this as movement vectors means that the tangent equals speed. It makes so much sense now. My friend, you've given me a renewed interest in trigonometry. Funny thing is, I hated trig when I was in school, more so than any other branch of math.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  13. #13
    Only Slightly Obsessive jemidiah's Avatar
    Join Date
    Apr 2002
    Posts
    2,431

    Re: [RESOLVED] Rise/Run to Angle

    That's wonderful, glad to be helpful in sparking some interest in math.
    The time you enjoy wasting is not wasted time.
    Bertrand Russell

    <- Remember to rate posts you find helpful.

  14. #14
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: [RESOLVED] Rise/Run to Angle

    Sin, sin, everywhere are sin
    circling the origin
    and taking all my time.
    Opposite over hypotenuse:
    Can't you just use sin?

    (I think I stuck an extra syllable in the penultimate line).
    My usual boring signature: Nothing

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width