const scaleCache = {}, earthDiameter = 12756274, deg2rad = Math.PI / 180, rad2deg = 180 / Math.PI, quadPI = Math.PI / 4, half2PI = 0.5 / Math.PI function getScale(level) { scaleCache[level] || (scaleCache[level] = 256 * Math.pow(2, level)) return scaleCache[level] } function project(lnglat) { let lat = lnglat[1], x = lnglat[0] * deg2rad, y = lat * deg2rad y = Math.log(Math.tan(quadPI + y / 2)) return [x, y] } function transform(point, scale) { scale = scale || 1 const a = half2PI, b = 0.5, c = -a, d = 0.5 return [scale * (a * point[0] + b), scale * (c * point[1] + d)] } function unproject(point) { const lng = point[0] * rad2deg, lat = (2 * Math.atan(Math.exp(point[1])) - Math.PI / 2) * rad2deg return [parseFloat(lng.toFixed(6)), parseFloat(lat.toFixed(6))] } function untransform(point, scale) { const a = half2PI, b = 0.5, c = -a, d = 0.5 return [(point[0] / scale - b) / a, (point[1] / scale - d) / c] } function lngLatToPointByScale(lnglat, scale, round) { const p = transform(project(lnglat), scale) if (round) { p[0] = Math.round(p[0]) p[1] = Math.round(p[1]) } return p } function lngLatToPoint(lnglat, level, round?: any) { return lngLatToPointByScale(lnglat, getScale(level), round) } function pointToLngLat(point, level) { const scale = getScale(level), untransformedPoint = untransform(point, scale) return unproject(untransformedPoint) } function haversineDistance(point1, point2) { const cos = Math.cos, lat1 = point1[1] * deg2rad, lon1 = point1[0] * deg2rad, lat2 = point2[1] * deg2rad, lon2 = point2[0] * deg2rad, dLat = lat2 - lat1, dLon = lon2 - lon1, a = (1 - cos(dLat) + (1 - cos(dLon)) * cos(lat1) * cos(lat2)) / 2 return earthDiameter * Math.asin(Math.sqrt(a)) } export default { haversineDistance, getScale, lngLatToPointByScale, pointToLngLat, lngLatToPoint }