Android Question Get an angle between 2 lines

ilan

Expert
Licensed User
Longtime User
hi

i would like to rotate a polygon around his center.
i have already the formula for the center point my problem is how to get the angle

so what i do now is when i touch the screen i create a vector (polygon center (x,y)) and the touch x,y
so i have 1 line and this line is 0 angle (its the starting point) now when i move my finger i create everytime a new line (polygon center) and the new x,y and i want to rotate the polygon with the angle between both lines

i tried several formulas i found in the web but nothing gave me the result i wanted
i also found here something but still its not turning correctly. i get to a point where it turns back
(https://www.b4x.com/android/forum/threads/find-angle-for-two-drawlines.13127/#content)

does anyone can help me please?

the polygon center is the first point for both vectors! (like in the image)

rotate.jpg
 

klaus

Expert
Licensed User
Longtime User
Try this routine:
B4X:
'Calculates the smaller angle between 2 lines defined by 2 points each
'cordinates line 1 point1 : x11, y11
'cordinates line 1 point2 : x12, y12
'cordinates line 2 point1 : x21, y21
'cordinates line 2 point1 : x22, y22
'Degrees = True result in degrees, Degrees = False result in radians
Public Sub CalcAngleBetween2Lines(xx11 As Double, yy11 As Double, xx12 As Double, yy12 As Double, xx21 As Double, yy21 As Double, xx22 As Double, yy22 As Double, Degree As Boolean) As Double
    Private Angle As Double
   
    Angle = Abs((ATan2D(y12 - y11, x12 - x11) - ATan2D(y22 - y21, x22 - x21)))
   
    If Angle > 180 Then
        Angle = 360 - Angle
    End If
   
    If Degree = True Then
        Return Angle
    Else
        Return Angle *cPI / 180
    End If
End Sub
Attached a small test project.
 

Attachments

  • AngleBetween2Lines.zip
    7.2 KB · Views: 207
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi Ilan, using Klaus' code you obtain same result as your getangle corrected as follows:

B4X:
Sub getangle (p1 As vector, p2 As vector,p0 As vector) As Double
   Dim mr,ms As Double
   mr = (p1.x-p0.x) / (p1.y-p0.y)
   ms = (p2.x-p0.x) / (p2.y-p0.y)
   Log("AtanD: "&ATanD(Abs((mr-ms)/(1+(mr*ms)))))
   Return ATanD(Abs((mr-ms)/(1+(mr*ms))))
End Sub

fundamentally you missed the abs function.

udg
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
thank you very much @klaus now your example is working great only 1 little issue

when the degree is 180 it starts to go down
is it possible to keep going up until 359.99 then again 0?
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
Hi Ilan, using Klaus' code you obtain same result as your getangle corrected as follows:

B4X:
Sub getangle (p1 As vector, p2 As vector,p0 As vector) As Double
   Dim mr,ms As Double
   mr = (p1.x-p0.x) / (p1.y-p0.y)
   ms = (p2.x-p0.x) / (p2.y-p0.y)
   Log("AtanD: "&ATanD(Abs((mr-ms)/(1+(mr*ms)))))
   Return ATanD(Abs((mr-ms)/(1+(mr*ms))))
End Sub

fundamentally you missed the abs function.

udg

with klaus example i get from 0 to 180 and then start from 180 get back to 0 with your updated example i get from 0 to 9- and then back to 0 and then back to 90 and then back to 0 :)
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
A modified version:
B4X:
'Calculates the angle between 2 lines defined by 2 points each
'cordinates line 1 point1 : x11, y11
'cordinates line 1 point2 : x12, y12
'cordinates line 2 point1 : x21, y21
'cordinates line 2 point1 : x22, y22
'Degrees = True result in degrees, Degrees = False result in radians
'Mode360 = True 0 - 360  Mode360 = False 0 -180 - 0
Public Sub CalcAngleBetween2Lines(xx11 As Double, yy11 As Double, xx12 As Double, yy12 As Double, xx21 As Double, yy21 As Double, xx22 As Double, yy22 As Double, Degree As Boolean, Mode360 As Boolean) As Double
    Private Angle As Double
   
    If Mode360 = True Then
        Angle = ATan2D(y12 - y11, x12 - x11) - ATan2D(y22 - y21, x22 - x21)
        If Angle < 0 Then
            Angle = 360 + Angle
        End If
    Else
        Angle = Abs((ATan2D(y12 - y11, x12 - x11) - ATan2D(y22 - y21, x22 - x21)))
        If Angle > 180 Then
            Angle = 360 - Angle
        End If
    End If
   
    If Degree = True Then
        Return Angle
    Else
        Return Angle *cPI / 180
    End If
End Sub
And the test project.
 

Attachments

  • AngleBetween2Lines1.zip
    7.3 KB · Views: 202
Upvote 0

ilan

Expert
Licensed User
Longtime User
@klaus & @udg
Respect.jpg




thank you so much. klaus your code is perfect

i only changed 1 thing:

Angle = ATan2D(yy22 - yy21, xx22 - xx21)-ATan2D(yy12 - yy11, xx12 - xx11)

i wanted the degrees to go CW but everything is perfect thank you very much!!

and also lots of thanx to @udg. :)

(such great people here :))
 
Upvote 0

Beja

Expert
Licensed User
Longtime User
Klaus, UDG and Ilan
Thanks guys for this very useful solution.. I benefit from it as well.
If we added the length of the line to the angle then we can find absolute location on the screen with a single number, instead of the x,y coords. (in a special application)
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
If we added the length of the line to the angle

B4X:
Sub distance(x1 As Float, x2 As Float, y1 As Float, y2 As Float) As Double
    Return Sqrt(Power(x2-x1,2)+Power(y2-y1,2)) 'simple distance calculation
End Sub
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
is this what you wanted @Beja ?
 

Attachments

  • t8.zip
    1.3 KB · Views: 192
Upvote 0

ilan

Expert
Licensed User
Longtime User
@klaus and @udg look how beautiful your solution made my game :D

thank you so much guys!!! Big Respect from me :)

 
Last edited:
Upvote 0

klaus

Expert
Licensed User
Longtime User
@Beja
In geometry you have two coordinate systems:
- cartesian: which uses x and y
- polar: which uses angle and distance
Anyway, both need two coordinates.
Conversion:
B4X:
x = r * Cos(a)
y = r * Sin(a)

r = Sqrt(x * x + y * y)
a = ATan2(y, x)
 
Upvote 0
Top