Преглед на файлове

重叠线引入空间索引加快检查速度

欧阳劲驰 преди 1 месец
родител
ревизия
5e76e9daa9
променени са 1 файла, в които са добавени 34 реда и са изтрити 8 реда
  1. 34 8
      src/main/java/com/shkpr/service/alambizplugin/components/checker/OverlapLinesFinder.java

+ 34 - 8
src/main/java/com/shkpr/service/alambizplugin/components/checker/OverlapLinesFinder.java

@@ -14,6 +14,8 @@ import com.shkpr.service.alambizplugin.dto.GisSurveySystemCheckResultDetail;
 import org.locationtech.jts.algorithm.Orientation;
 import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.LineSegment;
+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;
@@ -23,8 +25,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;
 
@@ -65,26 +70,47 @@ public class OverlapLinesFinder {
         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 candidate : candidates) {
+                GisSurveyLayerApplyLine line2 = (GisSurveyLayerApplyLine) candidate;
+                //排除code相同或已经处理的元素,
+                if (Objects.equals(line1.getCode(), line2.getCode())
+                        || processedCodes.contains(line2.getCode())
+                        || line2.getGis() == null
+                ) continue;
                 //响应中断
                 if (Thread.interrupted()) throw new InterruptedException();
                 // 判断是否重叠
                 if (calcOverlapLines(line1, line2)) {
                     // 创建两两一组的重叠线对
-                    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));