public class MapUtil {
private static double EARTH_RADIUS = 6378137;//地球半径(m)
/**
* 点
* @author Administrator
*
*/
public static class Point{
public double x;
public double y;
public Point() {
super();
}
public Point(double x, double y) {
super();
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
/**
* 线
* @author Administrator
*
*/
static class Line{
public Point startPoint;
public Point endPoint;
public double k;
public double b;
public boolean isVerticalX = false;
public boolean isVerticalY = false;
}
private static double rad(double d)
{
return d * Math.PI / 180.0;
}
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 * 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 * 10000) / 10000;
return s;
}
/**
* 计算两点的距离
* @param a_x_point 经度
* @param a_y_point 纬度
* @param b_x_point 经度
* @param b_y_point 纬度
* @return
*/
public static long calDistance(Double a_x_point, Double a_y_point,
Double b_x_point, Double b_y_point) {
Double R = new Double(6378137);
Double dlat = (b_x_point - a_x_point) * Math.PI / 180;
Double dlon = (b_y_point - a_y_point) * Math.PI / 180;
Double aDouble = Math.sin(dlat / 2) * Math.sin(dlat / 2)
+ Math.cos(a_x_point * Math.PI / 180)
* Math.cos(b_x_point * Math.PI / 180) * Math.sin(dlon / 2)
* Math.sin(dlon / 2);
Double cDouble = 2 * Math.atan2(Math.sqrt(aDouble), Math
.sqrt(1 - aDouble));
long d = Math.round((R * cDouble) * 1000) / 1000;
return d;
}
/**
* 判断点是否在圆里
* @param a_lng
* @param a_lat
* @param b_lng
* @param b_lat
* @param c_lng
* @param c_lat
* @return
*/
public static Boolean isInRound(Double a_lng, Double a_lat,
Double b_lng, Double b_lat,Double c_lng, Double c_lat){
double s1 = calDistance(a_lat,a_lng,b_lat,b_lng);
double s2 = calDistance(b_lat,b_lng,c_lat,c_lng);
if(s1 > s2){
return false;
}else{
return true;
}
}
/**
* 判断点是否在矩形里
* @param a_lng 目标点
* @param a_lat 目标点
* @param b_lng 矩形左下角
* @param b_lat 矩形左下角
* @param c_lng 矩形右上角
* @param c_lat 矩形右上角
* @return
*/
public static Boolean isInRectangle(Double a_lng, Double a_lat,
Double b_lng, Double b_lat,Double c_lng, Double c_lat){
if(a_lng >= b_lng && a_lat >= b_lat && a_lng <= c_lng && a_lat <= c_lat){
return true;
}else{
return false;
}
}
/**
* 所求点A是否在多边形内
* 1.判断点是否在顶点
* 2.判断点是否在边线上
* (下方递归)
* 3.做A点右侧任意点和点A连线l
* 4.求出所有A点右侧多边形边(其中一个顶点在A右侧的边也算)和l的交点
* 5.判断是否有交点 是 :继续 ,否:判断线l是否与边线重合 是 :回到第3步并上调任意点Y值 否:跳过,判断下条边
* 6.判断交点是否在A点的右侧 是:继续 否 :跳过,判断下条边
* 7.判断交点是否在多边形的边上 是:继续 否:跳过,判断下条边
* 8.判断交点是否在顶点上 是:回到第3步并上调任意点Y值,否:计数并继续
* 9.判断交点数是否为奇数,是 : 点在多边形内 否 :不在多边形内
*/
public static boolean isInPolygon(String x ,String y,String points){
//目标点A
Point A = new Point();
A.x = new Double(x);
A.y = new Double(y);
//多边形顶点
Point[] peaks = toPoints(points);
boolean flag = isPointInPolygon2(A,peaks);
return flag;
}
/**
* 所求点A是否在多边形内
* @param lng
* @param lat
* @param points
* @return
*/
public static boolean isPointInPolygon2(double lng ,double lat,String points){
Point A = new Point();
A.x = lng;
A.y = lat;
//多边形顶点
Point[] peaks = toPoints(points);
boolean flag = isPointInPolygon2(A,peaks);
return flag;
}
/**
* 将字符串转换成点
* @param points
* @return
*/
private static Point[] toPoints(String points){
String[] _points = points.split(",");
Point[] pointsArr = new Point[_points.length];
for(int i=0;i<_points.length;i++){
String[] _p = _points[i].split("_");
Point point = new Point();
point.x = new Double(_p[0]);
point.y = new Double(_p[1]);
pointsArr[i] = point;
}
return pointsArr;
}
/**
* 验证点是否在多边形内
* @param point
* @param points
* @return
*/
public static boolean isPointInPolygon2(Point point, Point[] points) {
boolean re = false;
int nCross = 0;
for (int i = 0; i < points.length; i++) {
Point p1 = points[i];
Point p2 = points[(i + 1) % points.length];
if (p1.y == p2.y) {
continue;
}
double min = (p1.y > p2.y) ? p2.y: p1.y;
double max = (p1.y > p2.y) ? p1.y: p2.y;
if (point.y < min) {
continue;
}
if (point.y >= max) {
continue;
}
// 求交点的x 坐标
double x = (double) (point.y - p1.y)
* (double) (p2.x - p1.x)
/ (double) (p2.y - p1.y) + p1.x;
if (x > point.x) {
nCross++; // 只统计单边交点
}
re = nCross % 2 == 1;
}
return re;
}
/**
* 计算了两个地理坐标点(由经纬度表示)之间的方位角(bearing)。方位角是从正北方向顺时针测量的角度,用于表示从一个点到另一个点的方向。
* @param lat_a
* @param lng_a
* @param lat_b
* @param lng_b
* @return
*/
public static double direction(double lat_a, double lng_a, double lat_b, double lng_b){
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;
}
/**
* 根据两个经纬度点得到角度
* @param lat_a
* @param lng_a
* @param lat_b
* @param lng_b
* @return
*/
public static double getAngle(double lat_a, double lng_a, double lat_b, double lng_b){
Double dRotateAngle = Math.atan2(
Math.abs(lng_a - lng_b),
Math.abs(lat_a - lat_b)
);
if (lng_b >= lng_a) {
if (lat_b >= lat_a) {
} else {
dRotateAngle = Math.PI - dRotateAngle;
}
} else {
if (lat_b >= lat_a) {
dRotateAngle = 2 * Math.PI - dRotateAngle;
} else {
dRotateAngle = Math.PI + dRotateAngle;
}
}
dRotateAngle = (dRotateAngle * 180) / Math.PI;
return dRotateAngle;
}
/**
* 传入两个经纬度坐标,计算出两个坐标之间的角度,范围是0-360。
* // 计算方位角,正北向为0度,以顺时针方向递增
* 车机数据对比,有稍微的误差,基本上可用
*/
public static double computeAzimuth(double lat_a, double lng_a, double lat_b, double lng_b) {
double lat1 = lat_a, lon1 = lng_a, lat2 = lat_b,
lon2 = lng_b;
double result = 0.0;
int ilat1 = (int) (0.50 + lat1 * 360000.0);
int ilat2 = (int) (0.50 + lat2 * 360000.0);
int ilon1 = (int) (0.50 + lon1 * 360000.0);
int ilon2 = (int) (0.50 + lon2 * 360000.0);
lat1 = Math.toRadians(lat1);
lon1 = Math.toRadians(lon1);
lat2 = Math.toRadians(lat2);
lon2 = Math.toRadians(lon2);
if ((ilat1 == ilat2) && (ilon1 == ilon2)) {
return result;
} else if (ilon1 == ilon2) {
if (ilat1 > ilat2)
result = 180.0;
} else {
double c = Math
.acos(Math.sin(lat2) * Math.sin(lat1) + Math.cos(lat2)
* Math.cos(lat1) * Math.cos((lon2 - lon1)));
double A = Math.asin(Math.cos(lat2) * Math.sin((lon2 - lon1))
/ Math.sin(c));
result = Math.toDegrees(A);
if ((ilat2 > ilat1) && (ilon2 > ilon1)) {
} else if ((ilat2 < ilat1) && (ilon2 < ilon1)) {
result = 180.0 - result;
} else if ((ilat2 < ilat1) && (ilon2 > ilon1)) {
result = 180.0 - result;
} else if ((ilat2 > ilat1) && (ilon2 < ilon1)) {
result += 360.0;
}
}
return result;
}
}
地图计算工具
于 2024-03-22 17:46:43 首次发布