瀏覽代碼

解决自定义函数使用问题。改为代码中写表名

yucheng 3 年之前
父節點
當前提交
0b0a2a95b0

+ 139 - 0
revit-algorithm/src/main/kotlin/cn/sagacloud/server/algorithm/common/utils/FloorLevelCheckUtil.java

@@ -0,0 +1,139 @@
+package cn.sagacloud.server.algorithm.common.utils;
+
+import cn.sagacloud.server.algorithm.models.dataCheck.LevelCheckResult;
+import cn.sagacloud.server.algorithm.models.modelFile.FloorModelView;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+
+import java.util.*;
+
+/**
+ * 楼层号检查
+ * @author Administrator
+ * @date 2021-10-21
+ */
+public class FloorLevelCheckUtil {
+
+    /**
+     * 检查
+     * @param views
+     * @return
+     */
+    public static List<LevelCheckResult> checkLevel(List<FloorModelView> views) {
+        if(CollectionUtils.isEmpty(views)) {
+            return null;
+        }
+        // 排序
+        FloorModelView[] viewArr = views.toArray(new FloorModelView[0]);
+        Arrays.sort(viewArr, new FloorModelCompare());
+        Set<String> errorIds = new HashSet<>();
+        FloorModelView lastView = null;
+        // 检查有楼层号异常的楼层
+        for(FloorModelView view:viewArr) {
+            Double level = view.getBaseLevel();
+            if(level != null && (lastView == null || level > lastView.getBaseLevel())) {
+                lastView = view;
+                continue;
+            }
+            // 将前后的模型ID放入异常队列
+            errorIds.add(lastView.getCurrentModelId());
+            errorIds.add(view.getCurrentModelId());
+            lastView = null;
+        }
+        // 回写结果,按原顺序
+        List<LevelCheckResult> result = new ArrayList<>();
+        for(FloorModelView view:views) {
+            LevelCheckResult rs = new LevelCheckResult();
+            BeanUtils.copyProperties(view, rs);
+            rs.setHasError(errorIds.contains(view.getCurrentModelId()));
+            rs.setErrorMsg(rs.getHasError()?"标高冲突":null);
+            result.add(rs);
+        }
+        return result;
+    }
+
+    /**
+     * 根据楼层名称转换楼层信息
+     * @param floorName
+     * @return
+     */
+    private FloorLevel convertToFloorLevel(String floorName) {
+        FloorLevel floor = new FloorLevel();
+        if(StringUtils.isBlank(floorName)) {
+            return floor;
+        }
+        // 顶层夹层
+        if(floorName.startsWith("RFM")) {
+            floor.type = 2;
+            if(floorName.length() > 3) {
+                floor.middle = Integer.valueOf(floorName.substring(3));
+            }
+            return floor;
+        }
+        // 顶层
+        if(floorName.startsWith("RF")) {
+            floor.type = 2;
+            return floor;
+        }
+        // 正常楼层/地下
+        if(floorName.startsWith("F") || floorName.startsWith("B")) {
+            floor.type = floorName.startsWith("F")?1:0;
+            // 是否有夹层
+            int mIndex = floorName.indexOf("M");
+            if(mIndex < 0) {
+                floor.level = Integer.valueOf(floorName.substring(1));
+            } else if (floorName.endsWith("M")) {
+                // 没夹层数也算没夹层
+                floor.level = Integer.valueOf(floorName.substring(1, mIndex));
+            } else {
+                floor.level = Integer.valueOf(floorName.substring(1, mIndex));
+                floor.middle = Integer.valueOf(floorName.substring(mIndex+1));
+            }
+            return floor;
+        }
+        return floor;
+    }
+
+    /**
+     * 楼层比较器
+     */
+    protected static class FloorModelCompare implements Comparator<FloorModelView> {
+
+        @Override
+        public int compare(FloorModelView v1, FloorModelView v2) {
+            if(v1 == null || v2 == null) {
+                return v1 == null ? 1 : -1;
+            }
+            FloorLevel o1 = convertToFloorLevel(v1.getFloorName());
+            FloorLevel o2 = convertToFloorLevel(v2.getFloorName());
+            // 如果楼层类型不一样
+            if(o1.type != o2.type) {
+                return o1.type - o2.type;
+            }
+            // 楼层类型一样,则看层数
+            if(o1.level != o2.level) {
+                // 层号越大的越高,但地下则刚好相反
+                int result = o1.level - o2.level;
+                return o1.type == 0 ? -result:result;
+            }
+            // 都一样则看夹层号,夹层号越大越高
+            if(o1.middle != o2.middle) {
+                return o1.middle - o2.middle;
+            }
+            return 0;
+        }
+    }
+
+    /**
+     * 楼层信息
+     */
+    public static class FloorLevel {
+        /** 楼层类型:0-地下,1-正常,2-顶层 */
+        public int type = 1;
+        /** 楼层号 */
+        public int level = 1;
+        /** 夹层号 */
+        public int middle = 0;
+    }
+}

