Android Question Drawing equilateral triangle with latitude and longitude points

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Just in case somebody has worked this out already and saving some time:

Have a single line, based on two lat/lng coordinates on a geographical map.
Now I want to draw an equilateral triangle at one end of this line that points in the same direction as that line, so the bottom of that triangle
will be at 90 degrees in relation to that line.
So, the question is how do I calculate the 3 lat/lng coordinates of that triangle, based on the 2 lat/lng coordinates of that line?
For now the size of the triangle doesn't matter, I am sure I can work that out, once I have the principal calculation of this.

Thanks for any advice.

RBS
 

RB Smissaert

Well-Known Member
Licensed User
Longtime User
I think it will be simpler to do this with a rotated bitmap as I can get the angle of the initial line.
Will work it out.

RBS
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
Given that (presumably) it's for screen display and that thus near-enough-is-good-enough, I'd scale the longitude so that a degree of longitude was the same physical distance as a degree of latitude, effectively cartesian coordinates (x, y), and then it's easy, just add... probably easier to work an example through:

Say the pointy end of the line is (px, py) and the tail end is (tx, ty)

So the "size" of the line is (sx, sy) = (px - tx, py - ty)

You'd think we need to know the length of the line, by Pythagoras, but we don't.

Then let's say we make the edge length of the triangle one-tenth of that (1/10)

Work out the left-base point as (lx, ly) = (px - sy / 10 / 2, py - sx / 10 / 2)
the divide-by-twos are because the triangle base goes one-half left and one-half right from the end of the line

And the right-base point as (rx, ry) = (px + sy / 10 / 2, py + sx / 10 / 2)

And the sharp (ouch) point of the arrow triangle is (ox, oy) = (px + sx / 10 / 2 * sqrt(3), py + sy / 10 / 2 * sqrt(3))

I think.

(x, y) = (lon * cos(lat), lat)

which is close enough for smallish distances eg 1 degree is 100 km.
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Given that (presumably) it's for screen display and that thus near-enough-is-good-enough, I'd scale the longitude so that a degree of longitude was the same physical distance as a degree of latitude, effectively cartesian coordinates (x, y), and then it's easy, just add... probably easier to work an example through:

Say the pointy end of the line is (px, py) and the tail end is (tx, ty)

So the "size" of the line is (sx, sy) = (px - tx, py - ty)

You'd think we need to know the length of the line, by Pythagoras, but we don't.

Then let's say we make the edge length of the triangle one-tenth of that (1/10)

Work out the left-base point as (lx, ly) = (px - sy / 10 / 2, py - sx / 10 / 2)
the divide-by-twos are because the triangle base goes one-half left and one-half right from the end of the line

And the right-base point as (rx, ry) = (px + sy / 10 / 2, py + sx / 10 / 2)

And the sharp (ouch) point of the arrow triangle is (ox, oy) = (px + sx / 10 / 2 * sqrt(3), py + sy / 10 / 2 * sqrt(3))

I think.

(x, y) = (lon * cos(lat), lat)

which is close enough for smallish distances eg 1 degree is 100 km.
Thanks, will have a look at that.
For now I have gone with a B4XBitmap with rotation.
It is indeed just for a screen display and as you say, the direction doesn't have to be very precise.
It may need a bit of adjustment, but I get the rotation in this B4A Sub:

B4X:
Sub GetArrowRotation(tLL1 As TMapLatLng, tLL2 As TMapLatLng) As Int
   
    Dim dLatDiff As Double
    Dim dLngDiff As Double
    Dim dLatLngDiffRatio As Double
   
    dLatDiff = tLL2.fLat - tLL1.flat
    dLngDiff = tLL2.fLng - tLL1.flng
    dLatLngDiffRatio = Abs(dLatDiff) / Abs(dLngDiff)
   
    If dLatDiff < 0 Then
        'going down
        If dLngDiff > 0 Then
            'going down and right 90 to 180
            If dLatLngDiffRatio <= 1 Then
                'more right than down
                Return 90 + dLatLngDiffRatio * 45
            Else
                'more down than right
                Return 135 + Min((dLatLngDiffRatio / 20) * 45, 45)
            End If
        Else
            'going down and left 180 to 270
            If dLatLngDiffRatio <= 1 Then
                'more left than down
                Return 270 - dLatLngDiffRatio * 45
            Else
                'more down than left
                Return 225 + Min((dLatLngDiffRatio / 20) * 45, 45)
            End If
        End If
    Else
        'going up
        If dLngDiff > 0 Then
            'going up and right 0 to 90
            If dLatLngDiffRatio <= 1 Then
                'more right than up
                Return 90 - dLatLngDiffRatio * 45
            Else
                'more up than right
                Return 45 - Min((dLatLngDiffRatio / 20) * 45, 45)
            End If
        Else
            'going up and left 270 to 360
            If dLatLngDiffRatio <= 1 Then
                'more left than up
                Return 270 + dLatLngDiffRatio * 45
            Else
                'more up than left
                Return 315 + Min((dLatLngDiffRatio / 20) * 45, 45)
            End If
        End If
    End If
   
