球面两点间的球面距离的计算(2)

球面两点间的球面距离的计算(2)

 

1.计算

上篇中提到了两点间球面距离的计算的理论基础,在这篇中,进行计算。

 

同样,假设点A的经度为东经a1度,纬度为北纬b1度;点B的经度为东经a2度,纬度为南纬b2度。

所以α =  b1, β = b2, 设ACE的值为θ,那么θ = |a1 – a2|。

可以计算出

|OC| = R * sin(α)      |OD| = R * sin(β)

|AC| = R * cos(α)      |BD| = R * cos(β)

   

    由于|CE| = |BD|,|CD| = |OD| + |OC|

    由余弦定理可以知道

    |AE|2 = |AC|2 + |CE|2 – 2 * |AC| *|CE| * cos(θ)

ð        |AE|2 = R2 * cos2 (α) + R2 * cos2 (β) - 2 * R2 * cos(α)cos(β) * cos(θ)

 

|BE| = |CD|

|AB|2 = |AE|2 + |BE|2

ð        |AB|2 = R2 * cos2 (α) + R2 * cos2 (β) - 2 * R2 * cos(α)cos(β) * cos(θ) + R2 * sin2 (α) + R2 * sin2 (β) + 2 * R2 * sin(α) sin(β)

ð        |AB|2 = 2R2 (1 + sin(α) sin(β) - cos2 (α) cos2 (β) cos(θ))

 

在三角形AOB中,亦可用余弦定理得到

ð        |OA|2 + |OB|2– 2 |OA| * |OB| * cos(AOB) = |OB|2

ð        cos(AOB) = cos(α) * cos(β) * cos(θ) - sin(α) sin(β)

 

这样可以求出AOB的值(单位为弧度),最后球面距离为R * (AOB)。

完毕,呵呵。

 

注意到,

1)当A、B同为东经或同为西经时,θ = |a1 – a2|,那么当 A、B不是同为东经或同为西经时,θ = |a1 + a2|,若θ > 180度,θ = 360 -θ(假设单位是角度,而不是弧度)。

2)当A、B同为南半球或同为北半球时,|CD| = | |OC| - |OD| |,当A、B在不同的南北半球时,才是|CD| = |OC| + |OD|。

 

 

2.编程实现

1)函数接口定义

int CalGlobeDistance(const ST_GlobePnt a_stPntA,

const ST_GlobePnt a_stPntB,

const double a_dRadius,

double &a_dDistance)

 

返回值:

    0:执行OK,返回值正确;

1:a_stPntA 或a_stPntB 的东经、西经取值错误;

2:a_stPntA 或a_stPntB的南纬、北纬取值错误;

3:a_stPntA 或a_stPntB的经度范围越界;

4:a_stPntA 或a_stPntB的纬度范围越界;

10:半径取值错误(不能小于0)。

 

参数:

a_stPntA

    给定的第一个点的坐标,关于结构体ST_GlobePnt的请参照以下的ST_GlobePnt定义;

 

a_stPntB

    给定的第二个点的坐标,关于结构体ST_GlobePnt的请参照以下的ST_GlobePnt定义;

 

a_dRadius

给定的球体的半径,取值不能小于0;

 

a_dDistance

最后求得的球面距离,如果在计算过程中出现错误,则其值为负数。

 

结构体ST_GlobePnt

 

typedef struct

{

    byte btEorW;      // 取值为1,东经; 0,西经;

    byte btNorS;      // 取值为1,北纬; 0,南纬;   

    double dLong;     // 经度,取值范围[0.0,180.0)

    double dLat;      // 纬度,取值范围[0.0,90.0]

}ST_GlobePnt;

 

 

2程序代码

 

常量定义

typedef struct

{

char btEorW;        // 取值为1,东经; 0,西经;

char btNorS;        // 取值为1,北纬; 0,南纬;   

double dLong;       // 经度,取值范围[0.0,180.0)

double dLat;        // 纬度,取值范围[0.0,90.0]

}ST_GlobePnt;

 

const char EAST = 1;

const char WEST = 0;

const char NORTH = 1;

const char SOUTH = 0;

 

const int EXC_OK = 0;        // 0:执行OK,返回值正确;

const int EorW_ERROR = 1;    // 1:东经、西经取值错误;

const int NorS_ERROR = 2;    // 2:南纬、北纬取值错误;

const int LONG_ERROR = 3;    // 3:经度范围越界;

const int LAT_ERROR = 4;     // 4: 纬度范围越界;

const int RADIUS_ERROR = 10;  // 10:半径取值错误(不能小于0)。

 

const double ACCURACY = 0.00001;    // 精确度

 

const double PI = 3.14159265359;

 

