package com.stylefeng.guns.modular.crossCity.server.impl; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import com.stylefeng.guns.modular.crossCity.dao.LocationMapper; import com.stylefeng.guns.modular.crossCity.dao.SiteMapper; import com.stylefeng.guns.modular.crossCity.model.Site; import com.stylefeng.guns.modular.crossCity.server.ISiteService; import com.stylefeng.guns.modular.crossCity.warpper.SiteWarpper; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.*; @Service public class SiteServiceImpl extends ServiceImpl implements ISiteService { @Resource private SiteMapper siteMapper; @Resource private LocationMapper locationMapper; private static final double COORDINATE_EPSILON = 1E-10; /** * 获取站点 * @return * @throws Exception */ @Override public List querySite(Integer startSiteId) throws Exception { List> sites = null; if(null == startSiteId){ sites = siteMapper.querySite(null); }else{ sites = siteMapper.querySite(startSiteId); } Set set = new HashSet<>(); for(Map site : sites) { set.add(site.get("cityCode").toString()); } List list = new ArrayList<>(); for(String c : set){ SiteWarpper siteWarpper = new SiteWarpper(); List data = new ArrayList<>(); String name = ""; String code = ""; for(Map s : sites){ if(c.equals(s.get("cityCode").toString())){ Map map = new HashMap<>(); map.put("id", s.get("id")); map.put("name", s.get("name").toString()); name = s.get("cityName").toString(); code = s.get("cityCode").toString(); data.add(map); } } siteWarpper.setName(name); siteWarpper.setCode(code); siteWarpper.setSites(data); list.add(siteWarpper); } return list; } /** * 判断点是都在区域范围内 * @param siteId * @param code * @param lonLat * @return * @throws Exception */ @Override public boolean areaMonitoring(Integer siteId, String code, String lonLat) throws Exception { List> list = this.queryLocation(siteId); for(Map map : list){ if(Integer.valueOf(map.get("type").toString()) == 1){//行政区域 if(null != map.get("districtCode")){ if(code.equals(map.get("districtCode").toString())){ return true; } continue; } if(null != map.get("cityCode")){ if(code.equals(map.get("cityCode").toString())){ return true; } code = code.substring(0, 4) + "00"; if(code.equals(map.get("cityCode").toString())){ return true; } continue; } if(null != map.get("provinceCode")){ code = code.substring(0, 2) + "0000"; if(code.equals(map.get("provinceCode").toString())){ return true; } continue; } } if(Integer.valueOf(map.get("type").toString()) == 2){//电子围栏 Object coordinate = map.get("coordinate"); if(coordinate != null && isPointInElectronicFence(lonLat, coordinate.toString())){ return true; } continue; } } return false; } static boolean isPointInElectronicFence(String lonLat, String coordinate) { double[] point = parseCoordinate(lonLat); if (point == null || coordinate == null || coordinate.trim().isEmpty()) { return false; } String[] fences = coordinate.split("_"); for (String fence : fences) { String[] coordinatePoints = fence.split(";"); if (coordinatePoints.length < 3) { continue; } List polygon = new ArrayList<>(); boolean validPolygon = true; for (String coordinatePoint : coordinatePoints) { double[] vertex = parseCoordinate(coordinatePoint); if (vertex == null) { validPolygon = false; break; } polygon.add(vertex); } if (validPolygon && isPointInPolygon(point, polygon)) { return true; } } return false; } private static double[] parseCoordinate(String coordinate) { if (coordinate == null || coordinate.trim().isEmpty()) { return null; } String[] values = coordinate.trim().split(","); if (values.length != 2) { return null; } try { double longitude = Double.parseDouble(values[0].trim()); double latitude = Double.parseDouble(values[1].trim()); if (Double.isNaN(longitude) || Double.isInfinite(longitude) || Double.isNaN(latitude) || Double.isInfinite(latitude)) { return null; } return new double[]{longitude, latitude}; } catch (NumberFormatException e) { return null; } } private static boolean isPointInPolygon(double[] point, List polygon) { boolean inside = false; for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) { double[] start = polygon.get(j); double[] end = polygon.get(i); if (isPointOnSegment(point, start, end)) { return true; } boolean intersects = (start[1] > point[1]) != (end[1] > point[1]) && point[0] < (end[0] - start[0]) * (point[1] - start[1]) / (end[1] - start[1]) + start[0]; if (intersects) { inside = !inside; } } return inside; } private static boolean isPointOnSegment(double[] point, double[] start, double[] end) { double crossProduct = (point[0] - start[0]) * (end[1] - start[1]) - (point[1] - start[1]) * (end[0] - start[0]); if (Math.abs(crossProduct) > COORDINATE_EPSILON) { return false; } return point[0] >= Math.min(start[0], end[0]) - COORDINATE_EPSILON && point[0] <= Math.max(start[0], end[0]) + COORDINATE_EPSILON && point[1] >= Math.min(start[1], end[1]) - COORDINATE_EPSILON && point[1] <= Math.max(start[1], end[1]) + COORDINATE_EPSILON; } /** * 根据站点id获取地点区域 * @param siteId * @return * @throws Exception */ @Override public List> queryLocation(Integer siteId) throws Exception { return locationMapper.queryLocation(siteId); } }