End Sub

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Thanks, will have a look at that.
For now I have gone with a B4XBitmap with rotation.
It is indeed just for a screen display and as you say, the direction doesn't have to be very precise.
It may need a bit of adjustment, but I get the rotation in this B4A Sub:

B4X:
Sub GetArrowRotation(tLL1 As TMapLatLng, tLL2 As TMapLatLng) As Int
  
    Dim dLatDiff As Double
    Dim dLngDiff As Double
    Dim dLatLngDiffRatio As Double
  
    dLatDiff = tLL2.fLat - tLL1.flat
    dLngDiff = tLL2.fLng - tLL1.flng
    dLatLngDiffRatio = Abs(dLatDiff) / Abs(dLngDiff)
  
    If dLatDiff < 0 Then
        'going down
        If dLngDiff > 0 Then
            'going down and right 90 to 180
            If dLatLngDiffRatio <= 1 Then
                'more right than down
                Return 90 + dLatLngDiffRatio * 45
            Else
                'more down than right
                Return 135 + Min((dLatLngDiffRatio / 20) * 45, 45)
            End If
        Else
            'going down and left 180 to 270
            If dLatLngDiffRatio <= 1 Then
                'more left than down
                Return 270 - dLatLngDiffRatio * 45
            Else
                'more down than left
                Return 225 + Min((dLatLngDiffRatio / 20) * 45, 45)
            End If
        End If
    Else
        'going up
        If dLngDiff > 0 Then
            'going up and right 0 to 90
            If dLatLngDiffRatio <= 1 Then
                'more right than up
                Return 90 - dLatLngDiffRatio * 45
            Else
                'more up than right
                Return 45 - Min((dLatLngDiffRatio / 20) * 45, 45)
            End If
        Else
            'going up and left 270 to 360
            If dLatLngDiffRatio <= 1 Then
                'more left than up
                Return 270 + dLatLngDiffRatio * 45
            Else
                'more up than left
                Return 315 + Min((dLatLngDiffRatio / 20) * 45, 45)
            End If
        End If
    End If
  
End Sub

RBS
This gives a bit better results:

B4X:
Sub GetArrowRotation(tLL1 As TMapLatLng, tLL2 As TMapLatLng) As Int
    
    Dim dLatDiff As Double
    Dim dLngDiff As Double
    Dim dLatLngDiffRatio As Double
    Dim iMaxLatLngDiffRatio As Int = 6
    
    dLatDiff = tLL2.fLat - tLL1.flat
    dLngDiff = tLL2.fLng - tLL1.flng
    dLatLngDiffRatio = Abs(dLatDiff) / Abs(dLngDiff)
    
    Log("dLatLngDiffRatio: " & dLatLngDiffRatio)
    
    If dLatDiff < 0 Then
        'going down
        If dLngDiff > 0 Then
            'going down and right 90 to 180
            If dLatLngDiffRatio <= 1 Then
                'more right than down
                Return 90 + dLatLngDiffRatio * 45
            Else
                'more down than right
                Return 135 + Min((dLatLngDiffRatio / iMaxLatLngDiffRatio) * 45, 45)
            End If
        Else
            'going down and left 180 to 270
            If dLatLngDiffRatio <= 1 Then
                'more left than down
                Return 270 - dLatLngDiffRatio * 45
            Else
                'more down than left
                Return 225 + Min((dLatLngDiffRatio / iMaxLatLngDiffRatio) * 45, 45)
            End If
        End If
    Else
        'going up
        If dLngDiff > 0 Then
            'going up and right 0 to 90
            If dLatLngDiffRatio <= 1 Then
                'more right than up
                Return 90 - dLatLngDiffRatio * 45
            Else
                'more up than right
                Return 45 - Min((dLatLngDiffRatio / iMaxLatLngDiffRatio) * 45, 45)
            End If
        Else
            'going up and left 270 to 360
            If dLatLngDiffRatio <= 1 Then
                'more left than up
                Return 270 + dLatLngDiffRatio * 45
            Else
                'more up than left
                Return 315 + Min((dLatLngDiffRatio / iMaxLatLngDiffRatio) * 45, 45)
            End If
        End If
    End If
    
