基站定位

在一些项目中,可能会使用到不同的定位,如gps、基站、WiFi定位等。通过调用方法并传入3个基站的数据,则返回定位点的大体经纬度坐标,当然与实际位置坐标还是存在偏差的,小的话可能几十米,大的可能4、5百米。当然也可以付费调用其他定位接口,如图吧等。

 

//基站数据model
public class BaseStationModel {
    
    @Key
    private Long id;
    private String mcc;
    private Long mnc;
    private String lac;
    private String cell;
    private String lng;
    private String lat;
    private String b_lng;
    private String b_lat;
    private String precision;
    private String address;
    
    public BaseStationModel() {
        super();
    }

    /**
     * @return 获  得 id
     */
    public Long getId() {
        return id;
    }

    /**
     * @param id 设置 id
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @return 获得 mcc
     */
    public String getMcc() {
        return mcc;
    }

    /**
     * @param mcc 设置 mcc
     */
    public void setMcc(String mcc) {
        this.mcc = mcc;
    }

    /**
     * @return 获得 mnc
     */
    public Long getMnc() {
        return mnc;
    }

    /**
     * @param mnc 设置 mnc
     */
    public void setMnc(Long mnc) {
        this.mnc = mnc;
    }

    /**
     * @return 获得 lac
     */
    public String getLac() {
        return lac;
    }

    /**
     * @param lac 设置 lac
     */
    public void setLac(String lac) {
        this.lac = lac;
    }

    /**
     * @return 获得 cell
     */
    public String getCell() {
        return cell;
    }

    /**
     * @param cell 设置 cell
     */
    public void setCell(String cell) {
        this.cell = cell;
    }

    /**
     * @return 获得 lng
     */
    public String getLng() {
        return lng;
    }

    /**
     * @param lng 设置 lng
     */
    public void setLng(String lng) {
        this.lng = lng;
    }

    /**
     * @return 获得 lat
     */
    public String getLat() {
        return lat;
    }

    /**
     * @param lat 设置 lat
     */
    public void setLat(String lat) {
        this.lat = lat;
    }

    /**
     * @return 获得 b_lng
     */
    public String getB_lng() {
        return b_lng;
    }

    /**
     * @param b_lng 设置 b_lng
     */
    public void setB_lng(String b_lng) {
        this.b_lng = b_lng;
    }

    /**
     * @return 获得 b_lat
     */
    public String getB_lat() {
        return b_lat;
    }

    /**
     * @param b_lat 设置 b_lat
     */
    public void setB_lat(String b_lat) {
        this.b_lat = b_lat;
    }

    /**
     * @return 获得 precision
     */
    public String getPrecision() {
        return precision;
    }

    /**
     * @param precision 设置 precision
     */
    public void setPrecision(String precision) {
        this.precision = precision;
    }

    /**
     * @return 获得 address
     */
    public String getAddress() {
        return address;
    }

    /**
     * @param address 设置 address
     */
    public void setAddress(String address) {
        this.address = address;
    }
}//经纬度转平面坐标model
public class PlaneCoordinate {

    private double x;  //lng
    private double y;  //lat
    
     /**
     */
    public PlaneCoordinate() {
        super();
    }
    /**
     * @param x
     * @param y
     */
    public PlaneCoordinate(double x, double y) {
        super();
        this.x = x;
        this.y = y;
    }
    /**
     * @return 获得 x
     */
    public double getX() {
        return x;
    }
    /**
     * @param x 设置 x
     */
    public void setX(double x) {
        this.x = x;
    }
    /**
     * @return 获得 y
     */
    public double getY() {
        return y;
    }
    /**
     * @param y 设置 y
     */
    public void setY(double y) {
        this.y = y;
    }
    
    
}
//经纬度model
public class Point {
    double longitude;
    double latitude;
    
     
     /**
     */
    public Point() {
        super();
    }

    /**
     * @param longitude
     * @param latitude
     */
    public Point(double longitude, double latitude) {
        super();
        this.longitude = longitude;
        this.latitude = latitude;
    }

    public void setLongitude(double longitude) {
        this.longitude = longitude;
    }

    public void setLatitude(double latitude) {
        this.latitude = latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    public double getLatitude() {
        return latitude;
    }
}
//基站定位实现类
public class BaseStationPosition {
    
    public static double latDis1 = 111;    //纬度1度大约相差111Km
    private final static double EARTH_RADIUS = 6378137.0;   
    
    public static final double pi = 3.1415926535898; 
    public static final double X0 = 8;
    public static final double K = 3;//98899
    public static final double iPI = pi/180.0;
    public static final double a=6378137.0;//WGS84:版本长半轴
    public static final double f=1/298.257223563;//WGS84:版本扁率
    public static final int ZoneWide = 6; 带宽
    
