From 91e1d5b820bd39b6d6c97349facda304ec317606 Mon Sep 17 00:00:00 2001
From: 于杰 <1210123631@qq.com>
Date: 星期三, 13 八月 2025 09:29:58 +0800
Subject: [PATCH] 完善余料计算代码,修复余料部分重叠计算的问题

---
 north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue |  227 ++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 147 insertions(+), 80 deletions(-)

diff --git a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
index c0ba000..03bd17c 100644
--- a/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
+++ b/north-glass-erp/northglass-erp/src/views/pp/glassOptimize/page/OptimizationRect.vue
@@ -648,11 +648,11 @@
   adjustGrayRectangles(layoutIndex);
 };
 
-const mergeAdjacentGrayRects = (glassDetails,totalWidth,totalHeight) => {
+const mergeAdjacentGrayRects = (glassDetails, totalWidth, totalHeight) => {
   const grayRects = glassDetails.filter(r => r.isRemain);
-  const grayRects2 = glassDetails.filter(r => r.isRemain);
-  let merged = [];
+  const nonGrayRects = glassDetails.filter(r => !r.isRemain);
 
+  // 鎸夊潗鏍囨帓搴忥紝浼樺厛鎸墄鍧愭爣锛屽叾娆℃寜y鍧愭爣
   grayRects.sort((a, b) => {
     if (a.x !== b.x) return a.x - b.x;
     return a.y - b.y;
@@ -660,30 +660,31 @@
 
   if (grayRects.length === 0) return;
 
-  merged.push({ ...grayRects[0] });
+  const merged = [];
 
+  // 浠庣涓�涓煩褰㈠紑濮�
+  let current = { ...grayRects[0] };
+
+  // 閬嶅巻鎵�鏈変綑鏂欑煩褰㈣繘琛屽悎骞�
   for (let i = 1; i < grayRects.length; i++) {
-      const last = merged[merged.length-1];
-      const current = grayRects[i];
+    const next = grayRects[i];
 
-
-    if (current.x === last.x + last.width &&
-        current.y === last.y &&
-        current.height === last.height) {
-      last.width += current.width;
-      last.x = Math.round(last.x);
-      last.y = Math.round(last.y);
-      last.width = Math.round(last.width);
-      last.height = Math.round(last.height);
-    } else if (current.y === last.y + last.height &&
-               current.x === last.x &&
-               current.width === last.width) {
-      last.height += current.height;
-      last.x = Math.round(last.x);
-      last.y = Math.round(last.y);
-      last.width = Math.round(last.width);
-      last.height = Math.round(last.height);
-    } else {
+    // 妫�鏌ユ槸鍚﹀彲浠ユ按骞冲悎骞讹紙鍚屼竴琛岋紝楂樺害鐩稿悓锛岀浉閭伙級
+    if (current.y === next.y &&
+        current.height === next.height &&
+        current.x + current.width === next.x) {
+      // 姘村钩鍚堝苟
+      current.width += next.width;
+    }
+    // 妫�鏌ユ槸鍚﹀彲浠ュ瀭鐩村悎骞讹紙鍚屼竴鍒楋紝瀹藉害鐩稿悓锛岀浉閭伙級
+    else if (current.x === next.x &&
+        current.width === next.width &&
+        current.y + current.height === next.y) {
+      // 鍨傜洿鍚堝苟
+      current.height += next.height;
+    }
+    else {
+      // 鏃犳硶鍚堝苟锛屼繚瀛樺綋鍓嶇煩褰紝寮�濮嬫柊鐨勫悎骞�
       merged.push({
         x: Math.round(current.x),
         y: Math.round(current.y),
@@ -691,54 +692,100 @@
         height: Math.round(current.height),
         isRemain: true
       });
+      current = { ...next };
     }
   }
-
-  const nonGray = glassDetails.filter(r => !r.isRemain);
-  //鍒犻櫎鍘熸暟缁勬嫾鎺ユ柊鐨勫皬鐗囪窡浣欐枡
-  glassDetails.splice(0, glassDetails.length, ...nonGray, ...merged);
+  // 閲嶆柊鏋勫缓鏁扮粍锛氶潪浣欐枡 + 鍚堝苟鍚庣殑浣欐枡
+  glassDetails.splice(0, glassDetails.length, ...nonGrayRects, ...merged);
 };
+
+// 纭繚杩斿洖鐨勫尯鍩熶笉閲嶅彔
+const calculateRemainingAreas = (totalWidth, totalHeight, obstacles) => {
+  // 浠庢暣涓師鐗囧紑濮�
+  let remaining = [{ x: 0, y: 0, width: totalWidth, height: totalHeight }];
+
+  // 閫愪釜澶勭悊闅滅鐗╋紙宸叉斁缃殑鐜荤拑鐗囷級
+  obstacles.forEach(obstacle => {
+    remaining = cutRemainingAreas(remaining, obstacle, totalWidth, totalHeight);
+  });
+
+  // 瀵圭粨鏋滆繘琛屾帓搴忥紝纭繚涓�鑷存��
+  remaining.sort((a, b) => {
+    if (a.x !== b.x) return a.x - b.x;
+    return a.y - b.y;
+  });
+
+  return remaining;
+};
+
 
 // 璋冩暣鍚庨噸鏂拌绠楃伆鑹蹭綑鏂�
 const adjustGrayRectangles = (layoutIndex) => {
   const layout = layouts.value[layoutIndex];
   const glassDetails = layout.glassDetails;
-  //灏忕墖鐨勬暟鎹�
+
+  // 1. 绛涢�夊嚭闈炰綑鏂欑殑鐜荤拑鐗囷紙鍗冲疄闄呰鍒囧壊鐨勭幓鐠冪墖锛�
   const nonGrayRects = glassDetails.filter(glassDetail => !glassDetail.isRemain);
 
-  //鎵�鏈夌殑灏忕墖浣欐枡鍧愭爣璺熷昂瀵�
+  // 2. 璁$畻鍓╀綑鍙敤鍖哄煙
   let remainingAreas = calculateRemainingAreas(layout.width, layout.height, nonGrayRects);
-  const uniqueArr = Array.from(
-      new Set(remainingAreas.map(item => JSON.stringify(item)))
-  ).map(item => JSON.parse(item));
-  //浣欐枡鐨勬暟鎹�
+
+  // 3. 鍘婚噸澶勭悊 - 鏇翠弗鏍肩殑鍘婚噸閫昏緫
+  const uniqueArr = removeDuplicateAreas(remainingAreas);
+
+  // 4. 鑾峰彇褰撳墠宸插瓨鍦ㄧ殑浣欐枡鐭╁舰锛堥渶瑕佷繚鐣欏紩鐢ㄤ互渚挎洿鏂帮級
   const currentGrayRects = glassDetails.filter(r => r.isRemain);
-  //寰幆浣欐枡鏁版嵁璺熷叏閮ㄧ殑瀵规瘮
-  currentGrayRects.forEach((_, index) => {
-    if (index >= remainingAreas.length) {
-      glassDetails.splice(index, 1);
-    }
+
+  // 5. 娓呴櫎鎵�鏈夌幇鏈夌殑浣欐枡鐭╁舰
+  // 鍏堟敹闆嗛潪浣欐枡鐭╁舰
+  const nonRemainRects = glassDetails.filter(r => !r.isRemain);
+
+  // 6. 閲嶆柊鏋勫缓鐜荤拑璇︽儏鏁扮粍
+  // 淇濈暀闈炰綑鏂欑煩褰�
+  const newGlassDetails = [...nonRemainRects];
+
+  // 娣诲姞鏂扮殑浣欐枡鐭╁舰
+  uniqueArr.forEach((area) => {
+    newGlassDetails.push({
+      x: Math.round(area.x),
+      y: Math.round(area.y),
+      width: Math.round(area.width),
+      height: Math.round(area.height),
+      isRemain: true
+    });
   });
 
-  uniqueArr.forEach((area, index) => {
-    if (index < currentGrayRects.length) {
-      currentGrayRects[index].x = Math.round(area.x);
-      currentGrayRects[index].y = Math.round(area.y);
-      currentGrayRects[index].width = Math.round(area.width);
-      currentGrayRects[index].height = Math.round(area.height);
-    } else {
-      glassDetails.push({
-        x: Math.round(area.x),
-        y: Math.round(area.y),
-        width: Math.round(area.width),
-        height: Math.round(area.height),
-        isRemain: true
-      });
-    }
-  });
+  // 7. 鏇存柊甯冨眬鐨勭幓鐠冭鎯�
+  layout.glassDetails = newGlassDetails;
 
-  mergeAdjacentGrayRects(glassDetails,layout.width, layout.height);
+  // 8. 鍚堝苟鐩搁偦鐨勪綑鏂欑煩褰�
+  mergeAdjacentGrayRects(layout.glassDetails, layout.width, layout.height);
 };
+
+
+const removeDuplicateAreas = (areas) => {
+  const result = [];
+
+  areas.forEach(area => {
+    // 妫�鏌ユ槸鍚︿笌宸插瓨鍦ㄧ殑鍖哄煙閲嶅彔鎴栫浉绛�
+    const isDuplicate = result.some(existingArea => {
+      return (
+          existingArea.x === area.x &&
+          existingArea.y === area.y &&
+          existingArea.width === area.width &&
+          existingArea.height === area.height
+      );
+    });
+
+    if (!isDuplicate) {
+      result.push(area);
+    }
+  });
+
+  return result;
+};
+
+
 
 //鏃嬭浆鏂规硶
 const rotateRect = (layoutIndex, rectIndex) => {
@@ -882,19 +929,24 @@
 };
 
 //閲嶆柊璁$畻浣欐枡鍧愭爣浠ュ強灏哄1
-const calculateRemainingAreas = (totalWidth, totalHeight, obstacles) => {
-  let remaining = [{ x: 0, y: 0, width: totalWidth, height: totalHeight }];
-  obstacles.forEach(glassDetail => {
-    remaining = cutRemainingAreas(remaining, glassDetail,totalWidth,totalHeight);
-  });
-  return remaining;
-};
+// const calculateRemainingAreas = (totalWidth, totalHeight, obstacles) => {
+//   let remaining = [{ x: 0, y: 0, width: totalWidth, height: totalHeight }];
+//   obstacles.forEach(glassDetail => {
+//     remaining = cutRemainingAreas(remaining, glassDetail,totalWidth,totalHeight);
+//   });
+//   return remaining;
+// };
 
 //閲嶆柊璁$畻浣欐枡鍧愭爣浠ュ強灏哄2
-const cutRemainingAreas = (remainingAreas, obstacle,totalWidth,totalHeight) => {
+const cutRemainingAreas = (remainingAreas, obstacle, totalWidth, totalHeight) => {
   const newRemaining = [];
+
   remainingAreas.forEach(area => {
+    // 濡傛灉闅滅鐗╀笌褰撳墠鍖哄煙鏈夐噸鍙�
     if (checkOverlap(area, obstacle)) {
+      // 鍒囧垎褰撳墠鍖哄煙涓烘渶澶�4涓柊鍖哄煙
+
+      // 宸︿晶鍖哄煙
       if (obstacle.x > area.x) {
         newRemaining.push({
           x: area.x,
@@ -903,35 +955,50 @@
           height: area.height
         });
       }
+
+      // 鍙充晶鍖哄煙
       if (obstacle.x + obstacle.width < area.x + area.width) {
         newRemaining.push({
           x: obstacle.x + obstacle.width,
           y: area.y,
-          width: area.width - (obstacle.x + obstacle.width - area.x),
+          width: area.x + area.width - (obstacle.x + obstacle.width),
           height: area.height
         });
       }
-      if (obstacle.y > area.y) {
-        newRemaining.push({
-          x: area.x,
-          y: area.y,
-          width: area.width,
-          height: obstacle.y - area.y
-        });
-      }
-      if (obstacle.y + obstacle.height < area.y + area.height ) {
-          newRemaining.push({
-            x: area.x,
-            y: obstacle.y + obstacle.height,
-            width: area.width,
-            height: area.height - (obstacle.y + obstacle.height - area.y)
-          });
 
+      // 涓婃柟鍖哄煙锛堜粎鍦ㄩ殰纰嶇墿宸﹀彸杈圭晫涔嬮棿鐨勫尯鍩燂級
+      if (obstacle.y > area.y) {
+        const startX = Math.max(area.x, obstacle.x);
+        const endX = Math.min(area.x + area.width, obstacle.x + obstacle.width);
+        if (endX > startX) {
+          newRemaining.push({
+            x: startX,
+            y: area.y,
+            width: endX - startX,
+            height: obstacle.y - area.y
+          });
+        }
+      }
+
+      // 涓嬫柟鍖哄煙锛堜粎鍦ㄩ殰纰嶇墿宸﹀彸杈圭晫涔嬮棿鐨勫尯鍩燂級
+      if (obstacle.y + obstacle.height < area.y + area.height) {
+        const startX = Math.max(area.x, obstacle.x);
+        const endX = Math.min(area.x + area.width, obstacle.x + obstacle.width);
+        if (endX > startX) {
+          newRemaining.push({
+            x: startX,
+            y: obstacle.y + obstacle.height,
+            width: endX - startX,
+            height: area.y + area.height - (obstacle.y + obstacle.height)
+          });
+        }
       }
     } else {
+      // 娌℃湁閲嶅彔锛屼繚鐣欏師鍖哄煙
       newRemaining.push(area);
     }
   });
+
   return newRemaining;
 };
 

--
Gitblit v1.8.0