From e0cee09916a315d6012b8d44b4c493c4f3adc5d1 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 31 三月 2026 17:05:49 +0800
Subject: [PATCH] #出入库模式

---
 src/main/java/com/zy/asrs/service/impl/BasMapEditorServiceImpl.java |  167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 166 insertions(+), 1 deletions(-)

diff --git a/src/main/java/com/zy/asrs/service/impl/BasMapEditorServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/BasMapEditorServiceImpl.java
index fe0f13a..77f6936 100644
--- a/src/main/java/com/zy/asrs/service/impl/BasMapEditorServiceImpl.java
+++ b/src/main/java/com/zy/asrs/service/impl/BasMapEditorServiceImpl.java
@@ -54,6 +54,8 @@
     private static final double DEFAULT_CANVAS_HEIGHT = 5200D;
     private static final int X_SCALE = 40;
     private static final int Y_SCALE = 8;
+    private static final double AUTO_BRIDGE_MAX_GAP_DISPLAY = 2.0d;
+    private static final double AUTO_BRIDGE_MIN_OVERLAP_RATIO = 0.85d;
 
     @Autowired
     private BasMapService basMapService;
@@ -330,6 +332,10 @@
         for (BasMapEditorElement element : elements) {
             CompiledRect rect = toCompiledRect(element);
             rects.add(rect);
+        }
+        List<CompiledRect> allRects = new ArrayList<>(rects);
+        allRects.addAll(buildAutoBridgeRects(rects));
+        for (CompiledRect rect : allRects) {
             xBounds.add(rect.left);
             xBounds.add(rect.right);
             yBounds.add(rect.top);
@@ -359,7 +365,7 @@
             stored.add(row);
         }
 
