# 一、高德地图、奥维地图、百度地图之前的互转，WGS-84坐标系、GCJ－02坐标系、BD-09坐标系之间的互转。（转）

3.百度坐标系:bd-09，百度坐标系是在GCJ－02坐标系的基础上再次加密偏移后形成的坐标系，只适用于百度地图。(目前百度API提供了从其它坐标系转换为百度坐标系的API，但却没有从百度坐标系转为其他坐标系的API)

/**
* 坐标转换工具
* 奥维地图:WGS-84坐标系
* 百度坐标系:BD-09坐标系  百度坐标系是在GCJ－02坐标系的基础上再次加密偏移后形成的坐标系
*/
public class CoordinateTransitionUtils {
public static double pi = 3.1415926535897932384626;
public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
public static double a = 6378245.0;
public static double ee = 0.00669342162296594323;

public 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;
}

public 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 double[] transform(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new double[]{lat,lon};
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[]{mgLat,mgLon};
}
public static boolean outOfChina(double lat, double lon) {
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
}
/**
* 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
* @param initAxis -->"经度,纬度"这样形式的坐标
* @return 火星坐标系坐标
*/
public static String gps84_To_Gcj02(String initAxis) {
String[] split = initAxis.split(",");
double lon = Double.parseDouble(split[0]);
double lat = Double.parseDouble(split[1]);
if (outOfChina(lat, lon)) {
String resultAxis = lon+","+lat;
return resultAxis;
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
String resultAxis = mgLon+","+mgLat;
return resultAxis;
}

/**
*  火星坐标系 (GCJ-02) to 84 坐标系
*  @param initAxis -->"经度,纬度"这样形式的坐标
* */
public static String gcj02_To_Gps84(String initAxis) {
String[] split = initAxis.split(",");
double lon = Double.parseDouble(split[0]);
double lat = Double.parseDouble(split[1]);
double[] gps = transform(lat, lon);
double lontitude = lon * 2 - gps[1];
double latitude = lat * 2 - gps[0];
String resultAxis = lontitude+","+latitude;
return resultAxis;
}
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
* @param initAxis -->"经度,纬度"这样形式的坐标
*/
public static String gcj02_To_Bd09(String initAxis) {
String[] split = initAxis.split(",");
double lon = Double.parseDouble(split[0]);
double lat = Double.parseDouble(split[1]);
double x = lon, y = lat;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
double tempLon = z * Math.cos(theta) + 0.0065;
double tempLat = z * Math.sin(theta) + 0.006;
String resultAxis = tempLon+","+tempLat;
return resultAxis;
}

/**
* 火星坐标系 (GCJ-02)<----百度坐标系 (BD-09)
* BD-09 坐标转换成GCJ-02 坐标
* @param initAxis -->"经度,纬度"这样形式的坐标
*/
public static String bd09_To_Gcj02(String initAxis) {
String[] split = initAxis.split(",");
double lon = Double.parseDouble(split[0]);
double lat = Double.parseDouble(split[1]);
double x = lon - 0.0065, y = lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
double tempLon = z * Math.cos(theta);
double tempLat = z * Math.sin(theta);
String resultAxis = tempLon+","+tempLat;
return resultAxis;
}

/**
* 将gps84转为bd09
* @param initAxis -->"经度,纬度"这样形式的坐标
* @return  /
*/
public static String gps84_To_bd09(String initAxis){
String gcj02 = gps84_To_Gcj02(initAxis);
String bd09 = gcj02_To_Bd09(gcj02);
return bd09;
}
/**
* 将bd09转为gps84
* @param initAxis -->"经度,纬度"这样形式的坐标
* @return /
*/
public static String bd09_To_gps84(String initAxis){
String gcj02 = bd09_To_Gcj02(initAxis);
String gps84 = gcj02_To_Gps84(gcj02);
//保留小数点后六位
String[] split = gps84.split(",");
double lon = Double.parseDouble(split[0]);
double lat = Double.parseDouble(split[1]);
lon = retain6(lon);
lat = retain6(lat);
return lon+","+lat;
}

/**
* 保留小数点后六位
* @param num 位数
* @return /
*/
private static double retain6(double num){
String result = String .format("%.6f", num);
return Double.valueOf(result);
}
}


# 二、根据经纬度坐标判断两个区域是否重叠的工具类

