78、gps经纬度转百度地图经纬度
需求:把得到的gps的基站数据的经纬度转换成百度的经纬度,适配百度地图
package com.lzh.springcloud;
import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
/**
* gps经纬度转百度地图经纬度
*
* @author LZH
* @version 1.0
* @date 2023/04/14 19:32:51
*/
public class Map {
public static void main(String[] args) {
String url = "http://api.map.baidu.com/ag/coord/convert?from=0&to=4&x=109.840836&y=25.848595";
String back = HttpUtil.get(url);
String x = Base64.decodeStr(JSONUtil.parseObj(back).getStr("x"));
String y = Base64.decodeStr(JSONUtil.parseObj(back).getStr("y"));
System.out.println("精度:"+x);
System.out.println("纬度:"+y);
double[] doubles = CoordinateTransformUtil.wgs84tobd09(109.840836, 25.848595);
System.out.println("精度:"+doubles[0]);
System.out.println("纬度:"+doubles[1]);
String apiUrl = "https://api.map.baidu.com/geoconv/v1/?coords=109.840836,25.848595&from=1&to=5&ak=百度服务的ak";
String apiBack = HttpUtil.get(apiUrl);
System.out.println(apiBack);
JSONObject jsonObject = JSONObject.parseObject(apiBack);
if (jsonObject.getInteger("status") == 0){
JSONArray result = jsonObject.getJSONArray("result");
result.stream().forEach(r->{
JSONObject jsonObject1 = JSONObject.parseObject(r.toString());
System.out.println("精度:"+jsonObject1.get("x"));
System.out.println("纬度:"+jsonObject1.get("y"));
});
}
}
}
工具类:
package com.lzh.springcloud;
import java.math.BigDecimal;
/**
* gps转百度经纬度
*
* @author LZH
* @version 1.0
* @date 2023/04/14 19:33:16
*/
public class CoordinateTransformUtil {
static int B_DIV_SCALE = 15;
static BigDecimal x_pi = new BigDecimal("3.14159265358979324").multiply(new BigDecimal("3000")).divide(new BigDecimal("180"), B_DIV_SCALE, BigDecimal.ROUND_HALF_UP);
// π
static BigDecimal pi = new BigDecimal("3.1415926535897932384626");
// 长半轴
static BigDecimal a = new BigDecimal("6378245");
// 扁率
static BigDecimal ee = new BigDecimal("0.00669342162296594323");
static BigDecimal b_1 = new BigDecimal("-1");
static BigDecimal b_2 = new BigDecimal("10");
static BigDecimal b_3 = new BigDecimal("2");
static BigDecimal b_4 = new BigDecimal("105");
static BigDecimal b_5 = new BigDecimal("3");
static BigDecimal b_6 = new BigDecimal("35");
static BigDecimal b_7 = new BigDecimal("160");
static BigDecimal b_8 = new BigDecimal("1");
static BigDecimal b_9 = new BigDecimal("150");
static BigDecimal b_10 = new BigDecimal("180");
static BigDecimal b_11 = new BigDecimal("0.00002");
static BigDecimal b_12 = new BigDecimal("0.000003");
static BigDecimal b_13 = new BigDecimal("0.0065");
static BigDecimal b_14 = new BigDecimal("0.006");
/**
* WGS坐标转百度坐标系(BD-09)
*
* @param lng WGS84坐标系的经度
* @param lat WGS84坐标系的纬度
* @return 百度坐标数组
*/
public static double[] wgs84tobd09(double lng, double lat) {
double[] gcj = wgs84togcj02(lng, lat);
double[] bd09 = gcj02tobd09(gcj[0], gcj[1]);
return bd09;
}
/**
* 火星坐标系(GCJ-02)转百度坐标系(BD-09)
*
* @param lng 火星坐标经度
* @param lat 火星坐标纬度
* @return 百度坐标数组
* @see 谷歌、高德——>百度
*/
public static double[] gcj02tobd09(double lng, double lat) {
BigDecimal b_lng = new BigDecimal(lng);
BigDecimal b_lat = new BigDecimal(lat);
BigDecimal z = new BigDecimal(Math.sqrt(b_lng.multiply(b_lng).add(b_lat.multiply(b_lat)).doubleValue())).add(b_11.multiply(new BigDecimal(Math.sin(b_lat.multiply(x_pi).doubleValue()))));
BigDecimal theta = new BigDecimal(Math.atan2(b_lat.doubleValue(), b_lng.doubleValue())).add(b_12.multiply(new BigDecimal(Math.cos(b_lng.multiply(x_pi).doubleValue()))));
BigDecimal bd_lng = z.multiply(new BigDecimal(Math.cos(theta.doubleValue()))).add(b_13);
// z * Math.cos(theta) + 0.0065;
BigDecimal bd_lat = z.multiply(new BigDecimal(Math.sin(theta.doubleValue()))).add(b_14);
return new double[]{bd_lng.doubleValue(), bd_lat.doubleValue()};
}
/**
* WGS84转GCJ02(火星坐标系)
*
* @param lng WGS84坐标系的经度
* @param lat WGS84坐标系的纬度
* @return 火星坐标数组
*/
public static double[] wgs84togcj02(double lng, double lat) {
BigDecimal b_lng = new BigDecimal(lng + "");
BigDecimal b_lat = new BigDecimal(lat + "");
if (out_of_china(b_lng, b_lat)) {
return new double[]{b_lng.doubleValue(), b_lat.doubleValue()};
}
BigDecimal dlat = transformlat(b_lng.subtract(b_4), b_lat.subtract(b_6));
BigDecimal dlng = transformlng(b_lng.subtract(b_4), b_lat.subtract(b_6));
BigDecimal radlat = b_lat.divide(b_10, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(pi);
BigDecimal magic = new BigDecimal(Math.sin(radlat.doubleValue()));
magic = b_8.subtract(ee.multiply(magic).multiply(magic));
BigDecimal sqrtmagic = new BigDecimal(Math.sqrt(magic.doubleValue()));
dlat = (dlat.multiply(b_10)).divide((a.multiply(b_8.subtract(ee))).divide((magic.multiply(sqrtmagic)), B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(pi), B_DIV_SCALE, BigDecimal.ROUND_HALF_UP);
dlng = (dlng.multiply(b_10)).divide((a.divide(sqrtmagic, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(Math.cos(radlat.doubleValue())).multiply(pi))), B_DIV_SCALE, BigDecimal.ROUND_HALF_UP);
BigDecimal mglat = b_lat.add(dlat);
BigDecimal mglng = b_lng.add(dlng);
return new double[]{mglng.doubleValue(), mglat.doubleValue()};
}
/**
* 纬度转换
*
* @param lng
* @param lat
* @return
*/
public static BigDecimal transformlat(BigDecimal lng, BigDecimal lat) {
BigDecimal bet = b_1.multiply(b_2).multiply(b_2)
.add(b_3.multiply(lng))
.add(b_5.multiply(lat))
.add(b_3.divide(b_2, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(lat).multiply(lat))
.add(b_8.divide(b_2, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(lng).multiply(lat))
.add(b_3.divide(b_2, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(Math.sqrt(Math.abs(lng.doubleValue())))));
bet = bet.add((b_3.multiply(b_2).multiply(new BigDecimal(Math.sin(b_3.multiply(b_5).multiply(lng).multiply(pi).doubleValue())))
.add(b_3.multiply(b_2).multiply(new BigDecimal(Math.sin(b_3.multiply(lng).multiply(pi).doubleValue()))))).multiply(b_3).divide(b_5, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP));
bet = bet.add((b_3.multiply(b_2).multiply(new BigDecimal(Math.sin(lat.multiply(pi).doubleValue())))
.add(b_3.multiply(b_3).multiply(b_2).multiply(new BigDecimal(Math.sin(lat.divide(b_5, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(pi).doubleValue()))))).multiply(b_3).divide(b_5, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP));
bet = bet.add((b_7.multiply(new BigDecimal(Math.sin(lat.divide(b_5.multiply(b_3).multiply(b_3), B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(pi).doubleValue())))
.add(b_7.multiply(b_3).multiply(new BigDecimal(Math.sin(lat.multiply(pi).divide(b_5.multiply(b_2), B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue()))))).multiply(b_3).divide(b_5, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP));
return bet;
}
/**
* 经度转换
*
* @param lng
* @param lat
* @return
*/
public static BigDecimal transformlng(BigDecimal lng, BigDecimal lat) {
BigDecimal bet = b_2.multiply(b_2).multiply(b_5).add(lng).add(b_3.multiply(lat)).add(b_8.divide(b_2, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(lng).multiply(lng))
.add(b_8.divide(b_2, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(lng).multiply(lat)).add(b_8.divide(b_2, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(Math.sqrt(Math.abs(lng.doubleValue())))));
bet = bet.add((b_3.multiply(b_2).multiply(new BigDecimal(Math.sin(b_3.multiply(b_5).multiply(lng).multiply(pi).doubleValue())))
.add(b_3.multiply(b_2).multiply(new BigDecimal(Math.sin(b_3.multiply(lng).multiply(pi).doubleValue()))))).multiply(b_3).divide(b_5, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP));
bet = bet.add((b_3.multiply(b_2).multiply(new BigDecimal(Math.sin(lng.multiply(pi).doubleValue())))
.add(b_3.multiply(b_3).multiply(b_2).multiply(new BigDecimal(Math.sin(lng.divide(b_5, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(pi).doubleValue()))))).multiply(b_3).divide(b_5, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP));
bet = bet.add((b_9.multiply(new BigDecimal(Math.sin(lng.divide(b_3.multiply(b_3).multiply(b_5), B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(pi).doubleValue())))
.add(b_9.multiply(b_3).multiply(new BigDecimal(Math.sin(lng.divide(b_5.multiply(b_2), B_DIV_SCALE, BigDecimal.ROUND_HALF_UP).multiply(pi).doubleValue())))).multiply(b_3).divide(b_5, B_DIV_SCALE, BigDecimal.ROUND_HALF_UP)));
return bet;
}
/**
* 判断是否在国内,不在国内不做偏移
*
* @param lng
* @param lat
* @return
*/
public static boolean out_of_china(BigDecimal lng, BigDecimal lat) {
if (lng.compareTo(new BigDecimal("73.66")) < 0 || lng.compareTo(new BigDecimal("135.05")) > 0) {
return true;
} else if (lat.compareTo(new BigDecimal("3.86")) < 0 || lat.compareTo(new BigDecimal("53.55")) > 0) {
return true;
}
return false;
}
}
一共三种方式:
1、第一种调用接口(网上搜到的),精确度还可以(调用次数好像是每天10万次)
2、工具类得到的,精确度最差
3、百度官网的api,标准(个人认证每天只能调用5000次)
结果如下所示:
申请百度地图开发者认证,很快就认证成功了
创建应用
如果接口报错210,app ip认证问题,修改ip白名单限制
设置为0.0.0.0/0,不限制,然后再次访问就可以成功了
具体业务实现:
批量更新数据,一次更新5000条
使用 update 表名 set aa = case when id =1 then bb case when id =2 then cc end where id in(1,2)
public void updateCellId(){
int index = 1;
int from = 0;
Integer size = 5000;
List<Cellidnew> info = this.getBaseMapper().getInfo(from, size);
String sqlAll = "update 表名 set LNG_BD_UTILS = %s ,LAT_BD_UTILS = %s where id in (%s)";
String salSub = " when id = %s then %s ";
String salSubStart = " case ";
String salSubEnd = " end ";
// 当数据不为空的时候
while (ObjectUtil.isNotEmpty(info)){
System.out.println("这是第 "+index+" 次");
StringBuilder lngsb = new StringBuilder();
StringBuilder latsb = new StringBuilder();
lngsb.append(salSubStart);
latsb.append(salSubStart);
List<Cellidnew> list = new ArrayList<>();
info.forEach(i->{
if (ObjectUtil.isNotEmpty(i.getLng()) && ObjectUtil.isNotEmpty(i.getLat())){
double[] doubles = CoordinateTransformUtil.wgs84tobd09(i.getLng(), i.getLat());
lngsb.append(String.format(salSub,i.getId(),doubles[0]));
latsb.append(String.format(salSub,i.getId(),doubles[1]));
}
});
lngsb.append(salSubEnd);
latsb.append(salSubEnd);
// 获取id
String collect = info.stream().map(i -> {
return i.getId().toString();
}).collect(Collectors.joining(","));
// 批量更新数据
String executeSql = String.format(sqlAll, lngsb.toString(), latsb.toString(), collect);
if (ObjectUtil.isNotEmpty(executeSql)){
// 执行脚本插入语句
this.getBaseMapper().executeSql(executeSql);
}
index++;
from = (index - 1) * size;
//再次查询数据进行循环
info = this.getBaseMapper().getInfo(from, size);
}
}