Browse Source

调用矩形分组,分布执行异形群组 大幅提高速度

Hongwenjun 2 weeks ago
parent
commit
f6d0cb6f0d

+ 29 - 2
09_BoundaryGroup/BoundaryGroup.cpp

@@ -1,4 +1,6 @@
 #include "cdrapp.h"
+#include <cerrno>
+#include <cmath>
 
 bool isDPCurve(IVGShapePtr s) {
   auto dpc = (s->Type == cdrRectangleShape) || (s->Type == cdrEllipseShape) ||
@@ -69,7 +71,8 @@ bool BoundaryGroup(corel *cdr, IVGShapeRange *sr, IVGShapeRange *srs) {
 
   // 处理文字和影响的物件
   auto txtbox = cdr->CreateShapeRange();
-  auto sr_text = sr->Shapes->FindShapes(_bstr_t(), cdrTextShape, VARIANT_TRUE, _bstr_t());
+  auto sr_text =
+      sr->Shapes->FindShapes(_bstr_t(), cdrTextShape, VARIANT_TRUE, _bstr_t());
   if (sr_text->Count > 0) {
     auto al = cdr->ActiveLayer;
     for (auto i = 0; i != sr_text->Count; i++) {
@@ -85,6 +88,7 @@ bool BoundaryGroup(corel *cdr, IVGShapeRange *sr, IVGShapeRange *srs) {
   bounds->Fill->UniformColor->RGBAssign(255, 0, 0);    // 填充红色
   auto sbox = bounds->BreakApartEx(); // 把边界 拆分为多个边界 用来分组
 
+
   // 删除文字添加的方框
   if (sr_text->Count > 0) {
     sr->RemoveRange(txtbox);
@@ -124,14 +128,37 @@ bool BoundaryGroup(corel *cdr, IVGShapeRange *sr, IVGShapeRange *srs) {
 // 测试运行 异形群组
 void run_BoundaryGroup(corel *cdr) {
   auto start = std::chrono::high_resolution_clock::now(); // 开始时间
+  if (cdr->VersionMajor < 17) {
+    sprintf(infobuf, "异形群组目前只支持X7以上版本!");
+    return;
+  }
+
   BeginOpt(cdr);
 
   auto sr = cdr->ActiveSelectionRange;
   auto srs = cdr->CreateShapeRange();
+  auto sr_box = cdr->CreateShapeRange();
+
   int cnt = sr->Count;
 
+  // 取消选择,速度优化
   cdr->ActiveDocument->ClearSelection();
-  BoundaryGroup(cdr, sr, srs);
+
+  if (cnt > 300) {
+    // 调用矩形分组,分布执行异形群组
+    if (BoxGrouping(cdr, sr, sr_box, 1.0)) {
+      for (int i = 0; i < sr_box->Count; i++) {
+        auto s = sr_box->Shapes->Item[i + 1];
+        if (!s->IsSimpleShape) {
+          auto sr2 = s->UngroupEx();
+          BoundaryGroup(cdr, sr2, srs);
+        }
+      }
+    }
+  } else {
+    BoundaryGroup(cdr, sr, srs);
+  }
+
   srs->CreateSelection();
 
   // 计算持续时间

+ 3 - 1
09_BoundaryGroup/ToolsBox.cpp

@@ -1,4 +1,5 @@
-#include "cdrapp.h"
+#include "cdrapi.h"
+#include "cdrapp.h"
 #include <stdio.h>
 #include <windows.h>
 #include "resource.h"
@@ -275,6 +276,7 @@ intptr_t CALLBACK ToolsBoxPlugin::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, L
 
         } catch (_com_error &e) {
             MessageBox(NULL, e.Description(), "Error", MB_ICONSTOP);
+            EndOpt(cdr);
         }
 
     } else if (uMsg == WM_INITDIALOG) {

+ 53 - 0
09_BoundaryGroup/boxAutoGroup.cpp

@@ -190,4 +190,57 @@ bool Box_AutoGroup(corel *cdr, double exp) {
   sprintf(infobuf, "选择物件: %d 个, 分组: %.2f秒\n总共群组: %d 组, 总时间: %.2f秒", sr->Count, runtime[0] + 0.01, srs->Count, runtime[1] + 0.02);
   EndOpt(cdr);
   return true;
+}
+
+// 按矩形框范围分组,供其他功能调用 
+bool BoxGrouping(corel *cdr, IVGShapeRange *sr, IVGShapeRange *srs, double exp ) {
+  BoundingBox box;
+  auto al = cdr->ActiveLayer;          // 获得当前层
+  if (!sr || !al) return false;
+
+  std::vector<BoundingBox> boxes;
+  std::vector<int> parent;
+
+  // CorelDRAW Shapes 物件 Item 编号从1开始
+  for (auto i = 0; i != sr->Count; i++) {
+    sr->Shapes->Item[i + 1]->GET_BOUNDING_BOX(box);
+    boxes.push_back(box);
+    parent.push_back(i);
+  }
+
+  // 扩展边界框,或者收缩边界框
+  if (fabs(exp) > 0.02 ) {
+    expand_bounding_boxes(boxes, exp);
+  }
+
+  // 实现 Union-Find 算法来合并重叠的区域
+  for (int i = 0; i < boxes.size(); i++) {
+    for (int j = i + 1; j < boxes.size(); j++) {
+      if (isOverlapped(boxes[i], boxes[j])) {
+        unionSet(parent, i, j);
+      }
+    }
+  }
+
+  // 输出分组结果
+  std::map<int, std::vector<int>> groups;
+  for (int i = 0; i < parent.size(); i++) {
+    int root = find(parent, i);
+    groups[root].push_back(i + 1); // CorelDRAW Shapes 物件 Item 编号从1开始
+  }
+
+  auto srgp = cdr->CreateShapeRange();
+  // 分组分别进行群组
+  for (const auto& group : groups) {
+      for (int index : group.second) 
+        srgp->Add(sr->Shapes->Item[index]);
+      
+      if(sr->Count >1)
+        srs->Add(srgp->Group());
+      else
+        srs->AddRange(srgp);  
+
+      srgp->RemoveAll();
+  }
+  return true;
 }

+ 2 - 1
09_BoundaryGroup/cdrapp.h

@@ -34,7 +34,8 @@ typedef struct {
   double w; 
   double h; 
 } BoundingBox;
-bool isOverlapped(const BoundingBox &a, const BoundingBox &b);
 
+bool isOverlapped(const BoundingBox &a, const BoundingBox &b);
+bool BoxGrouping(corel *cdr, IVGShapeRange *sr, IVGShapeRange *srs, double exp );
 
 #endif // CDRAPP_H_INCLUDED