Browse Source

实现sp2sp_ConvectionNetwork_1关系计算,计算逻辑主要在dmp-rwd中实现,新增一种计算器

lijie 3 years ago
parent
commit
4282ac817e

+ 8 - 10
src/main/java/com/persagy/proxy/adm/controller/AdmRelCalController.java

@@ -168,10 +168,6 @@ public class AdmRelCalController {
     }
     /***
      * Description: 添加关系(图类型关系为SensorRelationship)
-     * @param relType : 关系类型
-     * @param objectTypeStr : 参与计算的业务空间(为空表示所有业务空间类型),以英文逗号隔开 HeatingZone,CleanZone,
-     *                      DomesticWaterSupplyZone,NetworkZone,TenantZone,AirConditioningZone,FunctionZone,
-     *                      FireZone,SecurityZone,GeneralZone,PowerSupplyZone,LightingZone
      * eq2sp_SensorRelationship_ss2sp:传感器测量空间关系
      * @return : com.persagy.proxy.adm.request.AdmCreateResponse
      * @author : lijie
@@ -179,14 +175,16 @@ public class AdmRelCalController {
      * Update By lijie 2021/8/31 12:10
      */
     @PostMapping(value = {"eq2sp_SensorRelationship_ss2sp"})
-    public AdmResponse sensorRelationshipCalcRelation( @PathVariable("relType") String relType,
-                                     @QueryParam("projectId") String projectId,
-                                     @QueryParam("objectTypes") String objectTypeStr,
-                                     @QueryParam("relationType") String relationTypeStr) throws Exception {
+    public AdmResponse sensorRelationshipCalcRelation(@RequestParam("projectId") String projectId,
+                                                      @RequestParam("groupCode") String groupCode,
+                                                      @RequestParam("appId") String appId,
+                                                      @RequestParam("userId") String userId) throws Exception {
         // 资产暂时未引入,直接返回成功
         // 组装上下文条件
-        InstanceUrlParam context = new InstanceUrlParam(groupCode, null, projectId, AdmCommonConstant.APP_ID);
-        // admRelCalService.calcRelation(context,relType,objectTypeStr,relationTypeStr);
+        InstanceUrlParam context = new InstanceUrlParam(StrUtil.isNotBlank(groupCode)?groupCode:this.groupCode,
+                null, projectId, StrUtil.isNotBlank(appId)?appId:AdmCommonConstant.APP_ID,
+                StrUtil.isNotBlank(userId)?userId:AdmCommonConstant.USER_ID);
+        admRelCalService.calcRelation(context,CollUtil.newArrayList(AdmRelationTypeEnum.EQ2SP_SENSORRELATIONSHIP_SS2SP),null,null);
         return AdmResponse.success(new ArrayList<>());
     }
     /***

+ 9 - 0
src/main/java/com/persagy/proxy/adm/dto/TwicePointDTO.java

@@ -1,11 +1,20 @@
 package com.persagy.proxy.adm.dto;
 
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
 /***
  * Description: 记录两组坐标的DTO类
  * @author : lijie
  * @date :2021/10/8 10:01
  * Update By lijie 2021/10/8 10:01
  */
+@Builder
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
 public class TwicePointDTO {
 
     private Double x1;

+ 234 - 47
src/main/java/com/persagy/proxy/adm/service/impl/AdmRelCalServiceImpl.java

@@ -1,6 +1,7 @@
 package com.persagy.proxy.adm.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.math.MathUtil;
 import cn.hutool.core.util.StrUtil;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -14,7 +15,9 @@ import com.persagy.dmp.common.helper.SpringHelper;
 import com.persagy.dmp.common.model.response.CommonResult;
 import com.persagy.dmp.digital.client.DigitalObjectFacade;
 import com.persagy.dmp.digital.client.DigitalRelationCaclFacade;
+import com.persagy.dmp.digital.client.DigitalRelationFacade;
 import com.persagy.dmp.digital.entity.ObjectDigital;
+import com.persagy.dmp.digital.entity.ObjectRelation;
 import com.persagy.proxy.adm.constant.AdmObjectInfoConstant;
 import com.persagy.proxy.adm.constant.AdmObjectType;
 import com.persagy.proxy.adm.constant.AdmRelationTypeEnum;
@@ -22,14 +25,14 @@ import com.persagy.proxy.adm.constant.ObjTypeMapping;
 import com.persagy.proxy.adm.dto.TwicePointDTO;
 import com.persagy.proxy.adm.request.AdmResponse;
 import com.persagy.proxy.adm.service.AdmRelCalService;
+import com.persagy.proxy.adm.utils.GeoToolsUtil;
 import com.persagy.proxy.common.entity.InstanceUrlParam;
 import lombok.Data;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
 @Service
 @Slf4j
@@ -75,50 +78,59 @@ public class AdmRelCalServiceImpl implements AdmRelCalService {
     @Override
     public AdmResponse calcRelationForArchForArchSpToSp(InstanceUrlParam context, String buildingId, String objectType,
                                                         String type, AdmRelationTypeEnum relationTypeEnum) {
-        double distance = 100.00;
         if (StrUtil.isBlank(buildingId)){
             return AdmResponse.success(new ArrayList<>());
         }
+        RequestData requestData = RequestData
+                .builder()
+                .buildingId(buildingId)
+                .objTypes(CollUtil.newHashSet(AdmObjectType.FLOOR.getIndex()))
+                .build();
         // 1.根据建筑id查询建筑下的所有楼层
         CommonResult<List<ObjectDigital>> commonResult = DigitalObjectFacade
                 .queryObjectListSuperiorIdPrototype(context.getGroupCode(), context.getProjectId(),
-                context.getAppId(), context.getUserId(), RequestData
-                        .builder()
-                        .buildingId(buildingId)
-                        .objTypes(CollUtil.newHashSet(AdmObjectType.FLOOR.getIndex()))
-                        .build());
+                context.getAppId(), context.getUserId(), requestData);
         if (!"success".equals(commonResult.getResult())){
             return AdmResponse.failure(commonResult.getMessage());
         }
         Long count = commonResult.getCount();
         List<ObjectDigital> data = commonResult.getData();
-        handleFloorRelationCalc(data,context);
-
-        long skip = data.size();
-        while (skip<count){
-            // 有未处理完的楼层
-
-
-
+        handleFloorRelationCalc(data,context,objectType,relationTypeEnum);
+        if (data.size() == count){
+            // 不需要分页查询
+            return AdmResponse.success();
         }
-
-
-        return null;
-
+        // 有结果集未查完
+        long page = (count % CommonConstant.QUERY_DEFAULT_PAGE_SIZE) == 0
+                ? (count / CommonConstant.QUERY_DEFAULT_PAGE_SIZE) : (count / CommonConstant.QUERY_DEFAULT_PAGE_SIZE + 1);
+        for (long i = 1; i < page; i++) {
+            requestData.setPage(i);
+            requestData.setSize(CommonConstant.QUERY_DEFAULT_PAGE_SIZE);
+            List<ObjectDigital> pageFloors = DigitalObjectFacade
+                    .queryObjectListSuperiorId(context.getGroupCode(),
+                            context.getProjectId(), context.getAppId(), context.getUserId(), requestData);
+            handleFloorRelationCalc(pageFloors,context,objectType,relationTypeEnum);
+        }
+        return AdmResponse.success();
     }
     /***
      * Description: 处理楼层下的关系计算(BDTP平台已经限制查询数据量)
      * @param data : 楼层数据
-     * @param context: 请求参数
+     * @param context : 请求参数
+     * @param classCode : 对象类型code
+     * @param relationTypeEnum: 图类型对象
      * @return : void
      * @author : lijie
      * @date :2021/9/30 16:46
      * Update By lijie 2021/9/30 16:46
      */
-    private void handleFloorRelationCalc(List<ObjectDigital> data, InstanceUrlParam context) {
+    private void handleFloorRelationCalc(List<ObjectDigital> data, InstanceUrlParam context, String classCode,
+                                         AdmRelationTypeEnum relationTypeEnum) {
         if (CollUtil.isEmpty(data)){
             return;
         }
+        ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
+        List<ObjectNode> relations = new ArrayList<>();
         // 2.循环所有楼层
         for (ObjectDigital floor : data) {
             if (!floor.getInfos().has(AdmObjectInfoConstant.MODEL_ID)
@@ -131,22 +143,140 @@ public class AdmRelCalServiceImpl implements AdmRelCalService {
                             .getInfos()
                             .get(AdmObjectInfoConstant.MODEL_ID)
                             .asText(),context);
-            // 2.1 根据楼层id和classCode查询所有的空间
-
-
+            if (CollUtil.isEmpty(pointDTOS)){
+                continue;
+            }
+            // 2.2 根据楼层id和classCode查询所有的空间
+            List<ObjectDigital> spaces = queryAllSpacesByFloorIdAndClassCode(floor.getId(),
+                    classCode,floor.getProjectId(),context);
+            if (CollUtil.isEmpty(spaces)){
+                continue;
+            }
             // 2.3 遍历所有的门,得到门拥有的两组x,y坐标
-            // 2.4 遍历坐标组,与空间进行对比,得到所有符合的空间id数组
+            Map<Integer,List<String>> spaceIndexMap = new HashMap<>();
+            for (int i = 0; i < pointDTOS.size(); i++) {
+                TwicePointDTO pointDTO = pointDTOS.get(i);
+                ObjectNode point1 = objectMapper
+                        .createObjectNode()
+                        .put("x", pointDTO.getX1())
+                        .put("y", pointDTO.getY1())
+                        .put("z", 0.00);
+                ObjectNode point2 = objectMapper
+                        .createObjectNode()
+                        .put("x", pointDTO.getX2())
+                        .put("y", pointDTO.getY2())
+                        .put("z", 0.00);
+                // 2.4 遍历坐标组,与空间进行对比,得到所有符合的空间id数组
+                for (ObjectDigital space : spaces) {
+                    if (null==space.getInfos()){
+                        continue;
+                    }
+                    if (!space.getInfos().has("outline")
+                            || !(space.getInfos().get("outline").size()>0)
+                            || !(space.getInfos().get("outline").get(0).size()>0)){
+                        continue;
+                    }
+                    // 空间的第一个数组
+                    JsonNode jsonNode = space.getInfos().get("outline").get(0).get(0);
+                    if (jsonNode==null || !jsonNode.isArray()){
+                        continue;
+                    }
+                    ArrayNode jsonNodes = (ArrayNode) jsonNode;
+                    List<ObjectNode> temp = new ArrayList<>();
+                    jsonNodes.forEach(node->temp.add((ObjectNode) node));
+                    if (GeoToolsUtil.isPointInPoly(point1,temp) || GeoToolsUtil.isPointInPoly(point2,temp)){
+                        List<String> spaceIds = spaceIndexMap.getOrDefault(i, new ArrayList<>());
+                        spaceIds.add(space.getId());
+                        spaceIndexMap.put(i,spaceIds);
+                    }
+                }
+            }
             // 2.5 创建空间服务关系的关系数据
-
-
+            Set<Map.Entry<Integer, List<String>>> entries = spaceIndexMap.entrySet();
+
+            for (Map.Entry<Integer, List<String>> entry : entries) {
+                List<String> list = entry.getValue();
+                if(CollUtil.isEmpty(list) || list.size()<2){
+                    continue;
+                }
+                String oneSpaceId = list.get(0);
+                for (int i = 1; i < list.size(); i++) {
+                    String otherSpaceId = list.get(i);
+                    ObjectNode objectNode = objectMapper.createObjectNode()
+                            .put("graphCode", relationTypeEnum.getGraphCode())
+                            .put("relCode", relationTypeEnum.getRelCode())
+                            .put("graphId", StrUtil.format(CommonConstant.DEFAULT_GRAPH_ID_FORMAT, relationTypeEnum.getGraphCode()))
+                            .put("projectId", floor.getProjectId())
+                            .put("objTo", otherSpaceId)
+                            .put("objFrom", oneSpaceId)
+                            .put("valid", 1)
+                            .put("createApp", context.getAppId())
+                            .put("updateApp", context.getAppId())
+                            .put("groupCode", context.getGroupCode())
+                            .put("creator", context.getUserId())
+                            .put("modifier", context.getUserId());
+                    if (StrUtil.isNotBlank(classCode)){
+                        objectNode.put("relValue",classCode);
+                    }
+                    relations.add(objectNode);
+                }
+            }
+        }
+        if (CollUtil.isNotEmpty(relations)){
+            DigitalRelationFacade.create(context.getGroupCode(),context.getProjectId(),context.getAppId(),context.getUserId(),relations);
         }
-
-
-
-
-
     }
     /***
+     * Description: 查询楼层下的所有空间
+     * @param floorId : 楼层id
+     * @param classCode : 对象类型code
+     * @param projectId : 项目id
+     * @param context: 内容上下文
+     * @return : java.util.List<com.persagy.dmp.digital.entity.ObjectDigital>
+     * @author : lijie
+     * @date :2021/10/8 14:47
+     * Update By lijie 2021/10/8 14:47
+     */
+    private List<ObjectDigital> queryAllSpacesByFloorIdAndClassCode(String floorId, String classCode,
+                                                                    String projectId, InstanceUrlParam context) {
+        RequestData requestData = RequestData
+                .builder()
+                .projectId(projectId)
+                .floorId(floorId)
+                .objTypes(CollUtil.newHashSet(AdmObjectType.SPACE.getIndex()))
+                .classCodes(CollUtil.newHashSet(classCode))
+                .build();
+        // 1.查询通用结果集
+        CommonResult<List<ObjectDigital>> commonResult = DigitalObjectFacade
+                .queryObjectListSuperiorIdPrototype(context.getGroupCode(),
+                        context.getProjectId(), context.getAppId(), context.getUserId(), requestData);
+        List<ObjectDigital> spaces = commonResult.getData();
+        if (CollUtil.isEmpty(spaces)){
+            return new ArrayList<>();
+        }
+        Long count = commonResult.getCount();
+        if (spaces.size() == count){
+            // 不需要分页查询
+            return spaces;
+        }
+        // 有结果集未查完
+        long page = (count % CommonConstant.QUERY_DEFAULT_PAGE_SIZE) == 0
+                ? (count / CommonConstant.QUERY_DEFAULT_PAGE_SIZE) : (count / CommonConstant.QUERY_DEFAULT_PAGE_SIZE + 1);
+        for (long i = 1; i < page; i++) {
+            requestData.setPage(i);
+            requestData.setSize(CommonConstant.QUERY_DEFAULT_PAGE_SIZE);
+            List<ObjectDigital> pageSpaces = DigitalObjectFacade
+                    .queryObjectListSuperiorId(context.getGroupCode(),
+                            context.getProjectId(), context.getAppId(), context.getUserId(), requestData);
+            if (CollUtil.isEmpty(pageSpaces)){
+                continue;
+            }
+            spaces.addAll(pageSpaces);
+        }
+        return spaces;
+    }
+
+    /***
      * Description: 根据楼层模型id查询所有门数据(BDTP限制了查询条数,需要做分页查询)
      * @param floorModelId : 楼层模型id
      * @param context: 请求参数上下文
@@ -156,18 +286,50 @@ public class AdmRelCalServiceImpl implements AdmRelCalService {
      * Update By lijie 2021/10/8 10:02
      */
     private List<TwicePointDTO> queryAllDoorByFloorModelId(String floorModelId, InstanceUrlParam context) {
+
         // 门的classCode:CFBEDR,obj_type为equipment
         QueryCriteria queryCriteria = new QueryCriteria();
         queryCriteria.getCriteria().put("classCode","CFBEDR")
                 .put("objType",AdmObjectType.EQUIPMENT.getIndex())
                 .put("modelId",floorModelId);
-        List<ObjectNode> objectNodes = DigitalObjectFacade
-                .query(context.getGroupCode(), context.getProjectId(), context.getAppId(),
+        CommonResult<List<ObjectNode>> commonResult = DigitalObjectFacade
+                .queryPrototype(context.getGroupCode(), context.getProjectId(), context.getAppId(),
                         context.getUserId(), queryCriteria);
+        List<TwicePointDTO> result = new ArrayList<>();
+        List<ObjectNode> objectNodes = commonResult.getData();
+        Long count = commonResult.getCount();
+        analysisDoorResultData(result,objectNodes);
+        if (objectNodes.size()==count){
+            // 查询结果集小于BDTP默认分页条数
+            return result;
+        }
+        // 有结果集未查完
+        long page = (count % CommonConstant.QUERY_DEFAULT_PAGE_SIZE) == 0
+                ? (count / CommonConstant.QUERY_DEFAULT_PAGE_SIZE) : (count / CommonConstant.QUERY_DEFAULT_PAGE_SIZE + 1);
+        for (long i = 1; i < page; i++) {
+            queryCriteria.setPage(i);
+            queryCriteria.setSize(CommonConstant.QUERY_DEFAULT_PAGE_SIZE);
+            analysisDoorResultData(result,DigitalObjectFacade
+                    .query(context.getGroupCode(), context.getProjectId(), context.getAppId(),
+                            context.getUserId(), queryCriteria));
+        }
+        return result;
+    }
+
+    /***
+     * Description: 解析门查询结果集
+     * @param result : 存储结果集
+     * @param objectNodes : 对象结果集
+     * @return : void
+     * @author : lijie
+     * @date :2021/10/8 14:26
+     * Update By lijie 2021/10/8 14:26
+     */
+    private void analysisDoorResultData(List<TwicePointDTO> result, List<ObjectNode> objectNodes) {
+        double distance = 100.00;
         if (CollUtil.isEmpty(objectNodes)){
-            return new ArrayList<>();
+            return;
         }
-        List<TwicePointDTO> result = new ArrayList<>();
         for (ObjectNode objectNode : objectNodes) {
             // 1.获得outline
             if (!objectNode.has("outline")
@@ -186,19 +348,44 @@ public class AdmRelCalServiceImpl implements AdmRelCalService {
             ArrayNode points = (ArrayNode) objectNode.get("outline").get(0);
             JsonNode firstPoint = points.get(0);
             JsonNode secondPoint = points.get(1);
-
-
-
-
-
+            Double k=getPoints(firstPoint.get("x").asDouble(),firstPoint.get("y").asDouble(),
+                    secondPoint.get("x").asDouble(),secondPoint.get("y").asDouble());
+            if (null==k){
+                result.add(TwicePointDTO
+                        .builder()
+                        .x1(point.get("x").asDouble())
+                        .y1(point.get("y").asDouble()+distance)
+                        .x2(point.get("x").asDouble())
+                        .y2(point.get("y").asDouble()-distance)
+                        .build());
+                continue;
+            }
+            result.add(getPointByDistance(point.get("x").asDouble(),point.get("y").asDouble(),k,distance*2));
         }
+    }
 
-
-        return null;
-
-
-
+    /***
+     * Description: 计算两点之间的距离(我不太明白这个算法是怎么算的)
+     * @param baseX : 坐标点1的x值
+     * @param baseY : 坐标点1的y值
+     * @param k : 坐标点2的x值
+     * @param distance : 坐标点2的y值
+     * @return : java.lang.Double
+     * @author : lijie
+     * @date :2021/10/8 11:31
+     * Update By lijie 2021/10/8 11:31
+     */
+    private TwicePointDTO getPointByDistance(Double baseX,Double baseY,Double k,Double distance){
+        if (null==k){
+            return TwicePointDTO.builder().x1(baseX).y1(baseY+distance).x2(baseX).y2(baseY-distance).build();
+        }
+        double vectorX1 = Math.sqrt(distance * distance / (1 + k * k));
+        double vectorX2 = -vectorX1;
+        double vectorY1 = k*vectorX1;
+        double vectorY2 = k*vectorX2;
+        return TwicePointDTO.builder().x1(baseX+vectorX1).y1(baseY+vectorY1).x2(baseX+vectorX2).y2(baseY+vectorY2).build();
     }
+
     /***
      * Description: 计算两点之间的距离(我不太明白这个算法是怎么算的)
      * @param x1 : 坐标点1的x值