I want to find the direction of Qibla (a simple compass for directions) in Swift

All code works well, but it does not give the desired result. The direction arrow does not move to the ideal 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 } 
+5
source share
2 answers

In fact, what you are doing wrong is to make the compass rotate in the didLocationChange method. In fact, you need to have a rotation in accordance with the True North of the Earth, and for this you need to use didUpdateLocationHeader . This gives you readings according to the true north of the earth. I am posting my code below. You can also find the complete working project on 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) } } 
+8
source
 // // 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 } } 
+3
source

All Articles