-        for (CompiledRect rect : rects) {
+        for (CompiledRect rect : allRects) {
             Integer rowStart = yIndexMap.get(String.valueOf(rect.top));
             Integer rowEndIndex = yIndexMap.get(String.valueOf(rect.bottom));
             Integer colStart = xIndexMap.get(String.valueOf(rect.left));
@@ -426,6 +432,8 @@
         rect.id = element.getId();
         rect.type = element.getType();
         rect.value = normalizeCellValue(element.getType(), element.getValue());
+        JSONObject valueObject = parseJsonObject(rect.value);
+        rect.stationId = valueObject == null ? null : valueObject.getInteger("stationId");
         rect.left = toRawWidth(element.getX());
         rect.top = toRawHeight(element.getY());
         rect.right = toRawWidth(safeDouble(element.getX()) + safeDouble(element.getWidth()));
@@ -434,6 +442,162 @@
             throw new CoolException("鍏冪礌灏哄鏃犳晥: " + element.getId());
         }
         return rect;
+    }
+
+    private List<CompiledRect> buildAutoBridgeRects(List<CompiledRect> sourceRects) {
+        List<CompiledRect> bridgeRects = new ArrayList<>();
+        if (sourceRects == null || sourceRects.size() < 2) {
+            return bridgeRects;
+        }
+        for (int i = 0; i < sourceRects.size(); i++) {
+            CompiledRect first = sourceRects.get(i);
+            if (!isAutoBridgeCandidate(first)) {
+                continue;
+            }
+            for (int j = i + 1; j < sourceRects.size(); j++) {
+                CompiledRect second = sourceRects.get(j);
+                if (!isAutoBridgeCandidate(second)) {
+                    continue;
+                }
+                CompiledRect bridgeRect = buildAutoBridgeRect(first, second);
+                if (bridgeRect == null) {
+                    continue;
+                }
+                if (hasRectConflict(bridgeRect, sourceRects, bridgeRects, first, second)) {
+                    continue;
+                }
+                bridgeRects.add(bridgeRect);
+            }
+        }
+        return bridgeRects;
+    }
+
+    private boolean isAutoBridgeCandidate(CompiledRect rect) {
+        return rect != null && "devp".equals(rect.type) && rect.stationId != null && rect.stationId > 0;
+    }
+
+    private CompiledRect buildAutoBridgeRect(CompiledRect first, CompiledRect second) {
+        CompiledRect horizontalBridge = buildHorizontalBridgeRect(first, second);
+        if (horizontalBridge != null) {
+            return horizontalBridge;
+        }
+        return buildVerticalBridgeRect(first, second);
+    }
+
+    private CompiledRect buildHorizontalBridgeRect(CompiledRect first, CompiledRect second) {
+        CompiledRect left = first.left <= second.left ? first : second;
+        CompiledRect right = left == first ? second : first;
+        int gap = right.left - left.right;
+        if (gap <= 0 || gap > toRawWidth(AUTO_BRIDGE_MAX_GAP_DISPLAY)) {
+            return null;
+        }
+        int overlapTop = Math.max(left.top, right.top);
+        int overlapBottom = Math.min(left.bottom, right.bottom);
+        int overlapSize = overlapBottom - overlapTop;
+        if (!passesAutoBridgeOverlapThreshold(overlapSize, left.bottom - left.top, right.bottom - right.top)) {
+            return null;
+        }
+        return buildBridgeRect(
+                "bridge_h_" + left.stationId + "_" + right.stationId,
+                left.right,
+                overlapTop,
+                right.left,
+                overlapBottom,
+                Arrays.asList("left", "right"),
+                left.stationId,
+                right.stationId
+        );
+    }
+
+    private CompiledRect buildVerticalBridgeRect(CompiledRect first, CompiledRect second) {
+        CompiledRect top = first.top <= second.top ? first : second;
+        CompiledRect bottom = top == first ? second : first;
+        int gap = bottom.top - top.bottom;
+        if (gap <= 0 || gap > toRawHeight(AUTO_BRIDGE_MAX_GAP_DISPLAY)) {
+            return null;
+        }
+        int overlapLeft = Math.max(top.left, bottom.left);
+        int overlapRight = Math.min(top.right, bottom.right);
+        int overlapSize = overlapRight - overlapLeft;
+        if (!passesAutoBridgeOverlapThreshold(overlapSize, top.right - top.left, bottom.right - bottom.left)) {
+            return null;
+        }
+        return buildBridgeRect(
+                "bridge_v_" + top.stationId + "_" + bottom.stationId,
+                overlapLeft,
+                top.bottom,
+                overlapRight,
+                bottom.top,
+                Arrays.asList("top", "bottom"),
+                top.stationId,
+                bottom.stationId
+        );
+    }
+
+    private boolean passesAutoBridgeOverlapThreshold(int overlapSize, int firstSpan, int secondSpan) {
+        if (overlapSize <= 0 || firstSpan <= 0 || secondSpan <= 0) {
+            return false;
+        }
+        double overlapRatio = overlapSize * 1.0d / Math.max(firstSpan, secondSpan);
+        return overlapRatio >= AUTO_BRIDGE_MIN_OVERLAP_RATIO;
+    }
+
+    private CompiledRect buildBridgeRect(String id,
+                                         int left,
+                                         int top,
+                                         int right,
+                                         int bottom,
+                                         List<String> directions,
+                                         Integer firstStationId,
+                                         Integer secondStationId) {
+        if (left >= right || top >= bottom) {
+            return null;
+        }
+        CompiledRect rect = new CompiledRect();
+        rect.id = id;
+        rect.type = "devp";
+        rect.value = buildBridgeValue(directions, firstStationId, secondStationId);
+        rect.left = left;
+        rect.top = top;
+        rect.right = right;
+        rect.bottom = bottom;
+        return rect;
+    }
+
+    private String buildBridgeValue(List<String> directions, Integer firstStationId, Integer secondStationId) {
+        JSONObject value = new JSONObject();
+        value.put("direction", directions);
+        value.put("bridgeStationIds", Arrays.asList(firstStationId, secondStationId));
+        value.put("autoBridge", 1);
+        return value.toJSONString();
+    }
+
+    private boolean hasRectConflict(CompiledRect candidate,
+                                    List<CompiledRect> sourceRects,
+                                    List<CompiledRect> bridgeRects,
+                                    CompiledRect firstIgnore,
+                                    CompiledRect secondIgnore) {
+        for (CompiledRect rect : sourceRects) {
+            if (rect == null || rect == firstIgnore || rect == secondIgnore) {
+                continue;
+            }
+            if (compiledRectsOverlap(candidate, rect)) {
+                return true;
+            }
+        }
+        for (CompiledRect rect : bridgeRects) {
+            if (rect != null && compiledRectsOverlap(candidate, rect)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean compiledRectsOverlap(CompiledRect first, CompiledRect second) {
+        return first.left < second.right
+                && first.right > second.left
+                && first.top < second.bottom
+                && first.bottom > second.top;
     }
 
     private Map<String, Integer> buildBoundaryIndexMap(List<Integer> bounds) {
@@ -893,6 +1057,7 @@
         private String id;
         private String type;
         private String value;
+        private Integer stationId;
         private int left;
         private int top;
         private int right;

--
Gitblit v1.9.1