End Sub

I do have a formula for the angle of the lat/lng line:

'Dim dAngle As Double = ACos(SinD(tLL1.fLat) * SinD(tLL2.fLat) + CosD(tLL1.fLat) * CosD(tLL2.fLat) * CosD(tLL2.fLng - tLL1.fLng))

But not sure this is right and can't translate the produced values to rotation to be used for the bitmap.

RBS
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
Test
B4X:
Public Sub CalculateThirdEquilateralVertex(lat1 As Double, lon1 As Double, lat2 As Double, lon2 As Double) As List
    Dim METERS_PER_DEGREE_LATITUDE As Double = 111320
    Dim Middle_latitude As Double = (lat1 + lat2) / 2
    Dim METERS_PER_DEGREE_LONGITUDE As Double = 111320 * Cos(Middle_latitude * cPI / 180)
  
    Dim deltaX As Double = (lon2 - lon1) * METERS_PER_DEGREE_LONGITUDE
    Dim deltaY As Double = (lat2 - lat1) * METERS_PER_DEGREE_LATITUDE
  
    Dim a As Double = Sqrt(Power(deltaX, 2) + Power(deltaY, 2))
    Dim h As Double = (Sqrt(3) / 2) * a
  
    Dim mx As Double = deltaX / 2
    Dim my As Double = deltaY / 2
  
    Dim vx As Double = -deltaY
    Dim vy As Double = deltaX
    Dim moduloV As Double = Sqrt(Power(vx, 2) + Power(vy, 2))
    Dim ux As Double = vx / moduloV
    Dim uy As Double = vy / moduloV
  
    Dim cx1_m As Double = mx + h * ux
    Dim cy1_m As Double = my + h * uy
  
    Dim cx2_m As Double = mx - h * ux
    Dim cy2_m As Double = my - h * uy
  
    Dim cx1_lat As Double = lat1 + (cy1_m / METERS_PER_DEGREE_LATITUDE)
    Dim cx1_lon As Double = lon1 + (cx1_m / METERS_PER_DEGREE_LONGITUDE)
  
    Dim cx2_lat As Double = lat1 + (cy2_m / METERS_PER_DEGREE_LATITUDE)
    Dim cx2_lon As Double = lon1 + (cx2_m / METERS_PER_DEGREE_LONGITUDE)
  
    Dim Result As List
    Result.Initialize
    Result.Add(Array As Double(cx1_lat, cx1_lon))
    Result.Add(Array As Double(cx2_lat, cx2_lon))
  
    Return Result
End Sub

Note:
Use drawing: Polygon or polyline, boundsBuilder for camera view

EDIT:
If you want measurements in kilometers, change the measurement variable

B4X:
    Dim KILOMETERS_PER_DEGREE_LATITUDE As Double = 111.32
    Dim Middle_Latitude As Double = (lat1 + lat2) / 2
    Dim KILOMETERS_PER_DEGREE_LONGITUDE As Double = 111.32 * Cos(Middle_Latitude * cPI / 180)
 
