1

I'm trying to find out how to calculate the "west-east-facing" distance and the "north-south-facing" distance between two points respectively given the coordinates of the two points (with latitude and longitude), in order to find out the degree in which the line differs from the northern direction. In short I need to calculate x and y in meters in order to get the degree of alpha, when x and y are given by longitude and latitude.

I know CLLocation has a function to calculate the distance between two points:

distance(from location: CLLocation) -> CLLocationDistance

and I tried to open the source code of that function in order to figure out how to separate the two components but I did not find out how to open that code.

jscs
  • 63,694
  • 13
  • 151
  • 195
A. Claesson
  • 529
  • 4
  • 16

3 Answers3

1

You can use this

func getDistanceAndAngle(positionA: CLLocation, positionB: CLLocation) -> (Float, Float, Float){

    let distanceInMeters = Float(positionA.distance(from: positionB)) // result is in meters
    print(distanceInMeters)
    //search for the degree
    let angle = bearingFromLocation(fromLocation: positionA.coordinate, toLocation: positionB.coordinate)
    print("ANGLE", angle)
    let xDistance = abs(distanceInMeters * cos(DegreesToRadians(degrees: angle)))
    let yDistance = abs(distanceInMeters * sin(DegreesToRadians(degrees: angle)))

    return (xDistance,yDistance,angle)
}


func bearingFromLocation(fromLocation:CLLocationCoordinate2D, toLocation: CLLocationCoordinate2D)-> Float{

    let lat1 = DegreesToRadians(degrees: Float(fromLocation.latitude))
    let lon1 = DegreesToRadians(degrees: Float(fromLocation.longitude))

    let lat2 = DegreesToRadians(degrees: Float(toLocation.latitude))
    let lon2 = DegreesToRadians(degrees: Float(toLocation.longitude))

    let dLon = lon2 - lon1

    let y = sin(dLon) * cos(lat2)
    let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon)
    let radiansBearing = atan2(y, x)
    print("radian", radiansBearing)
    let degreesBearing = RadiansToDegrees(radians: radiansBearing)
    print("deg", degreesBearing)

    if (degreesBearing >= 0) {
        return degreesBearing
    } else {
        return degreesBearing + 360.0
    }
}

func DegreesToRadians(degrees: Float)->Float {return degrees * Float.pi / 180.0}
func RadiansToDegrees(radians: Float)->Float {return radians * 180.0/Float.pi}

notes: the angle is from north to east so north is 0 degree and east is 90 degree. the X and Y is always positive. So if you want to make it negative to the left and down, you can try to put use degree to make it right.

Darwin Harianto
  • 435
  • 4
  • 15
  • I need to be able to calculate the angle regardless of where the 2nd coordinate is placed (i.e. it can be placed in every quadrant), and I'm not sure I understand what you mean by "put use degree to make it right" – A. Claesson Feb 12 '19 at 09:55
  • yes, it can calculate every quadrant. for 0 to 90 degree, x and y is positive for 90 to 180 degree x is positive and y is negative. for 180 to 270 degree both are negative. for 270 to 360 degree x is negative and y is positive. I mean that I intentionally make that x and y is positive, because distance can't be negative. If you want to determine that west and south is negative, you can make use the degree to put the negative sign. – Darwin Harianto Feb 13 '19 at 01:53
0

You can convert point1 and point2 to MKMapPoint. It's gives you coordinates which is projected map in 2D plane. Then you can eaisily get difference of x's and y's.. And using simple math, you can calculate the alpha value. You can initialize MKMapPoint with CLLocationCoordinate2D.

https://developer.apple.com/documentation/mapkit/mkmappoint

Said Alır
  • 170
  • 2
  • 15
0

Assuming we have:

let locationA = CLLocation(..)
let locationB = CLLocation(..)

I would probably still want to use Apple's provided functions and create new locations that only differ in latitude or longitude. Something like:

let latitudeA = CLLocation(latitude: locationA.latitude, longitude: locationA.longitude)
// notice I use latitude from B but KEEP longitude from A to keep them parallel)
let latitudeB = CLLocation(latitude: locationB.latitude, longitude: locationA.longitude)
let northSouthDistance = latitudeA.distance(from: latitudeB)

etc

gadu
  • 1,816
  • 1
  • 17
  • 31
  • This seems to be the easiset way to go about it, however I'm not sure how I would handle "negative coordinates" in order to later calculate the correct angle as I presume the distance(from:)-method returns the absolute value of the distance. Assuming we have a coordinate system with locationA in the origin, locationB should be able to be placed in every quadrant and not just in the first. – A. Claesson Feb 12 '19 at 09:58
  • fair, id try looking on stack overflow for something along the lines of "calculating angle between two CLLocations", I found this for example: https://stackoverflow.com/questions/3925942/cllocation-category-for-calculating-bearing-w-haversine-function – gadu Feb 13 '19 at 17:25
  • oh I see the accepted answer just includes this, note this prob will break when switching like north-south on the poles. since it'll go from +180 degrees to -179 degrees which should really just be a one degree change. – gadu Feb 13 '19 at 17:28