+ 236 - 0
revit-algorithm/src/main/kotlin/cn/sagacloud/server/algorithm/common/utils/GridGroupUtil.java

@@ -0,0 +1,236 @@
+package cn.sagacloud.server.algorithm.common.utils;
+
+import cn.sagacloud.server.algorithm.models.dataCheck.GridCheckResult;
+import cn.sagacloud.server.algorithm.models.entities.Grid;
+import cn.sagacloud.server.algorithm.models.jsonAnalyzer.Location;
+import cn.sagacloud.server.algorithm.models.jsonAnalyzer.Point;
+import cn.sagacloud.server.algorithm.models.modelFile.FloorModelView;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Grid分组工具
+ * 基于python代码改写
+ * @author Administrator
+ * @date 2021-10-21
+ */
+public class GridGroupUtil {
+
+    /**
+     * 获取分组信息
+     * @param views
+     * @param gridMap
+     * @return
+     */
+    public static List<GridCheckResult> checkGridUpright(List<FloorModelView> views, Map<String, List<Grid>> gridMap) {
+        if(CollectionUtils.isEmpty(views)) {
+            return null;
+        }
+        // 组装名称位置信息
+        Map<String, Map<String, Location>> gridNameMap = convertGridMap(gridMap);
+        // 获取分组
+        Map<String, Integer> groupMap = groupGrids(gridNameMap);
+        // 转换结果
+        List<GridCheckResult> rsList = new ArrayList<>();
+        for(FloorModelView view:views) {
+            GridCheckResult rs = new GridCheckResult();
+            BeanUtils.copyProperties(view, rs);
+            rs.setGroupId(MapUtils.getInteger(groupMap, view.getCurrentModelId()));
+            rsList.add(rs);
+        }
+        return rsList;
+    }
+
+    /**
+     * 将GridMap转换为名称、位置对照
+     * @param gridMap
+     * @return
+     */
+    private static Map<String, Map<String, Location>> convertGridMap(Map<String, List<Grid>> gridMap) {
+        if(MapUtils.isEmpty(gridMap)) {
+            return null;
+        }
+        // 组装名称位置信息
+        Map<String, Map<String, Location>> gridNameMap = new HashMap<>(16);
+        for(String modelId:gridMap.keySet()) {
+            List<Grid> gridList = gridMap.get(modelId);
+            if(CollectionUtils.isEmpty(gridList)) {
+                continue;
+            }
+            Map<String, Location> nameMap = new HashMap<>(16);
+            gridNameMap.put(modelId, nameMap);
+            // 获取Name, Location存入Map
+            for(Grid grid:gridList) {
+                String name = grid.getName();
+                Location location = grid.getLocation();
+                if(StringUtils.isBlank(name) || location == null) {
+                    continue;
+                }
+                nameMap.put(name, location);
+            }
+        }
+        return gridNameMap;
+    }
+
+    /**
+     * 按Grid冲突关系,将ModelId分组
+     * 分组号从1开始.
+     * @param gridMap
+     * @return
+     */
+    private static Map<String, Integer> groupGrids(Map<String, Map<String, Location>> gridMap){
+        if(MapUtils.isEmpty(gridMap)) {
+            return null;
+        }
+        List<List<String>> modelIdList = groupGridToList(gridMap);
+        Map<String, Integer> modelIdMap = new HashMap<>(16);
+        for(int i = 0,j = modelIdList.size();i < j;i++) {
+            List<String> idList = modelIdList.get(i);
+            for(String modelId:idList) {
+                modelIdMap.put(modelId, i+1);
+            }
+        }
+        return modelIdMap;
+    }
+
+    /**
+     * 将grid按modelId分组
+     * 每组的ModelId都是不冲突的
+     * @param gridMap
+     * @return List<[id1,id2,id5],[id3,id4]>
+     */
+    private static List<List<String>> groupGridToList(Map<String, Map<String, Location>> gridMap){
+        List<List<String>> modelIdList = new ArrayList<>();
+        // 按ModelId循环
+        for(String modelId : gridMap.keySet()) {
+            // 是否所有分组都有冲突
+            boolean isAllConflict = true;
+            // 按分组循环
+            for(int i = 0,j = modelIdList.size();i < j;i++) {
+                List<String> idList = modelIdList.get(i);
+                // 当前分组内是否有冲突
+                boolean isConflict = false;
+                for(String toId:idList) {
+                    Map<String, Location> fromMap = gridMap.get(modelId);
+                    Map<String, Location> toMap = gridMap.get(modelIdList.get(i));
+                    // 如果有冲突,则不再比较
+                    if (isConflict(fromMap, toMap)) {
+                        isConflict = true;
+                        break;
+                    }
+                }
+                // 如果没有冲突,则放入此队列中
+                if(!isConflict) {
+                    idList.add(modelId);
+                    isAllConflict = false;
+                    break;
+                }
+            }
+            // 如果所有分组内都有冲突,则新增分组
+            if(isAllConflict) {
+                List<String> idList = new ArrayList<>();
+                idList.add(modelId);
+                modelIdList.add(idList);
+            }
+        }
+        return modelIdList;
+    }
+
+    /**
+     * 模型中的Grid是否有冲突
+     * @param fromMap
+     * @param toMap
+     * @return
+     */
+    private static boolean isConflict(Map<String, Location> fromMap, Map<String, Location> toMap) {
+        if(MapUtils.isEmpty(fromMap) || MapUtils.isEmpty(toMap)) {
+            return false;
+        }
+        // 按名称循环处理
+        for(String name:fromMap.keySet()) {
+            if(!toMap.containsKey(name)) {
+                continue;
+            }
+            // 只处理名称相同的比较
+            Location from = fromMap.get(name);
+            Location to = toMap.get(name);
+            if(from == null || to == null) {
+                continue;
+            }
+            // 位置有冲突
+            if(isConflict(from, to)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 位置是否冲突
+     * @param from
+     * @param to
+     * @return
+     */
+    public static boolean isConflict(Location from, Location to) {
+        // 只有都是线的类型才判断冲突
+        if(!(StringUtils.contains(from.getType(), "Line")
+                && StringUtils.contains(to.getType(), from.getType()))) {
+            return false;
+        }
+        // 点位应在2个以上
+        if(CollectionUtils.size(from.getPoints()) < 2 || CollectionUtils.size(to.getPoints()) < 2) {
+            return false;
+        }
+        // 取开始结束点位
+        Point fromBegin = from.getPoints().get(0);
+        Point fromEnd = from.getPoints().get(1);
+        Point toBegin = to.getPoints().get(0);
+        Point toEnd = to.getPoints().get(1);
+        // 计算相对角度和偏移量
+        try {
+            BigDecimal fromAngle = calAngle(fromBegin, fromEnd);
+            BigDecimal fromOffset = calOffset(fromBegin, fromAngle);
+            BigDecimal toAngle = calAngle(toBegin, toEnd);
+            BigDecimal toOffset = calOffset(toBegin, toAngle);
+            // 都相同则冲突
+            return fromAngle.equals(toAngle) && fromOffset.equals(toOffset);
+        } catch (Exception e) {
+            // 计算异常则直接判断点位X坐标
+            return fromEnd.getX() == toBegin.getX() && fromEnd.getX() == toEnd.getX();
+        }
+    }
+
+    /**
+     * 计算两个点的相对角度
+     * @param begin
+     * @param end
+     * @return
+     */
+    private static BigDecimal calAngle(Point begin, Point end) {
+        BigDecimal beginX = BigDecimal.valueOf(begin.getX());
+        BigDecimal beginY = BigDecimal.valueOf(begin.getY());
+        BigDecimal endX = BigDecimal.valueOf(end.getX());
+        BigDecimal endY = BigDecimal.valueOf(end.getY());
+        return beginY.subtract(endY).divide(beginX.subtract(endX));
+    }
+
+    /**
+     * 计算点位的偏移量
+     * @param begin
+     * @param angle
+     * @return
+     */
+    private static BigDecimal calOffset(Point begin, BigDecimal angle) {
+        BigDecimal beginX = BigDecimal.valueOf(begin.getX());
+        BigDecimal beginY = BigDecimal.valueOf(begin.getY());
+        return beginY.subtract(angle.multiply(beginX));
+    }
+}

+ 44 - 8
revit-algorithm/src/main/kotlin/cn/sagacloud/server/algorithm/services/modelCheck/ModelCheckService.kt

@@ -1,23 +1,33 @@
 package cn.sagacloud.server.algorithm.services.modelCheck
 
+import cn.sagacloud.server.algorithm.common.utils.FloorLevelCheckUtil
+import cn.sagacloud.server.algorithm.common.utils.GridGroupUtil
 import cn.sagacloud.server.algorithm.models.dataCheck.GridCheckResult
 import cn.sagacloud.server.algorithm.models.dataCheck.LevelCheckResult
+import cn.sagacloud.server.algorithm.models.entities.Grid
 import cn.sagacloud.server.algorithm.models.excel.IsPassedEnum
 import cn.sagacloud.server.algorithm.models.excel.report.ModelGridReport
 import cn.sagacloud.server.algorithm.models.excel.report.ModelLevelReport
 import cn.sagacloud.server.algorithm.models.excel.report.BlockingTotalReport
+import cn.sagacloud.server.algorithm.models.modelFile.FloorModelView
 import cn.sagacloud.server.algorithm.models.modelFile.ModelFile
 import cn.sagacloud.server.algorithm.models.scheduler.SagaCheckResult
 import cn.sagacloud.server.algorithm.models.scheduler.UnitCheckResult
 import cn.sagacloud.server.algorithm.services.comparator.FloorComparator
+import cn.sagacloud.server.algorithm.services.endpoint.FloorModelService
 import cn.sagacloud.server.algorithm.services.excel.ExcelService
 import cn.sagacloud.server.algorithm.services.message.MessageService
+import com.sybotan.database.SFilter
 import com.sybotan.mybatis.SMybatisDao
 import com.sybotan.service.SBaseService
+import com.sybotan.service.SObjectService
+import com.sybotan.service.models.requests.SQueryRequest
 import com.sybotan.service.utils.SSpringContextUtil
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Component
 import java.lang.StringBuilder
+import java.util.stream.Collectors
+import kotlin.collections.Map as Map
 
 @Component
 class ModelCheckService {
@@ -31,20 +41,46 @@ class ModelCheckService {
      * 检查轴网
      */
     fun checkGrid(projectId : String, folderId : String, modelId : String): ArrayList<GridCheckResult> {
-        var gridCheckService = SBaseService(SMybatisDao(GridCheckResult::class.java))
-        var queryBuilder = gridCheckService.selectAll()
-        queryBuilder.tableName = "revit_calc.check_grid_valid('${projectId}', '${folderId}', '${modelId}')"
-        return queryBuilder.exec()
+//        var gridCheckService = SBaseService(SMybatisDao(GridCheckResult::class.java))
+//        var queryBuilder = gridCheckService.selectAll()
+//        queryBuilder.tableName = "revit_calc.check_grid_valid('${projectId}', '${folderId}', '${modelId}')"
+        // 查询楼层模型
+        var request = SQueryRequest()
+        request.filters = " folder_id = '"+ folderId!! +"' and ( status = 4 or fid = '" + modelId!! + "') ";
+        val select = FloorModelService.pageQuery(request)
+        var list = select.content
+        if(list == null || list.isEmpty()){
+            return ArrayList()
+        }
+        // 收集modelId
+        val idSet = list.stream().map { FloorModelView::currentModelId }.collect(Collectors.toSet());
+        // 查询Grid
+        var gridService = SObjectService(SMybatisDao(Grid::class.java))
+        val gridRs = gridService.pageQuery(SQueryRequest(), arrayListOf(SFilter.inList("model_id", arrayListOf(idSet))))
+        val grids = gridRs.content;
+        val gridMap = grids!!.groupBy { it.id }
+        // 获取分组
+        return GridGroupUtil.checkGridUpright(list, gridMap) as ArrayList<GridCheckResult>
     }
 
     /**
      * 检查标高
      */
     fun checkLevel(projectId : String, folderId : String, modelId : String): ArrayList<LevelCheckResult> {
-        var levelCheckService = SBaseService(SMybatisDao(LevelCheckResult::class.java))
-        var queryBuilder = levelCheckService.selectAll()
-        queryBuilder.tableName = "revit_calc.check_level_valid('${projectId}', '${folderId}', '${modelId}')"
-        return queryBuilder.exec()
+//        var levelCheckService = SBaseService(SMybatisDao(LevelCheckResult::class.java))
+//        var queryBuilder = levelCheckService.selectAll()
+//        queryBuilder.tableName = "revit_calc.check_level_valid('${projectId}', '${folderId}', '${modelId}')"
+//        return queryBuilder.exec()
+        // 查询楼层模型
+        var request = SQueryRequest()
+        request.filters = " folder_id = '"+ folderId!! +"' and ( status = 4 or fid = '" + modelId!! + "') ";
+        val select = FloorModelService.pageQuery(request)
+        var list = select.content
+        if(list == null || list.isEmpty()){
+            return ArrayList()
+        }
+        // 检查标高
+        return FloorLevelCheckUtil.checkLevel(list) as ArrayList<LevelCheckResult>
     }
 
     /**