Last edited:
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Test
B4X:
Public Sub CalculateThirdEquilateralVertex(lat1 As Double, lon1 As Double, lat2 As Double, lon2 As Double) As List
    Dim METERS_PER_DEGREE_LATITUDE As Double = 111320
    Dim Middle_latitude As Double = (lat1 + lat2) / 2
    Dim METERS_PER_DEGREE_LONGITUDE As Double = 111320 * Cos(Middle_latitude * cPI / 180)
  
    Dim deltaX As Double = (lon2 - lon1) * METERS_PER_DEGREE_LONGITUDE
    Dim deltaY As Double = (lat2 - lat1) * METERS_PER_DEGREE_LATITUDE
  
    Dim a As Double = Sqrt(Power(deltaX, 2) + Power(deltaY, 2))
    Dim h As Double = (Sqrt(3) / 2) * a
  
    Dim mx As Double = deltaX / 2
    Dim my As Double = deltaY / 2
  
    Dim vx As Double = -deltaY
    Dim vy As Double = deltaX
    Dim moduloV As Double = Sqrt(Power(vx, 2) + Power(vy, 2))
    Dim ux As Double = vx / moduloV
    Dim uy As Double = vy / moduloV
  
    Dim cx1_m As Double = mx + h * ux
    Dim cy1_m As Double = my + h * uy
  
    Dim cx2_m As Double = mx - h * ux
    Dim cy2_m As Double = my - h * uy
  
    Dim cx1_lat As Double = lat1 + (cy1_m / METERS_PER_DEGREE_LATITUDE)
    Dim cx1_lon As Double = lon1 + (cx1_m / METERS_PER_DEGREE_LONGITUDE)
  
    Dim cx2_lat As Double = lat1 + (cy2_m / METERS_PER_DEGREE_LATITUDE)
    Dim cx2_lon As Double = lon1 + (cx2_m / METERS_PER_DEGREE_LONGITUDE)
  
    Dim Result As List
    Result.Initialize
    Result.Add(Array As Double(cx1_lat, cx1_lon))
    Result.Add(Array As Double(cx2_lat, cx2_lon))
  
    Return Result
End Sub

Note:
Use drawing: Polygon or polyline, boundsBuilder for camera view
Thanks, will have a look at that as well.

RBS
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
Just for fun, here's another example using the CalculateThirdEquilateralVertex function, converting the coordinates to draw a bitmap.
B4X:
    Dim bmp As B4XBitmap = DrawEquilateralTriangleOnBitmap(19.4326, -99.1332, 19.4426, -99.1432)
    ImageView1.SetBitmap(bmp)
B4X:
 Dim vertices As List = CalculateThirdEquilateralVertex(latA, lonA, latB, lonB)
 Dim vertice1 As Map = vertices.Get(0)
1754071947484.png


B4X:
Dim vertices As List = CalculateThirdEquilateralVertex(latA, lonA, latB, lonB)
Dim vertice1 As Map = vertices.Get(1)
1754072045032.png
 
Last edited:
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Just for fun, here's another example using the CalculateThirdEquilateralVertex function, converting the coordinates to draw a bitmap.
B4X:
    Dim bmp As B4XBitmap = DrawEquilateralTriangleOnBitmap(19.4326, -99.1332, 19.4426, -99.1432)
    ImageView1.SetBitmap(bmp)
B4X:
 Dim vertices As List = CalculateThirdEquilateralVertex(latA, lonA, latB, lonB)
 Dim vertice1 As Map = vertices.Get(0)
View attachment 165750

B4X:
Dim vertices As List = CalculateThirdEquilateralVertex(latA, lonA, latB, lonB)
Dim vertice1 As Map = vertices.Get(1)
View attachment 165751
Thanks, will also have a look at that one.

RBS
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
Test
B4X:
Public Sub CalculateThirdEquilateralVertex(lat1 As Double, lon1 As Double, lat2 As Double, lon2 As Double) As List
    Dim METERS_PER_DEGREE_LATITUDE As Double = 111320
    Dim Middle_latitude As Double = (lat1 + lat2) / 2
    Dim METERS_PER_DEGREE_LONGITUDE As Double = 111320 * Cos(Middle_latitude * cPI / 180)
 
    Dim deltaX As Double = (lon2 - lon1) * METERS_PER_DEGREE_LONGITUDE
    Dim deltaY As Double = (lat2 - lat1) * METERS_PER_DEGREE_LATITUDE
 
    Dim a As Double = Sqrt(Power(deltaX, 2) + Power(deltaY, 2))
    Dim h As Double = (Sqrt(3) / 2) * a
 
    Dim mx As Double = deltaX / 2
    Dim my As Double = deltaY / 2
 
    Dim vx As Double = -deltaY
    Dim vy As Double = deltaX
    Dim moduloV As Double = Sqrt(Power(vx, 2) + Power(vy, 2))
    Dim ux As Double = vx / moduloV
    Dim uy As Double = vy / moduloV
 
    Dim cx1_m As Double = mx + h * ux
    Dim cy1_m As Double = my + h * uy
 
    Dim cx2_m As Double = mx - h * ux
    Dim cy2_m As Double = my - h * uy
 
    Dim cx1_lat As Double = lat1 + (cy1_m / METERS_PER_DEGREE_LATITUDE)
    Dim cx1_lon As Double = lon1 + (cx1_m / METERS_PER_DEGREE_LONGITUDE)
 
    Dim cx2_lat As Double = lat1 + (cy2_m / METERS_PER_DEGREE_LATITUDE)
    Dim cx2_lon As Double = lon1 + (cx2_m / METERS_PER_DEGREE_LONGITUDE)
 
    Dim Result As List
    Result.Initialize
    Result.Add(Array As Double(cx1_lat, cx1_lon))
    Result.Add(Array As Double(cx2_lat, cx2_lon))
 
    Return Result
