From fbea1c2c2abfe6534aff04d59fed3b186787d6bc Mon Sep 17 00:00:00 2001 From: lcj <2331845269@qq.com> Date: Mon, 9 Jun 2025 19:59:39 +0800 Subject: [PATCH] =?UTF-8?q?[update]=20=E4=BF=AE=E6=94=B9=E5=85=89=E4=BC=8F?= =?UTF-8?q?=E6=9D=BF=E5=92=8C=E5=90=8D=E7=A7=B0=E5=8C=B9=E9=85=8D=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/FacPhotovoltaicPanelServiceImpl.java | 45 +++++------ .../main/java/org/dromara/utils/JSTUtil.java | 75 +++++++++++++++++-- 2 files changed, 87 insertions(+), 33 deletions(-) diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacPhotovoltaicPanelServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacPhotovoltaicPanelServiceImpl.java index fe8e54f8..93a6646b 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacPhotovoltaicPanelServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacPhotovoltaicPanelServiceImpl.java @@ -17,7 +17,10 @@ import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.facility.constant.FacRedisKeyConstant; import org.dromara.facility.domain.FacMatrix; import org.dromara.facility.domain.FacPhotovoltaicPanel; -import org.dromara.facility.domain.dto.geojson.*; +import org.dromara.facility.domain.dto.geojson.FacFeatureByPlane; +import org.dromara.facility.domain.dto.geojson.FacFeatureByPoint; +import org.dromara.facility.domain.dto.geojson.FacGeoJsonByPlane; +import org.dromara.facility.domain.dto.geojson.FacGeoJsonByPoint; import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelCreateByGeoJsonReq; import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelCreateReq; import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelQueryReq; @@ -201,28 +204,30 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl> progressCategoryMap = progressCategoryList.stream() .collect(Collectors.groupingBy(PgsProgressCategory::getMatrixId)); - ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); List allPanels = new ArrayList<>(); - try { - List>> futures = new ArrayList<>(); - Long userId = LoginHelper.getUserId(); - for (FacFeatureByPlane locationFeature : locationFeatures) { + List>> futures = new ArrayList<>(); + Long userId = LoginHelper.getUserId(); + // 构建光伏板实体集合 + try (ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())) { + for (FacFeatureByPoint nameFeature : nameFeatures) { Future> future = executorService.submit(() -> { List panelList = new ArrayList<>(); - // ① 获取 geometry 坐标 - FacGeometryByPlane geometry = locationFeature.getGeometry(); - List> coordinates = geometry.getCoordinates().getFirst(); - // ② 判断方阵 + // ① 找到该点对应的 polygon(优先包含,否则最近) + FacFeatureByPlane matchedPolygon = JSTUtil.findNearestOrContainingPolygon(nameFeature, locationFeatures); + if (matchedPolygon == null) return Collections.emptyList(); + // ② 获取 geometry 坐标 + List> coordinates = matchedPolygon.getGeometry().getCoordinates().getFirst(); + // ③ 判断所属方阵 FacMatrix matrix = matrixService.getMatrixIdBy2Coordinates(matrixList, coordinates); if (matrix == null) return Collections.emptyList(); - // ③ 获取名称 - String name = JSTUtil.findNearestPointText(coordinates, nameFeatures); - if (name == null) return Collections.emptyList(); - // ④ 获取进度类别 Long matrixId = matrix.getId(); + // ④ 获取进度类别 List progressCategoryListByMatrix = progressCategoryMap.get(matrixId); if (CollUtil.isEmpty(progressCategoryListByMatrix)) return Collections.emptyList(); - // ⑤ 构建光伏板 + // ⑤ 获取名称 + String name = nameFeature.getProperties() != null ? nameFeature.getProperties().getText() : null; + if (StringUtils.isBlank(name)) return Collections.emptyList(); + // ⑥ 构建面板数据 for (PgsProgressCategory progressCategory : progressCategoryListByMatrix) { FacPhotovoltaicPanel panel = new FacPhotovoltaicPanel(); panel.setMatrixId(matrixId); @@ -259,16 +264,6 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl new Coordinate(coord.getFirst(), coord.get(1))) .toArray(Coordinate[]::new); Polygon jtsPolygon = geometryFactory.createPolygon(polygonCoords); - // 2. 查找最近点 - FacFeatureByPoint nearestFeature = null; - double minDistance = Double.MAX_VALUE; + // 2. 构建空间索引(JTS STRtree) + STRtree spatialIndex = new STRtree(); + Map coordToFeatureMap = new HashMap<>(); for (FacFeatureByPoint feature : points) { List coords = feature.getGeometry().getCoordinates(); if (coords == null || coords.size() != 2) continue; - Point point = geometryFactory.createPoint(new Coordinate(coords.get(0), coords.get(1))); + Coordinate coord = new Coordinate(coords.get(0), coords.get(1)); + Point point = geometryFactory.createPoint(coord); + // 用点的 Envelope 加入索引 + spatialIndex.insert(point.getEnvelopeInternal(), point); + coordToFeatureMap.put(coord, feature); + } + // 3. 查询距离 polygon 最近的点 + // 用 polygon 中心点附近构造 Envelope(扩大一些范围) + Envelope searchEnv = jtsPolygon.getEnvelopeInternal(); + searchEnv.expandBy(10); // 扩大搜索半径 + @SuppressWarnings("unchecked") + List candidatePoints = spatialIndex.query(searchEnv); + double minDistance = Double.MAX_VALUE; + Coordinate nearestCoord = null; + for (Point point : candidatePoints) { double distance = point.distance(jtsPolygon); if (distance < minDistance) { minDistance = distance; - nearestFeature = feature; + nearestCoord = point.getCoordinate(); } } - // 3. 返回最近点的 text - if (nearestFeature != null && nearestFeature.getProperties() != null) { - return nearestFeature.getProperties().getText(); + if (nearestCoord != null) { + FacFeatureByPoint nearestFeature = coordToFeatureMap.get(nearestCoord); + if (nearestFeature != null && nearestFeature.getProperties() != null) { + return nearestFeature.getProperties().getText(); + } } return null; } + /** + * 匹配最近的面,获取该面的信息 + * + * @param pointFeature 点位 + * @param polygons 平面列表 + * @return 最近面的信息 + */ + public static FacFeatureByPlane findNearestOrContainingPolygon( + FacFeatureByPoint pointFeature, + List polygons + ) { + if (pointFeature == null || polygons == null || polygons.isEmpty()) { + return null; + } + List coords = pointFeature.getGeometry().getCoordinates(); + if (coords == null || coords.size() != 2) return null; + Coordinate pointCoord = new Coordinate(coords.get(0), coords.get(1)); + Point point = geometryFactory.createPoint(pointCoord); + FacFeatureByPlane nearestPolygon = null; + double minDistance = Double.MAX_VALUE; + for (FacFeatureByPlane polygonFeature : polygons) { + List> polyCoords = polygonFeature.getGeometry().getCoordinates().getFirst(); + Coordinate[] polygonCoords = polyCoords.stream() + .map(c -> new Coordinate(c.getFirst(), c.get(1))) + .toArray(Coordinate[]::new); + Polygon polygon = geometryFactory.createPolygon(polygonCoords); + // 优先使用包含点的 polygon + if (polygon.contains(point)) { + return polygonFeature; + } + double distance = polygon.distance(point); + if (distance < minDistance) { + minDistance = distance; + nearestPolygon = polygonFeature; + } + } + return nearestPolygon; + } + }