函数实现

辅助函数int CheckGPnt(const ST_GlobePnt &a_stPnt)

    功能判断点是否符合要求,实现如下:

 

int CheckGPnt(const ST_GlobePnt &a_stPnt)

{

    int iRet = EXC_OK;

   

    // check if east or west

    if(a_stPnt.btEorW != EAST && a_stPnt.btEorW != WEST)

    {

        iRet = EorW_ERROR;

        return iRet;

    }

   

    // check if nort or south

    if(a_stPnt.btNorS != NORTH && a_stPnt.btNorS != SOUTH)

    {

        iRet = EorW_ERROR;

        return iRet;

    }

   

    // check the range of Long.

    if(a_stPnt.dLong - 180.0 > ACCURACY || a_stPnt.dLong <= - ACCURACY)

    {

        iRet = LONG_ERROR;

        return iRet;       

    }

   

    // check the range of Lat

    if(a_stPnt.dLat - 90.0 > ACCURACY || a_stPnt.dLat <= -ACCURACY)

    {

        iRet = LAT_ERROR;

        return iRet;

    }   

   

    return iRet;

   

}

 

 

接口函数如下:

int CalGlobeDistance(const ST_GlobePnt &a_stPntA,

                    const ST_GlobePnt &a_stPntB,

                    const double &a_dRadius,

                    double &a_dDistance)

{

    int iRet = EXC_OK;   

    a_dDistance = -1.0;

 

     double dTheta;    // the angle of the two Longs

     double dAlpha;    // the angle of a_stPntA's Lat

     double dBeta;     // the angle of a_stPntB's Lat  

     double dResult;   // the angle of the two lines

                       //     which one is through the given point and the center

     double dCosResult; // = cos(dResult);

 

   // Check if the given points is OK --Begin-------   

    iRet = CheckGPnt(a_stPntA);

    if(iRet != EXC_OK)

    {

        return iRet;

    }

   

    iRet = CheckGPnt(a_stPntB);

    if(iRet != EXC_OK)

    {

        return iRet;

    }

   // Check if the given points is OK --End--------- 

 

   // check the range of Radius

    if(a_dRadius < -ACCURACY)

    {

        iRet = RADIUS_ERROR;

        return iRet;

    }

   

    dAlpha = a_stPntA.dLat;

    dBeta = a_stPntB.dLat;

   

   

    // Calculate the the angle of the two Longs --- Begin --------

    if(a_stPntA.btEorW == a_stPntB.btEorW)

    {

        dTheta = fabs(a_stPntA.dLong - a_stPntB.dLong);   

    }else // !=

    {

        dTheta = a_stPntA.dLong + a_stPntB.dLong;

    }

       

    if(dTheta - 180.00 > -ACCURACY)

    {

        dTheta = 360.0 - dTheta;

    }

    // Calculate the the angle of the two Longs --- End -------- 

    // Change DEGREE to RADIAN     --- Begin ------

    dAlpha = dAlpha / 180.0 * PI;

dBeta = dBeta / 180.0 * PI;

dTheta = dTheta / 180.0 * PI;

    // Change DEGREE to RADIAN     --- End ------ 

 

    // Calculate the angle of the two lines  --- Begin ---------

    if(a_stPntA.btNorS != a_stPntB.btNorS)

    {

        dCosResult = cos(dAlpha) * cos(dBeta) * cos(dTheta) - sin(dAlpha) * sin(dBeta);

    }else // !=

    {

        dCosResult = cos(dAlpha) * cos(dBeta) * cos(dTheta) + sin(dAlpha) * sin(dBeta);

    }

   

    dResult = acos(dCosResult);//  dResult ranges [0,Pi],needn't change

    // Calculate the angle of the two lines  --- End ---------

   

    // Get the distance around the globe

    a_dDistance = a_dRadius * dResult;           

   

    return iRet;

}

 

 

3补充说明

利用程序计算,可能存在一定的误差,减少误差的方法可能用到计算方法中提到的算法,呼呼,先告一段落,暂不考虑这个吧。


3.关于本文

    本文的版本为 Version 1.2 ,于 2007 5 8 日,在 1.1 的基础上稍作修改。 Version 1.1 ,完稿于 2005 1 12 日。

    你可以到我的个人主页http://zijinshi.cn(网站服务器在国外,可能需要代理服务器才能访问)中找到本文原文和相关源代码,当然,你也可以从我的bloghttp://blog.csdn.net/zijinshi 上找到这篇文章。

    我的Email:frank@zijinshi.cn, 欢迎不吝赐教。☺