End Sub

Note:
Use drawing: Polygon or polyline, boundsBuilder for camera view

EDIT:
If you want measurements in kilometers, change the measurement variable

B4X:
    Dim KILOMETERS_PER_DEGREE_LATITUDE As Double = 111.32
    Dim Middle_Latitude As Double = (lat1 + lat2) / 2
    Dim KILOMETERS_PER_DEGREE_LONGITUDE As Double = 111.32 * Cos(Middle_Latitude * cPI / 180)

I am still thinking that: once you've converted the coordinates into equal scale (eg, metres or pixels), then you don't need to do any (square) rooting.

But also that: if it ain't broke, don't fix it. 🍻

A minor improvement of clarity would be:

B4X:
Dim KILOMETERS_PER_DEGREE_LATITUDE As Double = 40000 / 360    'or 10000 / 90

because it is more (nominally) accurate and also visually correct, assuming that the original definition of the metre as being 1/10,000,000th of the distance from north pole to equator through Paris is ingrained in your mental list of measurement units.

Lol, similarly also:

B4X:
Dim NAUTICAL_MILES_PER_DEGREE_LATITUDE As Double = 60

although curiously this is no longer exactly correct after the nautical mile was redefined to be 1852 metres.
 
Last edited:
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Just for fun, here's another example using the CalculateThirdEquilateralVertex function, converting the coordinates to draw a bitmap.
B4X:
    Dim bmp As B4XBitmap = DrawEquilateralTriangleOnBitmap(19.4326, -99.1332, 19.4426, -99.1432)
    ImageView1.SetBitmap(bmp)
B4X:
 Dim vertices As List = CalculateThirdEquilateralVertex(latA, lonA, latB, lonB)
 Dim vertice1 As Map = vertices.Get(0)
View attachment 165750

B4X:
Dim vertices As List = CalculateThirdEquilateralVertex(latA, lonA, latB, lonB)
Dim vertice1 As Map = vertices.Get(1)
View attachment 165751
Can you post code that gets the rotation of a lat/lng point line (so 2 lat/lng points)?
By rotation I mean a value between 0 and 360 (degrees).
I have that (as posted) and it is OK, but perhaps you have code that gets the rotation value
more accurate.

RBS
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
Do you want to include the angle between 0 and 360 degrees to obtain the third point corresponding to that rotation?

And if your solution works for you, why do you want it?
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Do you want to include the angle between 0 and 360 degrees to obtain the third point corresponding to that rotation?

And if your solution works for you, why do you want it?
I just want the rotation in degrees (0 to 360) to rotate a bitmap.
My solution works OK, but the rotated bitmap doesn't have the exact same rotation as the lat/lng line, but not far off.

I a few examples from the net, eg:

B4X:
Sub GetArrowRotation4(tLL1 As TMapLatLng, tLL2 As TMapLatLng) As Int
    
