Calculate bearing in MKMapView gives wrong value w

2019-01-29 07:00发布

I need to draw lines to demonstrate transportation of goods on apple maps. To clarify start- and end-point, I draw a little arrowhead on the destination side.The arrowhead is drawn separately but it is reversed in one case.

>-->-->-->- 

instead of

<--<--<--<-

I am using MKMapView and MKPolyline to draw lines. I am using MKOverlay to add direction arrows. The steps I follow are,

  1. calculate bearing of

    Source : CLLocationCoordinate2D(latitude: -33.8392932, longitude: 151.21519799999999) Destination: CLLocationCoordinate2D(latitude: 39.645516999999998, longitude: -104.598724)

    using the following function

    open static func getDirectionOf( _ supplyLineWithCoordinates: [CLLocationCoordinate2D]) -> CGFloat {
    guard let sourceCoordniate = supplyLineWithCoordinates.first,
        let destinationCoordniate = supplyLineWithCoordinates.last  else {
            fatalError("Coordinates of supply line not found")
    }
    let sourcePoint: MKMapPoint = MKMapPointForCoordinate(sourceCoordniate)
    let destinationPoint: MKMapPoint = MKMapPointForCoordinate(destinationCoordniate)
    let x: Double = destinationPoint.x - sourcePoint.x
    let y: Double = destinationPoint.y - sourcePoint.y
    var arrowDirection = CGFloat(fmod(atan2(y, x), 360.0))
    if arrowDirection < 0.0 {
        arrowDirection += 2 * .pi
    }
    return arrowDirection 
    

    }

  2. Rotate the arrow image and add it as the map overlay. The directions are calculated correctly in most of the cases, however, when I select the line shown below the direction is displayed 180 opposite. It starts from Sydney, Australia and ends in Denver, US

enter image description here

When trying to display the region with this two locations in mapView.setVisibleMapRect these region is not displayed, mapview tries to display region starting from Sydney (Australia) to Denver(US) through Asia and Europe, while it should display the map area I have attached above. If you have suggestions for optimisation, feel free to mention it.

I think this might be the reason, the direction should be calculated along the red line but it being calculated along the green line. Both lines are drawn by connecting same location coordinates in map. Any known workaround for this?

enter image description here

1条回答
迷人小祖宗
2楼-- · 2019-01-29 07:13

I solved it in a dirty way by converting coordinate to CGPoint and then calculating bearing between Points.

let destinationPoint = mapView.convert(destination, toPointTo: nil)
let sourcePoint = mapView.convert(source, toPointTo: nil)

let bearing = atan2(sourcePoint.y - destinationPoint.y, sourcePoint.x - destinationPoint.x) - .pi

Caution: This calculation will go wrong when map is rotated

查看更多
登录 后发表回答