Determining Midpoint Between 2 Coordinates

后端 未结 5 1425
深忆病人
深忆病人 2020-12-15 04:55

I am trying to determine the midpoint between two locations in an MKMapView. I am following the method outlined here (and here) and rewrote it in Objective-C,

相关标签:
5条回答
  • 2020-12-15 05:09

    I think you are over thinking it a bit. Just do:

    float lon3 = ((lon1 + lon2) / 2)
    float lat3 = ((lat1 + lat2) / 2)
    

    lat3 and lon3 will be the center point.

    0 讨论(0)
  • 2020-12-15 05:17

    In case someone need code in Swift, I have written library function in Swift to calculate the midpoint between MULTIPLE coordinates:

    //        /** Degrees to Radian **/
    class func degreeToRadian(angle:CLLocationDegrees) -> CGFloat {
        return (  (CGFloat(angle)) / 180.0 * CGFloat(M_PI)  )
    }
    
    //        /** Radians to Degrees **/
    class func radianToDegree(radian:CGFloat) -> CLLocationDegrees {
        return CLLocationDegrees(  radian * CGFloat(180.0 / M_PI)  )
    }
    
    class func middlePointOfListMarkers(listCoords: [CLLocationCoordinate2D]) -> CLLocationCoordinate2D {
    
        var x = 0.0 as CGFloat
        var y = 0.0 as CGFloat
        var z = 0.0 as CGFloat
    
        for coordinate in listCoords{
            var lat:CGFloat = degreeToRadian(coordinate.latitude)
            var lon:CGFloat = degreeToRadian(coordinate.longitude)
            x = x + cos(lat) * cos(lon)
            y = y + cos(lat) * sin(lon)
            z = z + sin(lat)
        }
    
        x = x/CGFloat(listCoords.count)
        y = y/CGFloat(listCoords.count)
        z = z/CGFloat(listCoords.count)
    
        var resultLon: CGFloat = atan2(y, x)
        var resultHyp: CGFloat = sqrt(x*x+y*y)
        var resultLat:CGFloat = atan2(z, resultHyp)
    
        var newLat = radianToDegree(resultLat)
        var newLon = radianToDegree(resultLon)
        var result:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: newLat, longitude: newLon)
    
        return result
    
    }
    

    Detailed answer can be found here

    Updated For Swift 5

    func geographicMidpoint(betweenCoordinates coordinates: [CLLocationCoordinate2D]) -> CLLocationCoordinate2D {
    
        guard coordinates.count > 1 else {
            return coordinates.first ?? // return the only coordinate
                CLLocationCoordinate2D(latitude: 0, longitude: 0) // return null island if no coordinates were given
        }
    
        var x = Double(0)
        var y = Double(0)
        var z = Double(0)
    
        for coordinate in coordinates {
            let lat = coordinate.latitude.toRadians()
            let lon = coordinate.longitude.toRadians()
            x += cos(lat) * cos(lon)
            y += cos(lat) * sin(lon)
            z += sin(lat)
        }
    
        x /= Double(coordinates.count)
        y /= Double(coordinates.count)
        z /= Double(coordinates.count)
    
        let lon = atan2(y, x)
        let hyp = sqrt(x * x + y * y)
        let lat = atan2(z, hyp)
    
        return CLLocationCoordinate2D(latitude: lat.toDegrees(), longitude: lon.toDegrees())
    }
    

    }

    0 讨论(0)
  • 2020-12-15 05:18

    For swift users, corrected variant as @dinjas suggest

    import Foundation
    import MapKit
    extension CLLocationCoordinate2D {
        // MARK: CLLocationCoordinate2D+MidPoint
        func middleLocationWith(location:CLLocationCoordinate2D) -> CLLocationCoordinate2D {
    
            let lon1 = longitude * M_PI / 180
            let lon2 = location.longitude * M_PI / 180
            let lat1 = latitude * M_PI / 180
            let lat2 = location.latitude * M_PI / 180
            let dLon = lon2 - lon1
            let x = cos(lat2) * cos(dLon)
            let y = cos(lat2) * sin(dLon)
    
            let lat3 = atan2( sin(lat1) + sin(lat2), sqrt((cos(lat1) + x) * (cos(lat1) + x) + y * y) )
            let lon3 = lon1 + atan2(y, cos(lat1) + x)
    
            let center:CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat3 * 180 / M_PI, lon3 * 180 / M_PI)
            return center
        }
    }
    
    0 讨论(0)
  • 2020-12-15 05:19

    It's important to say that the formula the OP used to calculate geographic midpoint is based on this formula which explains the cos/sin/sqrt calculation.

    This formula will give you the geographic midpoint for any long distance including the four quarters and the prime meridian.

    But, if your calculation is for short-range around 1 Kilometer, using a simple average will produce the same midpoint results. i.e:

    let firstPoint = CLLocation(....)
    let secondPoint = CLLocation(....)
    
    let midPointLat = (firstPoint.coordinate.latitude + secondPoint.coordinate.latitude) / 2
    let midPointLong = (firstPoint.coordinate.longitude + secondPoint.coordinate.longitude) / 2
    

    You can actually use it for 10km but expect a deviation - if you only need an estimation for a short range midpoint with a fast solution it will be sufficient.

    0 讨论(0)
  • 2020-12-15 05:31

    Just a hunch, but I noticed your lon2 and lat2 variables are being computed with M_PI/100 and not M_PI/180.

    double lon1 = _lo1.longitude * M_PI / 180;
    double lon2 = _loc2.longitude * M_PI / 100;
    
    double lat1 = _lo1.latitude * M_PI / 180;
    double lat2 = _loc2.latitude * M_PI / 100;
    

    Changing those to 180 might help you out a bit.

    0 讨论(0)
提交回复
热议问题