GIS算法总结(求经纬度,求距离,求方位角)

公司项目中用到的一些GIS算法,记录一下。所有经纬度都是基于WGS-84标准,为Google Earth上的经纬度。
1.已知两个点的经纬度,求它们的直线距离

python代码实现

from math import *
def getDistance(latA, lonA, latB, lonB):
    ra = 6378140  # radius of equator: meter
    rb = 6356755  # radius of polar: meter
    flatten = (ra - rb) / ra  # Partial rate of the earth
    # change angle to radians
    radLatA = radians(latA)
    radLonA = radians(lonA)
    radLatB = radians(latB)
    radLonB = radians(lonB)
 
    pA = atan(rb / ra * tan(radLatA))
    pB = atan(rb / ra * tan(radLatB))
    x = acos(sin(pA) * sin(pB) + cos(pA) * cos(pB) * cos(radLonA - radLonB))
    c1 = (sin(x) - x) * (sin(pA) + sin(pB))**2 / cos(x / 2)**2
    c2 = (sin(x) + x) * (sin(pA) - sin(pB))**2 / sin(x / 2)**2
    dr = flatten / 8 * (c1 - c2)
    distance = ra * (x + dr)
    return distance
    
distance = getDistance(30.25482684590,120.01375138640,30.25582684590,120.01375138640)
print(distance, '米')

2.已知两个点的经纬度,求它们的方位角

python代码实现

def getDegree(latA, lonA, latB, lonB):
    """
    Args:
        point p1(latA, lonA)
        point p2(latB, lonB)
    Returns:
        bearing between the two GPS points,
        default: the basis of heading direction is north
    """
    radLatA = radians(latA)
    radLonA = radians(lonA)
    radLatB = radians(latB)
    radLonB = radians(lonB)
    dLon = radLonB - radLonA
    y = sin(dLon) * cos(radLatB)
    x = cos(radLatA) * sin(radLatB) - sin(radLatA) * cos(radLatB) * cos(dLon)
    brng = degrees(atan2(y, x))
    brng = (brng + 360) % 360
    return brng
    
brng = getDegree(30.25482684590,120.01375138640,30.25582684590,120.01375138640)
print(brng)

3.已知一个点的经纬度,方位角,距离,求另一点的经纬度

python代码实现

from math import *


def rad(d):
    return d * pi / 180.0


def deg(x):
    return x * 180 / pi


def getLonAndLat(lat, lng, brng, dist):
    a = 6378137
    b = 6356752.3142
    f = 1.0 / 298.257223563

    lon1 = lng * 1
    lat1 = lat * 1
    s = dist
    alpha1 = rad(brng)
    sinAlpha1 = sin(alpha1)
    cosAlpha1 = cos(alpha1)

    tanU1 = (1 - f) * tan(rad(lat1))
    cosU1 = 1 / sqrt((1 + tanU1 * tanU1))
    sinU1 = tanU1 * cosU1
    sigma1 = atan2(tanU1, cosAlpha1)
    sinAlpha = cosU1 * sinAlpha1
    cosSqAlpha = 1 - sinAlpha * sinAlpha
    uSq = cosSqAlpha * (a * a - b * b) / (b * b)
    A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)))
    B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)))

    sigma = s / (b * A)
    sigmaP = 2 * pi
    while abs(sigma - sigmaP) > 1e-12:
        cos2SigmaM = cos(2 * sigma1 + sigma)
        sinSigma = sin(sigma)
        cosSigma = cos(sigma)
        deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
                                                           B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (
                                                                   -3 + 4 * cos2SigmaM * cos2SigmaM)))
        sigmaP = sigma
        sigma = s / (b * A) + deltaSigma

    tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1
    lat2 = atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
                 (1 - f) * sqrt(sinAlpha * sinAlpha + tmp * tmp))
    lambdA = atan2(sinSigma * sinAlpha1, cosU1*cosSigma - sinU1 * sinSigma * cosAlpha1)
    C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha))
    L = lambdA - (1-C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM+C * cosSigma * (-1+2 * cos2SigmaM * cos2SigmaM)))
    revAz = atan2(sinAlpha, -tmp)
    lngLatObj = {'latitude': deg(lat2), 'longitude': lon1 + deg(L), }
    return lngLatObj


print(getLonAndLat(30.2548268459,120.0137513864,0,110.85670061685299))

