1
votes

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
This fmod(atan2(y, x), 360.0)) // in radians raises two questions for me: 1) the comment says radians, but 360.0 is obviously in degrees; 2) The expression looks as if it would return a value in the interval 0 to 360, but do you want -180 to 180 perhaps? Also, shouldn't the arrows go along with the line? In your example picture, they point somewhere else.Arndt Jonasson
Sorry, the comment saying in radians was wrong, I removed it. Since lines could be in any direction so 0 to 360 will be preferred. The arrows should go along the line, that's I bug I am seeking solution :) It is showing exact direction and goes along with the line in all other cases.Abin Baby
I would add debug printout showing the values of sourcePoint, destinationPoint, and arrowDirection.Arndt Jonasson
I tried printing values but I could not notice anything from it since it calculates right direction for all other MKPolylines. I have added more information to questionAbin Baby
Looking closer at the values used for a calculation when something incorrect happens, is an important part of debugging. You must be able to notice something about how the wrong values are calculated.Arndt Jonasson

1 Answers

0
votes

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