     /**
     *  @Title: getDistance 
     *  @Description: 根据rssi计算出与基站距离 KM
     *  @author jf.gong  DateTime 2014年5月19日 下午2:50:50
     *  @return double 
     *  @param rssiVal
     *  @return
     */
    public static double getDistance(double rssiVal){
        /*
         * RSSI=发射功率(Pt)+天线增益(Pf)一路径损耗(PL(d))
            说是根据该公式可以推算出距离与 RSSI 的关系公式: 
            D = 10^((Pt+Pf-RSSI-PL(d0)-X0)/(10*K))
            
            
            
         * */
        
//        return (10*((195-rssiVal)/(10 * K)))*0.001;
//        return (rssiVal+X0)*K*0.001;
//        return Math.pow(10,(-rssiVal-97.5239)/(38));
        return Math.pow(10,(Math.abs(rssiVal)-60)/(10*K))*0.001;
    }
    
    
     /**
     *  @Title: getWantDouble 
     *  @Description: double保留指定小数位
     *  @author jf.gong  DateTime 2014年5月19日 下午7:48:42
     *  @return double 
     *  @param val
     *  @param unit
     *  @return
     */
    public static double getWantDouble(double val,int unit){
           
            BigDecimal bg = new BigDecimal(val);
            double re_value = bg.setScale(unit, BigDecimal.ROUND_HALF_UP).doubleValue();
            return re_value;
        }
    
     /**
     *  @Title: distance 
     *  @Description: 两坐标距离计算
     *  @author jf.gong  DateTime 2014年5月30日 下午3:40:34
     *  @return double 
     *  @param lat_a
     *  @param lng_a
     *  @param lat_b
     *  @param lng_b
     *  @return
     */
    public static double distance(double lat_a, double lng_a, double lat_b, double lng_b) {  
           double radLat1 = (lat_a * Math.PI / 180.0);  
           double radLat2 = (lat_b * Math.PI / 180.0);  
           double a = radLat1 - radLat2;  
           double b = (lng_a - lng_b) * Math.PI / 180.0;  
           double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)  
                  + Math.cos(radLat1) * Math.cos(radLat2)  
                  * Math.pow(Math.sin(b / 2), 2)));  
           s = s * EARTH_RADIUS;  
           s = Math.round(s * 10000) / 10000;  
           return s;  
        } 

 /**
 *  @Title: getPlanCoordinate 
 *  @Description: 由经纬度反算成高斯投影坐标
 *  @author jf.gong  DateTime 2014年5月30日 下午3:39:06
 *  @return PlaneCoordinate 
 *  @param longitude
 *  @param latitude
 *  @return
 */
public PlaneCoordinate getPlanCoordinate(double longitude, double latitude){
    int ProjNo=0;
    double longitude1,latitude1, longitude0, X0,Y0, xval,yval;
    double e2,ee, NN, T,C,A, M;
    
    ProjNo = (int)(longitude / ZoneWide) ;
    longitude0 = ProjNo * ZoneWide + ZoneWide / 2;
    longitude0 = longitude0 * iPI ;
    longitude1 = longitude * iPI ; //经度转换为弧度
    latitude1 = latitude * iPI ; //纬度转换为弧度
    e2=2*f-f*f;
    ee=e2*(1.0-e2);
    NN=a/Math.sqrt(1.0-e2*Math.sin(latitude1)*Math.sin(latitude1));
    T=Math.tan(latitude1)*Math.tan(latitude1);
    C=ee*Math.cos(latitude1)*Math.cos(latitude1);
    A=(longitude1-longitude0)*Math.cos(latitude1);
    M=a*((1-e2/4-3*e2*e2/64-5*e2*e2*e2/256)*latitude1-(3*e2/8+3*e2*e2/32+45*e2*e2
            *e2/1024)*Math.sin(2*latitude1)
            +(15*e2*e2/256+45*e2*e2*e2/1024)*Math.sin(4*latitude1)-(35*e2*e2*e2/3072)*Math.sin(6*latitude1));
    xval = NN*(A+(1-T+C)*A*A*A/6+(5-18*T+T*T+72*C-58*ee)*A*A*A*A*A/120);
    yval = M+NN*Math.tan(latitude1)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24
            +(61-58*T+T*T+600*C-330*ee)*A*A*A*A*A*A/720);
    X0 = 1000000L*(ProjNo+1)+500000L;
    Y0 = 0;
    xval = xval+X0; 
    yval = yval+Y0;
    
    return new PlaneCoordinate(xval,yval);

}

 /**
 *  @Title: GaussToBL 
 *  @Description: 由高斯投影坐标反算成经纬度
 *  @author jf.gong  DateTime 2014年5月30日 下午3:36:28
 *  @return Point 
 *  @param X
 *  @param Y
 *  @return
 */
