可以使用,百度地图坐标拾取器:https://lbs.baidu.com/maptool/getpoint
天地图:http://lbs.tianditu.gov.cn/api/js4.0/examples.html 在添加覆盖物,添加标注里面
测试类
package org.springblade.modules.api.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springblade.common.config.BladeRemoteConfig;
import org.springblade.common.utils.CommonUtil;
import org.springblade.core.http.util.HttpUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.api.entity.SimpleAuthentication;
import org.springblade.modules.api.service.IClueService;
import org.springblade.modules.api.vo.TestVo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@RestController
@AllArgsConstructor
@RequestMapping("/change")
@Api(value = "", tags = "接口")
public class TestController {
private final IClueService clueService;
/**
* @param longitude 经度
* @param latitude 纬度
* @return
*/
public static String changeItudeOne(String longitude, String latitude) {
//源坐标类型 from=5 bd09ll(百度经纬度坐标)
//目的坐标类型 to=3 google地图、soso地图、aliyun地图、mapabc地图和amap地图所用坐标
String url = "https://api.map.baidu.com" + "/geoconv/v1/?coords=" + longitude + "," + latitude + "&from=5&to=3&ak=写自己的ak";
Map header = new HashMap();
String s = HttpUtil.get(url, header, null);
//请求结果不为空并且不包含html(有html可能访问路径不对)
if (Func.isNotEmpty(s) && !s.contains("html")) {
Map<String, Object> baiDuMap = JsonUtil.toMap(s);
//如果包含status代表请求成功
if (baiDuMap.containsKey("status")) {
int status = Func.toInt(baiDuMap.get("status"));
//非0的状态码都是失败
if (status != 0) {
throw new ServiceException(Func.toStr(baiDuMap.get("message")));
}
List<Map> mapList = (List<Map>) baiDuMap.get("result");
List<String> list = new ArrayList();
mapList.forEach(a -> {
String x = Func.toStr(a.get("x"));
String y = Func.toStr(a.get("y"));
String str = (x.length() >= 10 ? x.substring(0, 10) : x) + "," + (y.length() >= 10 ? y.substring(0, 10) : y);
list.add(str);
});
return list.stream().map(String::valueOf).collect(Collectors.joining(";"));
}
}
throw new ServiceException("操作失败,坐标转换出现异常");
}
/**
* 转换多个如:120.00,31.00;120.01,31.01
*
* @param geometry
*/
public static String changeItudeMany(String geometry) {
if (Func.isNotEmpty(geometry) && !geometry.contains("[]")) {
if (geometry.endsWith(";")) {
geometry = geometry.substring(0, geometry.length() - 1);
}
if (geometry.contains(";")) {
String[] split = geometry.split(";");
System.err.println("多条经纬度 = " + split.length);
List<String> list = new ArrayList();
for (int i = 0; i < split.length; i++) {
System.err.println("第" + (i + 1) + "条," + split[i]);
//源坐标类型 from=3 google地图、soso地图、aliyun地图、mapabc地图和amap地图所用坐标
//目的坐标类型 to=5 bd09ll(百度经纬度坐标)
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
String url = "https://api.map.baidu.com" + "/geoconv/v1/?coords=" + split[i] + "&from=5&to=3&ak=自己的ak";
Map header = new HashMap();
String s = HttpUtil.get(url, header, null);
//请求结果不为空并且不包含html(有html可能访问路径不对)
if (Func.isNotEmpty(s) && !s.contains("html")) {
Map<String, Object> baiDuMap = JsonUtil.toMap(s);
//如果包含status代表请求成功
if (baiDuMap.containsKey("status")) {
int status = Func.toInt(baiDuMap.get("status"));
//非0的状态码都是失败
if (status != 0) {
throw new ServiceException(Func.toStr(baiDuMap.get("message")));
}
List<Map> mapList = (List<Map>) baiDuMap.get("result");
mapList.forEach(a -> {
String x = Func.toStr(a.get("x"));
String y = Func.toStr(a.get("y"));
String str = (x.length() >= 10 ? x.substring(0, 10) : x) + "," + (y.length() >= 10 ? y.substring(0, 10) : y);
list.add(str);
});
}
}
}
return list.stream().map(String::valueOf).collect(Collectors.joining(";"));
}
throw new ServiceException("操作失败,坐标转换出现异常");
}
return null;
}
/**
* 验证所传参数是否是经纬度
*/
private boolean checkItude(BigDecimal longitude, BigDecimal latitude) {
boolean flag = true;
//不为空的情况下,判断经度是否符合要求
if (!Func.isEmpty(longitude)) {
BigDecimal maxLongitude = new BigDecimal("180");
BigDecimal minLongitude = new BigDecimal("-180");
if (longitude.compareTo(maxLongitude) > 0 || longitude.compareTo(minLongitude) < 0) {
flag = false;
}
}
//不为空的情况下,判断纬度是否符合要求
if (!Func.isEmpty(latitude)) {
BigDecimal maxLatitude = new BigDecimal("90");
BigDecimal minLatitude = new BigDecimal("-90");
if (latitude.compareTo(maxLatitude) > 0 || latitude.compareTo(minLatitude) < 0) {
flag = false;
}
}
return flag;
}
public static void main(String[] args) {
//***********转换单条***********
//1、先把百度地图经纬度转为GCJ-02,天安门广场百度地图坐标
String s = changeItudeOne("116.403944","39.914780");
//得到GCJ-02:116.3975710494649,39.90843680810011
System.out.println("百度转GCJ-02坐标系:" + s);
String[] split = s.split(",");
//2、再把得到的GCJ-02坐标系转为天地图坐标系WGS-84坐标
String[] strings = GcjToWgs.gcj02ToWgs84(Func.toDouble(split[0]), Func.toDouble(split[1]));
System.out.println("GCJ-02坐标系转WGS-84坐标:" + strings[0] + "," + strings[1]);
//***********转换多条***********
String geometry = "119.63143, 32.227513;119.627368, 32.22366;119.626473, 32.251232;119.61682, 32.259295;119.605639, 32.257454;119.60443, 32.240967;119.594065, 32.237473;";
geometry = geometry.replaceAll("\\s", "");
//1、先把百度地图经纬度转为GCJ-02
String s1 = changeItudeMany(geometry);
//2、再把得到的GCJ-02坐标系转为天地图坐标系WGS-84坐标,保持原结构
String s2 = GcjToWgs.changeMany(s1);
System.out.println(s2);
}
}
工具类:将GCJ-02坐标转换为WGS-84坐标
package org.springblade.modules.api.controller;
import org.springblade.core.tool.utils.Func;
import java.util.ArrayList;
import java.util.List;
public class GcjToWgs {
private static final double PI = 3.1415926535897932384626;
private static final double EE = 0.00669342162296594323; // 偏心率平方
private static final double EARTH_RADIUS = 6378137; // 地球长半轴
/**
* 将GCJ-02坐标转换为WGS-84坐标
*
* @param lon 经度(GCJ-02)
* @param lat 纬度(GCJ-02)
* @return 包含WGS-84经度和纬度的数组
*/
public static String[] gcj02ToWgs84(double lon, double lat) {
// 创建初始点(假设初始为GCJ-02点)
double initLon = lon;
double initLat = lat;
// 计算初始点与WGS-84的偏差
double[] delta = delta(initLon, initLat);
double dLon = initLon - delta[0];
double dLat = initLat - delta[1];
// 迭代计算更精确的坐标
double threshold = 1e-6; // 精度阈值
for (int i = 0; i < 10000; i++) {
// 计算当前偏移量
double[] currentDelta = delta(dLon, dLat);
double curLon = initLon - currentDelta[0];
double curLat = initLat - currentDelta[1];
// 判断是否达到精度要求
if (Math.max(Math.abs(curLon - dLon), Math.abs(curLat - dLat)) < threshold) {
return new String[]{Func.toStr(curLon).substring(0, 10), Func.toStr(curLat).substring(0, 9)};
}
dLon = curLon;
dLat = curLat;
}
return new String[]{Func.toStr(dLon).substring(0, 10), Func.toStr(dLat).substring(0, 9)};
}
/**
* 计算坐标偏移量(WGS-84 -> GCJ-02)
*
* @param lon 经度
* @param lat 纬度
* @return 包含x方向偏移和y方向偏移的数组
*/
private static double[] delta(double lon, double lat) {
double[] result = new double[2];
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * PI;
double magic = Math.sin(radLat);
magic = 1 - EE * magic * magic;
double sqrtMagic = Math.sqrt(magic);
result[0] = (dLon * 180.0) / (EARTH_RADIUS / sqrtMagic * Math.cos(radLat) * PI);
result[1] = (dLat * 180.0) / ((EARTH_RADIUS * (1 - EE)) / (magic * sqrtMagic) * PI);
return result;
}
// 纬度变换公式
private static double transformLat(double x, double y) {
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
return ret;
}
// 经度变换公式
private static double transformLon(double x, double y) {
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
return ret;
}
public static String changeMany(String geometry) {
if (Func.isNotEmpty(geometry)) {
if (geometry.endsWith(";")) {
geometry = geometry.substring(0, geometry.length() - 1);
}
List<String> list = new ArrayList<>();
if (geometry.contains(";")) {
String[] split = geometry.split(";");
for (String s : split) {
if (s.contains(",")) {
String[] strings = s.split(",");
String[] wgs84 = gcj02ToWgs84(Func.toDouble(strings[0]), Func.toDouble(strings[1]));
list.add(Func.toStr(wgs84[0]) + "," + Func.toStr(wgs84[1]));
}
}
}
return Func.toStr(Func.join(list, ";"));
}
return null;
}
// 测试
public static void main(String[] args) {
// 示例:天安门广场的GCJ-02坐标
String[] wgs = gcj02ToWgs84(119.62499962917197, 32.221260580618359);
System.out.println("WGS-84经度: " + wgs[0]); // 约116.3975
System.out.println("WGS-84纬度: " + wgs[1]); // 约39.9087
// System.out.println(changeMany("119.637835,32.2338343;119.633788,32.2299422;119.632880,32.2574993;119.623269,32.2654158;119.612143,32.2633679;"));
}
}
可以看出来两个点差不多