我想在Swift中找到Qibla Direction(方向的简单指南针)

时间:2016-09-24 11:26:40

标签: ios swift core-location

所有代码都运行良好,但不能提供所需的结果。方向针不会移动到完美的位置。有时候它有效,有时候不行。

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
    }

2 个答案:

答案 0 :(得分:10)

实际上你在这里做错了的是让指南针在 didLocationChange 方法中旋转。实际上你需要根据地球的真北来进行旋转,为此你需要使用 didUpdateLocationHeader 。这会根据地球的真实北方给你读数。我在下面发布我的代码。您还可以在我的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)
}

}

答案 1 :(得分:4)

//
//  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
    }




}