地图计算工具

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


}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值