I am developing some navigation tasks on google map. I have to move markers as vehicles moves with turns as uber does in their app. I have tried different solutions as offered on @SO but It is not working as I need.
I am getting angle with previous lat/long with current lat/long and animating mapwithBearing with that rotation
Here is code
[CATransaction begin];
[CATransaction setAnimationDuration:2.0];
NSDictionary *data = [[result objectForKey:@"returnData"] objectForKey:@"data"];
if (![data isEqual: [NSNull null]]) {
driverLocationCoordinate = CLLocationCoordinate2DMake([[data objectForKey:@"lat"] doubleValue], [[data objectForKey:@"lng"] doubleValue]);
driverMarker.position = driverLocationCoordinate;
GMSCameraPosition * camera = [GMSCameraPosition cameraWithLatitude:driverLocationCoordinate.latitude
longitude:driverLocationCoordinate.longitude
zoom:16];
mapHomeView.camera = camera;
if ([data objectForKey:@"preLat"] != [NSNull null] && [data objectForKey:@"preLng"] !=[NSNull null]){
if ([[data objectForKey:@"preLat"] floatValue] != 0.0f && [[data objectForKey:@"preLng"] floatValue] != 0.0f) {
NSLog(@"pre_lat = %f and pre_lng = %f", [[data objectForKey:@"preLat"] floatValue], [[data objectForKey:@"preLng"] floatValue]);
CLLocationCoordinate2D previousCoordinates = CLLocationCoordinate2DMake([[data objectForKey:@"preLat"] floatValue], [[data objectForKey:@"preLng"] floatValue]);
driverMarker.rotation = [self DegreeBearing:previousCoordinates locationB:driverMarker.position];
[mapHomeView animateToBearing:driverMarker.rotation];
}
}
[CATransaction commit];
I just taken degree code from another @SO post, It works when I'm on straight road but when car is still or turning, it gives flickering
Here is code of getting angle from another SO post.
-(double) DegreeBearing:(CLLocationCoordinate2D) A locationB: (CLLocationCoordinate2D)B{
double dlon = [self ToRad:(B.longitude - A.longitude) ];
double dPhi = log(tan([self ToRad:(B.latitude)] / 2 + M_PI / 4) / tan([self ToRad:(A.latitude)] / 2 + M_PI / 4));
if (fabs(dlon) > M_PI){
dlon = (dlon > 0) ? (dlon - 2*M_PI) : (2*M_PI + dlon);
}
return [self ToBearing:(atan2(dlon, dPhi))];
}
-(double) ToRad: (double)degrees{
return degrees*(M_PI/180);
}
-(double) ToBearing:(double)radians{
return [self ToDegrees:radians] + 360 % 360;
}
-(double) ToDegrees: (double)radians{
return radians * 180 / M_PI;
}
Can anyone help on this or propose any other solution?
Some how working with this code. You can try with this code with some logics change. But, it will work fine.
CLLocationCoordinate2D oldCoodinate = CLLocationCoordinate2DMake([[data valueForKey:@"lat"]doubleValue],[[data valueForKey:@"lng"]doubleValue]);
CLLocationCoordinate2D newCoodinate = CLLocationCoordinate2DMake([[data valueForKey:@"lat"]doubleValue],[[data valueForKey:@"lng"]doubleValue]);
driverMarker.groundAnchor = CGPointMake(0.5, 0.5);
driverMarker.rotation = [self getHeadingForDirectionFromCoordinate:oldCoodinate toCoordinate:newCoodinate]; //found bearing value by calculation when marker add
driverMarker.position = oldCoodinate; //this can be old position to make car movement to new position
driverMarker.map = mapView_;
//marker movement animation
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:2.0] forKey:kCATransactionAnimationDuration];
[CATransaction setCompletionBlock:^{
driverMarker.groundAnchor = CGPointMake(0.5, 0.5);
driverMarker.rotation = [[data valueForKey:@"bearing"] doubleValue]; //New bearing value from backend after car movement is done
}];
driverMarker.position = newCoodinate; //this can be new position after car moved from old position to new position with animation
driverMarker.map = mapView_;
driverMarker.groundAnchor = CGPointMake(0.5, 0.5);
driverMarker.rotation = [self getHeadingForDirectionFromCoordinate:oldCoodinate toCoordinate:newCoodinate]; //found bearing value by calculation
[CATransaction commit];
define these two in .h file
#define degreesToRadians(x) (M_PI * x / 180.0)
#define radiansToDegrees(x) (x * 180.0 / M_PI)
method for get bearing value from old and new coordinates
- (float)getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc
{
float fLat = degreesToRadians(fromLoc.latitude);
float fLng = degreesToRadians(fromLoc.longitude);
float tLat = degreesToRadians(toLoc.latitude);
float tLng = degreesToRadians(toLoc.longitude);
float degree = radiansToDegrees(atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng)));
if (degree >= 0) {
return degree;
} else {
return 360+degree;
}
}
Swift 3.1
var oldCoodinate: CLLocationCoordinate2D? = CLLocationCoordinate2DMake(CDouble((data.value(forKey: "lat") as? CLLocationCoordinate2D)), CDouble((data.value(forKey: "lng") as? CLLocationCoordinate2D)))
var newCoodinate: CLLocationCoordinate2D? = CLLocationCoordinate2DMake(CDouble((data.value(forKey: "lat") as? CLLocationCoordinate2D)), CDouble((data.value(forKey: "lng") as? CLLocationCoordinate2D)))
driverMarker.groundAnchor = CGPoint(x: CGFloat(0.5), y: CGFloat(0.5))
driverMarker.rotation = getHeadingForDirection(fromCoordinate: oldCoodinate, toCoordinate: newCoodinate)
//found bearing value by calculation when marker add
driverMarker.position = oldCoodinate
//this can be old position to make car movement to new position
driverMarker.map = mapView_
//marker movement animation
CATransaction.begin()
CATransaction.setValue(Int(2.0), forKey: kCATransactionAnimationDuration)
CATransaction.setCompletionBlock({() -> Void in
driverMarker.groundAnchor = CGPoint(x: CGFloat(0.5), y: CGFloat(0.5))
driverMarker.rotation = CDouble(data.value(forKey: "bearing"))
//New bearing value from backend after car movement is done
})
driverMarker.position = newCoodinate
//this can be new position after car moved from old position to new position with animation
driverMarker.map = mapView_
driverMarker.groundAnchor = CGPoint(x: CGFloat(0.5), y: CGFloat(0.5))
driverMarker.rotation = getHeadingForDirection(fromCoordinate: oldCoodinate, toCoordinate: newCoodinate)
//found bearing value by calculation
CATransaction.commit()
extension Int {
var degreesToRadians: Double { return Double(self) * .pi / 180 }
}
extension FloatingPoint {
var degreesToRadians: Self { return self * .pi / 180 }
var radiansToDegrees: Self { return self * 180 / .pi }
}
func getHeadingForDirection(fromCoordinate fromLoc: CLLocationCoordinate2D, toCoordinate toLoc: CLLocationCoordinate2D) -> Float {
let fLat: Float = Float((fromLoc.latitude).degreesToRadians)
let fLng: Float = Float((fromLoc.longitude).degreesToRadians)
let tLat: Float = Float((toLoc.latitude).degreesToRadians)
let tLng: Float = Float((toLoc.longitude).degreesToRadians)
let degree: Float = (atan2(sin(tLng - fLng) * cos(tLat), cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(tLng - fLng))).radiansToDegrees
if degree >= 0 {
return degree
}
else {
return 360 + degree
}
}
for github link: ARCarMovement
来源:https://stackoverflow.com/questions/39383324/move-gmsmarker-on-google-map-like-uber