Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rotate GMSMarker in the direction which user is moving in Swift?

I am using this code.

 let marker = GMSMarker()
 marker.position = coordinates
 marker.tracksViewChanges = true     
 marker.icon = UIImage(named:"car")
 marker.appearAnimation = kGMSMarkerAnimationNone
 marker.map = mapView

location manager code

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{

    let location = locations.last! as CLLocation

    if(checkingLocation == false)
    {
    let camera = GMSCameraPosition.camera(withLatitude: (location.coordinate.latitude), longitude: (location.coordinate.longitude), zoom: 16.0)
    oldLocationCenter = location
    marker.position = (locationManager.location?.coordinate)!
         self.mapView?.animate(to: camera)
      //  checkingLocation = true
        locationManager.stopUpdatingLocation()

    }
    else
    {

        let updateCam = GMSCameraUpdate.setTarget(CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude))
        updateMarker(coordinates: location.coordinate, degrees:DegreeBearing(A: oldLocationCenter, B: location) , duration: 10.0)
        self.mapView?.animate(with: updateCam)
        locationManager.stopUpdatingLocation()

    }


}

func updateMarker(coordinates: CLLocationCoordinate2D, degrees: CLLocationDegrees, duration: Double){
    // Keep Rotation Short
    CATransaction.begin()
    CATransaction.setAnimationDuration(10.0)
    marker.rotation = degrees
    CATransaction.commit()

    // Movement
    CATransaction.begin()
    CATransaction.setAnimationDuration(duration)
    marker.position = coordinates

    // Center Map View
    let camera = GMSCameraUpdate.setTarget(coordinates)
    mapView.animate(with: camera)

    CATransaction.commit()
}

func DegreeBearing(A:CLLocation,B:CLLocation)-> Double{


    var dlon = self.ToRad(degrees: B.coordinate.longitude - A.coordinate.longitude)

    let dPhi = log(tan(self.ToRad(degrees: B.coordinate.latitude) / 2 + M_PI / 4) / tan(self.ToRad(degrees: A.coordinate.latitude) / 2 + M_PI / 4))

    if  abs(dlon) > M_PI{
        dlon = (dlon > 0) ? (dlon - 2*M_PI) : (2*M_PI + dlon)
    }
    return self.ToBearing(radians: atan2(dlon, dPhi))
}

func ToRad(degrees:Double) -> Double{
    return degrees*(M_PI/180)
}

func ToBearing(radians:Double)-> Double{
    return (ToDegrees(radians: radians) + 360) / 360
}

func ToDegrees(radians:Double)->Double{
    return radians * 180 / M_PI
}

By using above code my marker(car)is moving from old to new location also i used these locations for getting bearing angle. But it is not rotating. Is there any other way to achieve this ? Please guide me.

like image 414
Uma Madhavi Avatar asked Dec 02 '16 12:12

Uma Madhavi


2 Answers

I found solution by updating heading. In didUpdateLocations method , we need to update heading

locationManager.startUpdatingHeading()

So the marker rotates where the user moving.

func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading)
        {
            let  heading:Double = newHeading.trueHeading;
            marker.groundAnchor = CGPoint(x: 0.5, y: 0.5)
            marker.rotation = heading
            marker.map = mapView;
            print(marker.rotation)
        }
like image 93
Uma Madhavi Avatar answered Oct 15 '22 10:10

Uma Madhavi


For proper navigation first you need to setup your location manager object like this

fileprivate func initLocationManager()
    {
        locationManager = CLLocationManager();
        locationManager!.delegate = self;
        locationManager!.desiredAccuracy = kCLLocationAccuracyBest;
        locationManager!.activityType = .automotiveNavigation;
        if LocationTracker.authorized() == false
        {
            requestAuthorization()
        }
    }

After setting this you need to find the legitimate location because in ios system try to give best location but not sure so some time location also come from cache or your location may be zick zack so you need following code in locationUpdate

 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
    {
        if locations.count > 0
        {
            let _  = locations.first
            let location = locations[locations.count-1]

            let maxAge:TimeInterval = 60;
            let requiredAccuracy:CLLocationAccuracy = 100;

            let locationIsValid:Bool = Date().timeIntervalSince(location.timestamp) < maxAge && location.horizontalAccuracy <= requiredAccuracy;
            if locationIsValid
            {
                NSLog(",,, location : %@",location);


                NSLog("valid locations.....");

            }
        }
    }

your navigation go smoothly but make one thing note the location accuracy is not good in iPad this type of module only work for iphone good luck

like image 45
chirag shah Avatar answered Oct 15 '22 10:10

chirag shah