فهرست منبع

交叉线检查引入空间索引提升检查速度

欧阳劲驰 1 ماه پیش
والد
کامیت
77b650ab40
1فایلهای تغییر یافته به همراه35 افزوده شده و 9 حذف شده
  1. 35 9
      src/main/java/com/shkpr/service/alambizplugin/components/checker/CrossLinesFinder.java

+ 35 - 9
src/main/java/com/shkpr/service/alambizplugin/components/checker/CrossLinesFinder.java

@@ -11,6 +11,8 @@ 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.locationtech.jts.geom.LineString;
+import org.locationtech.jts.index.strtree.STRtree;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.AsyncResult;
 import org.springframework.stereotype.Component;
@@ -20,8 +22,11 @@ import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -60,26 +65,47 @@ public class CrossLinesFinder {
         LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行寻找重叠线========>");
         long begin = System.currentTimeMillis();
 
+        //创建空间索引
+        STRtree tree = new STRtree();
+        //元素存入索引
+        for (GisSurveyLayerApplyLine layerApplyLine : lines) {
+            if (layerApplyLine.getGis() == null) continue;
+            LineString line = layerApplyLine.getGis();
+            tree.insert(line.getEnvelopeInternal(), layerApplyLine);
+        }
+        tree.build();
+
         //结果
         List<List<GisSurveySystemCheckElement>> groupElements = new ArrayList<>();
-        //双层循环遍历所有线
-        for (int i = 0; i < lines.size(); i++) {
-            GisSurveyLayerApplyLine line1 = lines.get(i);
+        //处理过的code
+        Set<String> processedCodes = new HashSet<>();
+        //遍历所有线
+        for (GisSurveyLayerApplyLine line1 : lines) {
             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;
+            //查询索引内元素
+            List<?> candidates = tree.query(line1.getGis().getEnvelopeInternal());
+            for (Object obj : candidates) {
+                GisSurveyLayerApplyLine line2 = (GisSurveyLayerApplyLine) obj;
+                //排除code相同或已经处理的元素,
+                if (Objects.equals(line1.getCode(), line2.getCode())
+                        || processedCodes.contains(line2.getCode())
+                        || 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)));
+                    //创建两两一组交叉线对
+                    groupElements.add(Arrays.asList(
+                            BeanUtil.copy(line1, GisSurveySystemCheckElement.class),
+                            BeanUtil.copy(line2, GisSurveySystemCheckElement.class)
+                    ));
                 }
             }
+            //存入code,避免重复处理
+            processedCodes.add(line1.getCode());
         }
 
         return new AsyncResult<>(createResult(groupElements, systemCheckId, begin));