'    Let's say you want to find the rotation angle of a line connecting two points:
'    Point A: Latitude 34°N, Longitude 118°W (Los Angeles)
'    Point B: Latitude 37°N, Longitude 122°W (San Francisco)
'    Convert latitudes And longitudes To radians:
'    lat1 = 34 * π / 180
'    lon1 = -118 * π / 180
'    lat2 = 37 * π / 180
'    lon2 = -122 * π / 180
'    Calculate differences:
'    Δlat = lat2 - lat1
'    Δlon = lon2 - lon1
'    Calculate the bearing in radians:
'    bearingRad = ATan2(Δlon * Cos(lat2), Δlat)
'    Convert To degrees:
'    bearingDeg = bearingRad * 180 / π
    
    Dim dLatDiff As Double
    Dim dLngDiff As Double
    Dim dBearingRad As Double
    Dim iRotation As Int
    Dim dToRad As Double = dPi / 180
    Dim dY1 As Double = tLL1.fLat * dToRad
    Dim dY2 As Double = tLL2.fLat * dToRad
    Dim dX1 As Double = tLL1.fLng * dToRad
    Dim dX2 As Double = tLL2.fLng * dToRad
    
    dLatDiff = dY2 - dY1
    dLngDiff = dX2 - dX1
    dBearingRad = ATan2(dLngDiff * Cos(dY2), dLatDiff)
    iRotation = dBearingRad * dToRad
    
    Return iRotation
    
End Sub

But can't get it to work yet.

RBS
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
I just want the rotation in degrees (0 to 360) to rotate a bitmap.
My solution works OK, but the rotated bitmap doesn't have the exact same rotation as the lat/lng line, but not far off.

I a few examples from the net, eg:

B4X:
Sub GetArrowRotation4(tLL1 As TMapLatLng, tLL2 As TMapLatLng) As Int
   
'    Let's say you want to find the rotation angle of a line connecting two points:
'    Point A: Latitude 34°N, Longitude 118°W (Los Angeles)
'    Point B: Latitude 37°N, Longitude 122°W (San Francisco)
'    Convert latitudes And longitudes To radians:
'    lat1 = 34 * π / 180
'    lon1 = -118 * π / 180
'    lat2 = 37 * π / 180
'    lon2 = -122 * π / 180
'    Calculate differences:
'    Δlat = lat2 - lat1
'    Δlon = lon2 - lon1
'    Calculate the bearing in radians:
'    bearingRad = ATan2(Δlon * Cos(lat2), Δlat)
'    Convert To degrees:
'    bearingDeg = bearingRad * 180 / π
   
    Dim dLatDiff As Double
    Dim dLngDiff As Double
    Dim dBearingRad As Double
    Dim iRotation As Int
    Dim dToRad As Double = dPi / 180
    Dim dY1 As Double = tLL1.fLat * dToRad
    Dim dY2 As Double = tLL2.fLat * dToRad
    Dim dX1 As Double = tLL1.fLng * dToRad
    Dim dX2 As Double = tLL2.fLng * dToRad
   
    dLatDiff = dY2 - dY1
    dLngDiff = dX2 - dX1
    dBearingRad = ATan2(dLngDiff * Cos(dY2), dLatDiff)
    iRotation = dBearingRad * dToRad
   
    Return iRotation
   
End Sub

But can't get it to work yet.

RBS
?
It is of utilitarian class.
B4X:
Sub Process_Globals
    Type Coordenates (Latitude As Double, Longitude As Double)
End Sub
B4X:
Public Sub GetAngleCoordenates(p1 As Coordenates, p2 As Coordenates) As Double
    Dim toRadian = cPI / 180 As Double
    Dim dLng As Double = (p2.Longitude - p1.Longitude) * toRadian
    Dim Lat1 As Double = p1.Latitude * toRadian
    Dim Lat2 As Double = p2.Latitude * toRadian
    Dim y As Double = Sin(dLng) * Cos(Lat2)
    Dim x As Double = Cos(Lat1) * Sin(Lat2) - Sin(Lat1) * Cos(Lat2) * Cos(dLng)
    Dim Angle As Double = ATan2(y,x) * toRadian
    If Angle < 0 Then
        Angle = 360 + Angle
    End If
    Return Abs(Round(Angle))
End Sub
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
?
It is of utilitarian class.
B4X:
Sub Process_Globals
    Type Coordenates (Latitude As Double, Longitude As Double)
End Sub
B4X:
Public Sub GetAngleCoordenates(p1 As Coordenates, p2 As Coordenates) As Double
    Dim toRadian = cPI / 180 As Double
    Dim dLng As Double = (p2.Longitude - p1.Longitude) * toRadian
    Dim Lat1 As Double = p1.Latitude * toRadian
    Dim Lat2 As Double = p2.Latitude * toRadian
    Dim y As Double = Sin(dLng) * Cos(Lat2)
    Dim x As Double = Cos(Lat1) * Sin(Lat2) - Sin(Lat1) * Cos(Lat2) * Cos(dLng)
    Dim Angle As Double = ATan2(y,x) * toRadian
    If Angle < 0 Then
        Angle = 360 + Angle
    End If
    Return Abs(Round(Angle))
