1、经纬度转换工具类
import com.wh.whcloud.core.base.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
/**
* 经纬度工具类
*/
@Slf4j
public class LonlatUtils {
/* public static void main(String[] args) {
System.out.println(DmTurnD("120°39.516'"));
System.out.println(DmTurnD("30°46.237'"));
}*/
/**
* 表示角度的度、分、秒分别使用°、′、″符号进行表示。
* 1°=60′,1′=60″ ,1°=3600″。
* 由上述可知度分秒转换度的计算公式为:(dd°mm′ss″) dd+mm/60+ss/3600
* 经纬度转换 ,度分秒转度
* @param jwd
* @return
*/
public static String DmsTurnD(String jwd){
try{
if(StringUtil.isNotEmpty(jwd)&&(jwd.contains("°"))){//如果不为空并且存在度单位
//计算前进行数据处理
jwd = jwd.replace("E", "").replace("N", "").replace(":", "").replace(":", "");
double d=0,m=0,s=0;
d = Double.parseDouble(jwd.split("°")[0]);
//不同单位的分,可扩展
if(jwd.contains("′")){//正常的′
m = Double.parseDouble(jwd.split("°")[1].split("′")[0]);
}else if(jwd.contains("'")){//特殊的'
m = Double.parseDouble(jwd.split("°")[1].split("'")[0]);
}
//不同单位的秒,可扩展
if(jwd.contains("″")){//正常的″
//有时候没有分 如:112°10.25″
s = jwd.contains("′")?Double.parseDouble(jwd.split("′")[1].split("″")[0]):Double.parseDouble(jwd.split("°")[1].split("″")[0]);
}else if(jwd.contains("''")){//特殊的''
//有时候没有分 如:112°10.25''
s = jwd.contains("'")?Double.parseDouble(jwd.split("'")[1].split("''")[0]):Double.parseDouble(jwd.split("°")[1].split("''")[0]);
}
jwd = String.valueOf(d+m/60+s/60/60);//计算并转换为string
//使用BigDecimal进行加减乘除
/*BigDecimal bd = new BigDecimal("60");
BigDecimal d = new BigDecimal(jwd.contains("°")?jwd.split("°")[0]:"0");
BigDecimal m = new BigDecimal(jwd.contains("′")?jwd.split("°")[1].split("′")[0]:"0");
BigDecimal s = new BigDecimal(jwd.contains("″")?jwd.split("′")[1].split("″")[0]:"0");
//divide相除可能会报错(无限循环小数),要设置保留小数点
jwd = String.valueOf(d.add(m.divide(bd,6,BigDecimal.ROUND_HALF_UP)
.add(s.divide(bd.multiply(bd),6,BigDecimal.ROUND_HALF_UP))));*/
}
}catch (Exception e){
log.info("度分秒转换错误");
return jwd;
}
return jwd;
}
/**
* 度分 转度
* 十进制经纬度转换 ddd°mm.mmmm' 转 ddd.ddddd°
* 如:112°30.4128' = 112.50688
* @param jwd
* @return
*/
public static String DmTurnD(String jwd){
try {
if(StringUtil.isNotEmpty(jwd)&&(jwd.contains("°")&&jwd.contains("'"))){//如果不为空并且存在度、分单位
double d=0,m=0;
d = Double.parseDouble(jwd.split("°")[0]);
m = Double.parseDouble(jwd.split("°")[1].split("'")[0])/60;
jwd = String.valueOf(d+m);
}else if(StringUtil.isNotEmpty(jwd)&&(jwd.contains("°"))){//如果不为空并且存在度单位
double d=0,m=0;
d = Double.parseDouble(jwd.split("°")[0]);
m = Double.parseDouble(jwd.split("°")[1])/60;
jwd = String.valueOf(d+m);
}
}catch (Exception e){
log.info("度分转换错误");
return jwd;
}
return jwd;
}
}
2、DistanceUtil工具类
public class DistanceUtil {
public static final double earthRadius = 6371.393D;
public static final double nmi = 5.4E-4D;
public DistanceUtil() {
}
public static double meterToNmi(double len) {
return len * 5.4E-4D;
}
public static double meterToDegree(double len) {
return km2Degree(len / 1000.0D);
}
private static double rad(double d) {
return d * 3.141592653589793D / 180.0D;
}
public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lng1) - rad(lng2);
double s = 2.0D * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2.0D), 2.0D) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2.0D), 2.0D)));
s *= 6371.393D;
s = (double)Math.round(s * 10000.0D) / 10000.0D;
s *= 1000.0D;
return s;
}
public static Double km2Degree(Double l) {
Double degree = 0.008992661340005603D * l;
return degree;
}
public static Double degree2Km(Double degree) {
Double l = 111.20178578851908D * degree;
return l;
}
}
3、经纬度角度计算工具类
import com.util.DistanceUtil;
public class AngleUtil {
/**
* 根据俯仰角计算水平距离 俯仰角小于45度时适用
*
* @param h 单位米
* @param angle 单位度
* @return
*/
public static double HorizontalAngleCal(double h, double angle) {
return h * Math.tan(angle);
}
/**
* 获取云台和目标的直线距离(斜边长)
* @param lon1
* @param lat1
* @param lon2
* @param lat2
* @param h
* @return
*/
public static double getDistance(double lon1,double lat1,double lon2,double lat2,double h){
double l = DistanceUtil.getDistance(lat1,lon1,lat2,lon2);
return Math.sqrt(Math.pow(h,2)+ Math.pow(l,2));
}
/**
* 获取俯仰角度
* @param lon1
* @param lat1
* @param lon2
* @param lat2
* @param h
* @return
*/
public static double getTilAngle(double lon1,double lat1,double lon2,double lat2,double h){
double l = DistanceUtil.getDistance(lat1,lon1,lat2,lon2);
return Math.toDegrees(Math.atan (l/h));
}
/**
* 求两点连线与正北方向的角度(水平角度)
* @param A
* @param B
* @return
*/
public static double getPanAngle(LatLon A, LatLon B) {
double dx = (B.m_RadLo - A.m_RadLo) * A.Ed;
double dy = (B.m_RadLa - A.m_RadLa) * A.Ec;
double angle = 0.0;
angle = Math.atan(Math.abs(dx / dy)) * 180 / Math.PI;
double dLo = B.m_Longitude - A.m_Longitude;
double dLa = B.m_Latitude - A.m_Latitude;
if (dLo > 0 && dLa <= 0) {
angle = (90 - angle) + 90;
} else if (dLo <= 0 && dLa < 0) {
angle = angle + 180;
} else if (dLo < 0 && dLa >= 0) {
angle = (90 - angle) + 270;
}
return angle;
}
/**
* 获取方位角
* @param lat_a 纬度1
* @param lng_a 经度1
* @param lat_b 纬度2
* @param lng_b 经度2
* @return
*/
public static double getBearingAngle(double lat_a, double lng_a, double lat_b, double lng_b) {
try {
double y = Math.sin(lng_b-lng_a) * Math.cos(lat_b);
double x = Math.cos(lat_a)*Math.sin(lat_b) - Math.sin(lat_a)*Math.cos(lat_b)*Math.cos(lng_b-lng_a);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
if(brng < 0){
brng = brng +360;
}
return brng;
}catch (Exception e){
e.printStackTrace();
return 0d;
}
}
}
4、判断经纬度坐标点是否在区域内工具类
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PolygonUtil {
/**
* 求一个坐标点距离区域最近距离
*
* @param lon
* @param lat
* @param plotPointModelList
* @return
*/
/*public static double getDistanceFromPointToPolygon(BigDecimal lon, BigDecimal lat,
List<PlotPointModel> plotPointModelList) {
if (plotPointModelList.size() > 2) {
//求出距离最短的两个点
PlotPointModel minPoint1 = plotPointModelList.get(0);
PlotPointModel minPoint2 = plotPointModelList.get(1);
double d1 = DistanceUtil.getDistance(lat.doubleValue(), lon.doubleValue(),
minPoint1.getLat().doubleValue(), minPoint1.getLon().doubleValue());
double d2 = DistanceUtil.getDistance(lat.doubleValue(), lon.doubleValue(),
minPoint2.getLat().doubleValue(), minPoint2.getLon().doubleValue());
if (d1 > d2) {
PlotPointModel temp = minPoint1;
minPoint1 = minPoint2;
minPoint2 = temp;
}
for (int i = 2; i < plotPointModelList.size(); i++) {
PlotPointModel plotPoint = plotPointModelList.get(i);
double d = DistanceUtil.getDistance(lat.doubleValue(), lon.doubleValue(),
plotPoint.getLat().doubleValue(), plotPoint.getLon().doubleValue());
if (d < d1) {
d2 = d1;
d1 = d;
minPoint2 = minPoint1;
minPoint1 = plotPoint;
} else if (d < d2) {
d2 = d;
minPoint2 = plotPoint;
}
}
//根据最短两点,求最短距离
double c = DistanceUtil
.getDistance(minPoint1.getLat().doubleValue(), minPoint1.getLon().doubleValue(),
minPoint2.getLat().doubleValue(), minPoint2.getLon().doubleValue());
if (Math.pow(d2, 2) >= Math.pow(d1, 2) + Math.pow(c, 2)) {
//钝角三角形
return d1;
}
//锐角三角形,计算垂足,海伦公式
//计算周长
double p = (d1 + d2 + c) / 2;
//计算面积
double a = p * (p - d1) * (p - d2) * (p - c);
double s = Math.sqrt(a);
//返回高
return s / c;
}
return -1;
}*/
/**
* <p>
* 计算点到折线的最短距离
* 计算点到每条线段的最短距离,排序之后,拿最短的一条
* </p>
*
* @param lon
* @param lat
* @param plotPointModelList
* @return {@link double}
* @author hahalouti
* @date 2021/10/26
*/
public static double getDistanceFromPointToPolygon(BigDecimal lon, BigDecimal lat,
List<PlotPointModel> plotPointModelList) {
List<Double> distance = new ArrayList<>();
for (int i = 0; i < plotPointModelList.size() - 1; i++) {
PlotPointModel plotPoint = plotPointModelList.get(i);
PlotPointModel plotPoint2 = plotPointModelList.get(i + 1);
double d1 = DistanceUtil.getDistance(lat.doubleValue(), lon.doubleValue(),
plotPoint.getLat().doubleValue(), plotPoint.getLon().doubleValue());
double d2 = DistanceUtil.getDistance(lat.doubleValue(), lon.doubleValue(),
plotPoint2.getLat().doubleValue(), plotPoint2.getLon().doubleValue());
double c = DistanceUtil
.getDistance(plotPoint.getLat().doubleValue(), plotPoint.getLon().doubleValue(),
plotPoint2.getLat().doubleValue(), plotPoint2.getLon().doubleValue());
// 判断是否是钝角三角形
if (Math.pow(d1, 2) >= Math.pow(d2, 2) + Math.pow(c, 2)) {
//钝角三角形
distance.add(d2);
} else if (Math.pow(d2, 2) >= Math.pow(d1, 2) + Math.pow(c, 2)) {
//钝角三角形
distance.add(d1);
} else {
double p = (d1 + d2 + c) / 2;
//计算面积
double a = p * (p - d1) * (p - d2) * (p - c);
double s = Math.sqrt(a);
//返回高
distance.add(s / c);
}
}
Collections.sort(distance);
return distance.get(0);
}
/**
* 判断坐标点是否在一个区域内
*
* @param lon
* @param lat
* @param plotPointModelList
* @return
*/
public static boolean checkInPolygon(BigDecimal lon, BigDecimal lat,
List<PlotPointModel> plotPointModelList) {
double pointLon = lon.doubleValue();
double pointLat = lat.doubleValue();
int size = plotPointModelList.size();
if (size < 3) {
return false;
} else {
PlotPointModel first = plotPointModelList.get(0);
PlotPointModel end = plotPointModelList.get(size - 1);
if (first.getLon().doubleValue() == end.getLon().doubleValue()
&& first.getLat().doubleValue() == end.getLat().doubleValue()) {
plotPointModelList.remove(size - 1);
}
int pointCount = plotPointModelList.size();
int intersectPointCount = 0;
float intersectPointWeights = 0.0F;
double precision = 2.0E-10D;
for (int i = 1; i <= pointCount; ++i) {
PlotPointModel next = plotPointModelList.get(i % pointCount);
double firstLon = first.getLon().doubleValue();
double firstLat = first.getLat().doubleValue();
double nextLon = next.getLon().doubleValue();
double nextLat = next.getLat().doubleValue();
if (pointLat >= Math.min(firstLat, nextLat) && pointLat <= Math.max(firstLat, nextLat)) {
if (pointLat > Math.min(firstLat, nextLat) && pointLat < Math.max(firstLat, nextLat)) {
if (firstLon == nextLon) {
if (pointLon == firstLon) {
return true;
}
if (pointLon < firstLon) {
++intersectPointCount;
}
} else if (pointLon <= Math.min(firstLon, nextLon)) {
++intersectPointCount;
} else if (pointLon > Math.min(firstLon, nextLon) && pointLon < Math
.max(firstLon, nextLon)) {
double slopeDiff = 0.0D;
if (firstLat > nextLat) {
slopeDiff = (pointLat - nextLat) / (pointLon - nextLon) - (firstLat - nextLat) / (
firstLon - nextLon);
} else {
slopeDiff = (pointLat - firstLat) / (pointLon - firstLon) - (nextLat - firstLat) / (
nextLon - firstLon);
}
if (slopeDiff > 0.0D) {
if (slopeDiff < precision) {
return true;
}
++intersectPointCount;
}
}
} else {
if (firstLat == nextLat && pointLon <= Math.max(firstLon, nextLon) && pointLon >= Math
.min(firstLon, nextLon)) {
return true;
}
if (pointLat == firstLat && pointLon < firstLon
|| pointLat == nextLat && pointLon < nextLon) {
if (nextLat < firstLat) {
intersectPointWeights = (float) ((double) intersectPointWeights + -0.5D);
} else if (nextLat > firstLat) {
intersectPointWeights = (float) ((double) intersectPointWeights + 0.5D);
}
}
}
first = next;
} else {
first = next;
}
}
if (((float) intersectPointCount + Math.abs(intersectPointWeights)) % 2.0F == 0.0F) {
return false;
} else {
return true;
}
}
}
//
//
// public static void main(String[] args) {
// BigDecimal lon = new BigDecimal(122.63987);
// BigDecimal lat = new BigDecimal(39.25399);
// List<PlotPointModel> plotPointModelList = new ArrayList<>();
// PlotPointModel plotPointModel = new PlotPointModel();
// plotPointModel.setLon(new BigDecimal(122.6244164));
// plotPointModel.setLat(new BigDecimal(39.2591590));
// plotPointModelList.add(plotPointModel);
//
// PlotPointModel plotPointModel2 = new PlotPointModel();
// plotPointModel2.setLon(new BigDecimal(122.6244164));
// plotPointModel2.setLat(new BigDecimal(39.2463846));
// plotPointModelList.add(plotPointModel2);
//
// PlotPointModel plotPointModel3 = new PlotPointModel();
// plotPointModel3.setLon(new BigDecimal(122.6494789));
// plotPointModel3.setLat(new BigDecimal(39.2466508));
// plotPointModelList.add(plotPointModel3);
//
// PlotPointModel plotPointModel4 = new PlotPointModel();
// plotPointModel4.setLon(new BigDecimal(122.6499939));
// plotPointModel4.setLat(new BigDecimal(39.2588929));
// plotPointModelList.add(plotPointModel4);
//
// System.out.println(checkInPolygon(lon,lat,plotPointModelList));
// }
}