Results 1 to 10 of 10

Thread: is there a better way...?

  1. #1

    Thread Starter
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755

    is there a better way...?

    is there a faster (better) way of doing this?

    VB Code:
    1. Private Function GetAngle(X1 As Single, Y1 As Single, X2 As Single, Y2 As Single) As Single
    2.     On Error Resume Next
    3.     Dim XDiff As Long
    4.     Dim YDiff As Long
    5.     Dim Angle As Single
    6.     XDiff = Abs(X1 - X2)
    7.     YDiff = Abs(Y2 - Y1)
    8.     Angle = Atn(XDiff / YDiff)
    9.     Angle = Angle * 180 / Pi
    10.     If Y2 > Y1 Then Angle = 180 - Angle
    11.     If X2 < X1 Then Angle = 0 - Angle
    12.    
    13.     If Angle < 0 Then Angle = 360 + Angle
    14.    
    15.     If YDiff = 0 And X1 - X2 < 0 Then
    16.         Angle = 90
    17.     End If
    18.    
    19.     If YDiff = 0 And X1 - X2 > 0 Then
    20.         Angle = 270
    21.     End If
    22.    
    23.     GetAngle = Angle
    24. End Function
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  2. #2
    Fanatic Member prog_tom's Avatar
    Join Date
    May 2001
    Location
    Los Angeles and Little Rock
    Posts
    810
    Did you want to get the Reference Angle?

    prog_tom
    JOIN THE REVOLUTION!!!! Dual T3 backedup science community.
    http://physics.sviesoft.com/forum

  3. #3

    Thread Starter
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    yep
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  4. #4
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863
    Hi, my function also uses 5 "IF'S" but I arranged them a bit different, faster ?? I don't know. But for sure I don'T have a division by 0 if dy=0 ( in yours YDif=0)!
    Sorry for any typos, I had to change some GERMAN Variable-names to ENGLISH.
    VB Code:
    1. Public Function Bearing(X1 As Single, Y1 As Single, X2 As Single, Y2 As Single)
    2. 'Input X1, Y1, X2, Y2
    3. 'Calculates Bearing  from X1,Y1 to X2,Y2 (0-360)
    4. Const PI = 3.141592654
    5. Dim dx As Single
    6. Dim dy As Single
    7. dx = X2 - X1
    8. dy = Y2 - Y1
    9. If dy <> 0 Then
    10.         Bearing = (Atn(dx / dy) * 180 / PI)
    11.         If X2 > X1 Then
    12.                 If Y2 > Y1 Then
    13.                         Bearing = Bearing
    14.                 Else
    15.                         Bearing = 180 + Bearing
    16.                 End If
    17.         Else
    18.                 If Y2 > Y1 Then
    19.                         Bearing = 360 + Bearing
    20.                 Else
    21.                         Bearing = 180 + Bearing
    22.                 End If
    23.         End If
    24. Else
    25.         If X1 > X2 Then
    26.                 Bearing = 270
    27.         Else
    28.                 Bearing= 90
    29.         End If
    30. End If
    31. End Function
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  5. #5
    Fanatic Member riis's Avatar
    Join Date
    Nov 2001
    Posts
    551
    I've made a sample project. It has only one form and one command button. The form code is shown here.
    If you convert all parameters and the return value to double floating point values, it will give a performance boost of about 20 %, when run in the VB IDE (see function GetAngle1). The reason for this is that most functions use doubles, instead of singles. So there is less type conversion. Another strange thing in your code is that you dimmed XDiff and YDiff as longs. All decimals will then be cut off.
    The best performance gives the last function (GetAngle2), which also uses arctan extensively. The extra code in the arctan2 function is to guarantee that opposite directions will give opposite angles. The extra performance boost between this function and GetAngle1 is not much, but the code is much simpler.
    Good luck!

    VB Code:
    1. Option Explicit
    2.  
    3. Private Const m_iTimes = 100000
    4. Private Const PI = 3.14159265358979
    5. Private Const HALFPI = 1.5707963267949
    6.  
    7. Private Declare Function GetTickCount Lib "kernel32" () As Long
    8.  
    9. Private Sub Command1_Click()
    10.   Dim l As Long
    11.   Dim ang As Single
    12.   Dim t1 As Long, t2 As Long, t3 As Long, t4 As Long
    13.  
    14.   Randomize Timer
    15.  
    16.   t1 = GetTickCount()
    17.   For l = 1 To m_iTimes
    18.     ang = GetAngle(Rnd, Rnd, Rnd, Rnd)
    19.   Next l
    20.  
    21.   t2 = GetTickCount()
    22.   For l = 1 To m_iTimes
    23.     ang = GetAngle1(Rnd, Rnd, Rnd, Rnd)
    24.   Next l
    25.  
    26.   t3 = GetTickCount()
    27.   For l = 1 To m_iTimes
    28.     ang = GetAngle2(Rnd, Rnd, Rnd, Rnd)
    29.   Next l
    30.  
    31.   t4 = GetTickCount()
    32.  
    33.   MsgBox "First function: " & (t2 - t1) & vbCrLf & _
    34.     "Second function: " & (t3 - t2) & vbCrLf & _
    35.     "Third function: " & (t4 - t3)
    36.  
    37. End Sub
    38.  
    39.  
    40. Private Function GetAngle(X1 As Single, Y1 As Single, X2 As Single, Y2 As Single) As Single
    41.     On Error Resume Next
    42.     Dim XDiff As Long
    43.     Dim YDiff As Long
    44.     Dim Angle As Single
    45.     XDiff = Abs(X1 - X2)
    46.     YDiff = Abs(Y2 - Y1)
    47.     Angle = Atn(XDiff / YDiff)
    48.     Angle = Angle * 180 / PI
    49.     If Y2 > Y1 Then Angle = 180 - Angle
    50.     If X2 < X1 Then Angle = 0 - Angle
    51.    
    52.     If Angle < 0 Then Angle = 360 + Angle
    53.    
    54.     If YDiff = 0 And X1 - X2 < 0 Then
    55.         Angle = 90
    56.     End If
    57.         If YDiff = 0 And X1 - X2 > 0 Then
    58.         Angle = 270
    59.     End If
    60.         GetAngle = Angle
    61. End Function
    62.  
    63. Private Function GetAngle1(X1 As Double, Y1 As Double, X2 As Double, Y2 As Double) As Double
    64.     On Error Resume Next
    65.     Dim XDiff As Double
    66.     Dim YDiff As Double
    67.     Dim Angle As Double
    68.     XDiff = Abs(X1 - X2)
    69.     YDiff = Abs(Y2 - Y1)
    70.     Angle = Atn(XDiff / YDiff)
    71.     Angle = Angle * 180 / PI
    72.     If Y2 > Y1 Then Angle = 180 - Angle
    73.     If X2 < X1 Then Angle = 0 - Angle
    74.    
    75.     If Angle < 0 Then Angle = 360 + Angle
    76.    
    77.     If YDiff = 0 And X1 - X2 < 0 Then
    78.         Angle = 90
    79.     End If
    80.         If YDiff = 0 And X1 - X2 > 0 Then
    81.         Angle = 270
    82.     End If
    83.         GetAngle1 = Angle
    84. End Function
    85.  
    86. Private Function GetAngle2(X1 As Double, Y1 As Double, X2 As Double, Y2 As Double) As Double
    87.   Dim XDiff As Double, YDiff As Double
    88.  
    89.   XDiff = X2 - X1
    90.   YDiff = Y2 - Y1
    91.  
    92.   GetAngle2 = Arctan2(YDiff, XDiff)
    93.   If GetAngle2 < 0 Then GetAngle2 = GetAngle2 + 2 * PI
    94.   GetAngle2 = GetAngle2 * 180 / PI
    95.  
    96. End Function
    97.  
    98. Public Function Arctan2(y As Double, x As Double) As Double
    99.  
    100.     If x = 0 Then
    101.         If y > 0 Then
    102.             Arctan2 = HALFPI
    103.         Else
    104.             Arctan2 = -HALFPI
    105.         End If
    106.     ElseIf x > 0 Then
    107.         Arctan2 = Atn(y / x)
    108.     Else
    109.         If y < 0 Then
    110.             Arctan2 = Atn(y / x) - PI
    111.         Else
    112.             Arctan2 = Atn(y / x) + PI
    113.         End If
    114.     End If
    115.    
    116. End Function

  6. #6
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863
    Thanks riis, I think i'll use your code (GetAngle2) instead of mine.
    Anybody using GetAngle or GetAngle1 should keep in mind, that the division by Zero is only stepped over by:
    VB Code:
    1. On Error Resume Next
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  7. #7
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863
    Or after testing my function with your "test-code" (using it in VBA-EXCEL) I think I stick to my approach.

    GetAngle2 290 vs. Bearing 280
    And I didn't change my single declaritions!
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  8. #8
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863
    Looked at it more closely.
    The difference between GetAngle2 and Bearing is the most if the Division by Zero comes into the game.
    In my Function, this event is handled earlier, i.e. faster.
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  9. #9
    Fanatic Member riis's Avatar
    Join Date
    Nov 2001
    Posts
    551
    The disadvantage of the GetAngle2 function is that it uses an extra function call, i.e. ArcTan2. Of course it is possible to integrate the ArcTan2 function into the GetAngle2 function.
    By the way, it looks like your and Cyborg's function has North as 0 degrees and the angle increases clockwise. By using Arctan2 the way I did East is 0 degrees and the angle increases counterclockwise. If anyone is going to work with it, he should keep this in mind!

  10. #10
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863
    Yes Riis,
    you are using this function in the more "technical" way.
    Since I'm using it more for navigational stuff, I need North to be Zero and East to be 90.

    You're right, anybody who is using one of this functions should keep that in mind.
    I had to learn it the hard way, on work I have to use a simulation-system build by people who think more in the "technical" way. So they are using the Degrees like you (0 is East and counting counterclockwise).
    That was no problem as long they didin't show anything on the UserInterface.
    But that system is a simulation for Naval Things, so they have to show bearings, and these have to be "understandable" be Navigators.
    So far I found about 5 places in the system that they had to change (soetimes more than once), and I'm still looking.............
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

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