计算地图上正方(矩)形区域点坐标集合判断电子围栏

背景:公司业务需要在地图上绘画出以任意地址且斜长为500m的正方形区域点坐标集合作为电子围栏集合区域,绘画出来的正方形区域点坐标集合通过前端APP作为触发电子围栏条件。

实现方法:

1、将中心点地址通过高德API接口地理编码解析为高德经纬度

2、通过中心点经纬度、斜长、角度计算出正方形(矩形)每个点坐标经纬度

3、最后四个点坐标组合成区域点集合

现通过java实现代码如下:

/**
	 * 
	 * @Description: 计算正方(矩)形区域点坐标集合
	 * @param address 地址
	 * @param margin 斜长(km)
	 * @param angle 角度
	 * @return
	 * @throws NumberFormatException
	 * @author 
	 * @date 2019年1月3日 下午8:07:58
	 */
	public String calculatUtilSquareRegion(String address,double margin,double angle){
		// 地理编码(地址解析为高德经纬度)
		List<AmapGeocodes> amapGeocodesList = this.adressAnalysis(address, false);
		JSONArray jsonObject = null;
		String location = "";
		if (!CollectionUtils.isEmpty(amapGeocodesList)) {
			location = amapGeocodesList.get(0).getLocation();
		}
		String pointX = "";
		String pointY = "";
		// 获取原始点经纬度
		if (StringUtils.isNotBlank(location)) {
			pointX = location.split(",")[0];
			pointY = location.split(",")[1];
			List<LngLatPointVo> list = new ArrayList<LngLatPointVo>();
			// 计算角度为margin的经纬度
			LngLatPointVo pointA = getLngLat(Double.parseDouble(pointY), Double.parseDouble(pointX), margin, angle);
			list.add(pointA);
			// 计算角度为margin+90的经纬度
			LngLatPointVo pointB = getLngLat(Double.parseDouble(pointY), Double.parseDouble(pointX), margin, angle + 90);
			list.add(pointB);
			// 计算角度为margin+180的经纬度
			LngLatPointVo pointC = getLngLat(Double.parseDouble(pointY), Double.parseDouble(pointX), margin, angle + 180);
			list.add(pointC);
			// 计算角度为margin+270的经纬度
			LngLatPointVo pointD = getLngLat(Double.parseDouble(pointY), Double.parseDouble(pointX), margin, angle + 270);
			list.add(pointD);
			list.toArray();
			jsonObject = (JSONArray) JSONArray.toJSON(list.toArray());
		}
		return jsonObject == null ? "" : jsonObject.toString();
	}
