| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- 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;
- import com.fasterxml.jackson.databind.node.ArrayNode;
- import com.fasterxml.jackson.databind.node.ObjectNode;
- import com.persagy.dmp.basic.dto.RequestData;
- import com.persagy.dmp.basic.model.QueryCriteria;
- import com.persagy.dmp.basic.utils.QueryCriteriaHelper;
- import com.persagy.dmp.common.constant.CommonConstant;
- 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;
- 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.*;
- @Service
- @Slf4j
- @RequiredArgsConstructor
- public class AdmRelCalServiceImpl implements AdmRelCalService {
- /***
- * Description: 计算关系
- * @param context : 请求参数
- * @param admRelationTypeEnums : 关系类型集合
- //* @param objectTypeStr : 参与计算的业务空间(为空表示所有业务空间类型)
- //* @param relationTypeStr : 关系类型
- * return : void
- * @author : lijie
- * date :2021/9/11 20:35
- * Update By lijie 2021/9/11 20:35
- */
- @Override
- public void calcRelation(InstanceUrlParam context, List<AdmRelationTypeEnum> admRelationTypeEnums,String relValue) {
- for (AdmRelationTypeEnum admRelationTypeEnum : admRelationTypeEnums) {
- RequestData requestData = RequestData.builder()
- .graphCode(admRelationTypeEnum.getGraphCode())
- .relCode(admRelationTypeEnum.getRelCode())
- .calBeforeRelFlag(true)
- .build();
- if (StrUtil.isNotBlank(relValue)){
- requestData.setRelValue(relValue);
- }
- // 调用中台的计算逻辑
- DigitalRelationCaclFacade.calculatingObjRelationPrototype(context.getGroupCode(),context.getProjectId(),
- context.getAppId(), CommonConstant.DEFAULT_ID, requestData);
- }
- }
- /***
- * Description: 计算空间交通关系
- * @param context : 通用参数
- * @param buildingId : 建筑id
- * @param objectType : 对象类型
- * @param type : 类型
- * @param relationTypeEnum : 关系枚举类
- * @return : void
- * @author : lijie
- * @date :2021/9/30 14:49
- * Update By lijie 2021/9/30 14:49
- */
- @Override
- public AdmResponse calcRelationForArchForArchSpToSp(InstanceUrlParam context, String buildingId, String objectType,
- String type, AdmRelationTypeEnum relationTypeEnum) {
- 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);
- if (!"success".equals(commonResult.getResult())){
- return AdmResponse.failure(commonResult.getMessage());
- }
- Long count = commonResult.getCount();
- List<ObjectDigital> data = commonResult.getData();
- handleFloorRelationCalc(data,context,objectType,relationTypeEnum);
- if (data.size() == count){
- // 不需要分页查询
- return AdmResponse.success();
- }
- // 有结果集未查完
- 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 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, 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)
- || StrUtil.isBlank(floor.getInfos().get(AdmObjectInfoConstant.MODEL_ID).asText())){
- continue;
- }
- // 2.1 根据楼层的modelId查询所有的门
- List<TwicePointDTO> pointDTOS =
- queryAllDoorByFloorModelId(floor
- .getInfos()
- .get(AdmObjectInfoConstant.MODEL_ID)
- .asText(),context);
- 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坐标
- 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: 请求参数上下文
- * @return : java.util.List<com.persagy.proxy.adm.dto.TwicePointDTO>
- * @author : lijie
- * @date :2021/10/8 10:02
- * 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);
- 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;
- }
- for (ObjectNode objectNode : objectNodes) {
- // 1.获得outline
- if (!objectNode.has("outline")
- || !objectNode.get("outline").isArray()
- || !(objectNode.get("outline").size()>2)){
- continue;
- }
- if (!objectNode.has("location")
- || !objectNode.get("location").isObject()
- || !objectNode.get("location").has("points")
- || !objectNode.get("location").get("points").isArray()
- || !(objectNode.get("location").get("points").size()>=1)){
- continue;
- }
- JsonNode point = objectNode.get("location").get("points").get(0);
- 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));
- }
- }
- /***
- * 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值
- * @param y1 : 坐标点1的y值
- * @param x2 : 坐标点2的x值
- * @param y2 : 坐标点2的y值
- * @return : java.lang.Double
- * @author : lijie
- * @date :2021/10/8 11:31
- * Update By lijie 2021/10/8 11:31
- */
- private Double getPoints(Double x1,Double y1,Double x2,Double y2){
- if (x1.equals(x2) && y1.equals(y2)){
- return null;
- }
- Double k=null;
- if (!x1.equals(x2)){
- k=(y2-y1)/(x2-x1);
- }
- if (null==k){
- return 0.00;
- }
- if (0.00 == k){
- return null;
- }
- return 1/k;
- }
- }
|