经纬度计算

下面的代码是一个工具类,可直接拿去使用。

package com.framework.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.stereotype.Service;

import com.framework.entity.base.JcZd;
import com.framework.entity.business.YwClxx;
import com.framework.redis.GetRedisPool;
import com.framework.redis.RedisPrefix;
 import com.framework.redis.SerializeUtil;


@Service
public class GpsDistanceUtils {
// 常量定义如下: Crew
// WGS-84 长轴半径
private double EARTH_WGS84_A = 6378137.0000; // WGS-84Semi-major axis in
                                                // meters
// WGS-84 短轴半径
private double EARTH_WGS84_B = 6356752.3142; // WGS-84 Semi-minor axis in
                                                // meters
// WGS-84 偏心率的平方
private double EARTH_WGS84_E2 = 0.00669437999013; // WGS-84 Eccentricity
                                                    // squared
private double EARTH_WGS84_MPM = 1852.0; // meters per nmile
// WGS-84 地球扁率
private double EARTH_WGS84_FLATTENING = 298.257223563; // WGS-84 Flattening
// 圆周率
private double PI = 3.14159265359;

/**
 * 度为单位 返回公里 - 纬度1,经度1,纬度2,经度2
 * @param dLatitude
 * @param dLongitude
 * @param dLatitude1
 * @param dLongitude1
 * @return
 */
public double mileEarthDis(double dLatitude, double dLongitude, double dLatitude1, double dLongitude1) {
    double D, dis;
    double tmpVal;
    double fi1, fi2;
    double drda = dLongitude1 - dLongitude;
    drda = drda * PI / 180.0;// in radians
    fi1 = dLatitude;
    fi2 = dLatitude1;

    fi1 = fi1 * PI / 180.0;// in in radians
    fi2 = fi2 * PI / 180.0;// in in radians

    tmpVal = Math.sin(fi1) * Math.sin(fi2) + Math.cos(fi1) * Math.cos(fi2) * Math.cos(drda);
    if (Math.abs(tmpVal) > 1.0)
        return 0;
    D = Math.acos(tmpVal);// in radians
    if (D == 0)
        return 0;
    double tmp1, tmp2;
    tmp1 = (Math.sin(fi1) + Math.sin(fi2));
    tmp2 = (Math.sin(fi1) - Math.sin(fi2));
    tmpVal = ((3 * Math.sin(D) - D) * tmp1 * tmp1) / (1 + Math.cos(D));
    tmpVal = tmpVal - ((3 * Math.sin(D) + D) * tmp2 * tmp2) / (1 - Math.cos(D));

    dis = EARTH_WGS84_A * D + (EARTH_WGS84_A / (4 * EARTH_WGS84_FLATTENING)) * tmpVal;
    dis = dis / 1000;
    // System.out.println(" Dis is: " + dis);
    return dis;
}

/**
 * 度为单位 返回米 - 纬度1,经度1,纬度2,经度2
 * @param dLatitude
 * @param dLongitude
 * @param dLatitude1
 * @param dLongitude1
 * @return
 */
public double earthDis(double dLatitude, double dLongitude, double dLatitude1, double dLongitude1) {
    double D, dis;
    double tmpVal;
    double fi1, fi2;
    double drda = dLongitude1 - dLongitude;
    drda = drda * PI / 180.0;// in radians
    fi1 = dLatitude;
    fi2 = dLatitude1;

    fi1 = fi1 * PI / 180.0;// in in radians
    fi2 = fi2 * PI / 180.0;// in in radians

    tmpVal = Math.sin(fi1) * Math.sin(fi2) + Math.cos(fi1) * Math.cos(fi2) * Math.cos(drda);
    if (Math.abs(tmpVal) > 1.0)
        return 0;
    D = Math.acos(tmpVal);// in radians
    if (D == 0)
        return 0;
    double tmp1, tmp2;
    tmp1 = (Math.sin(fi1) + Math.sin(fi2));
    tmp2 = (Math.sin(fi1) - Math.sin(fi2));
    tmpVal = ((3 * Math.sin(D) - D) * tmp1 * tmp1) / (1 + Math.cos(D));
    tmpVal = tmpVal - ((3 * Math.sin(D) + D) * tmp2 * tmp2) / (1 - Math.cos(D));

    dis = EARTH_WGS84_A * D + (EARTH_WGS84_A / (4 * EARTH_WGS84_FLATTENING)) * tmpVal;

    // System.out.println(" Dis is: " + dis);
    return dis;
}

/**
 * 分为单位 返回公里 - 纬度1,经度1,纬度2,经度2
 * @param dLatitude_FEN
 * @param dLongitude_FEN
 * @param dLatitude1_FEN
 * @param dLongitude1_FEN
 * @return
 */
public double mileEarthDisFEN(double dLatitude_FEN, double dLongitude_FEN, double dLatitude1_FEN, double dLongitude1_FEN) {
    double dis;
    double dLatitude_DU = dLatitude_FEN / 60;
    double dLongitude_DU = dLongitude_FEN / 60;
    double dLatitude1_DU = dLatitude1_FEN / 60;
    double dLongitude1_DU = dLongitude1_FEN / 60;
    dis = mileEarthDis(dLatitude_DU, dLongitude_DU, dLatitude1_DU, dLongitude1_DU);
    return dis;
}

/**
 * 分为单位 返回米 - 纬度1,经度1,纬度2,经度2
 * @param dLatitude_FEN
 * @param dLongitude_FEN
 * @param dLatitude1_FEN
 * @param dLongitude1_FEN
 * @return
 */
public double earthDisFEN(double dLatitude_FEN, double dLongitude_FEN, double dLatitude1_FEN, double dLongitude1_FEN) {
    double dis;
    double dLatitude_DU = dLatitude_FEN / 60;
    double dLongitude_DU = dLongitude_FEN / 60;
    double dLatitude1_DU = dLatitude1_FEN / 60;
    double dLongitude1_DU = dLongitude1_FEN / 60;
    dis = earthDis(dLatitude_DU, dLongitude_DU, dLatitude1_DU, dLongitude1_DU);
    return dis;
}

/**
 * 分的1000倍为单位 返回公里 - 纬度1,经度1,纬度2,经度2
 * @param dLatitude_ThousandFEN
 * @param dLongitude_ThousandFEN
 * @param dLatitude1_ThousandFEN
 * @param dLongitude1_ThousandFEN
 * @return
 */
public double mileEarthDisThousandFEN(int dLatitude_ThousandFEN, int dLongitude_ThousandFEN, int dLatitude1_ThousandFEN, int dLongitude1_ThousandFEN) {
    double dis;
    double dLatitude_DU = dLatitude_ThousandFEN * 1.00000000 / 60000;
    double dLongitude_DU = dLongitude_ThousandFEN * 1.00000000 / 60000;
    double dLatitude1_DU = dLatitude1_ThousandFEN * 1.00000000 / 60000;
    double dLongitude1_DU = dLongitude1_ThousandFEN * 1.00000000 / 60000;
    dis = mileEarthDis(dLatitude_DU, dLongitude_DU, dLatitude1_DU, dLongitude1_DU);
    return dis;
}

/**
 * 分的1000倍为单位 返回米 - 纬度1,经度1,纬度2,经度2
 * @param dLatitude_ThousandFEN
 * @param dLongitude_ThousandFEN
 * @param dLatitude1_ThousandFEN
 * @param dLongitude1_ThousandFEN
 * @return
 */
public double earthDisThousandFEN(int dLatitude_ThousandFEN, int dLongitude_ThousandFEN, int dLatitude1_ThousandFEN, int dLongitude1_ThousandFEN) {
    double dis;
    double dLatitude_DU = dLatitude_ThousandFEN * 1.00000000 / 60000;
    double dLongitude_DU = dLongitude_ThousandFEN * 1.00000000 / 60000;
    double dLatitude1_DU = dLatitude1_ThousandFEN * 1.00000000 / 60000;
    double dLongitude1_DU = dLongitude1_ThousandFEN * 1.00000000 / 60000;
    dis = earthDis(dLatitude_DU, dLongitude_DU, dLatitude1_DU, dLongitude1_DU);
    return dis;
}

/**
 * 两个角度差 输入值 0~360 ; 返回值 0~360; 
 * @param StationAngle_R
 * @param n_Course
 * @return
 */
public int getCourseDes(int StationAngle_R, int n_Course) {
    int Angle_R_des = 360;

    if (StationAngle_R >= 270 && n_Course <= 90) {
        Angle_R_des = n_Course + 360 - StationAngle_R;
    } else if (n_Course >= 270 && StationAngle_R <= 90) {
        Angle_R_des = StationAngle_R + 360 - n_Course;
    } else {
        Angle_R_des = (StationAngle_R > n_Course) ? (StationAngle_R - n_Course) : (n_Course - StationAngle_R);
    }

    return Angle_R_des;
}

/**
 * z 出发点, 坐标参考点; 1 目标点;
 * @param xz
 * @param yz
 * @param x1
 * @param y1
 * @return
 */
public int get2PtAngle(int xz, int yz, int x1, int y1) {
    int ndx = x1 - xz;
    int ndy = y1 - yz;
    double dAng = 0;
    int nAng = 0;

    if (ndy == 0 && ndx == 0) // 全0 不计算
    {
        return -1;
    } else if (ndy != 0 && ndx == 0) // x0 竖直
    {
        if (ndy > 0) {
            nAng = 0;
        } else {
            nAng = 180;
        }

    } else if (ndy == 0 && ndx != 0) // y0 水平
    {
        if (ndx > 0) {
            nAng = 90;
        } else {
            nAng = 270;
        }

    } else {
        dAng = Math.atan2((double) ndx, (double) ndy);

        nAng = (int) (dAng / PI * 180 + 0.5);

        if (nAng < 0) {
            nAng += 360;
        }
    }

    return nAng;
}

/**
 * 分的1000倍为单位 返回li米 - 纬度1,经度1,纬度2,经度2
 * @param dLatitude_ThousandFEN
 * @param dLongitude_ThousandFEN
 * @param dLatitude1_ThousandFEN
 * @param dLongitude1_ThousandFEN
 * @return
 */
public double earthDisThousandFEN100(int dLatitude_ThousandFEN, int dLongitude_ThousandFEN, int dLatitude1_ThousandFEN, int dLongitude1_ThousandFEN) {
    double dis;
    double dLatitude_DU = dLatitude_ThousandFEN * 1.00000000 / 60000;
    double dLongitude_DU = dLongitude_ThousandFEN * 1.00000000 / 60000;
    double dLatitude1_DU = dLatitude1_ThousandFEN * 1.00000000 / 60000;
    double dLongitude1_DU = dLongitude1_ThousandFEN * 1.00000000 / 60000;
    dis = earthDis(dLatitude_DU, dLongitude_DU, dLatitude1_DU, dLongitude1_DU);
    return dis * 100;
}

/**
 * 根据车辆GPS点位计算出来距离线路站点(第一站)上下行方向的距离大小,返回结果。
 * @param 线路id
 * @return 上行:0  下行:1 
 */
public Short getRunFlag(String clid) {
    Short fxFlag = null;
    // Redis获取车辆信息
    Map<String, String> clInfoMap = GetRedisPool.getHashAll(RedisPrefix.REDIS_PREFIX_BUSRUNINFO + clid);
    if (clInfoMap != null) {
        // 车辆信息对象生成
        YwClxx clInfo = BeanUtil.getMapBean(clInfoMap, YwClxx.class);
        // 经度(最近一条记录)
        int clJd = clInfo.getJd();
        // 纬度(最近一条记录)
        int clWd = clInfo.getWd();

        if (0 == clJd || 0 == clWd) {
            return fxFlag;
        }

        String xlid = clInfo.getYyxl();

        // 查询上行站点信息
        Set<byte[]> sxset = GetRedisPool
                .getSortedSetByte(RedisPrefix.REDIS_PREFIX_STATION + xlid + RedisPrefix.REDIS_PREFIX_LIMIT + RedisPrefix.REDIS_PREFIX_UP, 1);
        Set<byte[]> xxset = GetRedisPool
                .getSortedSetByte(RedisPrefix.REDIS_PREFIX_STATION + xlid + RedisPrefix.REDIS_PREFIX_LIMIT + RedisPrefix.REDIS_PREFIX_DOWN, 1);
        List<byte[]> sxlist = new ArrayList(sxset);
        List<byte[]> xxlist = new ArrayList(xxset);
        JcZd sxjcZd = (JcZd) SerializeUtil.unserizlize(sxlist.get(0));
        JcZd xxjcZd = (JcZd) SerializeUtil.unserizlize(xxlist.get(0));

        // 经度(上行)
        long sxJd = sxjcZd.getZwjd().longValue();
        // 纬度(上行)
        long sxWd = sxjcZd.getZwwd().longValue();

        // 经度(下行)
        long xxJd = xxjcZd.getZwjd().longValue();
        // 纬度(下行)
        long xxWd = xxjcZd.getZwwd().longValue();

        // 取得车辆位置和第一站点之间的距离
        double sxRange = earthDisFEN(clWd / 10000.00, clJd / 10000.00, sxWd / 10000.00, sxJd / 10000.00);
        double xxRange = earthDisFEN(clWd / 10000.00, clJd / 10000.00, xxWd / 10000.00, xxJd / 10000.00);

        if (sxRange < xxRange) {
            fxFlag = 0;
        } else {
            fxFlag = 1;
        }
    }

    return fxFlag;
}

/**
 * 根据车辆GPS点位计算出来距离线路站点(第一站)上下行方向的距离大小,返回结果。
 * @param 线路id
 * @return 上行:0  下行:1 
 */
public double getGPSRunDis(String clid, String xlid, Byte yxfx, long clJd, long clWd) {
    // 方向
    String direction = yxfx == 1 ? RedisPrefix.REDIS_PREFIX_DOWN : RedisPrefix.REDIS_PREFIX_UP;
    // 查询上行站点信息
    Set<byte[]> zdset = GetRedisPool.getSortedSetByte(RedisPrefix.REDIS_PREFIX_STATION + xlid + RedisPrefix.REDIS_PREFIX_LIMIT + direction, 1);
    List<byte[]> zdlist = new ArrayList(zdset);
    JcZd jcZd = (JcZd) SerializeUtil.unserizlize(zdlist.get(0));

    // 经度(上行)
    long jd = jcZd.getZwjd().longValue();
    // 纬度(上行)
    long wd = jcZd.getZwwd().longValue();

    // 取得车辆位置和第一站点之间的距离
    return earthDisFEN(clWd / 10000.00, clJd / 10000.00, wd / 10000.00, jd / 10000.00);
}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容