2020-02-10-howto如何使用漂逸算法及边改iOS的swift语言Struct式的Framework边调App

howto如何使用漂逸算法及边改iOS的swift语言Struct式的Framework边调App

Transform coordinate between earth(WGS-84) and mars in china(GCJ-02).
火星坐标:我国自己加了飘逸搞的一套加密坐标 还原了飘逸算法

usage

1
2
3
import HameToolsFramework
let location = LocationTransform.gcj2wgs(gcjLat: 30.581237, gcjLng: 104.065644)
print(location)

Framework code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import Foundation
/**
* Struct transform coordinate between earth(WGS-84) and mars in china(GCJ-02).
*/
public struct LocationTransform {
static let EARTH_R: Double = 6378137.0
static func isOutOfChina(lat: Double, lng: Double) -> Bool {
if lng < 72.004 || lng > 137.8347 {
return true
}
if lat < 0.8293 || lat > 55.8271 {
return true
}
return false
}
static func transform(x: Double, y: Double) -> (lat: Double, lng: Double) {
let xy = x * y
let absX = sqrt(fabs(x))
let xPi = x * Double.pi
let yPi = y * Double.pi
let d = 20.0 * sin(6.0 * xPi) + 20.0 * sin(2.0 * xPi)
var lat = d
var lng = d
lat += 20.0 * sin(yPi) + 40.0 * sin(yPi / 3.0)
lng += 20.0 * sin(xPi) + 40.0 * sin(xPi / 3.0)
lat += 160.0 * sin(yPi / 12.0) + 320 * sin(yPi / 30.0)
lng += 150.0 * sin(xPi / 12.0) + 300 * sin(xPi / 30.0)
lat *= 2.0 / 3.0
lng *= 2.0 / 3.0
lat += -100 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * xy + 0.2 * absX
lng += 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * xy + 0.1 * absX
return (lat, lng)
}
static func delta(lat: Double, lng: Double) -> (dLat: Double, dLng: Double) {
let ee = 0.00669342162296594323
let radLat = lat / 180.0 * Double.pi
var magic = sin(radLat)
magic = 1 - ee * magic * magic
let sqrtMagic = sqrt(magic)
var (dLat, dLng) = transform(x: lng - 105.0, y: lat - 35.0)
dLat = (dLat * 180.0) / ((EARTH_R * (1 - ee)) / (magic * sqrtMagic) * Double.pi)
dLng = (dLng * 180.0) / (EARTH_R / sqrtMagic * cos(radLat) * Double.pi)
return (dLat, dLng)
}
/**
* wgs2gcj convert WGS-84 coordinate(wgsLat, wgsLng) to GCJ-02 coordinate(gcjLat, gcjLng).
*/
public static func wgs2gcj(wgsLat: Double, wgsLng: Double) -> (gcjLat: Double, gcjLng: Double) {
if isOutOfChina(lat: wgsLat, lng: wgsLng) {
return (wgsLat, wgsLng)
}
let (dLat, dLng) = delta(lat: wgsLat, lng: wgsLng)
return (wgsLat + dLat, wgsLng + dLng)
}
/**
* gcj2wgs convert GCJ-02 coordinate(gcjLat, gcjLng) to WGS-84 coordinate(wgsLat, wgsLng).
* The output WGS-84 coordinate's accuracy is 1m to 2m. If you want more exactly result, use gcj2wgs_exact.
*/
public static func gcj2wgs(gcjLat: Double, gcjLng: Double) -> (wgsLat: Double, wgsLng: Double) {
if isOutOfChina(lat: gcjLat, lng: gcjLng) {
return (gcjLat, gcjLng)
}
let (dLat, dLng) = delta(lat: gcjLat, lng: gcjLng)
return (gcjLat - dLat, gcjLng - dLng)
}
/**
* gcj2wgs_exact convert GCJ-02 coordinate(gcjLat, gcjLng) to WGS-84 coordinate(wgsLat, wgsLng).
* The output WGS-84 coordinate's accuracy is less than 0.5m, but much slower than gcj2wgs.
*/
public static func gcj2wgs_exact(gcjLat: Double, gcjLng: Double) -> (wgsLat: Double, wgsLng: Double) {
let initDelta = 0.01, threshold = 0.000001
var (dLat, dLng) = (initDelta, initDelta)
var (mLat, mLng) = (gcjLat - dLat, gcjLng - dLng)
var (pLat, pLng) = (gcjLat + dLat, gcjLng + dLng)
var (wgsLat, wgsLng) = (gcjLat, gcjLng)
for _ in 0 ..< 30 {
(wgsLat, wgsLng) = ((mLat + pLat) / 2, (mLng + pLng) / 2)
let (tmpLat, tmpLng) = wgs2gcj(wgsLat: wgsLat, wgsLng: wgsLng)
(dLat, dLng) = (tmpLat - gcjLat, tmpLng - gcjLng)
if (fabs(dLat) < threshold) && (fabs(dLng) < threshold) {
return (wgsLat, wgsLng)
}
if dLat > 0 {
pLat = wgsLat
} else {
mLat = wgsLat
}
if dLng > 0 {
pLng = wgsLng
} else {
mLng = wgsLng
}
}
return (wgsLat, wgsLng)
}
/**
* Distance calculate the distance between point(latA, lngA) and point(latB, lngB), unit in meter.
*/
public static func Distance(latA: Double, lngA: Double, latB: Double, lngB: Double) -> Double {
let arcLatA = latA * Double.pi / 180
let arcLatB = latB * Double.pi / 180
let x = cos(arcLatA) * cos(arcLatB) * cos((lngA-lngB) * Double.pi/180)
let y = sin(arcLatA) * sin(arcLatB)
var s = x + y
if s > 1 {
s = 1
}
if s < -1 {
s = -1
}
let alpha = acos(s)
let distance = alpha * EARTH_R
return distance
}
}
extension LocationTransform {
public static func gcj2bd(gcjLat: Double, gcjLng: Double) -> (bdLat: Double, bdLng: Double) {
if isOutOfChina(lat: gcjLat, lng: gcjLng) {
return (gcjLat, gcjLng)
}
let x = gcjLng, y = gcjLat
let z = sqrt(x * x + y * y) + 0.00002 * sin(y * Double.pi)
let theta = atan2(y, x) + 0.000003 * cos(x * Double.pi)
let bdLng = z * cos(theta) + 0.0065
let bdLat = z * sin(theta) + 0.006
return (bdLat, bdLng)
}
public static func bd2gcj(bdLat: Double, bdLng: Double) -> (gcjLat: Double, gcjLng: Double) {
if isOutOfChina(lat: bdLat, lng: bdLng) {
return (bdLat, bdLng)
}
let x = bdLng - 0.0065, y = bdLat - 0.006
let z = sqrt(x * x + y * y) - 0.00002 * sin(y * Double.pi)
let theta = atan2(y, x) - 0.000003 * cos(x * Double.pi)
let gcjLng = z * cos(theta)
let gcjLat = z * sin(theta)
return (gcjLat, gcjLng)
}
public static func wgs2bd(wgsLat: Double, wgsLng: Double) -> (bdLat: Double, bdLng: Double) {
let (gcjLat, gcjLng) = wgs2gcj(wgsLat: wgsLat, wgsLng: wgsLng)
return gcj2bd(gcjLat: gcjLat, gcjLng: gcjLng)
}
public static func bd2wgs(bdLat: Double, bdLng: Double) -> (wgsLat: Double, wgsLng: Double) {
let (gcjLat, gcjLng) = bd2gcj(bdLat: bdLat, bdLng: bdLng)
return gcj2wgs(gcjLat: gcjLat, gcjLng: gcjLng)
}
}