/**
	 * @Description 根据一个点的经纬度坐标、边长距离、角度计算另一个点的经纬度(方法1)
	 * @param lat 纬度
	 * @param lng 经度
	 * @param margin 斜长距离(km)
	 * @param angle 角度
	 * @return
	 * @author 
	 */
	public LngLatPointVo getLngLat(double lat, double lng, double margin, double angle){
		LngLatPointVo lngLat = new LngLatPointVo();
		double Ea = 6378137; // 赤道半径
		double Eb = 6356725; // 极半径
		double dx = margin * 1000 * Math.sin(angle * Math.PI / 180.0);
		double dy = margin * 1000 * Math.cos(angle * Math.PI / 180.0);
		double ec = Eb + (Ea - Eb) * (90.0 - lat) / 90.0;
		double ed = ec * Math.cos(lat * Math.PI / 180);
		double newLng = (dx / ed + lng * Math.PI / 180.0) * 180.0 / Math.PI;
		double newLat = (dy / ec + lat * Math.PI / 180.0) * 180.0 / Math.PI;
		lngLat.setLat(newLat);
		lngLat.setLng(newLng);
		return lngLat;
	}
	/**
	 * @Description 根据一个点的经纬度坐标、边长距离、角度计算另一个点的经纬度(方法2)
	 * @param lat 纬度
	 * @param lng 经度
	 * @param distance 边长距离
	 * @param angle 角度
	 * @return
	 * @author liuhai
	 */
	public LngLatPointVo getLngLat1(double lat, double lng, double distance,
			double angle) {
		LngLatPointVo lngLat = new LngLatPointVo();
		double R = 6378.137;
		double φ1 = ConvertDegreesToRadians(lat);
		double λ1 = ConvertDegreesToRadians(lng);
		double θ = ConvertDegreesToRadians(angle);
		double φ2 = Math.asin(Math.sin(φ1) * Math.cos(distance / R)
				+ Math.cos(φ1) * Math.sin(distance / R) * Math.cos(θ));
		double λ2 = λ1
				+ Math.atan2(
						Math.sin(θ) * Math.sin(distance / R) * Math.cos(φ1),
						Math.cos(distance / R) - Math.sin(φ1) * Math.sin(φ2));
		λ2 = (λ2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalise to
															// -180..+180°
		double lat2 = ConvertRadiansToDegrees(φ2);
		double lon2 = ConvertRadiansToDegrees(λ2);
		lngLat.setLat(lat2);
		lngLat.setLng(lon2);
		return lngLat;
	}

	public double ConvertDegreesToRadians(double degrees) {
		return degrees * Math.PI / 180;
	}
	public static double ConvertRadiansToDegrees(double radian) {
		return radian * 180.0 / Math.PI;
	}
/**
	 * @Title: adressAnalysis
	 * @param adress
	 *            ,batch(批量查询控制:batch 参数设置为 true 时进行批量查询操作,最多支持 10 个地址进行批量查询)
	 * @Description: 地理编码(地址解析为高德经纬度)
	 * @return 返回List
	 */
	public List<AmapGeocodes> adressAnalysis(String adress, Boolean batch) {
		List<AmapGeocodes> list = new ArrayList<AmapGeocodes>();
		SystemConfig scKey = systemConfigBiz.findCacheByCode("AMAP_API_SERVER_AK");
		SystemConfig scUrl = systemConfigBiz.findCacheByCode("AMP_API_ADRESS_ANALYSIS");
		String key = "", url = "";
		// 非空判断
		if (null != scUrl && null != scKey) {
			key = scKey.getConfigValue();
			url = scUrl.getConfigValue();
		}
		if (StringUtils.isBlank(key) || StringUtils.isBlank(url)) {
			log.info("缺少AMAP_API_SERVER_AK或者AMP_API_ADRESS_ANALYSIS的系統配置項,請先在系統配置管理中進行配置");
			return list;
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("address", adress.trim());
		params.put("output", "JSON");
		params.put("batch", false);
		params.put("key", key);
		String json = HttpUtil.sendGet(url, params, "UTF-8");
		// 将返回结果转换成map
		Map<?, ?> reMap = JSON.parseObject(json);
		// 请求成功
		if (reMap != null && ((reMap.get("status") == null ? "" : reMap.get("status").toString()).equals("1"))) {
			String geocodesArray = reMap.get("geocodes") == null ? "" : reMap.get("geocodes").toString();
			if (Integer.parseInt(reMap.get("count") == null ? "0" : reMap.get("count").toString()) > 0) {
				list = JSONObject.parseArray(geocodesArray, AmapGeocodes.class);
			}
		}
		return list;
	}

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Python中的OpenCV库来实现。以下是一个简单的例子: 1. 首先,读取图像并将其转换为灰度图像: ``` python import cv2 img = cv2.imread('image.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ``` 2. 然后,使用Canny算子进行边缘检测: ``` python edges = cv2.Canny(gray, 50, 150, apertureSize=3) ``` 3. 接下来,使用霍夫变换检测图像中的直线: ``` python lines = cv2.HoughLines(edges, 1, np.pi/180, 200) ``` 4. 对于每个检测到的直线,计算其与图像边界的交: ``` python for line in lines: rho, theta = line[0] a = np.cos(theta) b = np.sin(theta) x0 = a * rho y0 = b * rho x1 = int(x0 + 1000 * (-b)) y1 = int(y0 + 1000 * (a)) x2 = int(x0 - 1000 * (-b)) y2 = int(y0 - 1000 * (a)) cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) ``` 5. 最后,使用这些交计算正方的四个角坐标: ``` python corners = cv2.goodFeaturesToTrack(gray, 4, 0.01, 10) corners = np.int0(corners) for corner in corners: x, y = corner.ravel() cv2.circle(img, (x, y), 3, (0, 255, 0), -1) ``` 完整代码如下: ``` python import cv2 import numpy as np img = cv2.imread('image.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150, apertureSize=3) lines = cv2.HoughLines(edges, 1, np.pi/180, 200) for line in lines: rho, theta = line[0] a = np.cos(theta) b = np.sin(theta) x0 = a * rho y0 = b * rho x1 = int(x0 + 1000 * (-b)) y1 = int(y0 + 1000 * (a)) x2 = int(x0 - 1000 * (-b)) y2 = int(y0 - 1000 * (a)) cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) corners = cv2.goodFeaturesToTrack(gray, 4, 0.01, 10) corners = np.int0(corners) for corner in corners: x, y = corner.ravel() cv2.circle(img, (x, y), 3, (0, 255, 0), -1) cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值