算法-入门篇(球面距离)

这篇博客介绍了球面上两点间距离的计算公式,适用于地理定位的计算。内容包括概念解释、应用场景及代码实现,帮助读者理解并运用该算法进行距离判断。

概述

球面距离公式是计算球面上两点间距离的公式。设所求点A ,纬度角β1 ,经度角α1 ;点B ,纬度角β2 ,经度角α2。则距离S=R·arc cos[cosβ1cosβ2cos(α1-α2)+sinβ1sinβ2],其中R为球体半径。
详见 百度百科https://baike.baidu.com/item/%E7%90%83%E9%9D%A2%E8%B7%9D%E7%A6%BB%E5%85%AC%E5%BC%8F/5374455?fr=aladdin

数学模型
在这里插入图片描述
计算公式

L=R·arc cos[cos(wA)cos(wB)cos(jB-jA) + sin(wA)sin(wB)]
补充:

  • 弧长=弧度*R -------------弧度=角度 x (π/180)
  • 因为180°=π(π是弧度单位) 两边同÷180 得1°=π/180弧度

使用

球面距离在开发中一般用在,地理位置的位移量计算中。


本文将根据 风控系统中,用户登录的位移量评估 简单介绍此算法的使用。

一般的,我们再日志中,可以获取客户端的登录IP,根据IP将可以得到 地理位置经纬度,根据前一次登录的经纬度下一次的登录的经纬度做对比,如果,在这两个时间的间隔时间内,发生了超乎寻常的平均位移量,将判断为有风险。

代码实现

 public boolean doEval(long evaluateTime, GeoPoint currentGeoPoint,long lastLoginTime,GeoPoint lastLoginGeoPoint){
      //判断如果没有上一次登陆的地理位置,则不进行评估
        if(lastLoginGeoPoint==null){
            return false;
        }else {
            /**
             * 第一步,求2个时间段的时间差
             */
            //当前时间减去上一次的登录时间  单位时间 小时  3600*1000 ==>得到1小时的毫秒值
            Double time = (evaluateTime-lastLoginTime)*1.0/(3600*1000);
            /**
             * 第二步,计算地球上2个坐标之间的距离
             */
            Double distanc = geoDistance(currentGeoPoint,lastLoginGeoPoint);
            /**
             * 第三步,计算位移的平均速度
             */
            Double speed = distanc/time ;
            System.out.println("speed = " + speed);
            return speed>thresholdSpeed;
        }
    }

    //提供一个计算球体上两点间距离的方法 S = R*arCos(COSw1*COSw2*COS(j2-ji)+SINw1*SINw2)
    public Double geoDistance(GeoPoint currentGeo,GeoPoint lastGeo){
     	private static final Double EARTH_RADIUS=6371.393;//千米
        //将角速值转换为弧度
        //w - 表示 纬度 j - 表示经度
        Double Aw = toRadians(currentGeo.getLatitude());
        Double Aj = toRadians(currentGeo.getLongtitude());

        Double Bw = toRadians(lastGeo.getLatitude());
        Double Bj = toRadians(lastGeo.getLongtitude());

        //使用公式进行计算
        Double acos = acos(cos(Aw) * cos(Bw) * cos(Bj - Aj) + sin(Aw) * sin(Bw));
        return EARTH_RADIUS*acos;
    }

测试

public static void main(String[] args) throws ParseException {
        SpeedEvaluate speedEvaluate = new SpeedEvaluate(600.0);//设置位移阈值
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long evaluateTime=sdf.parse("2020-04-01 10:10:00").getTime();
        GeoPoint p1=new GeoPoint();
        p1.setLongtitude(116.2317);//京
        p1.setLatitude(39.5427);

        long lastLoginTime=sdf.parse("2020-04-01 08:00:00").getTime();
        GeoPoint p2=new GeoPoint();
        p2.setLongtitude(114.14);//豫
        p2.setLatitude(34.16);

        speedEvaluate.doEval(evaluateTime,p1,lastLoginTime,p2);
    }
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值