diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/JtsPointMatcher.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/JtsPointMatcher.java index c5001a21..0f77ae72 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/JtsPointMatcher.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/common/utils/JtsPointMatcher.java @@ -79,6 +79,38 @@ public class JtsPointMatcher { return matched; } + /** + * 计算多边形的中心点 + * + * @param points 多边形的顶点坐标 + * @return 中心点的坐标 + */ + public static List polygonCentroid(List> points) { + double area = 0; + double cx = 0; + double cy = 0; + + int size = points.size(); + for (int i = 0; i < size - 1; i++) { + double x0 = points.get(i).get(0); + double y0 = points.get(i).get(1); + double x1 = points.get(i + 1).get(0); + double y1 = points.get(i + 1).get(1); + + double cross = x0 * y1 - x1 * y0; + area += cross; + cx += (x0 + x1) * cross; + cy += (y0 + y1) * cross; + } + + area *= 0.5; + cx /= (6 * area); + cy /= (6 * area); + + return List.of(cx, cy); + } + + public static void main(String[] args) { // A列表:待匹配点 List listA = List.of( diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/geojson/FacFeature.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/geojson/FacFeature.java index 17402135..a1741421 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/geojson/FacFeature.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/geojson/FacFeature.java @@ -4,6 +4,9 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import java.io.Serial; +import java.io.Serializable; + /** * @author lilemy * @date 2025/4/24 17:38 @@ -11,7 +14,10 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor -public class FacFeature { +public class FacFeature implements Serializable { + + @Serial + private static final long serialVersionUID = -6103275857879306244L; private String type; diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/geojson/FacGeometry.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/geojson/FacGeometry.java index 5cedddae..079d2ea5 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/geojson/FacGeometry.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/geojson/FacGeometry.java @@ -4,6 +4,8 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import java.io.Serial; +import java.io.Serializable; import java.util.List; /** @@ -13,7 +15,10 @@ import java.util.List; @Data @NoArgsConstructor @AllArgsConstructor -public class FacGeometry { +public class FacGeometry implements Serializable { + + @Serial + private static final long serialVersionUID = -2582318447932685848L; private String type; diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/photovoltaicpanelparts/FacPhotovoltaicPanelPartsCreateByGeoJsonReq.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/photovoltaicpanelparts/FacPhotovoltaicPanelPartsCreateByGeoJsonReq.java index 80fd1645..84ed1927 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/photovoltaicpanelparts/FacPhotovoltaicPanelPartsCreateByGeoJsonReq.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/domain/dto/photovoltaicpanelparts/FacPhotovoltaicPanelPartsCreateByGeoJsonReq.java @@ -1,6 +1,7 @@ package org.dromara.facility.domain.dto.photovoltaicpanelparts; import lombok.Data; +import org.dromara.facility.domain.dto.geojson.FacGeoJson; import org.dromara.facility.domain.dto.geojson.FacGeoJsonByPoint; import java.io.Serial; @@ -24,7 +25,7 @@ public class FacPhotovoltaicPanelPartsCreateByGeoJsonReq implements Serializable /** * 桩点、立柱、支架 GeoJson */ - private FacGeoJsonByPoint locationGeoJson; + private FacGeoJson locationGeoJson; /** * 批次上传标识 diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacPhotovoltaicPanelPartsServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacPhotovoltaicPanelPartsServiceImpl.java index 2581071c..733dadcd 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacPhotovoltaicPanelPartsServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/service/impl/FacPhotovoltaicPanelPartsServiceImpl.java @@ -24,7 +24,7 @@ import org.dromara.facility.domain.FacPhotovoltaicPanel; import org.dromara.facility.domain.FacPhotovoltaicPanelColumn; import org.dromara.facility.domain.FacPhotovoltaicPanelPoint; import org.dromara.facility.domain.FacPhotovoltaicPanelSupport; -import org.dromara.facility.domain.dto.geojson.FacFeatureByPoint; +import org.dromara.facility.domain.dto.geojson.FacFeature; import org.dromara.facility.domain.dto.photovoltaicpanelparts.FacPhotovoltaicPanelPartsCreateByGeoJsonReq; import org.dromara.facility.domain.dto.photovoltaicpanelparts.FacPhotovoltaicPanelPartsCreateReq; import org.dromara.facility.domain.dto.photovoltaicpanelparts.FacPhotovoltaicPanelPartsQueryReq; @@ -38,6 +38,7 @@ import org.dromara.progress.constant.PgsProgressCategoryConstant; import org.dromara.progress.domain.PgsProgressCategory; import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailRecognizerVo; import org.dromara.progress.service.IPgsProgressCategoryService; +import org.dromara.project.domain.BusProject; import org.dromara.project.service.IBusProjectService; import org.locationtech.jts.geom.Coordinate; import org.springframework.beans.BeanUtils; @@ -146,12 +147,19 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan // 第一次接收请求,进行数据校验 int batchNum = geoJson.getBatchNum(); if (batchNum == 1) { - if (projectService.getById(projectId) == null) { + BusProject project = projectService.getById(projectId); + if (project == null) { throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND); } + Long pId = project.getPId(); + List subProject = projectService.lambdaQuery() + .eq(BusProject::getPId, pId) + .list(); + List projectIds = subProject.stream().map(BusProject::getId).collect(Collectors.toList()); + projectIds.add(projectId); // 查询项目下光伏板 Long count = photovoltaicPanelService.lambdaQuery() - .eq(FacPhotovoltaicPanel::getProjectId, projectId).count(); + .in(FacPhotovoltaicPanel::getProjectId, projectIds).count(); if (count <= 0) { throw new ServiceException("项目下无光伏板信息,请先创建光伏板信息后再添加桩点、立柱、支架信息", HttpStatus.NOT_FOUND); } @@ -159,7 +167,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan // 获取 redis key String sessionId = geoJson.getSessionId(); int totalBatch = geoJson.getTotalBatch(); - List dataList = geoJson.getLocationGeoJson().getFeatures(); + List dataList = geoJson.getLocationGeoJson().getFeatures(); String redisKey = FacRedisKeyConstant.getBatchUploadPartsRedisKey(sessionId, batchNum); // 存储到 Redis,设置过期时间 30 分钟 redisTemplate.opsForValue().set(redisKey, dataList, 1800, TimeUnit.SECONDS); @@ -172,13 +180,13 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan messageDto.setProjectId(projectId); // 如果是最后一批,开始合并 if (batchNum == totalBatch) { - List allData = new ArrayList<>(); + List allData = new ArrayList<>(); for (int i = 1; i <= totalBatch; i++) { String batchKey = FacRedisKeyConstant.getBatchUploadPartsRedisKey(sessionId, i); Object batchObj = redisTemplate.opsForValue().get(batchKey); if (batchObj instanceof List) { @SuppressWarnings("unchecked") - List batch = (List) batchObj; + List batch = (List) batchObj; allData.addAll(batch); } } @@ -222,11 +230,19 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan * @param features 数据 * @param userId 操作用户id */ - private void saveBatch(Long projectId, List features, Long userId) { + private void saveBatch(Long projectId, List features, Long userId) { + BusProject project = projectService.getById(projectId); + Long pId = project.getPId(); + List subProject = projectService.lambdaQuery() + .eq(BusProject::getPId, pId) + .list(); + List projectIds = subProject.stream().map(BusProject::getId).collect(Collectors.toList()); + projectIds.add(projectId); // 获取进度类别 Map List progressCategoryList = progressCategoryService.lambdaQuery() - .select(PgsProgressCategory::getId, PgsProgressCategory::getName, PgsProgressCategory::getMatrixId, PgsProgressCategory::getWorkType) - .eq(PgsProgressCategory::getProjectId, projectId) + .select(PgsProgressCategory::getId, PgsProgressCategory::getName, PgsProgressCategory::getProjectId, + PgsProgressCategory::getMatrixId, PgsProgressCategory::getWorkType) + .in(PgsProgressCategory::getProjectId, projectIds) .and(lqw -> lqw .likeRight(PgsProgressCategory::getWorkType, PgsProgressCategoryConstant.PHOTOVOLTAIC_PANEL_POINT_WORK_TYPE + "_") .or() @@ -241,7 +257,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan )); // 查询项目下光伏板 List photovoltaicPanelList = photovoltaicPanelService.lambdaQuery() - .eq(FacPhotovoltaicPanel::getProjectId, projectId) + .in(FacPhotovoltaicPanel::getProjectId, projectIds) .list(); Map photovoltaicPanelMap = photovoltaicPanelList.stream() .collect(Collectors.toMap( @@ -256,7 +272,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan FacPhotovoltaicPanelPoint::getFinishType, FacPhotovoltaicPanelPoint::getFinishDate, FacPhotovoltaicPanelPoint::getStatus) - .eq(FacPhotovoltaicPanelPoint::getProjectId, projectId) + .in(FacPhotovoltaicPanelPoint::getProjectId, projectIds) .list(); Map oldPointMap = oldPointList.stream() .collect(Collectors.toMap( @@ -270,7 +286,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan FacPhotovoltaicPanelColumn::getFinishType, FacPhotovoltaicPanelColumn::getFinishDate, FacPhotovoltaicPanelColumn::getStatus) - .eq(FacPhotovoltaicPanelColumn::getProjectId, projectId) + .in(FacPhotovoltaicPanelColumn::getProjectId, projectIds) .list(); Map oldColumnMap = oldColumnList.stream() .collect(Collectors.toMap( @@ -284,7 +300,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan FacPhotovoltaicPanelSupport::getFinishType, FacPhotovoltaicPanelSupport::getFinishDate, FacPhotovoltaicPanelSupport::getStatus) - .eq(FacPhotovoltaicPanelSupport::getProjectId, projectId) + .in(FacPhotovoltaicPanelSupport::getProjectId, projectIds) .list(); Map oldSupportMap = oldSupportList.stream() .collect(Collectors.toMap( @@ -299,7 +315,15 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan try (ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())) { // 所有点列表 List> pointPositionList = new ArrayList<>(features.stream() - .map(featureByPoint -> featureByPoint.getGeometry().getCoordinates()) + .map(feature -> { + String type = feature.getProperties().getType(); + List coordinates = feature.getGeometry().getCoordinates(); + if (type.equalsIgnoreCase("CIRCLE")) { + return JtsPointMatcher.polygonCentroid(castToDoubleList(coordinates)); + } else { + return toDoubleList(coordinates); + } + }) .toList()); // 多线程处理 List> futures = new ArrayList<>(); @@ -324,7 +348,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan if (CollUtil.isNotEmpty(categoryList)) { for (PgsProgressCategory category : categoryList) { FacPhotovoltaicPanelPoint point = new FacPhotovoltaicPanelPoint(); - point.setProjectId(projectId); + point.setProjectId(category.getProjectId()); point.setMatrixId(matrixId); point.setName(name); point.setPositions(jsonStr); @@ -349,7 +373,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan if (CollUtil.isNotEmpty(categoryList)) { for (PgsProgressCategory category : categoryList) { FacPhotovoltaicPanelColumn column = new FacPhotovoltaicPanelColumn(); - column.setProjectId(projectId); + column.setProjectId(category.getProjectId()); column.setMatrixId(matrixId); column.setName(name); column.setPositions(jsonStr); @@ -374,7 +398,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan if (CollUtil.isNotEmpty(categoryList)) { for (PgsProgressCategory category : categoryList) { FacPhotovoltaicPanelSupport support = new FacPhotovoltaicPanelSupport(); - support.setProjectId(projectId); + support.setProjectId(category.getProjectId()); support.setMatrixId(matrixId); support.setName(name); support.setPositions(jsonStr); @@ -941,4 +965,45 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan } } + /** + * 将原始数据转换为List> + * + * @param rawList 原始数据 + * @return 转换后的数据 + */ + public static List> castToDoubleList(List rawList) { + List> result = new ArrayList<>(); + + for (Object item : rawList) { + if (item instanceof List innerList) { + List point = new ArrayList<>(); + for (Object value : innerList) { + if (value instanceof Number num) { + point.add(num.doubleValue()); + } + } + result.add(point); + } + } + return result; + } + + /** + * 将原始数据转换为 List + * + * @param list 原始数据 + * @return 转换后的数据 + */ + public static List toDoubleList(List list) { + return list.stream() + .filter(Objects::nonNull) + .map(o -> { + if (o instanceof Number n) { + return n.doubleValue(); + } + throw new IllegalArgumentException("非数字类型:" + o); + }) + .toList(); + } + }