/**
* Author: oldou
* Date: 2020/12/23
* Description:判断两个区域是否重叠、根据两个坐标的经纬度连线判断该线段是否穿过某个区域
*/
public class AreaOverlapCheckUtils {
/**
* 判断线是否穿过某个区域
* @param lineAxisList 两点确定一条直线的坐标集合 {"经度1,纬度1","经度2,纬度2","经度3,纬度3".....}
* @param AreaAxisList 区域的坐标集合 {"经度1,纬度1","经度2,纬度2","经度3,纬度3".....}
* @return /
*/
public static boolean isLineAcrossArea(List<String> lineAxisList,List<String> AreaAxisList){
List<Location> locationList1 = new ArrayList<>();
List<Location> locationList2 = new ArrayList<>();
/* 线的坐标转换处理*/
for (String s : lineAxisList) {
String[] split = s.split(",");
Location location = new Location(Double.parseDouble(split[0]),Double.parseDouble(split[1]));
}
/* 区域的坐标转换处理*/
for (String s : AreaAxisList) {
String[] split = s.split(",");
Location location = new Location(Double.parseDouble(split[0]),Double.parseDouble(split[1]));
}
//获取线的坐标线段
List<Line> lineList = getLines(locationList1);
//获取区域的线段
List<Line> lineList2 = getLines(locationList2);
//判断是否相交
boolean isIntersect = isIntersect(lineList, lineList2);
if (isIntersect) return true;
//如果不相交判断是否包含-由于没有相交线段只要存在点在多边形内就说明包含
boolean isPolygonInPolygon = isPolygonInPolygon(locationList1, locationList2);
if (isPolygonInPolygon) return true;
return false;
}

/**
* 判断根据给定的区域经纬度判断两个区域是否有重叠地方  A
* @param AreaList1 区域一坐标的字符串集合 {"经度1,纬度1","经度2,纬度2","经度3,纬度3".....}
* @param AreaList2 区域二坐标的字符串集合 {"经度1,纬度1","经度2,纬度2","经度3,纬度3".....}
* @return 是否相交的标识
*/
public static boolean isCoinCide(List<String> AreaList1, List<String> AreaList2) {
List<Location> locationList1 = new ArrayList<>();
List<Location> locationList2 = new ArrayList<>();
/* 区域一转换*/
for (String s : AreaList1) {
String[] split = s.split(",");
Location location = new Location(Double.parseDouble(split[0]),Double.parseDouble(split[1]));
}
/* 区域二转换*/
for (String s : AreaList2) {
String[] split = s.split(",");
Location location = new Location(Double.parseDouble(split[0]),Double.parseDouble(split[1]));
}
//获取四边形的线段
List<Line> lineList = getLines(locationList1);
//获取三角形的线段
List<Line> lineList2 = getLines(locationList2);
//判断是否相交
boolean isIntersect = isIntersect(lineList, lineList2);
if (isIntersect) return true;
//如果不相交判断是否包含-由于没有相交线段只要存在点在多边形内就说明包含
boolean isPolygonInPolygon = isPolygonInPolygon(locationList1, locationList2);
if (isPolygonInPolygon) return true;
return false;
}

/**
* 判断线段是否相交，A的附属方法 B
* @param locationList /
* @param locationList2 /
* @return /
*/
private static boolean isPolygonInPolygon(List<Location> locationList, List<Location> locationList2) {
//判断第一个多边形是否在第二个多边形内
for (Location location : locationList) {
boolean isPointInPolygon = isPointInPolygon(location, locationList2);
if (isPointInPolygon) return true;
}
//判断第二个多边形是否在第一个多边形内
for (Location location : locationList2) {
boolean isPointInPolygon = isPointInPolygon(location, locationList);
if (isPointInPolygon) return true;
}
return false;
}

/**
* 判断点是否在区域内，B的附属方法
* @param location
* @param locationList2
* @return
*/
private static boolean isPointInPolygon(Location location, List<Location> locationList2) {
//点是否在多边形内
GeneralPath path = new GeneralPath();
//设定多边形起始点
path.moveTo(locationList2.get(0).getLongitude(), locationList2.get(0).getLatitude());
for (Location l : locationList2) {
path.lineTo(l.getLongitude(), l.getLatitude());
}
//图像完成，封闭
path.moveTo(locationList2.get(0).getLongitude(), locationList2.get(0).getLatitude());
//多边形结束
path.closePath();
return path.contains(location.getLongitude(), location.getLatitude());
}

/**
* 判断线段是否相交 A的附属方法
* @param lineList /
* @param lineList2 /
* @return /
*/
private static boolean isIntersect(List<Line> lineList, List<Line> lineList2) {
for (Line line : lineList) {
for (Line line1 : lineList2) {
//两条线段是否相交
boolean b = Line2D.linesIntersect(line.location1.longitude, line.location1.latitude, line.location2.longitude, line.location2.latitude,
line1.location1.longitude, line1.location1.latitude, line1.location2.longitude, line1.location2.latitude);
if (b) {
return true;
}
}
}
return false;
}

/**
* 根据坐标经纬度获取线的方法
* @param locationList /
* @return /
*/
private static List<Line> getLines(List<Location> locationList) {
List<Line> lineList = new ArrayList();
for (int i = 0; i < locationList.size(); i++) {
if (i < locationList.size() - 1) {
Location l = locationList.get(i);
Location l2 = locationList.get(i + 1);
Line line = new Line(l, l2);
} else {
Location l = locationList.get(i);
Location l2 = locationList.get(0);
Line line = new Line(l, l2);
}
}
return lineList;
}

/**
* 辅助静态类-线
*/
public static class Line {
private Location location1;//起点
private Location location2;//终点

public Line(Location location1, Location location2) {
this.location1 = location1;
this.location2 = location2;
}

public Location getLocation1() {
return location1;
}

public void setLocation1(Location location1) {
this.location1 = location1;
}

public Location getLocation2() {
return location2;
}

public void setLocation2(Location location2) {
this.location2 = location2;
}

@Override
public String toString() {
return "Line{" +
"location1=" + location1 +
", location2=" + location2 +
'}';
}
}

/**
* 辅助静态类-坐标
*/
public static class Location {

private double longitude;//经度
private double latitude;//纬度

public Location(double longitude, double latitude) {
this.longitude = longitude;
this.latitude = latitude;
}

public double getLongitude() {
return longitude;
}

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

public double getLatitude() {
return latitude;
}

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

@Override
public String toString() {
return "Location{" +
"longitude=" + longitude +
", latitude=" + latitude +
'}';
}
}
}