End Sub
Can't get it to work yet.

B4X:
Sub GetArrowRotation5(tLL1 As TMapLatLng, tLL2 As TMapLatLng) As Int
    
    Log(tLL1.fLat & "," & tLL1.fLng & " _ " & tLL2.fLat & "," & tLL2.fLng)
    
    Dim toRadian = cPI / 180 As Double
    Dim dLng As Double = (tLL2.fLng - tLL1.flng) * toRadian
    Dim Lat1 As Double = tLL1.flat * toRadian
    Dim Lat2 As Double = tLL2.flat * toRadian
    Dim y As Double = Sin(dLng) * Cos(Lat2)
    Dim x As Double = Cos(Lat1) * Sin(Lat2) - Sin(Lat1) * Cos(Lat2) * Cos(dLng)
    Dim Angle As Double = ATan2(y,x) * toRadian
    
    Log(Angle)
    
    If Angle < 0 Then
        Angle = 360 + Angle
    End If
    
    Return Abs(Round(Angle))
    
End Sub

Log shows this:

52.62160980510403,-2.153019905090332 _ 52.620550308374774,-2.153348922729492
-0.051578891819494155

RBS
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Try this:
B4X:
    Private Lat1, Lat2, Lon1, Lon2 As Double
    Private x1, y1, x2, y2, angle As Double
    Lat1 = 52.62160980510403
    Lon1 = -2.153019905090332
    Lat2 = 52.620550308374774
    Lon2 =-2.153348922729492
    x1 = Lon1 * CosD(Lat1) 'converts Lon to a distance
    y1 = Lat1
    x2 = Lon2 * CosD(Lat2) 'converts Lon to a distance
    y2 = Lat2
    angle = ATan2D((y2 - y1), (x2 - x1)) 'trigonometric angle 3 o'clock, positve couterclockwise
    angle = ATan2D((y1 - y2), (x2 - x1)) 'trigonometric angle 3 o'clock, positve clockwise
    angle = angle + 90 'angle 12 o'clock, positve clockwise
    angle = angle + 360 'only positive values
    angle = angle Mod 360 'values between 0 and 360
    
    angle = ATan2D((y1 - y2), (x2 - x1)) + 90 + 360 Mod 360 'the angle in one line
    Log(angle)
    angle = ATan2D((Lat1 - Lat2), (Lon2 * CosD(Lat2) - Lon1 * CosD(Lat1))) + 90 + 360 Mod 360 'all in one line
    Log(angle)
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Try this:
B4X:
    Private Lat1, Lat2, Lon1, Lon2 As Double
    Private x1, y1, x2, y2, angle As Double
    Lat1 = 52.62160980510403
    Lon1 = -2.153019905090332
    Lat2 = 52.620550308374774
    Lon2 =-2.153348922729492
    x1 = Lon1 * CosD(Lat1) 'converts Lon to a distance
    y1 = Lat1
    x2 = Lon2 * CosD(Lat2) 'converts Lon to a distance
    y2 = Lat2
    angle = ATan2D((y2 - y1), (x2 - x1)) 'trigonometric angle 3 o'clock, positve couterclockwise
    angle = ATan2D((y1 - y2), (x2 - x1)) 'trigonometric angle 3 o'clock, positve clockwise
    angle = angle + 90 'angle 12 o'clock, positve clockwise
    angle = angle + 360 'only positive values
    angle = angle Mod 360 'values between 0 and 360
   
    angle = ATan2D((y1 - y2), (x2 - x1)) + 90 + 360 Mod 360 'the angle in one line
    Log(angle)
    angle = ATan2D((Lat1 - Lat2), (Lon2 * CosD(Lat2) - Lon1 * CosD(Lat1))) + 90 + 360 Mod 360 'all in one line
    Log(angle)
Thanks, will give that a try.

Not sure what is happening here:

angle = ATan2D((y2 - y1), (x2 - x1)) 'trigonometric angle 3 o'clock, positve couterclockwise
angle = ATan2D((y1 - y2), (x2 - x1)) 'trigonometric angle 3 o'clock, positve clockwise

Should there be 2 different angles, so 2 different variables?
Otherwise the first of these lines can be left out.

RBS
 
Upvote 0
Top