webmastx
webmastx

Reputation: 683

Mapbox iOS SDK create a curve MGLPolyline with MKGeodesicPolyline get some strange

I've tried to create a curve MGLPolyline on a map view using Mapbox SDK for iOS with following code,

func lineBetweenLocation(location1: CLLocation, location2: CLLocation)
{   
    var points: [CLLocationCoordinate2D]
    points = [location1.coordinate, location2.coordinate]
    let geodesic = MKGeodesicPolyline(coordinates: &points, count:2)
    let line = MGLPolyline(coordinates: geodesic.coordinates, count: UInt(geodesic.coordinates.count))

    DispatchQueue.main.async(execute: {
        // Unowned reference to self to prevent retain cycle
        [unowned self] in

        self.mapboxView!.add(line)
    })


}

With advantage of MKGeodesicPolyline, the code above works perfect only for a short distance!
If the given locations quit far like from USA to Asia, it will create an unwanted horizon strange line above the curve.

There is no issue on Apple Map!

Please anyone help. Thank you

enter image description here

enter image description here

Note: iOS 11.1 Xcode 9.1 Swift 4 , Mapbox-iOS-SDK Version 3.7.0

Upvotes: 1

Views: 977

Answers (1)

Ludovic Landry
Ludovic Landry

Reputation: 11774

This is due to the fact the the line cross the international date change line so it's wrapping all the way around.

To avoid that you can add or subtract 360 from your longitude to fix it. https://github.com/mapbox/mapbox.js/issues/360

For example:

import Mapbox
import MapKit

public extension MGLPolyline {
    class func geodesicPolyline(fromCoordinate: CLLocationCoordinate2D, toCoordinate: CLLocationCoordinate2D) -> MGLPolyline {
        var coordinates = [fromCoordinate, toCoordinate]
        let geodesicPolyline = MKGeodesicPolyline(coordinates: &coordinates, count: 2)

        var normalizedCoordinates: [CLLocationCoordinate2D] = []
        var previousCoordinate: CLLocationCoordinate2D?
        for coordinate in geodesicPolyline.coordinates {
            var normalizedCoordinate = coordinate
            if let previousCoordinate = previousCoordinate, abs(previousCoordinate.longitude - coordinate.longitude) > 180 {
                if (previousCoordinate.longitude > coordinate.longitude) {
                    normalizedCoordinate.longitude += 360
                } else {
                    normalizedCoordinate.longitude -= 360
                }
            }
            normalizedCoordinates.append(normalizedCoordinate)
            previousCoordinate = normalizedCoordinate
        }

        return MGLPolyline(coordinates: normalizedCoordinates, count: UInt(geodesicPolyline.pointCount))
    }
}

public extension MKPolyline {
    var coordinates: [CLLocationCoordinate2D] {
        var coords = [CLLocationCoordinate2D](repeating: kCLLocationCoordinate2DInvalid, count: self.pointCount)
        self.getCoordinates(&coords, range: NSRange(location: 0, length: self.pointCount))
        return coords
    }
}

Upvotes: 1

Related Questions