# 根据两个坐标的经纬度，计算两点之间的中心点经纬度

/**
* 根据输入的地点坐标计算中心点
* @param startAxis 起点坐标 "经度,纬度"
* @param endAxis 终点坐标 "经度,纬度"
* @return 返回中心点坐标 "经度,纬度"
*/
public static String getCenterPoint(String startAxis,String endAxis) {
String[] arr = {startAxis,endAxis};
int total = arr.length;
double X = 0, Y = 0, Z = 0;
for (int i = 0; i < arr.length; i++) {
double lat, lon, x, y, z;
lon = Double.parseDouble(arr[i].split(",")[0]) * Math.PI / 180;
lat = Double.parseDouble(arr[i].split(",")[1]) * Math.PI / 180;
x = Math.cos(lat) * Math.cos(lon);
y = Math.cos(lat) * Math.sin(lon);
z = Math.sin(lat);
X += x;
Y += y;
Z += z;
}
X = X / total;
Y = Y / total;
Z = Z / total;
double Lon = Math.atan2(Y, X);
double Hyp = Math.sqrt(X * X + Y * Y);
double Lat = Math.atan2(Z, Hyp);
String centreAxis = (Lon * 180 / Math.PI) + "," + (Lat * 180 / Math.PI);
return centreAxis;
}


# 根据圆心坐标经纬度和半径，得到圆上的坐标

/**
* 给定一个圆心的经纬度和半径，求圆弧上的坐标
* @param centerPoint 经纬度坐标
*/
public static List<String> getCircleAxis(Double[] centerPoint, int radius) {
Double X; //经度
Double Y; //纬度
double r = 6371000.79;
List<String> optionsAxis = new ArrayList<>();
int numpoints = 360; // 角度
double phase = 2 * Math.PI / numpoints;

//画图
for (int i = 0; i < numpoints; i++) {
/**
* 计算坐标点
*/
double dx = (radius * Math.cos(i * phase));
double dy = (radius * Math.sin(i * phase)); //乘以1.6 椭圆比例

/**
* 转换成经纬度
*/
double dlng = dx / (r * Math.cos(centerPoint[1] * Math.PI / 180) * Math.PI / 180); //纬度的差值
double dlat = dy / (r * Math.PI / 180);  // 经度的差值

X = centerPoint[1] + dlat;
Y = centerPoint[0] + dlng;
String optAxis = Y+","+X;
}
return optionsAxis;
}


04-22 1万+

10-30 3753
07-24 1万+
11-16 1281
01-23 2129
11-02 3487
11-29 1603
06-04 4992
04-26 9343
11-17 1879
08-17 7019