| | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 判断一个坐标点位是否在一个坐标区域内 |
| | | * @param longitude 经度 |
| | | * @param latitude 纬度 |
| | | * @param fencePoints 围栏点位字符串,格式为 "lng1_lat1,lng2_lat2,..." |
| | | * @return 是否在区域内 true在 false不在 |
| | | */ |
| | | public boolean isPointInPolygon(double longitude, double latitude, String fencePoints) { |
| | | if (fencePoints == null || fencePoints.trim().isEmpty()) { |
| | | return false; |
| | | } |
| | | |
| | | // 解析围栏点位 |
| | | String[] points = fencePoints.split(","); |
| | | if (points.length < 3) { |
| | | return false; |
| | | } |
| | | |
| | | int n = points.length; |
| | | boolean inside = false; |
| | | |
| | | double x = longitude, y = latitude; |
| | | double[] xs = new double[n]; |
| | | double[] ys = new double[n]; |
| | | |
| | | for (int i = 0; i < n; i++) { |
| | | String[] coords = points[i].split("_"); |
| | | if (coords.length != 2) { |
| | | continue; |
| | | } |
| | | try { |
| | | xs[i] = Double.parseDouble(coords[0]); |
| | | ys[i] = Double.parseDouble(coords[1]); |
| | | } catch (NumberFormatException e) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // 使用射线法判断点是否在多边形内 |
| | | for (int i = 0, j = n - 1; i < n; j = i++) { |
| | | if (((ys[i] > y) != (ys[j] > y)) && |
| | | (x < (xs[j] - xs[i]) * (y - ys[i]) / (ys[j] - ys[i]) + xs[i])) { |
| | | inside = !inside; |
| | | } |
| | | } |
| | | |
| | | return inside; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 判断一个坐标区域(多边形A)是否完全在另一个坐标区域(多边形B)内 |
| | | * 原理:如果多边形A的所有顶点都在多边形B内,则认为A在B内 |
| | | * @param innerFencePoints 内部围栏点位字符串(待判断是否在外的围栏),格式为 "lng1_lat1,lng2_lat2,..." |
| | | * @param outerFencePoints 外部围栏点位字符串(参考围栏),格式为 "lng1_lat1,lng2_lat2,..." |
| | | * @return 是否在内 true在内 false不在 |
| | | */ |
| | | @Override |
| | | public boolean isPolygonInPolygon(String innerFencePoints, String outerFencePoints) { |
| | | if (innerFencePoints == null || innerFencePoints.trim().isEmpty() |
| | | || outerFencePoints == null || outerFencePoints.trim().isEmpty()) { |
| | | return false; |
| | | } |
| | | |
| | | // 解析内部围栏点位 |
| | | String[] innerPoints = innerFencePoints.split(","); |
| | | if (innerPoints.length < 3) { |
| | | return false; |
| | | } |
| | | |
| | | // 检查内部围栏的每一个顶点是否都在外部围栏内 |
| | | for (String pointStr : innerPoints) { |
| | | String[] coords = pointStr.split("_"); |
| | | if (coords.length != 2) { |
| | | continue; |
| | | } |
| | | try { |
| | | double lon = Double.parseDouble(coords[0]); |
| | | double lat = Double.parseDouble(coords[1]); |
| | | |
| | | // 如果有一个顶点不在外部围栏内,则整个区域不在内部 |
| | | if (!isPointInPolygon(lon, lat, outerFencePoints)) { |
| | | return false; |
| | | } |
| | | } catch (NumberFormatException e) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 根据围栏点位字符串计算中心点坐标 |
| | | * @param fencePoints 围栏点位字符串,格式为 "lng1_lat1,lng2_lat2,..." |
| | | * @return double[0] 经度, double[1] 纬度 |
| | | */ |
| | | public double[] calculateCenterPoint(String fencePoints) { |
| | | if (fencePoints == null || fencePoints.trim().isEmpty()) { |
| | | return new double[]{0.0, 0.0}; |
| | | } |
| | | |
| | | String[] points = fencePoints.split(","); |
| | | if (points.length == 0) { |
| | | return new double[]{0.0, 0.0}; |
| | | } |
| | | |
| | | double sumLon = 0.0; |
| | | double sumLat = 0.0; |
| | | int count = 0; |
| | | |
| | | for (String point : points) { |
| | | String[] coords = point.split("_"); |
| | | if (coords.length == 2) { |
| | | try { |
| | | double lon = Double.parseDouble(coords[0]); |
| | | double lat = Double.parseDouble(coords[1]); |
| | | sumLon += lon; |
| | | sumLat += lat; |
| | | count++; |
| | | } catch (NumberFormatException e) { |
| | | // 忽略解析错误的点 |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (count == 0) { |
| | | return new double[]{0.0, 0.0}; |
| | | } |
| | | |
| | | double centerLon = sumLon / count; |
| | | double centerLat = sumLat / count; |
| | | |
| | | return new double[]{centerLon, centerLat}; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void validate(XpStationVo dto) { |
| | | if (dto.getElectronicAreaId() == null) { |
| | |
| | | XpElectronicFence electronicFence = xpElectronicFenceService.getById(electronicFenceArea.getElectronicId()); |
| | | dto.setCityCode(electronicFence.getCityCode()); |
| | | |
| | | double[] centerPoints = calculateCenterPoint(dto.getFencePoints());//场站中心点位 |
| | | double[] centerPoints = polygonOverlapService.calculateCenterPoint(dto.getFencePoints());//场站中心点位 |
| | | dto.setCenterLon(centerPoints[0]); |
| | | dto.setCenterLat(centerPoints[1]); |
| | | //判断场站是否在 围栏里 |
| | | boolean polygonInPolygon = isPolygonInPolygon( dto.getFencePoints(),electronicFenceArea.getFencePoints()); |
| | | boolean polygonInPolygon = polygonOverlapService.isPolygonInPolygon( dto.getFencePoints(),electronicFenceArea.getFencePoints()); |
| | | if(!polygonInPolygon){ |
| | | throw new ServiceException("场站不在"+electronicFence.getElectronicName()+"围栏内"); |
| | | |
| | |
| | | |
| | | if(!dto.getXpPointList().isEmpty()) { |
| | | for (XpPoint xpPoint : dto.getXpPointList()) { |
| | | if(!isPointInPolygon(xpPoint.getPointLon(),xpPoint.getPointLat(),dto.getFencePoints())){ |
| | | if(!polygonOverlapService.isPointInPolygon(xpPoint.getPointLon(),xpPoint.getPointLat(),dto.getFencePoints())){ |
| | | throw new ServiceException(xpPoint.getPointName()+" 点位不在 "+dto.getStationName()+"场站内"); |
| | | } |
| | | } |
| | |
| | | if(dto.getStatus() == 2){//场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效 |
| | | //运营状态 1=待启用 2=启用中 3=已停用 4=已失效 |
| | | xpPoint.setOperationStatus(2); |
| | | }else if(dto.getStatus() == 3){ |
| | | xpPoint.setOperationStatus(3); |
| | | } |
| | | |
| | | if(xpPoint.getId() == null){ |