在一些项目中,可能会使用到不同的定位,如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());
}
}