public Point getLngLat(double X, double Y){
  int ProjNo;
  double longitude1,latitude1, longitude0, X0,Y0, xval,yval;//latitude0,
  double e1,e2, ee, NN, T,C, M, D,R,u,fai;
  
  ProjNo = (int)(X/1000000L) ; //查找带号
  longitude0 = (ProjNo-1) * ZoneWide + ZoneWide / 2;
  longitude0 = longitude0 * iPI ; //中央经线
  X0 = ProjNo*1000000L+500000L;
  Y0 = 0;
  xval = X-X0;
  yval = Y-Y0; //带内大地坐标
  e2 = 2*f-f*f;
  e1 = (1.0-Math.sqrt(1-e2))/(1.0+Math.sqrt(1-e2));
  ee = e2/(1-e2);
  M = yval;
  u = M/(a*(1-e2/4-3*e2*e2/64-5*e2*e2*e2/256));
  fai = u+(3*e1/2-27*e1*e1*e1/32)*Math.sin(2*u)+(21*e1*e1/16-55*e1*e1*e1*e1/32)*Math.sin(
          4*u)+(151*e1*e1*e1/96)*Math.sin(6*u)+(1097*e1*e1*e1*e1/512)*Math.sin(8*u);
  C = ee*Math.cos(fai)*Math.cos(fai);
  T = Math.tan(fai)*Math.tan(fai);
  NN = a/Math.sqrt(1.0-e2*Math.sin(fai)*Math.sin(fai));
  R = a*(1-e2)/Math.sqrt((1-e2*Math.sin(fai)*Math.sin(fai))*(1-e2*Math.sin(fai)*Math.sin(fai))*(1-e2*Math.sin
          (fai)*Math.sin(fai)));
  D = xval/NN;
  //计算经度(Longitude) 纬度(Latitude)
  longitude1 = longitude0+(D-(1+2*T+C)*D*D*D/6+(5-2*C+28*T-3*C*C+8*ee+24*T*T)*D  //
          *D*D*D*D/120)/Math.cos(fai);
  latitude1 = fai -(NN*Math.tan(fai)/R)*(D*D/2-(5+3*T+10*C-4*C*C-9*ee)*D*D*D*D/24  //
          +(61+90*T+298*C+45*T*T-256*ee-3*C*C)*D*D*D*D*D*D/720);
  
  return new Point(getWantDouble(longitude1/iPI,6), getWantDouble(latitude1/iPI,6));
}


 /**
 *  @Title: getTargetCoordinate 
 *  @Description: lbs基站定位
 *  @author jf.gong  DateTime 2014年5月30日 下午3:41:59
 *  @return Point 
 *  @param cellId
 *  @return
 */
