美文网首页
geohash各种计算方法

geohash各种计算方法

作者: 很好就这样吧 | 来源:发表于2023-01-15 18:18 被阅读0次

    Geohash算法介绍

    参考文章:https://blog.csdn.net/usher_ou/article/details/122716877
    GeoHash是空间索引的一种方式,其基本原理是将地球理解为一个二维平面,通过把二维的空间经纬度数据编码为一个字符串,可以把平面递归分解成更小的子块,每个子块在一定经纬度范围内拥有相同的编码。

    以GeoHash方式建立空间索引,可以提高对空间poi数据进行经纬度检索的效率。

    编码规则为:先将纬度范围(-90, 90)平分成两个区间(-90, 0)和(0, 90),如果目标维度位于前一个区间,则编码为0,否则编码为1,然后根据目标纬度所落的区间再平均分成两个区间进行编码,以此类推,直到精度满足要求,经度也用同样的算法,对(-180, 180)依次细分,然后合并经度和纬度的编码,奇数位放纬度,偶数位放经度,组成一串新的二进制编码,按照Base32进行编码。

    算法库

    参考文章:https://blog.csdn.net/qq_41737172/article/details/118539350

    var BASE32_CODES = "0123456789bcdefghjkmnpqrstuvwxyz"
    var BASE32_CODES_DICT = {}
    for (var i = 0; i < BASE32_CODES.length; i++) {
      BASE32_CODES_DICT[BASE32_CODES.charAt(i)] = i
    }
    
    var ENCODE_AUTO = "auto"
    
    var MIN_LAT = -90
    var MAX_LAT = 90
    var MIN_LON = -180
    var MAX_LON = 180
    /**
     * Significant Figure Hash Length
     *
     * This is a quick and dirty lookup to figure out how long our hash
     * should be in order to guarantee a certain amount of trailing
     * significant figures. This was calculated by determining the error:
     * 45/2^(n-1) where n is the number of bits for a latitude or
     * longitude. Key is # of desired sig figs, value is minimum length of
     * the
     * @type Array
     */
    //     Desired sig figs:  0  1  2  3  4   5   6   7   8   9  10
    var SIGFIG_HASH_LENGTH = [0, 5, 7, 8, 11, 12, 13, 15, 16, 17, 18]
    /**
     * Encode
     *
     * Create a Geohash out of a latitude and longitude that is
     * `numberOfChars` long.
     *
     * @param {Number|String} latitude
     * @param {Number|String} longitude
     * @param {Number} numberOfChars
     * @returns {String}
     */
    var encode = function (latitude, longitude, numberOfChars) {
      if (numberOfChars === ENCODE_AUTO) {
        if (typeof latitude === "number" || typeof longitude === "number") {
          throw new Error("string notation required for auto precision.")
        }
        var decSigFigsLat = latitude.split(".")[1].length
        var decSigFigsLong = longitude.split(".")[1].length
        var numberOfSigFigs = Math.max(decSigFigsLat, decSigFigsLong)
        numberOfChars = SIGFIG_HASH_LENGTH[numberOfSigFigs]
      } else if (numberOfChars === undefined) {
        numberOfChars = 9
      }
    
      var chars = [],
        bits = 0,
        bitsTotal = 0,
        hash_value = 0,
        maxLat = MAX_LAT,
        minLat = MIN_LAT,
        maxLon = MAX_LON,
        minLon = MIN_LON,
        mid
      while (chars.length < numberOfChars) {
        if (bitsTotal % 2 === 0) {
          mid = (maxLon + minLon) / 2
          if (longitude > mid) {
            hash_value = (hash_value << 1) + 1
            minLon = mid
          } else {
            hash_value = (hash_value << 1) + 0
            maxLon = mid
          }
        } else {
          mid = (maxLat + minLat) / 2
          if (latitude > mid) {
            hash_value = (hash_value << 1) + 1
            minLat = mid
          } else {
            hash_value = (hash_value << 1) + 0
            maxLat = mid
          }
        }
    
        bits++
        bitsTotal++
        if (bits === 5) {
          var code = BASE32_CODES[hash_value]
          chars.push(code)
          bits = 0
          hash_value = 0
        }
      }
      return chars.join("")
    }
    
    /**
     * Encode Integer
     *
     * Create a Geohash out of a latitude and longitude that is of "bitDepth".
     *
     * @param {Number} latitude
     * @param {Number} longitude
     * @param {Number} bitDepth
     * @returns {Number}
     */
    var encode_int = function (latitude, longitude, bitDepth) {
      bitDepth = bitDepth || 52
    
      var bitsTotal = 0,
        maxLat = MAX_LAT,
        minLat = MIN_LAT,
        maxLon = MAX_LON,
        minLon = MIN_LON,
        mid,
        combinedBits = 0
    
      while (bitsTotal < bitDepth) {
        combinedBits *= 2
        if (bitsTotal % 2 === 0) {
          mid = (maxLon + minLon) / 2
          if (longitude > mid) {
            combinedBits += 1
            minLon = mid
          } else {
            maxLon = mid
          }
        } else {
          mid = (maxLat + minLat) / 2
          if (latitude > mid) {
            combinedBits += 1
            minLat = mid
          } else {
            maxLat = mid
          }
        }
        bitsTotal++
      }
      return combinedBits
    }
    
    /**
     * Decode Bounding Box
     *
     * Decode hashString into a bound box matches it. Data returned in a four-element array: [minlat, minlon, maxlat, maxlon]
     * @param {String} hash_string
     * @returns {Array}
     */
    var decode_bbox = function (hash_string) {
      var isLon = true,
        maxLat = MAX_LAT,
        minLat = MIN_LAT,
        maxLon = MAX_LON,
        minLon = MIN_LON,
        mid
    
      var hashValue = 0
      for (var i = 0, l = hash_string.length; i < l; i++) {
        var code = hash_string[i].toLowerCase()
        hashValue = BASE32_CODES_DICT[code]
    
        for (var bits = 4; bits >= 0; bits--) {
          var bit = (hashValue >> bits) & 1
          if (isLon) {
            mid = (maxLon + minLon) / 2
            if (bit === 1) {
              minLon = mid
            } else {
              maxLon = mid
            }
          } else {
            mid = (maxLat + minLat) / 2
            if (bit === 1) {
              minLat = mid
            } else {
              maxLat = mid
            }
          }
          isLon = !isLon
        }
      }
      return [minLat, minLon, maxLat, maxLon]
    }
    
    /**
     * Decode Bounding Box Integer
     *
     * Decode hash number into a bound box matches it. Data returned in a four-element array: [minlat, minlon, maxlat, maxlon]
     * @param {Number} hashInt
     * @param {Number} bitDepth
     * @returns {Array}
     */
    var decode_bbox_int = function (hashInt, bitDepth) {
      bitDepth = bitDepth || 52
    
      var maxLat = MAX_LAT,
        minLat = MIN_LAT,
        maxLon = MAX_LON,
        minLon = MIN_LON
    
      var latBit = 0, lonBit = 0
      var step = bitDepth / 2
    
      for (var i = 0; i < step; i++) {
        lonBit = get_bit(hashInt, (step - i) * 2 - 1)
        latBit = get_bit(hashInt, (step - i) * 2 - 2)
    
        if (latBit === 0) {
          maxLat = (maxLat + minLat) / 2
        } else {
          minLat = (maxLat + minLat) / 2
        }
    
        if (lonBit === 0) {
          maxLon = (maxLon + minLon) / 2
        } else {
          minLon = (maxLon + minLon) / 2
        }
      }
      return [minLat, minLon, maxLat, maxLon]
    }
    
    function get_bit(bits, position) {
      return (bits / Math.pow(2, position)) & 0x01
    }
    
    /**
     * Decode
     *
     * Decode a hash string into pair of latitude and longitude. A javascript object is returned with keys `latitude`,
     * `longitude` and `error`.
     * @param {String} hashString
     * @returns {Object}
     */
    var decode = function (hashString) {
      var bbox = decode_bbox(hashString)
      var lat = (bbox[0] + bbox[2]) / 2
      var lon = (bbox[1] + bbox[3]) / 2
      var latErr = bbox[2] - lat
      var lonErr = bbox[3] - lon
      return {
        latitude: lat,
        longitude: lon,
        error: { latitude: latErr, longitude: lonErr },
      }
    }
    
    /**
     * Decode Integer
     *
     * Decode a hash number into pair of latitude and longitude. A javascript object is returned with keys `latitude`,
     * `longitude` and `error`.
     * @param {Number} hash_int
     * @param {Number} bitDepth
     * @returns {Object}
     */
    var decode_int = function (hash_int, bitDepth) {
      var bbox = decode_bbox_int(hash_int, bitDepth)
      var lat = (bbox[0] + bbox[2]) / 2
      var lon = (bbox[1] + bbox[3]) / 2
      var latErr = bbox[2] - lat
      var lonErr = bbox[3] - lon
      return {
        latitude: lat,
        longitude: lon,
        error: { latitude: latErr, longitude: lonErr }
      }
    }
    
    /**
     * Neighbor
     *
     * Find neighbor of a geohash string in certain direction. Direction is a two-element array, i.e. [1,0] means north, [-1,-1] means southwest.
     * direction [lat, lon], i.e.
     * [1,0] - north
     * [1,1] - northeast
     * ...
     * @param {String} hashString
     * @param {Array} Direction as a 2D normalized vector.
     * @returns {String}
     */
    var neighbor = function (hashString, direction) {
      var lonLat = decode(hashString)
      var neighborLat = lonLat.latitude + direction[0] * lonLat.error.latitude * 2
      var neighborLon = lonLat.longitude + direction[1] * lonLat.error.longitude * 2
      neighborLon = ensure_valid_lon(neighborLon)
      neighborLat = ensure_valid_lat(neighborLat)
      return encode(neighborLat, neighborLon, hashString.length)
    }
    
    /**
     * Neighbor Integer
     *
     * Find neighbor of a geohash integer in certain direction. Direction is a two-element array, i.e. [1,0] means north, [-1,-1] means southwest.
     * direction [lat, lon], i.e.
     * [1,0] - north
     * [1,1] - northeast
     * ...
     * @param {String} hash_string
     * @returns {Array}
     */
    var neighbor_int = function (hash_int, direction, bitDepth) {
      bitDepth = bitDepth || 52
      var lonlat = decode_int(hash_int, bitDepth)
      var neighbor_lat = lonlat.latitude + direction[0] * lonlat.error.latitude * 2
      var neighbor_lon = lonlat.longitude + direction[1] * lonlat.error.longitude * 2
      neighbor_lon = ensure_valid_lon(neighbor_lon)
      neighbor_lat = ensure_valid_lat(neighbor_lat)
      return encode_int(neighbor_lat, neighbor_lon, bitDepth)
    }
    
    /**
     * Neighbors
     *
     * Returns all neighbors" hashstrings clockwise from north around to northwest
     * 7 0 1
     * 6 x 2
     * 5 4 3
     * @param {String} hash_string
     * @returns {encoded neighborHashList|Array}
     */
    var neighbors = function (hash_string) {
      var hashstringLength = hash_string.length
    
      var lonlat = decode(hash_string)
      var lat = lonlat.latitude
      var lon = lonlat.longitude
      var latErr = lonlat.error.latitude * 2
      var lonErr = lonlat.error.longitude * 2
    
      var neighbor_lat, neighbor_lon
    
      var neighborHashList = [
        encodeNeighbor(1, 0),
        encodeNeighbor(1, 1),
        encodeNeighbor(0, 1),
        encodeNeighbor(-1, 1),
        encodeNeighbor(-1, 0),
        encodeNeighbor(-1, -1),
        encodeNeighbor(0, -1),
        encodeNeighbor(1, -1)
      ]
    
      function encodeNeighbor(neighborLatDir, neighborLonDir) {
        neighbor_lat = lat + neighborLatDir * latErr
        neighbor_lon = lon + neighborLonDir * lonErr
        neighbor_lon = ensure_valid_lon(neighbor_lon)
        neighbor_lat = ensure_valid_lat(neighbor_lat)
        return encode(neighbor_lat, neighbor_lon, hashstringLength)
      }
    
      return neighborHashList
    }
    
    /**
     * Neighbors Integer
     *
     * Returns all neighbors" hash integers clockwise from north around to northwest
     * 7 0 1
     * 6 x 2
     * 5 4 3
     * @param {Number} hash_int
     * @param {Number} bitDepth
     * @returns {encode_int"d neighborHashIntList|Array}
     */
    var neighbors_int = function (hash_int, bitDepth) {
      bitDepth = bitDepth || 52
    
      var lonlat = decode_int(hash_int, bitDepth)
      var lat = lonlat.latitude
      var lon = lonlat.longitude
      var latErr = lonlat.error.latitude * 2
      var lonErr = lonlat.error.longitude * 2
    
      var neighbor_lat, neighbor_lon
    
      var neighborHashIntList = [
        encodeNeighbor_int(1, 0),
        encodeNeighbor_int(1, 1),
        encodeNeighbor_int(0, 1),
        encodeNeighbor_int(-1, 1),
        encodeNeighbor_int(-1, 0),
        encodeNeighbor_int(-1, -1),
        encodeNeighbor_int(0, -1),
        encodeNeighbor_int(1, -1)
      ]
    
      function encodeNeighbor_int(neighborLatDir, neighborLonDir) {
        neighbor_lat = lat + neighborLatDir * latErr
        neighbor_lon = lon + neighborLonDir * lonErr
        neighbor_lon = ensure_valid_lon(neighbor_lon)
        neighbor_lat = ensure_valid_lat(neighbor_lat)
        return encode_int(neighbor_lat, neighbor_lon, bitDepth)
      }
    
      return neighborHashIntList
    }
    
    /**
     * Bounding Boxes
     *
     * Return all the hashString between minLat, minLon, maxLat, maxLon in numberOfChars
     * @param {Number} minLat
     * @param {Number} minLon
     * @param {Number} maxLat
     * @param {Number} maxLon
     * @param {Number} numberOfChars
     * @returns {bboxes.hashList|Array}
     */
    var bboxes = function (minLat, minLon, maxLat, maxLon, numberOfChars) {
      if (numberOfChars <= 0) {
        throw new Error("numberOfChars must be strictly positive")
      }
      numberOfChars = numberOfChars || 9
    
      var hashSouthWest = encode(minLat, minLon, numberOfChars)
      var hashNorthEast = encode(maxLat, maxLon, numberOfChars)
    
      var latLon = decode(hashSouthWest)
    
      var perLat = latLon.error.latitude * 2
      var perLon = latLon.error.longitude * 2
    
      var boxSouthWest = decode_bbox(hashSouthWest)
      var boxNorthEast = decode_bbox(hashNorthEast)
    
      var latStep = Math.round((boxNorthEast[0] - boxSouthWest[0]) / perLat)
      var lonStep = Math.round((boxNorthEast[1] - boxSouthWest[1]) / perLon)
    
      var hashList = []
    
      for (var lat = 0; lat <= latStep; lat++) {
        for (var lon = 0; lon <= lonStep; lon++) {
          hashList.push(neighbor(hashSouthWest, [lat, lon]))
        }
      }
    
      return hashList
    }
    
    /**
     * Bounding Boxes Integer
     *
     * Return all the hash integers between minLat, minLon, maxLat, maxLon in bitDepth
     * @param {Number} minLat
     * @param {Number} minLon
     * @param {Number} maxLat
     * @param {Number} maxLon
     * @param {Number} bitDepth
     * @returns {bboxes_int.hashList|Array}
     */
    var bboxes_int = function (minLat, minLon, maxLat, maxLon, bitDepth) {
      bitDepth = bitDepth || 52
    
      var hashSouthWest = encode_int(minLat, minLon, bitDepth)
      var hashNorthEast = encode_int(maxLat, maxLon, bitDepth)
    
      var latlon = decode_int(hashSouthWest, bitDepth)
    
      var perLat = latlon.error.latitude * 2
      var perLon = latlon.error.longitude * 2
    
      var boxSouthWest = decode_bbox_int(hashSouthWest, bitDepth)
      var boxNorthEast = decode_bbox_int(hashNorthEast, bitDepth)
    
      var latStep = Math.round((boxNorthEast[0] - boxSouthWest[0]) / perLat)
      var lonStep = Math.round((boxNorthEast[1] - boxSouthWest[1]) / perLon)
    
      var hashList = []
    
      for (var lat = 0; lat <= latStep; lat++) {
        for (var lon = 0; lon <= lonStep; lon++) {
          hashList.push(neighbor_int(hashSouthWest, [lat, lon], bitDepth))
        }
      }
    
      return hashList
    }
    
    function ensure_valid_lon(lon) {
      if (lon > MAX_LON) return MIN_LON + (lon % MAX_LON)
      if (lon < MIN_LON) return MAX_LON + (lon % MAX_LON)
      return lon
    }
    
    function ensure_valid_lat(lat) {
      if (lat > MAX_LAT) return MAX_LAT
      if (lat < MIN_LAT) return MIN_LAT
      return lat
    }
    
    // 静态网格相关计算方法拓展--------------------------------------------------------------------------------------start
    
    export const NUM_OF_CHARS = 7 // 静态网格计算所用 geohash 位数
    
    export const ORIGIN_GEOHASH = "v9s1psg" // 中国范围内计算静态网格所用的参考点hash值,在中国范围的左上角
    
    // 获取水平方向下一个静态网格的左上角geohash,
    // 入参:当前静态网格左上角geohash,视图右侧最大经度值,静态网格尺寸(10、14、20)
    // 出参:水平方向下一个静态网格的左上角geohash
    function getHorizontalNextStaticGeohash(hashString, maxLon, stepCount) {
      if (!hashString) return false
      const rightNextGeohash = neighbor(hashString, [0, stepCount])
      const bBox = decode_bbox(rightNextGeohash) //[minLat, minLon, maxLat, maxLon]
      if (bBox[1] > maxLon) {
        return false
      } else {
        return rightNextGeohash
      }
    }
    
    // 获取垂直方向下一个静态网格的左上角geohash
    // 入参:当前静态网格左上角geohash,视图下方最小纬度值,静态网格尺寸(10、14、20)
    // 出参:垂直方向下一个静态网格的左上角geohash
    function getVerticalNextStaticGeohash(hashString, minLat, stepCount) {
      if (!hashString) return false
      const bottomNextGeohash = neighbor(hashString, [-stepCount, 0])
      const bBox = decode_bbox(bottomNextGeohash) //[minLat, minLon, maxLat, maxLon]
      if (bBox[2] < minLat) {
        return false
      } else {
        return bottomNextGeohash
      }
    }
    // 根据静态网格左上角geohash和静态网格尺寸,计算出静态网格的paths点阵围栏
    function getStaticPaths(hashString, stepCount) {
      const leftTop = hashString
      // const lb = neighbor(hashString, [0, 9]);
      // const rt = neighbor(hashString, [0, 9]);
      const rightBottom = neighbor(hashString, [-(stepCount - 1), stepCount - 1])
    
      const bBox_lt = decode_bbox(leftTop) //[minLat, minLon, maxLat, maxLon]
      const bBox_rb = decode_bbox(rightBottom) //[minLat, minLon, maxLat, maxLon]
    
      const minLat = bBox_rb[0]
      const minLon = bBox_lt[1]
      const maxLat = bBox_lt[2]
      const maxLon = bBox_rb[3]
    
      const paths = [
        [minLat, minLon],
        [minLat, maxLon],
        [maxLat, maxLon],
        [maxLat, minLon]
      ]
      const center = [(maxLat + minLat) / 2, (maxLon + minLon) / 2]
      return { paths, center }
    }
    // 获取视图范围内所有静态网格数据:hash:左上角geohash,paths:静态网格点阵围栏
    function getStaticList(firstGeohash, maxLon, minLat, stepCount) {
      let staticList = [{ hash: firstGeohash, ...getStaticPaths(firstGeohash, stepCount) }]
      let current_h = firstGeohash
      do {
        let current_v = current_h
        do {
          current_v = getVerticalNextStaticGeohash(current_v, minLat, stepCount)
          current_v &&
            staticList.push({
              hash: current_v,
              ...getStaticPaths(current_v, stepCount)
            })
        } while (current_v)
        current_h = getHorizontalNextStaticGeohash(current_h, maxLon, stepCount)
        current_h &&
          staticList.push({
            hash: current_h,
            ...getStaticPaths(current_h, stepCount)
          })
      } while (current_h)
      // console.log(staticList);
      return staticList
    }
    
    // 通过 经纬度坐标点 获取该点所在静态网格的左上角geohash
    // 入参:计算点、静态网格尺寸
    function getLeftTopGeohashOfStaticByPoint(LatLngPoint, stepCount) {
      const { lat, lng } = LatLngPoint
      const leftTopGeohash = encode(lat, lng, NUM_OF_CHARS) // wx4kpt1
      const direction = getDirection(leftTopGeohash, stepCount) // [15,-11]
      const firstGeohash = neighbor(leftTopGeohash, direction)
      return firstGeohash
    }
    
    // 静态网格尺寸(10、14、20),计算当前geohash所在静态网格的位置
    // 返回 direction [lat, lon] ---- [15,-11]
    function getDirection(hashString, stepCount) {
      const currentPonit = decode(hashString) //originPonit.latitude, originPonit.longitude
    
      let rightNext = ORIGIN_GEOHASH
      let rightNextPonit = decode(rightNext) //originPonit.latitude, originPonit.longitude
      let count_h = 0 // 水平方向计数,当前geohash与originGeohash间隔的hash个数
      do {
        rightNext = neighbor(rightNext, [0, 1])
        rightNextPonit = decode(rightNext)
        count_h++
      } while (rightNextPonit.longitude < currentPonit.longitude)
      // console.log(count_h, count_h % stepCount);
    
      let bottomNext = ORIGIN_GEOHASH
      let bottomNextPonit = decode(bottomNext) //originPonit.latitude, originPonit.longitude
      let count_v = 0 // 垂直方向计数,当前geohash与originGeohash间隔的hash个数
      do {
        bottomNext = neighbor(bottomNext, [-1, 0])
        bottomNextPonit = decode(bottomNext)
        count_v++
      } while (bottomNextPonit.latitude > currentPonit.latitude)
      // console.log(count_v, count_v % stepCount);
    
      return [count_v % stepCount, -(count_h % stepCount)]
    }
    
    // 计算某矩形范围的左上角geohash所在静态网格的位置,
    // 计算出该静态网格左上角第一个geohash,
    // 从某矩形范围的左上角第一个静态网格开始,计算出 该矩形范围内的所有 静态网格数据
    // 出参:[{hash,  paths, center},...]
    function getStaticListByBounds(LatLngBounds, stepCount) {
      const { _northEast, _southWest } = LatLngBounds
      const minLat = _southWest.lat
      const maxLon = _northEast.lng
      // 矩形范围左上角经纬度坐标点
      const point = { lat: _northEast.lat, lng: _southWest.lng }
      // 矩形范围左上角经纬度坐标点----计算----所在静态网格的左上角的geohash
      const firstGeohash = getLeftTopGeohashOfStaticByPoint(point, stepCount)
      // 矩形范围内所有的静态网的
      const staticList = getStaticList(firstGeohash, maxLon, minLat, stepCount)
      return staticList
    }
    
    // 根据静态网格的尺寸和左上角的geohash,计算出该静态网格内的所有geohash-----自测用
    function getAllHashInStatic(hashString, stepCount) {
      const hashList = []
      // 水平方向 horizontal
      for (let h = 0; h < stepCount; h++) {
        // 垂直方向 vertical
        for (let v = 0; v < stepCount; v++) {
          // hashString反解出所在区域的 最大、最小经度  和 最大、最小纬度  [minLat, minLon, maxLat, maxLon]
          const bBox = decode_bbox(hashString)
          hashList.push({
            hash: neighbor(hashString, [-v, h]),
            paths: [
              [bBox[0], bBox[1]],
              [bBox[0], bBox[3]],
              [bBox[2], bBox[3]],
              [bBox[2], bBox[1]]
            ]
          })
        }
      }
      return hashList
    }
    // 静态网格相关计算方法拓展-----------------------------------------------------------------------------------------end
    
    var geohash = {
      ENCODE_AUTO: ENCODE_AUTO,
      encode: encode,
      encode_uint64: encode_int, // keeping for backwards compatibility, will deprecate
      encode_int: encode_int,
      decode: decode,
      decode_int: decode_int,
      decode_uint64: decode_int, // keeping for backwards compatibility, will deprecate
      decode_bbox: decode_bbox,
      decode_bbox_uint64: decode_bbox_int, // keeping for backwards compatibility, will deprecate
      decode_bbox_int: decode_bbox_int,
      neighbor: neighbor,
      neighbor_int: neighbor_int,
      neighbors: neighbors,
      neighbors_int: neighbors_int,
      bboxes: bboxes,
      bboxes_int: bboxes_int,
      getHorizontalNextStaticGeohash: getHorizontalNextStaticGeohash,
      getVerticalNextStaticGeohash: getVerticalNextStaticGeohash,
      getStaticPaths: getStaticPaths,
      getStaticList: getStaticList,
      getStaticListByBounds: getStaticListByBounds,
      getDirection: getDirection,
      getAllHashInStatic: getAllHashInStatic
    }
    
    //module.exports = geohash;
    
    export default geohash
    
    

    相关文章

      网友评论

          本文标题:geohash各种计算方法

          本文链接:https://www.haomeiwen.com/subject/ohuacdtx.html