All code works well but it does not give required result. The direction needle does not move to the perfect location. Sometimes it works, sometimes not.
func DegreesToRadians (value:Double) -> Double {
return value * M_PI / 180.0
}
func RadiansToDegrees (value:Double) -> Double {
return value * 180.0 / M_PI
}
class ViewController: UIViewController , CLLocationManagerDelegate {
var needleAngle : Double?
//Main Composs
@IBOutlet weak var composs: UIImageView!
//Needle Move with respect to compose
@IBOutlet weak var needle: UIImageView!
@IBOutlet weak var mapView: MKMapView!
// Kabhalocation
var kabahLocation : CLLocation?
var latitude : Double?
var longitude : Double?
var distanceFromKabah : Double?
let locationManger = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
//KabhaLocation Hardcoded.
kabahLocation = CLLocation(latitude: 21.42 , longitude: 39.83)
//Delegate
self.locationManger.delegate = self
self.locationManger.desiredAccuracy = kCLLocationAccuracyBest
if #available(iOS 8.0, *) {
self.locationManger.requestAlwaysAuthorization()
} else {
// Fallback on earlier versions
}
self.locationManger.startUpdatingLocation()
self.locationManger.startUpdatingHeading()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Mark: - LocationManger Delegate
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center = CLLocationCoordinate2D(latitude: (location?.coordinate.latitude)!, longitude: (location?.coordinate.longitude)!)
print("current location latitude \((location?.coordinate.latitude)!) and longitude \((location?.coordinate.longitude)!)")
self.latitude = location?.coordinate.latitude
self.longitude = location?.coordinate.longitude
//
// self.latitude = 31.5497
// self.longitude = 74.3436
self.locationManger.startUpdatingLocation()
needleAngle = self.setLatLonForDistanceAndAngle(location!)
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Error " + error.localizedDescription)
}
func setLatLonForDistanceAndAngle(userlocation: CLLocation) -> Double
{
let lat1 = DegreesToRadians(userlocation.coordinate.latitude)
let lon1 = DegreesToRadians(userlocation.coordinate.longitude)
let lat2 = DegreesToRadians(kabahLocation!.coordinate.latitude)
let lon2 = DegreesToRadians(kabahLocation!.coordinate.longitude)
distanceFromKabah = userlocation.distanceFromLocation(kabahLocation!)
let dLon = lon2 - lon1;
let y = sin(dLon) * cos(lat2)
let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon)
var radiansBearing = atan2(y, x)
if(radiansBearing < 0.0)
{
radiansBearing += 2*M_PI;
}
// print("Initial Bearing \(radiansBearing*180/M_PI)")
let distanceFromKabahUnit = 0.0
return radiansBearing
}
func locationManager(manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
let needleDirection = -newHeading.trueHeading;
let compassDirection = -newHeading.magneticHeading;
self.needle.transform = CGAffineTransformMakeRotation(CGFloat(((Double(needleDirection) ) / 180.0) + needleAngle!))
print("Needle \(CGAffineTransformMakeRotation(CGFloat(((Double(needleDirection) ) / 180.0) + needleAngle!)))")
self.composs.transform = CGAffineTransformMakeRotation(CGFloat((Double(compassDirection) ) / 180.0))
print("composs \(CGAffineTransformMakeRotation(CGFloat((Double(compassDirection) ) / 180.0)))")
}
override func viewDidAppear(animated: Bool) {
needleAngle = 0.0
self.locationManger.startUpdatingHeading()
kabahLocation = CLLocation(latitude: 21.42 , longitude: 39.83)
self.locationManger.delegate = self
}
override func viewDidDisappear(animated: Bool) {
self.locationManger.delegate = nil
}
Actually what you are doing wrong here is making the compass rotate in didLocationChange method. Actually you need to have the rotation according to True north of Earth and for that you need to use didUpdateLocationHeader .This gives you the readings according to true north of Earth. I am posting my code below. You can also find a full working project on my github
import UIKit
import CoreLocation
class ViewController: UIViewController ,CLLocationManagerDelegate{
@IBOutlet weak var ivCompassBack: UIImageView!
@IBOutlet weak var ivCompassNeedle: UIImageView!
let latOfKabah = 21.4225
let lngOfKabah = 39.8262
var location: CLLocation?
let locationManager = CLLocationManager()
var bearingOfKabah = Double()
override func viewDidLoad() {
super.viewDidLoad()
initManager()
}
func initManager(){
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
locationManager.startUpdatingHeading()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateHeading heading: CLHeading) {
let north = -1 * heading.magneticHeading * Double.pi/180
let directionOfKabah = bearingOfKabah * Double.pi/180 + north
ivCompassBack.transform = CGAffineTransform(rotationAngle: CGFloat(north));
ivCompassNeedle.transform = CGAffineTransform(rotationAngle: CGFloat(directionOfKabah));
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let newLocation = locations.last!
location = newLocation
bearingOfKabah = getBearingBetweenTwoPoints1(location!, latitudeOfKabah: self.latOfKabah, longitudeOfKabah: self.lngOfKabah) //calculating the bearing of KABAH
}
func degreesToRadians(_ degrees: Double) -> Double { return degrees * Double.pi / 180.0 }
func radiansToDegrees(_ radians: Double) -> Double { return radians * 180.0 / Double.pi }
func getBearingBetweenTwoPoints1(_ point1 : CLLocation, latitudeOfKabah : Double , longitudeOfKabah :Double) -> Double {
let lat1 = degreesToRadians(point1.coordinate.latitude)
let lon1 = degreesToRadians(point1.coordinate.longitude)
let lat2 = degreesToRadians(latitudeOfKabah);
let lon2 = degreesToRadians(longitudeOfKabah);
let dLon = lon2 - lon1;
let y = sin(dLon) * cos(lat2);
let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
var radiansBearing = atan2(y, x);
if(radiansBearing < 0.0){
radiansBearing += 2 * Double.pi;
}
return radiansToDegrees(radiansBearing)
}
}
//
// ViewController.swift
// CurrentLocation
//
// Created by Muhammad Rizwan Anjum on 26/8/16.
// Copyright © 2016 Muhammad Rizwan Anjum. All rights reserved.
//
import UIKit
import MapKit
import CoreLocation
func DegreesToRadians (value:Double) -> Double {
return value * M_PI / 180.0
}
func RadiansToDegrees (value:Double) -> Double {
return value * 180.0 / M_PI
}
class ViewController: UIViewController , CLLocationManagerDelegate {
var needleAngle : Double?
@IBOutlet weak var composs: UIImageView!
@IBOutlet weak var needle: UIImageView!
@IBOutlet weak var mapView: MKMapView!
var kabahLocation : CLLocation?
var latitude : Double?
var longitude : Double?
var distanceFromKabah : Double?
let locationManger = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
kabahLocation = CLLocation(latitude: 21.42 , longitude: 39.83)
self.locationManger.delegate = self
self.locationManger.desiredAccuracy = kCLLocationAccuracyBest
if #available(iOS 8.0, *) {
self.locationManger.requestAlwaysAuthorization()
} else {
// Fallback on earlier versions
}
self.locationManger.startUpdatingLocation()
self.locationManger.startUpdatingHeading()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Mark: - LocationManger Delegate
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
// let center = CLLocationCoordinate2D(latitude: (location?.coordinate.latitude)!, longitude: (location?.coordinate.longitude)!)
print("current location latitude \((location?.coordinate.latitude)!) and longitude \((location?.coordinate.longitude)!)")
self.latitude = location?.coordinate.latitude
self.longitude = location?.coordinate.longitude
//
// self.latitude = 31.5497
// self.longitude = 74.3436
self.locationManger.startUpdatingLocation()
needleAngle = self.setLatLonForDistanceAndAngle(location!)
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Error " + error.localizedDescription)
}
func setLatLonForDistanceAndAngle(userlocation: CLLocation) -> Double
{
let lat1 = DegreesToRadians(userlocation.coordinate.latitude)
let lon1 = DegreesToRadians(userlocation.coordinate.longitude)
let lat2 = DegreesToRadians(kabahLocation!.coordinate.latitude)
let lon2 = DegreesToRadians(kabahLocation!.coordinate.longitude)
distanceFromKabah = userlocation.distanceFromLocation(kabahLocation!)
let dLon = lon2 - lon1;
let y = sin(dLon) * cos(lat2)
let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon)
var radiansBearing = atan2(y, x)
if(radiansBearing < 0.0)
{
radiansBearing += 2*M_PI;
}
// print("Initial Bearing \(radiansBearing*180/M_PI)")
let distanceFromKabahUnit = 0.0
return radiansBearing
}
func locationManager(manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
let needleDirection = -newHeading.trueHeading;
let compassDirection = -newHeading.magneticHeading;
//you Need to Multiply With M_PI
self.needle.transform = CGAffineTransformMakeRotation(CGFloat(((Double(needleDirection) * M_PI) / 180.0) + needleAngle!))
print("Needle \(CGAffineTransformMakeRotation(CGFloat(((Double(needleDirection) * M_PI) / 180.0) + needleAngle!)))")
self.composs.transform = CGAffineTransformMakeRotation(CGFloat((Double(compassDirection) * M_PI) / 180.0))
print("composs \(CGAffineTransformMakeRotation(CGFloat((Double(compassDirection) * M_PI) / 180.0)))")
}
override func viewDidAppear(animated: Bool) {
needleAngle = 0.0
self.locationManger.startUpdatingHeading()
kabahLocation = CLLocation(latitude: 21.42 , longitude: 39.83)
self.locationManger.delegate = self
}
override func viewDidDisappear(animated: Bool) {
self.locationManger.delegate = nil
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With