Explorar o código

实现交叉线检查基本算法

欧阳劲驰 hai 1 mes
pai
achega
ec8246c6cb

+ 22 - 2
src/main/java/com/shkpr/service/alambizplugin/components/GisSurveySystemChecker.java

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
 import com.global.base.log.LogLevelFlag;
 import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.alambizplugin.apiparam.GisSurveyCheckParams;
+import com.shkpr.service.alambizplugin.components.checker.CrossLinesFinder;
 import com.shkpr.service.alambizplugin.components.checker.DuplicatePointsFinder;
 import com.shkpr.service.alambizplugin.components.checker.ElevationDiffFinder;
 import com.shkpr.service.alambizplugin.components.checker.InvalidLinesFinder;
@@ -59,13 +60,15 @@ public class GisSurveySystemChecker {
     private final DuplicatePointsFinder duplicatePointsFinder;
     private final InvalidLinesFinder invalidLinesFinder;
     private final OverlapLinesFinder overlapLinesFinder;
+    private final CrossLinesFinder crossLinesFinder;
     private final ElevationDiffFinder elevationDiffFinder;
 
     public GisSurveySystemChecker(AsyncResultManager asyncResultManager
             , GisSurveyLayerApplyService gisSurveyLayerApplyService, TypeDefineService typeDefineService
             , IsolatedPointsFinder isolatedPointsFinder, IsolatedLinesFinder isolatedLinesFinder
             , DuplicatePointsFinder duplicatePointsFinder, InvalidLinesFinder invalidLinesFinder
-            , OverlapLinesFinder overlapLinesFinder, ElevationDiffFinder elevationDiffFinder) {
+            , OverlapLinesFinder overlapLinesFinder, CrossLinesFinder crossLinesFinder
+            , ElevationDiffFinder elevationDiffFinder) {
         mStrClassName = "GisSurveySystemChecker";
         mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
         this.asyncResultManager = asyncResultManager;
@@ -76,6 +79,7 @@ public class GisSurveySystemChecker {
         this.duplicatePointsFinder = duplicatePointsFinder;
         this.invalidLinesFinder = invalidLinesFinder;
         this.overlapLinesFinder = overlapLinesFinder;
+        this.crossLinesFinder = crossLinesFinder;
         this.elevationDiffFinder = elevationDiffFinder;
     }
 
@@ -110,6 +114,8 @@ public class GisSurveySystemChecker {
         ListenableFuture<GisSurveySystemCheckResultDetail> invalidLinesFuture = null;
         //重叠线任务
         ListenableFuture<GisSurveySystemCheckResultDetail> overlapLinesFuture = null;
+        //交叉线任务
+        ListenableFuture<GisSurveySystemCheckResultDetail> crossLinesFuture = null;
         //高程差任务
         ListenableFuture<GisSurveySystemCheckResultDetail> elevationDiffFuture = null;
 
@@ -171,16 +177,23 @@ public class GisSurveySystemChecker {
                     subtask.put(GisSurveySystemCheckKeys.DUPLICATE_POINTS, duplicatePointsFuture);
                 }
             }
-            //孤立线\重叠线\高程差异常检查
             if (lines != null) {
+                //孤立线检查
                 if (params.getStartSubitemKeys().contains(GisSurveySystemCheckKeys.ISOLATED_LINES)) {
                     isolatedLinesFuture = isolatedLinesFinder.findIsolatedLines(lines, systemCheckId);
                     subtask.put(GisSurveySystemCheckKeys.ISOLATED_LINES, isolatedLinesFuture);
                 }
+                //重叠线检查
                 if (params.getStartSubitemKeys().contains(GisSurveySystemCheckKeys.OVERLAP_LINES)) {
                     overlapLinesFuture = overlapLinesFinder.findOverlapLines(lines, systemCheckId);
                     subtask.put(GisSurveySystemCheckKeys.OVERLAP_LINES, overlapLinesFuture);
                 }
+                //交叉线检查
+                if (params.getStartSubitemKeys().contains(GisSurveySystemCheckKeys.CROSS_LINES)) {
+                    crossLinesFuture = crossLinesFinder.findCrossLines(lines, systemCheckId);
+                    subtask.put(GisSurveySystemCheckKeys.CROSS_LINES, crossLinesFuture);
+                }
+                //高程差异常检查
                 if (params.getStartSubitemKeys().contains(GisSurveySystemCheckKeys.ELEVATION_DIFF)) {
                     elevationDiffFuture = elevationDiffFinder.findElevationDiff(lines, systemCheckId);
                     subtask.put(GisSurveySystemCheckKeys.ELEVATION_DIFF, elevationDiffFuture);
@@ -237,6 +250,12 @@ public class GisSurveySystemChecker {
                 data.put(GisSurveySystemCheckKeys.OVERLAP_LINES, overlapLinesResult);
                 refreshTimes.put(GisSurveySystemCheckKeys.OVERLAP_LINES, params.getRefreshTime());
             }
+            if (crossLinesFuture != null) {
+                //监听交叉线
+                final GisSurveySystemCheckResultDetail crossLinesResult = crossLinesFuture.get();
+                data.put(GisSurveySystemCheckKeys.CROSS_LINES, crossLinesResult);
+                refreshTimes.put(GisSurveySystemCheckKeys.CROSS_LINES, params.getRefreshTime());
+            }
             if (elevationDiffFuture != null) {
                 //监听高程差异常
                 final GisSurveySystemCheckResultDetail elevationDiffResult = elevationDiffFuture.get();
@@ -297,6 +316,7 @@ public class GisSurveySystemChecker {
             if (duplicatePointsFuture != null) duplicatePointsFuture.cancel(true);
             if (invalidLinesFuture != null) invalidLinesFuture.cancel(true);
             if (overlapLinesFuture != null) overlapLinesFuture.cancel(true);
+            if (crossLinesFuture != null) crossLinesFuture.cancel(true);
             if (elevationDiffFuture != null) elevationDiffFuture.cancel(true);
 
             //失败信息

+ 143 - 0
src/main/java/com/shkpr/service/alambizplugin/components/checker/CrossLinesFinder.java

@@ -0,0 +1,143 @@
+package com.shkpr.service.alambizplugin.components.checker;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.alambizplugin.commtools.BeanUtil;
+import com.shkpr.service.alambizplugin.components.AsyncResultManager;
+import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckKeys;
+import com.shkpr.service.alambizplugin.constants.GisSurveySystemCheckResultHead;
+import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
+import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApplyLine;
+import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckElement;
+import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckId;
+import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Component;
+import org.springframework.util.concurrent.ListenableFuture;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * 交叉线差寻找器
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Component
+public class CrossLinesFinder {
+    /**
+     * log
+     */
+    private final String mStrClassName;
+    private final String mBizType;
+    private final AsyncResultManager asyncResultManager;
+
+    public CrossLinesFinder(AsyncResultManager asyncResultManager) {
+        mStrClassName = "OverlapLinesFinder";
+        mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
+        this.asyncResultManager = asyncResultManager;
+    }
+
+    /**
+     * 寻找交叉线
+     * <p>返回的为交叉线组,未交叉的线不会出现在返回结果</p>
+     * <p>一组线,仅为两条交叉的线,长度固定为2</p>
+     *
+     * @param lines 线集合
+     * @return 交叉线分组
+     */
+    @Async
+    public ListenableFuture<GisSurveySystemCheckResultDetail> findCrossLines(List<GisSurveyLayerApplyLine> lines
+            , GisSurveySystemCheckId systemCheckId) throws InterruptedException {
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找重叠线========>");
+        long begin = System.currentTimeMillis();
+
+        //结果
+        List<List<GisSurveySystemCheckElement>> groupElements = new ArrayList<>();
+        //双层循环遍历所有线
+        for (int i = 0; i < lines.size(); i++) {
+            GisSurveyLayerApplyLine line1 = lines.get(i);
+            if (line1.getGis() == null) continue;
+            //响应中断
+            if (Thread.interrupted()) throw new InterruptedException();
+            for (int j = i + 1; j < lines.size(); j++) {
+                GisSurveyLayerApplyLine line2 = lines.get(j);
+                if (line2.getGis() == null) continue;
+                //响应中断
+                if (Thread.interrupted()) throw new InterruptedException();
+                // 判断是否交叉
+                if (line1.getGis().crosses(line2.getGis())) {
+                    // 创建两两一组交叉线对
+                    groupElements.add(Arrays.asList(BeanUtil.copy(line1, GisSurveySystemCheckElement.class),
+                            BeanUtil.copy(line2, GisSurveySystemCheckElement.class)));
+                }
+            }
+        }
+
+        return new AsyncResult<>(createResult(groupElements, systemCheckId, begin));
+    }
+
+    /**
+     * 创建结果
+     *
+     * @param data          数据
+     * @param systemCheckId 系统检查id
+     * @param begin         开始时间
+     * @return 结果
+     */
+    private GisSurveySystemCheckResultDetail createResult(List<List<GisSurveySystemCheckElement>> data
+            , GisSurveySystemCheckId systemCheckId, long begin) {
+        //数据大小
+        final int size = data.size();
+        //结果flag
+        final String FLAG = systemCheckId.getFlag();
+        //写入json和excel结果
+        Path jsonPath = asyncResultManager.writeJson(data, FLAG, GisSurveySystemCheckKeys.CROSS_LINES + ".json");
+        Path excelPath = asyncResultManager.writeExcel(GisSurveySystemCheckResultHead.CROSS_LINES,
+                buildExcel(data), FLAG, GisSurveySystemCheckKeys.CROSS_LINES + ".xlsx");
+
+        long end = System.currentTimeMillis();
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
+                , String.format(
+                        "结束执行寻找交叉线,用时(毫秒):%d"
+                        , (end - begin)
+                )
+        );
+
+        //构建结果
+        return new GisSurveySystemCheckResultDetail(true
+                , FLAG + "/" + jsonPath.getFileName()
+                , FLAG + "/" + excelPath.getFileName()
+                , size);
+    }
+
+    /**
+     * 构建excel数据
+     *
+     * @param data 数据
+     * @return excel数据
+     */
+    private List<Map<String, Object>> buildExcel(List<List<GisSurveySystemCheckElement>> data) {
+        return IntStream.range(0, data.size())
+                .boxed()
+                .flatMap(i -> data.get(i).stream().map(element -> {
+                    Map<String, Object> map = new HashMap<>();
+                    map.put(GisSurveySystemCheckResultHead.KEYS.GROUP_NAME, i + 1);
+                    map.put(GisSurveySystemCheckResultHead.KEYS.UP_NO, element.getUpNo());
+                    map.put(GisSurveySystemCheckResultHead.KEYS.DOWN_NO, element.getDownNo());
+                    map.put(GisSurveySystemCheckResultHead.KEYS.CODE, element.getCode());
+                    map.put(GisSurveySystemCheckResultHead.KEYS.UP_NODE, element.getUpNode());
+                    map.put(GisSurveySystemCheckResultHead.KEYS.DOWN_NODE, element.getDownNode());
+                    map.put(GisSurveySystemCheckResultHead.KEYS.NAME, element.getName());
+                    return map;
+                })).collect(Collectors.toList());
+    }
+}

+ 4 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveySystemCheckKeys.java

@@ -28,6 +28,10 @@ public interface GisSurveySystemCheckKeys {
      */
     String OVERLAP_LINES = "overlapLines";
     /**
+     * 交叉线
+     */
+    String CROSS_LINES = "crossLines";
+    /**
      * 高程差异常
      */
     String ELEVATION_DIFF = "elevationDiff";

+ 12 - 0
src/main/java/com/shkpr/service/alambizplugin/constants/GisSurveySystemCheckResultHead.java

@@ -63,6 +63,18 @@ public class GisSurveySystemCheckResultHead {
         put(KEYS.NAME, "类型");
     }};
     /**
+     * 交叉线
+     */
+    public final static Map<String, String> CROSS_LINES = new LinkedHashMap<String, String>() {{
+        put(KEYS.GROUP_NAME, "组名");
+        put(KEYS.UP_NO, "起点号");
+        put(KEYS.DOWN_NO, "终点号");
+        put(KEYS.CODE, "编码");
+        put(KEYS.UP_NODE, "起点编码");
+        put(KEYS.DOWN_NODE, "终点编码");
+        put(KEYS.NAME, "类型");
+    }};
+    /**
      * 高程差异常
      */
     public final static Map<String, String> ELEVATION_DIFF = new LinkedHashMap<String, String>() {{