public Point getTargetCoordinate(String cellId){
    String []cellIdArr = cellId.split("\\|");
    Point point = new Point();
    if(cellIdArr.length >= 4){
        String []mccMncArr =  cellIdArr[0].split(":");
        List<BaseStationModel> baseList = new ArrayList<BaseStationModel>();
        Map<Long,Double> disMap = new HashMap<Long, Double>();
        //获取数据库基站model数据,取前三个信号最强的基站
        for (int i = 1; i < cellIdArr.length; i++) {
            String []baseArr = cellIdArr[i].split(":");
             BaseStationModel baseModel = (BaseStationModel) JdbcUtils.getInstance().getModel(" MCC='"+mccMncArr[0]+"'"
                    + "  AND MNC="+ Long.parseLong(mccMncArr[1])+" AND LAC='"+baseArr[0]+"' AND CELL='"+baseArr[1]+"'",new BaseStationModel());
            if(null != baseModel){
                baseList.add(baseModel);
                disMap.put(baseModel.getId(), getDistance(Double.parseDouble(baseArr[2])));
            }
        }
        if(baseList.size() >= 3){
            PlaneCoordinate plance1 = getPlanCoordinate(Double.parseDouble(baseList.get(0).getLng()),Double.parseDouble(baseList.get(0).getLat()));
            PlaneCoordinate plance2 = getPlanCoordinate(Double.parseDouble(baseList.get(1).getLng()),Double.parseDouble(baseList.get(1).getLat()));
            PlaneCoordinate plance3 = getPlanCoordinate(Double.parseDouble(baseList.get(2).getLng()),Double.parseDouble(baseList.get(2).getLat()));
            //根据信号强度得到与基站距离
            double da = disMap.get(baseList.get(0).getId());
            double db = disMap.get(baseList.get(1).getId());
            double dc = disMap.get(baseList.get(2).getId());
//            //三角质心原理求坐标
//            double y1 = (db*db-dc*dc-plance2.getX()*plance2.getX()+plance3.getX()*plance3.getX()-plance2.getY()*plance2.getY()+plance3.getY()*plance3.getY())*(plance1.getX()-plance2.getX());
//            double y2 =(da*da-db*db-plance1.getX()*plance1.getX()+plance2.getX()*plance2.getX()-plance1.getY()*plance1.getY()+plance2.getY()*plance2.getY())*(plance2.getX()-plance3.getX());
//            double y3 = 2*((plance2.getX()-plance3.getX())*(plance1.getY()-plance2.getY())-(plance1.getX()-plance2.getX())*(plance2.getY()-plance3.getY()));
//            double y = (y1 - y2)/y3;
//            double x1 = da*da-db*db-plance1.getX()*plance1.getX()+plance2.getX()*plance2.getX()-plance1.getY()*plance1.getY()+plance2.getY()*plance2.getY()+2*y*plance1.getY()-2*y*plance2.getY();
//            double x2 = (-2)*(plance1.getX()-plance2.getX());
//            double x = x1/x2;
            
//             // 外切圆圆心
            double x1 = plance1.getX();
            double x2 = plance2.getX();
            double x3 = plance3.getX();
            double y1 = plance1.getY();
            double y2 = plance2.getY();
            double y3 = plance3.getY();
//            double x = ((y2 - y1) * (y3 * y3 - y1 * y1 + x3 * x3 - x1 * x1) - (y3 - y1)
//                        * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1))
//                        / (2 * (x3 - x1) * (y2 - y1) - 2 * ((x2 - x1) * (y3 - y1)));
//
//            double y = ((x2 - x1) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1) - (x3 - x1)
//                        * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1))
//                        / (2 * (y3 - y1) * (x2 - x1) - 2 * ((y2 - y1) * (x3 - x1)));
            
         // 内切圆圆心
            double d23 = distenceOfPoints(plance2, plance3);
            double d31 = distenceOfPoints(plance3, plance1);
            double d12 = distenceOfPoints(plance1, plance2);
            double sumd = d23+d31+d12;
            double x = (x1 * d23 + x2 * d31 + x3 * d12) / sumd;

            double y = (y1 * d23 + y2 * d31 + y3 * d12) / sumd;
            double d1 = distenceOfPoints(new PlaneCoordinate(x, y), plance2);    
            //计算gps坐标
            point = getLngLat(x,y);
        }
    }
    return point;
}

// 两点之间的距离

public static double distenceOfPoints(PlaneCoordinate plance1, PlaneCoordinate plance2) {

    return Math.sqrt((plance1.getX()- plance2.getX()) * (plance1.getX()- plance2.getX()) + (plance1.getY() - plance2.getY()) * (plance1.getY() - plance2.getY()));

}

 /**
 *  @Title: combination 
 *  @Description: Java实现排列组合去重复
 *  @author jf.gong  DateTime 2014年5月30日 下午6:52:20
 *  @return void 
 */
public static void combination(){
      int data[] = {1,2,3,4,5,6,7};
      f_1(data);
     }
     private static void f_1(int data[]) {
      for(int i=0;i<=2;i++) {
       for(int j=i+1;j<=3;j++) {
           //k<= length-1
        for(int k=j+1;k<=6;k++) {
            System.out.println(data[i]+" "+data[j]+" "+data[k]);
        }
       }
      }
     }
    




 /**
 *  @Title: main 
 *  @Description: TODO
 *  @author jf.gong  DateTime 2014年6月6日 下午2:29:11
 *  @return void 
 *  @param args
 */
public static void main(String[] args) {
    for (int i = 16289; i < 16439; i++) {
        BaseStationPosition stationPosition = new BaseStationPosition();
        T3 t3 = (T3) JdbcUtils.getInstance().getModel(" id="+i,new T3());
        Point point = stationPosition.getTargetCoordinate(t3.getCell_id());
        double s = distance(point.latitude,point.longitude,Double.parseDouble(t3.getLat()),Double.parseDouble(t3.getLng()));
//        if(s > 800){
            System.err.println(t3.getLat() +"," + t3.getLng());
            System.err.println(point.latitude + "," + point.longitude+ "---  distance:"+s + "--" + i);
//        }
        
        
    }
//    combination();
    //double lat_a, double lng_a, double lat_b, double lng_b
//    System.err.println(distance(31.294607,121.337825,31.2887316,121.3428055));
//    System.err.println(getDistance(-54));
    
    
//    BaseStationPosition stationPosition = new BaseStationPosition();
//    PlaneCoordinate coordinate = stationPosition.getPlanCoordinate(121.337825, 31.294607);
//    System.err.println(coordinate.getX()+","+coordinate.getY());
//    Point point = stationPosition.getLngLat(coordinate.getX(), coordinate.getY());
//    
//    System.err.println(point.getLatitude()+"," + point.getLongitude());
    
}

}
 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值