JavaScript代码实现

            /**
             * 度换成弧度
             * @param  {Float} d  度
             * @return {[Float}   弧度
             */
            function rad (d){
                return d * Math.PI / 180.0;
            };
            /**
             * 弧度换成度
             * @param  {Float} x 弧度
             * @return {Float}   度
             */
            function deg (x){
                return x*180/Math.PI;
            };
            /**
             * 
             * @param {*} lng 经度 113.3960698
             * @param {*} lat 纬度 22.941386
             * @param {*} brng 方位角 45   ---- 正北方:000°或360°  正东方:090° 正南方:180°  正西方:270°
             * @param {*} dist 距离 9000
             * 
            */
            function getLonAndLat (lat,lng,brng,dist){
                //大地坐标系资料WGS-84 长半径a=6378137 短半径b=6356752.3142 扁率f=1/298.2572236
                var a=6378137; 
                var b=6356752.3142; 
                var f=1/298.257223563;

                var lon1 = lng*1;
                var lat1 = lat*1;
                var s = dist;
                var alpha1 = rad(brng);
                var sinAlpha1 = Math.sin(alpha1);
                var cosAlpha1 = Math.cos(alpha1);

                var tanU1 = (1-f) * Math.tan(rad(lat1));
                var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
                var sigma1 = Math.atan2(tanU1, cosAlpha1);
                var sinAlpha = cosU1 * sinAlpha1;
                var cosSqAlpha = 1 - sinAlpha*sinAlpha;
                var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
                var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
                var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));

                var sigma = s / (b*A), sigmaP = 2*Math.PI;
                while (Math.abs(sigma-sigmaP) > 1e-12) {
                    var cos2SigmaM = Math.cos(2*sigma1 + sigma);
                    var sinSigma = Math.sin(sigma);
                    var cosSigma = Math.cos(sigma);
                    var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
                        B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
                    sigmaP = sigma;
                    sigma = s / (b*A) + deltaSigma;
                }

                var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
                var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
                    (1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));
                var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
                var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
                var L = lambda - (1-C) * f * sinAlpha *
                    (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));

                var revAz = Math.atan2(sinAlpha, -tmp);  // final bearing
                
                var lngLatObj = {latitude:deg(lat2),longitude:lon1+deg(L),}
                return lngLatObj;
            }
            //调用
            console.log(getLonAndLat(30.2548268459,120.0137513864,0,110.85670061685299));

  • 6
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: GIS(地理信息系统)中可以利用两个经纬度计算它们之间方位角方位方位角两个之间的连线方向与正北方向之间的夹角,通常是以度数表示。而方位则是指从一个出发到达另一个所需要朝向的方向,通常是用文本描述表示(如“东南方向”)。 计算方位角需要用到三角函数,根据勾股定理可以计算间的直线距离,然后再根据经度和纬度之差计算出两之间的夹角。最后,根据夹角与正北方向之间的关系计算方位角。这个计算过程需要专业的软件支持,例如GIS软件中的测量工具可以直接计算两个方位角方位。 利用这种方法,我们可以在GIS中方便地计算两个之间方位角方位,这对于地图制图、导航以及定位等应用具有重要的作用。例如,在开发地图应用程序时,我们可以利用方位角方位来确定用户的位置和朝向,以提高应用程序的准确性和用户体验。同时,这种计算也可以用于定位和跟踪移动设备的位置,例如车辆追踪和物流管理等领域。 ### 回答2: GIS(地理信息系统)是一种基于计算机处理能力的空间数据管理和分析系统。GIS的应用范围越来越广泛,包括地图制作与更新、城市规划、环境监测、资源管理、农业生产、交通运输等各个领域。而在GIS中,经度和纬度是表示地球表面位置的最常用坐标系统。 在GIS中,通过两经纬度可以确定这两个之间距离方位角方位角是从一个开始沿着大圆轨道前进到另一个所需旋转的角度,可以用数学方法进行计算。通常,方位角是以正北方向为0度,向东逐渐增加至360度的角度值。 确定两之间方位角需要考虑地球椭球体形状对大圆线的影响。由于地球并不是完全规则的球体,因此计算之间距离方位角时需要考虑大圆线的切线方向。这个方向可以通过两经纬度计算来确定,并将结果转化为度数表示。 GIS中常用的计算方法包括:球面三角测量法和椭球体三角测量法。常见的GIS软件都会提供这些计算工具,以帮助用户快速准确地计算间的距离方位角。 总之,通过两经纬度确定方位角方位GIS中非常基础的操作。在实际应用中,这些矢量计算方法可以帮助地理信息分析者更好地理解和分析地理现象,提高地理空间数据的效率和精度。 ### 回答3: 在GIS中,经纬度是一对地理坐标,代表了地球表面上的一个位置。而方位角则是一个方向指标,通常指的是一个相对于另一个的方向。因此,计算通过两经纬度确定方位角方位GIS中的常见操作之一。 要计算方位角方位,必须先知道两个经纬度。在GIS软件中,可以通过手动输入或者从地图中拾取的方式获取这些坐标值。接着,计算之间距离和方向即可得到方位角方位。 具体计算方法如下: 1. 根据经纬度计算间的距离,可以使用海卫公式(haversine formula)、Vincenty公式、球面余弦定理等方法。其中,Vincenty公式是最为精确的方法之一,但计算复杂度较高。如果只是简单计算,可以使用海卫公式。例如,两A和B的经纬度分别为(latA,lonA)和(latB,lonB),则它们之间距离可以计算如下: R = 6371 # 地球半径,单位为千米 dlat = radians(latB - latA) dlon = radians(lonB - lonA) a = sin(dlat/2)**2 + cos(radians(latA)) * cos(radians(latB)) * sin(dlon/2)**2 c = 2 * atan2(sqrt(a), sqrt(1-a)) d = R * c 其中,radians()函数将角度转换为弧度。 2. 根据两间的经纬度计算方向角,可以使用反三角函数或者向量的方法。如果使用反三角函数,可以使用atan2()函数,该函数可根据提供的两个参数计算反正切值。例如,设方向角为θ,则可以计算如下: y = sin(lonB-lonA) * cos(latB) x = cos(latA)*sin(latB) - sin(latA)*cos(latB)*cos(lonB-lonA) θ = atan2(y, x) 其中,sin()、cos()函数计算正弦和余弦值。 3. 根据方向角来确定方位方位通常是以正北为0度,顺时针方向计算的角度,例如东方是90度,南方是180度。如果方向角为负数,则可以将其加上360度,以得到正确的方位角。 通过这个方法,我们可以轻松计算出通过两经纬度确定方位角方位。这对于许多需要基于方向的GIS应用非常重要,例如航线规划、地质探测和导航等。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔法战胜魔法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值