(完)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 在MATLAB中,可以使用haversine公式来计算两个经纬坐标之球面距离。具体步骤如下: 1. 首先,将经纬坐标转换为弧制。这可以通过将经纬值除以180再乘以π来实现。 2. 然后,使用haversine公式来计算球面距离。haversine公式如下: d = 2 * R * asin(sqrt(sin((lat2-lat1)/2)^2 + cos(lat1) * cos(lat2) * sin((lon2-lon1)/2)^2)) 其中,d是距离,R是地球的半径(一般情况下为6371千米),lat1和lon1是第一个点的纬和经,lat2和lon2是第二个点的纬和经。 3. 最后,根据需要可以将距离换算为其他单位。 下面是一个MATLAB代码示例,可以根据上述步骤计算两个经纬坐标之球面距离: ```matlab function distance = calculateDistance(lat1, lon1, lat2, lon2) R = 6371; % 地球半径,单位:千米 % 将经纬转换为弧制 lat1 = deg2rad(lat1); lon1 = deg2rad(lon1); lat2 = deg2rad(lat2); lon2 = deg2rad(lon2); % 使用haversine公式计算球面距离 dlat = lat2 - lat1; dlon = lon2 - lon1; a = sin(dlat/2)^2 + cos(lat1) * cos(lat2) * sin(dlon/2)^2; c = 2 * atan2(sqrt(a), sqrt(1-a)); distance = R * c; end ``` 使用这个函数,可以通过传入经纬坐标调用该函数来计算两点球面距离。例如: ```matlab lat1 = 31.21563; lon1 = 121.50891; lat2 = 39.90420; lon2 = 116.40740; distance = calculateDistance(lat1, lon1, lat2, lon2); disp(distance); % 输出球面距离,单位:千米 ``` 运行以上代码,将会输出上海和北京之球面距离约为1030千米。 ### 回答2: 在Matlab中,计算两点球面距离可以利用Haversine公式。该公式基于经纬坐标系,以一个球体来近似地描述地球的形状,计算两点的弧长。以下是一个实现该功能的简单示例代码: ```matlab function distance = computeDistance(lat1, lon1, lat2, lon2) % 地球的平均半径(单位:千米) radius = 6371; % 将角转换为弧 lat1 = deg2rad(lat1); lon1 = deg2rad(lon1); lat2 = deg2rad(lat2); lon2 = deg2rad(lon2); % 计算两点的差值 dlat = lat2 - lat1; dlon = lon2 - lon1; % 使用Haversine公式计算球面距离 a = sin(dlat/2)^2 + cos(lat1) * cos(lat2) * sin(dlon/2)^2; c = 2 * atan2(sqrt(a), sqrt(1-a)); distance = radius * c; end ``` 在上述代码中,`lat1`和`lon1`表示第一个坐标点的纬和经,`lat2`和`lon2`表示第二个坐标点的纬和经。最终,函数返回两点球面距离。注意,这里使用的是地球的平均半径,该值为6371公里。 你可以调用这个函数并传入相应的经纬数据,以计算得到两点球面距离。 ### 回答3: 在Matlab中,我们可以使用Haversine公式来计算两点球面距离,该公式适用于两点的直线距离小于200km的情况。首先,我们需要获取两个点的经纬坐标。 假设点A的经纬坐标为(A_lat, A_lon),点B的经纬坐标为(B_lat, B_lon),则可以使用以下代码计算两点球面距离: ```matlab function distance = calculateDistance(A_lat, A_lon, B_lat, B_lon) R = 6371; % 地球半径(单位:km) % 将角转换为弧 lat1 = deg2rad(A_lat); lon1 = deg2rad(A_lon); lat2 = deg2rad(B_lat); lon2 = deg2rad(B_lon); % 使用Haversine公式计算球面距离 delta_lat = lat2 - lat1; delta_lon = lon2 - lon1; a = sin(delta_lat/2)^2 + cos(lat1) * cos(lat2) * sin(delta_lon/2)^2; c = 2 * atan2(sqrt(a), sqrt(1-a)); distance = R * c; end ``` 使用上述函数即可计算两个经纬坐标点之球面距离。函数参数A_lat、A_lon分别表示点A的纬和经,B_lat、B_lon表示点B的纬和经。最后,返回的距离单位为千米(km)。 例如,我们可以调用该函数进行实际计算: ```matlab A_lat = 39.9042; A_lon = 116.4074; B_lat = 31.2304; B_lon = 121.4737; distance = calculateDistance(A_lat, A_lon, B_lat, B_lon); disp(distance); % 输出两个点之球面距离(单位:km) ``` 通过以上示例,我们可以用Matlab计算任意两点球面距离。注意,如果两点的直线距离大于200km,我们应该使用其他更精确的球面距离计算方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值