{"id":1924,"date":"2021-02-23T17:27:13","date_gmt":"2021-02-23T09:27:13","guid":{"rendered":"http:\/\/123.57.164.21\/?p=1924"},"modified":"2021-03-09T14:37:40","modified_gmt":"2021-03-09T06:37:40","slug":"ios-corelocation%e5%9b%bd%e5%86%85%e5%9d%90%e6%a0%87%e5%81%8f%e7%a7%bb","status":"publish","type":"post","link":"https:\/\/92it.top\/?p=1924","title":{"rendered":"IOS CoreLocation\u56fd\u5185\u5750\u6807\u504f\u79fb"},"content":{"rendered":"\n<p>\u6982\u5ff5<\/p>\n\n\n\n<ul><li>\u5730\u56fe\uff1a\u7cfb\u7edf\u5730\u56fe\uff08MKMapView\uff09\uff0c\u9ad8\u5fb7\u5730\u56fe\uff08MAMapView\uff09<\/li><li>\u5750\u6807\u7cfb\uff1aGPS\u5750\u6807\u7cfb\uff08WGS84\uff09\uff0c\u706b\u661f\u5750\u6807\u7cfb\uff08GCJ02\uff09<\/li><li>\u5b9a\u4f4d\uff1a\u7cfb\u7edf\u5b9a\u4f4d\uff08CLLocationManager\uff09\uff0c<\/li><\/ul>\n\n\n\n<p>\u82f9\u679c\u7cfb\u7edf\u5730\u56fe\u5728\u6d77\u5916\u5168\u7403\u901a\u7528\uff0c\u4e3aGPS\u5750\u6807\u7cfb\u3002\u5728\u56fd\u5185\u4f7f\u7528\u7684\u662f\u9ad8\u5fb7\u6570\u636e\uff0c\u6240\u4ee5\u8fd4\u56de\u7684\u7ecf\u7eac\u5ea6\u662f\u706b\u661f\u5750\u6807\u7cfb\u7684\u3002\u800cCoreLocation\u8fd4\u56de\u7684\u5750\u6807\u662fGPS\u5750\u6807\u7cfb\uff08WGS84\uff09\uff0c\u6240\u4ee5\u9700\u8981\u628aCoreLocation\u8fd4\u56de\u7684\u5750\u6807\u8f6c\u6362\u4f4d\u706b\u661f\u5750\u6807\u3002<\/p>\n\n\n\n<p>\u53ef\u4ee5\u7528\u4e0b\u9762\u7684\u4ee3\u7801\u8fdb\u884c\u4fee\u6b63\uff0c\u8c03\u7528transformFromWGSToGCJ\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import Foundation\nimport CoreLocation\n\nclass ZJ_MapKits{\n    \n    \/\/WGS-84\uff1a\u662f\u56fd\u9645\u6807\u51c6\uff0cGPS\u5750\u6807\uff08Google Earth\u4f7f\u7528\u3001\u6216\u8005GPS\u6a21\u5757\uff09\n    \/\/GCJ-02\uff1a\u4e2d\u56fd\u5750\u6807\u504f\u79fb\u6807\u51c6\uff0cGoogle Map\u3001\u9ad8\u5fb7\u3001\u817e\u8baf\u4f7f\u7528\n    \/\/BD-09\uff1a \u767e\u5ea6\u5750\u6807\u504f\u79fb\u6807\u51c6\uff0cBaidu Map\u4f7f\u7528\n    \n    \n    let  a = 6378245.0;\n    let  ee = 0.00669342162296594323;\n    let  pi = 3.14159265358979324;\n    let  xPi = Double.pi  * 3000.0 \/ 180.0;\n    \n    \/\/WGS-84 --> GCJ-02\n    func transformFromWGSToGCJ(wgsLoc:CLLocationCoordinate2D)->CLLocationCoordinate2D\n    {\n        var adjustLoc=CLLocationCoordinate2D();\n        if( isLocationOutOfChina(location: wgsLoc))\n        {\n            adjustLoc = wgsLoc;\n        }\n        else\n        {\n            var adjustLat = transformLatWithX(x: wgsLoc.longitude - 105.0 ,y:wgsLoc.latitude - 35.0);\n            var adjustLon = transformLonWithX(x: wgsLoc.longitude - 105.0 ,y:wgsLoc.latitude - 35.0);\n            let radLat = wgsLoc.latitude \/ 180.0 * pi;\n            var magic = sin(radLat);\n            magic = 1 - ee * magic * magic;\n            let sqrtMagic = sqrt(magic);\n            adjustLat = (adjustLat * 180.0) \/ ((a * (1 - ee)) \/ (magic * sqrtMagic) * pi);\n            adjustLon = (adjustLon * 180.0) \/ (a \/ sqrtMagic * cos(radLat) * pi);\n            adjustLoc.latitude = wgsLoc.latitude + adjustLat;\n            adjustLoc.longitude = wgsLoc.longitude + adjustLon;\n        }\n        return adjustLoc;\n    }\n    \n    func transformLatWithX(x:Double,y:Double)->Double\n    {\n        var lat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y ;\n        lat += 0.2 * sqrt(fabs(x));\n        \n        lat += (20.0 * sin(6.0 * x * pi)) * 2.0 \/ 3.0;\n        lat += (20.0 * sin(2.0 * x * pi)) * 2.0 \/ 3.0;\n        lat += (20.0 * sin(y * pi)) * 2.0 \/ 3.0;\n        lat += (40.0 * sin(y \/ 3.0 * pi)) * 2.0 \/ 3.0;\n        lat += (160.0 * sin(y \/ 12.0 * pi)) * 2.0 \/ 3.0;\n        lat += (320 * sin(y * pi \/ 30.0)) * 2.0 \/ 3.0;\n        return lat;\n    }\n    \n    func transformLonWithX(x:Double,y:Double)->Double\n    {\n        var lon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y ;\n        lon +=  0.1 * sqrt(fabs(x));\n        lon += (20.0 * sin(6.0 * x * pi)) * 2.0 \/ 3.0;\n        lon += (20.0 * sin(2.0 * x * pi)) * 2.0 \/ 3.0;\n        lon += (20.0 * sin(x * pi)) * 2.0 \/ 3.0;\n        lon += (40.0 * sin(x \/ 3.0 * pi)) * 2.0 \/ 3.0;\n        lon += (150.0 * sin(x \/ 12.0 * pi)) * 2.0 \/ 3.0;\n        lon += (300.0 * sin(x \/ 30.0 * pi)) * 2.0 \/ 3.0;\n        return lon;\n    }\n    \n    \/\/GCJ-02 --> BD-09\n    func transformFromGCJToBaidu(p:CLLocationCoordinate2D) -> CLLocationCoordinate2D\n    {\n        let z = sqrt(p.longitude * p.longitude + p.latitude * p.latitude) + 0.00002 * sqrt(p.latitude * pi);\n        let theta = atan2(p.latitude, p.longitude) + 0.000003 * cos(p.longitude * pi);\n        var geoPoint=CLLocationCoordinate2D();\n        geoPoint.latitude  = (z * sin(theta) + 0.006);\n        geoPoint.longitude = (z * cos(theta) + 0.0065);\n        return geoPoint;\n    }\n\n    \n    \/\/BD-09 --> GCJ-02\n    func transformFromBaiduToGCJ(p:CLLocationCoordinate2D)-> CLLocationCoordinate2D\n    {\n        let x = p.longitude - 0.0065, y = p.latitude - 0.006;\n        let z = sqrt(x * x + y * y) - 0.00002 * sin(y * xPi);\n        let theta = atan2(y, x) - 0.000003 * cos(x * xPi);\n        var geoPoint = CLLocationCoordinate2D();\n        geoPoint.latitude  = z * sin(theta);\n        geoPoint.longitude = z * cos(theta);\n        return geoPoint;\n    }\n    \n    \/\/GCJ-02 --> WGS-84\n    func transformFromGCJToWGS(p:CLLocationCoordinate2D) -> CLLocationCoordinate2D\n    {\n        let threshold = 0.00001;\n        \n        \/\/ The boundary\n        var minLat = p.latitude - 0.5;\n        var maxLat = p.latitude + 0.5;\n        var minLng = p.longitude - 0.5;\n        var maxLng = p.longitude + 0.5;\n        \n        var delta = 1.0;\n        let maxIteration = 30;\n        \/\/ Binary search\n        while(true)\n        {\n            let leftBottom  = transformFromWGSToGCJ(wgsLoc: CLLocationCoordinate2D(latitude: minLat,longitude: minLng));\n            let rightBottom = transformFromWGSToGCJ(wgsLoc: CLLocationCoordinate2D(latitude : minLat,longitude : maxLng));\n            let leftUp      = transformFromWGSToGCJ(wgsLoc: CLLocationCoordinate2D(latitude : maxLat,longitude : minLng));\n            let midPoint    = transformFromWGSToGCJ(wgsLoc: CLLocationCoordinate2D(latitude : ((minLat + maxLat) \/ 2),longitude : ((minLng + maxLng) \/ 2)));\n            delta = fabs(midPoint.latitude - p.latitude) + fabs(midPoint.longitude - p.longitude);\n            \n            if(maxIteration &lt;= 1 || delta &lt;= threshold)\n            {\n                return CLLocationCoordinate2D(latitude: (minLat + maxLat) \/ 2, longitude: (minLng + maxLng) \/ 2);\n                \n            }\n            \n            if(isContains(point: p, p1: leftBottom, p2: midPoint))\n            {\n                maxLat = (minLat + maxLat) \/ 2;\n                maxLng = (minLng + maxLng) \/ 2;\n            }\n            else if(isContains(point: p, p1: rightBottom, p2: midPoint))\n            {\n                maxLat = (minLat + maxLat) \/ 2;\n                minLng = (minLng + maxLng) \/ 2;\n            }\n            else if(isContains(point: p, p1: leftUp, p2: midPoint))\n            {\n                minLat = (minLat + maxLat) \/ 2;\n                maxLng = (minLng + maxLng) \/ 2;\n            }\n            else\n            {\n                minLat = (minLat + maxLat) \/ 2;\n                minLng = (minLng + maxLng) \/ 2;\n            }\n        }\n        \n    }\n    \n    \/\/WGS-84 --> BD-09\n    func transformFromWGSToBaidu(p:CLLocationCoordinate2D) -> CLLocationCoordinate2D\n    {\n        let gcj = transformFromWGSToGCJ(wgsLoc: p);\n        let bd = transformFromGCJToBaidu(p: gcj)\n        return bd;\n    }\n    \n    \/\/BD-09 --> WGS-84\n    func transformFromBaiduToWGS(p:CLLocationCoordinate2D) -> CLLocationCoordinate2D\n    {\n        let gcj = transformFromBaiduToGCJ(p: p)\n        let wgs = transformFromGCJToWGS(p: gcj)\n        return wgs;\n    }\n    \n    \/\/\u5224\u65ad\u70b9\u662f\u5426\u5728p1\u548cp2\u4e4b\u95f4\n    \/\/point: \u70b9\n    \/\/p1:    \u5de6\u4e0a\u89d2\n    \/\/p2:    \u53f3\u4e0b\u89d2\n    func isContains(point:CLLocationCoordinate2D , p1:CLLocationCoordinate2D, p2:CLLocationCoordinate2D)->Bool\n    {\n        \n        return (point.latitude >= min(p1.latitude, p2.latitude) &amp;&amp; point.latitude &lt;= max(p1.latitude, p2.latitude)) &amp;&amp; (point.longitude >= min(p1.longitude,p2.longitude) &amp;&amp; point.longitude &lt;= max(p1.longitude, p2.longitude));\n    }\n    \n    \n    \/\/\u662f\u5426\u5728\u4e2d\u56fd\u4ee5\u5916\n    func isLocationOutOfChina(location:CLLocationCoordinate2D) -> Bool\n    {\n        if (location.longitude &lt; 72.004 || location.longitude > 137.8347 || location.latitude &lt; 0.8293 || location.latitude > 55.8271){\n            return true;\n        }else{\n            return false;\n        }\n        \n    }\n    \n    \/\/\/\u83b7\u53d6\u4e24\u70b9\u4e4b\u95f4\u7684\u8ddd\u79bb\n    static func distanceByPoint(lat1:Double,lat2 :Double,lng1 :Double,lng2:Double)->Double{\n        let dd = Double.pi\/180;\n        let x1=lat1*dd;\n        let x2=lat2*dd;\n        let y1=lng1*dd;\n        let y2=lng2*dd;\n        let R = 6371004;\n        \n        let temp = 2 - 2 * cos(x1) * cos(x2) * cos(y1-y2) - 2 * sin(x1) * sin(x2);\n        \n        let distance = Double(2) * Double(R) * asin(sqrt(temp)\/2);\n        \n        \/\/\u8fd4\u56de m\n        return   distance;\n        \n    }\n    \n    \/\/\/\u83b7\u53d6\u4e24\u70b9\u4e4b\u95f4\u7684\u8ddd\u79bb\n    static  func distanceByPoint(point1:CLLocationCoordinate2D,point2:CLLocationCoordinate2D)->Double{\n        return distanceByPoint(lat1: point1.latitude, lat2: point2.latitude, lng1: point1.longitude, lng2: point2.longitude);\n    \n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u6982\u5ff5 \u5730\u56fe\uff1a\u7cfb\u7edf\u5730\u56fe\uff08MKMapView\uff09\uff0c\u9ad8\u5fb7\u5730\u56fe\uff08MAMapView\uff09 \u5750\u6807\u7cfb\uff1aGPS\u5750\u6807\u7cfb\uff08WGS84\uff09 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,8],"tags":[],"_links":{"self":[{"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts\/1924"}],"collection":[{"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1924"}],"version-history":[{"count":5,"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts\/1924\/revisions"}],"predecessor-version":[{"id":2086,"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts\/1924\/revisions\/2086"}],"wp:attachment":[{"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1924"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1924"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1924"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}