计算两个经纬度的距离和角度值

发布时间 2023-12-21 09:14:34作者: echo_lovely

/**
 * 计算第二个坐标对相对于第一个坐标的方位和距离
 * @param {Array</number>} coordinates 坐标数组
 * @returns 第二个坐标到第一个坐标的距离和方位
 */
function calcAngleAndDistance(coordinates) {
  const lonlats = coordinates.map(e => { return ol.proj.toLonLat(e) })
  const lon1 = lonlats[0][0]
  const lat1 = lonlats[0][1]
  const lon2 = lonlats[1][0]
  const lat2 = lonlats[1][1]
  const distanceKm = calcDistanceByLatLon(lonlats[0], lonlats[1])

  const degree = calculateInitialBearing(lat1, lon1, lat2, lon2)
  return [distanceKm, degree]
}

/**
 * 计算两个经纬度坐标对之间的距离,单位: km
 * @param {Array} coord1 第一个点的经纬度 [lat, lon]
 * @param {Array} coord2 第二个点的经纬度 [lat, lon]
 * @returns 两个坐标对之间的距离,保留两位小数,单位 km
 */
function calcDistanceByLatLon(coord1, coord2) {
  const R = 6378.137
  const a = toRadians(coord1[0]) - toRadians(coord2[0])
  const b = toRadians(coord1[1]) - toRadians(coord2[1])
  const result = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(coord1[0]) * Math.cos(coord2[0]) * Math.pow(Math.sin(b / 2), 2))) * R
  return Math.round(result * 100) / 100
}

/**
 * 将经度/纬度转化为弧度
 * @param {number} degrees 经度或者纬度值
 * @returns 该值对应的弧度值
 */
function toRadians(degrees) {
  return degrees * Math.PI / 180
}

/**
 * 将弧度值转为对应的角度值
 * @param {number} radians 弧度制
 * @returns 将弧度制转换为对应的角度值
 */
function toDegrees(radians) {
  return radians * 180 / Math.PI
}

/**
 * 计算第二个点在第一个点的方位角,以正北为零
 * @param {number} lat1 第一个点的纬度值
 * @param {number} lon1 第一个点的经度值
 * @param {number} lat2 第二个点的纬度值
 * @param {number} lon2 第二个点的经度值
 * @returns 第二个点在第一个点的方位,角度值,正北为零
 */
function calculateInitialBearing(lat1, lon1, lat2, lon2) {
  var deltaLon = toRadians(lon2 - lon1)
  var x = Math.cos(toRadians(lat2)) * Math.sin(deltaLon)
  var y = Math.cos(toRadians(lat1)) * Math.sin(toRadians(lat2)) -
                Math.sin(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.cos(deltaLon)
  var bearing = Math.atan2(x, y)
  return Math.round((toDegrees(bearing) + 360) % 360 * 100) / 100
}