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

2

7

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.

Lazare answered 2/12, 2016 at 12:43 Comment(4)
this is possible with location manager you get the bearing angle from location from that you rotate the car and use genuine location move your marker ahead.Hjerpe
@chiragshah.. yes i want to move my location but when my location gets updating car is not moving.It is jumpingLazare
Can you post your location manager code?Hjerpe
Which filter you use for location manager use "Best" for itHjerpe
L
7

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)
        }
Lazare answered 16/12, 2016 at 5:1 Comment(5)
Heading may be not available in some device so make sure you check that before start heading. and one more thing heading may take more battery power so use with proper managementHjerpe
@chiragshah..Ok. how to check heading is available or not .Lazare
Code is in objective c if ([CLLocationManager headingAvailable]) { locManager.headingFilter = 5; [locManager startUpdatingHeading]; }Hjerpe
@chiragshah.. Is there any other option without using heading.Lazare
cllocation it self gives heading in CLLocation object if availableHjerpe
H
4

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

Hjerpe answered 3/12, 2016 at 9:21 Comment(6)
Thanks for ur response.. I will try .Lazare
@UmaMadhavi i already ask same question long ago here is the link #36451026 look onceHjerpe
..I have looked ur question.But i am working with swift.Did u get exact solution..Lazare
how to show rotation in tracking app. i only get latitude & longitude from server.Lazare
you need to find the heading between two locationHjerpe
I have not implemented that so you need to find that thing on SBHjerpe

© 2022 - 2024 — McMap. All rights reserved.