在开发地图的时候难免会遇到经纬度的一些算法,这里我分享一些经纬度的算法,主要包括,
- 判断两个经纬度坐标之间的距离
- 判断一个经纬度坐标是否在一个圆形面中(如共享单车的电子围栏为圆形)
判断一个经纬度坐标是否在一个多边形的中(电子围栏类型为多边形)
具体算法:
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import com.tbit.uqbike.client.pojo.Point;
import com.tbit.uqbike.client.pojo.PointArray;
/**
* @author Kang
* @date 2018年7月25日 上午8:51:28
* @description 坐标工具类
*/
public class CoordUtils {
private static double EARTH_RADIUS = 6371393;//地球半径
private static double rad(double d) {
return d * Math.PI / 180.0;
}
/**
* 通过经纬度获取距离(单位:米)
* @param lat1 用户纬度
* @param lng1 用户经度
* @param lat2 用户纬度
* @param lng2 用户经度
* @return
*/
public static double getDistance(double lng1, double lat1, double lng2, double lat2) {
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lng1) - rad(lng2);
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 * 10000d) / 10000d;
return s;
}
/**
* 判断一个点是否在圆形区域内
* @param lon1 经度1
* @param lat1 纬度1
* @param lon2 经度2
* @param lat2 纬度2
* @param radius 半径 米
* @return
*/
public static boolean isInCircle(double lon1, double lat1, double lon2, double lat2, double radius) {
double distance = getDistance(lon1, lat1, lon2, lat2);
if (distance > radius) {
return false;
} else {
return true;
}
}
/**
* 判断是否在多边形区域内
* @param pointLon 要判断的点的纵坐标 经度
* @param pointLat 要判断的点的横坐标 纬度
* @param lon 区域各顶点的纵坐标数组 经度集合
* @param lat 区域各顶点的横坐标数组 纬度集合
* @return
*/
public static boolean isInPolygon(double pointLon, double pointLat, double[] lon,
double[] lat) {
// 将要判断的横纵坐标组成一个点
Point2D.Double point = new Point2D.Double(pointLon, pointLat);
// 将区域各顶点的横纵坐标放到一个点集合里面
List<Point2D.Double> pointList = new ArrayList<Point2D.Double>();
double polygonPoint_x = 0.0, polygonPoint_y = 0.0;
for (int i = 0; i < lon.length; i++) {
polygonPoint_x = lon[i];
polygonPoint_y = lat[i];
Point2D.Double polygonPoint = new Point2D.Double(polygonPoint_x, polygonPoint_y);
pointList.add(polygonPoint);
}
return check(point, pointList);
}
/**
* 一个点是否在多边形内
* @param point 要判断的点的横纵坐标
* @param polygon 组成的顶点坐标集合
* @return
*/
private static boolean check(Point2D.Double point, List<Point2D.Double> polygon) {
java.awt.geom.GeneralPath peneralPath = new java.awt.geom.GeneralPath();
Point2D.Double first = polygon.get(0);
// 通过移动到指定坐标(以双精度指定),将一个点添加到路径中
peneralPath.moveTo(first.x, first.y);
polygon.remove(0);
for (Point2D.Double d : polygon) {
// 通过绘制一条从当前坐标到新指定坐标(以双精度指定)的直线,将一个点添加到路径中。
peneralPath.lineTo(d.x, d.y);
}
// 将几何多边形封闭
peneralPath.lineTo(first.x, first.y);
peneralPath.closePath();
// 测试指定的 Point2D 是否在 Shape 的边界内。
return peneralPath.contains(point);
}
public static void main(String[] args) {
//验证多边形,先画一个面,然后判断这个点是否在这个面中
double pointLat=39.946361;
double pointLon=115.597662;
double[] lat={40.065737,39.651002,39.645669};//纬度
double[] lon={116.403694,116.000103,116.924567};//经度
boolean flag = isInPolygon(pointLon, pointLat, lon, lat);
System.out.println(flag);
//验证圆形
boolean inCircle = isInCircle(113.956187,22.555855, 113.956268,22.555824, 9.1);
System.out.println(inCircle);
System.out.println(getDistance(113.956187,22.555855, 113.956268,22.555824));
}
/**
* 返回经纬度坐标数组集合包装类
* @param points
* @return
*/
public static PointArray getPoints(String points){
String[] latLons = points.split(";");
double[] lons=new double[latLons.length];
double[] lats=new double[latLons.length];
for(int i=0;i<latLons.length;i++){
String[] latLonArray = latLons[i].split(",");
double lo=Double.parseDouble(latLonArray[0]);//经度
lons[i]=lo;
double la=Double.parseDouble(latLonArray[1]);//纬度
lats[i]=la;
}
return new PointArray(lons,lats);
}
}
经纬度坐标数组包装类:
/**
* @author Kang
* @date 2018年7月26日 上午9:44:04
* @description 经纬度数组包装
*/
public class PointArray {
private double[] lons; //经度
private double[] lats; //纬度
public PointArray(double[] lons,double[] lats){
this.lons=lons;
this.lats=lats;
}
public double[] getLons() {
return lons;
}
public void setLons(double[] lons) {
this.lons = lons;
}
public double[] getLats() {
return lats;
}
public void setLats(double[] lats) {
this.lats = lats;
}
}