根据经纬度坐标点返回所在行政区域实现

根据经纬度坐标点返回所在行政区域实现

项目工程源码下载
行政区域数据下载

public Result getPosition (Double longitude, Double latitude) {
		
		// 获取所有district级别行政区域中心点
		List<Center> centers = this.regionsService.getAllDistrict();
		
		// 根据传入经纬度跟所有行政区域中心点按距离从小到大排序
		centers.sort(new Comparator<Center>() {
			@Override
			public int compare(Center o1, Center o2) {
				String point1 = (String) o1.getAdcode();
				Double lon1 = Double.valueOf(point1.split(",")[0]);
				Double lat1 = Double.valueOf(point1.split(",")[1]);
				Double dis1 = CalulateTwoLanLon.getDistance(lat1, lon1, latitude, longitude);
				
				String point2 = (String) o2.getAdcode();
				Double lon2 = Double.valueOf(point2.split(",")[0]);
				Double lat2 = Double.valueOf(point2.split(",")[1]);
				Double dis2 = CalulateTwoLanLon.getDistance(lat2, lon2, latitude, longitude);
				
				if (dis1 < dis2)
					return -1;
				else if (dis1 > dis2)
					return 1;
				else 
					return 0;
			}
		});
		
		String address = null;
		for (Center center : centers) {
			
			String point1 = (String) center.getAdcode();
			Double lon1 = Double.valueOf(point1.split(",")[0]);
			Double lat1 = Double.valueOf(point1.split(",")[1]);
			Double dis1 = CalulateTwoLanLon.getDistance(lat1, lon1, latitude, longitude);
			System.out.println(center.getId() + "   " + dis1);
			
			Integer id = center.getId();
			Region region = this.regionsService.findById(id);
			
			if(StringUtils.isEmpty(region.getPolyline()))
				continue;
			
			String[] polylines = region.getPolyline().split("\\|");
			
			for (int i = 0; i < polylines.length; i++) {
				// 如果点在区域内
				if(Profile.isInPolygon(longitude, latitude, polylines[i])) {
					address = this.regionsService.getFullNameById(id);
				}
			}
			
			if(!StringUtils.isEmpty(address))
				break;	    	
		}
		
		return new Result(Result.SUCCESS, "响应成功!",  address);
	}
public class Profile {
	
	/**
     * 判断是否在多边形区域内
     * @param pointLon 要判断的点的纵坐标
     * @param pointLat 要判断的点的横坐标
     * @param lon      区域各顶点的纵坐标数组
     * @param lat      区域各顶点的横坐标数组
     * @return
     */
    public static boolean isInPolygon(Double pointLon, Double pointLat, String polyline) {
    	
    	String[] points = polyline.split(";");
    	
    	double[] lon = new double[points.length];
    	double[] lat = new double[points.length];
    	
    	for (int i = 0; i < points.length; i++) {
			String[] point = points[i].split(",");
			lon[i] = Double.valueOf(point[0]);
			lat[i] = Double.valueOf(point[1]);
		}
    	
        // 将要判断的横纵坐标组成一个点
        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 class CalulateTwoLanLon {
	
	private static final double EARTH_RADIUS = 6378.137;//地球半径,单位千米
	
    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 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;
    }
}

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值