2 Angajamente 99d26d4abd ... f6d0cb6f0d

Autor SHA1 Permisiunea de a trimite mesaje. Dacă este dezactivată, utilizatorul nu va putea trimite nici un fel de mesaj Data
  Hongwenjun f6d0cb6f0d 调用矩形分组,分布执行异形群组 大幅提高速度 10 luni în urmă
  Hongwenjun a5cb0fbc9a 异形群组,添加文字处理情况 10 luni în urmă

+ 63 - 22
09_BoundaryGroup/BoundaryGroup.cpp

@@ -1,16 +1,7 @@
 #include "cdrapp.h"
+#include <cerrno>
+#include <cmath>
 
-#define GET_BOUNDING_BOX(box)                                                  \
-  GetBoundingBox(&(box).x, &(box).y, &(box).w, &(box).h, false)
-
-#define ZERO_4PC 0, 0, 0, 0
-
-typedef struct {
-  double x; // 左下角 x 坐标
-  double y; // 左下角 y 坐标
-  double w; // 宽度
-  double h; // 高度
-} BoundingBox;
 bool isDPCurve(IVGShapePtr s) {
   auto dpc = (s->Type == cdrRectangleShape) || (s->Type == cdrEllipseShape) ||
              (s->Type == cdrCurveShape) || (s->Type == cdrPolygonShape) ||
@@ -18,6 +9,7 @@ bool isDPCurve(IVGShapePtr s) {
   return dpc;
 }
 IVGShapePtr CreateBoundary(corel *cdr, IVGShapePtr s) {
+
   auto scp = s->CreateBoundary(0, 0, true, false);
 
   //  这个 API X7 以上才支持,所以现在直接画矩形
@@ -59,9 +51,9 @@ bool isIntWith(corel *cdr, IVGShape *s1, IVGShape *s2) {
 }
 
 // 从矩形边界坐标 获得中心坐标
-void calculate_center(const BoundingBox *box, double *cx, double *cy) {
-  *cx = box->x + (box->w / 2);
-  *cy = box->y + (box->h / 2);
+void calculate_center(const BoundingBox &box, double &cx, double &cy) {
+  cx = box.x + (box.w / 2);
+  cy = box.y + (box.h / 2);
 }
 
 // VGCore::cdrPositionOfPointOverShape VGCore::IVGShape::IsOnShape ( double x,
@@ -73,28 +65,53 @@ bool BoundaryGroup(corel *cdr, IVGShapeRange *sr, IVGShapeRange *srs) {
   if (sr->Count < 2)
     return false;
 
-  BoundingBox box;
+  BoundingBox box, bound_box;
   double x, y;
   int OnSh = 0;
+
+  // 处理文字和影响的物件
+  auto txtbox = cdr->CreateShapeRange();
+  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++) {
+      sr_text->Shapes->Item[i + 1]->GET_BOUNDING_BOX(box);
+      auto s = al->CreateRectangle2(box.x, box.y, box.w, box.h, ZERO_4PC);
+      txtbox->Add(s);
+    }
+    sr->AddRange(txtbox);
+  }
+
+  // 建立辅助的异性边界物件,需要填充颜色,搞了半天才搞定
   auto bounds = sr->CreateBoundary(0, 0, true, false); // 建立异性边界物件
   bounds->Fill->UniformColor->RGBAssign(255, 0, 0);    // 填充红色
-
   auto sbox = bounds->BreakApartEx(); // 把边界 拆分为多个边界 用来分组
 
+
+  // 删除文字添加的方框
+  if (sr_text->Count > 0) {
+    sr->RemoveRange(txtbox);
+    txtbox->Delete();
+  }
+
+  // 按照边界框异形范围进行分组群组
   auto srgp = cdr->CreateShapeRange();
 
   for (int k = 0; k < sbox->Count; k++) {
+    sbox->Shapes->Item[k + 1]->GET_BOUNDING_BOX(bound_box);
 
     for (int i = 0; i < sr->Count; i++) {
       auto sh = sr->Shapes->Item[i + 1];
-      sh->GET_BOUNDING_BOX(box);      // 获得物件矩形边界坐标
-      calculate_center(&box, &x, &y); // 获得物件中心坐标
+      sh->GET_BOUNDING_BOX(box);   // 获得物件矩形边界坐标
+      calculate_center(box, x, y); // 获得物件中心坐标
       OnSh = sbox->Shapes->Item[k + 1]->IsOnShape(x, y, -1);
 
       if (OnSh) {
         srgp->Add(sh);
-      } else if (isIntWith(cdr, sbox->Shapes->Item[k + 1], sh)) {
-        srgp->Add(sh);
+      } else if (isOverlapped(box, bound_box)) {
+        if (isIntWith(cdr, sbox->Shapes->Item[k + 1], sh))
+          srgp->Add(sh);
       }
     }
     // 从Range中移除已分组的图形
@@ -102,22 +119,46 @@ bool BoundaryGroup(corel *cdr, IVGShapeRange *sr, IVGShapeRange *srs) {
     srs->Add(srgp->Group());
     srgp->RemoveAll();
   }
+
+  // 删除辅助的异性边界物件
   sbox->Delete();
-  
   return true;
 }
 
 // 测试运行 异形群组
 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 - 12
09_BoundaryGroup/boxAutoGroup.cpp

@@ -1,17 +1,5 @@
 #include "cdrapp.h"
 
-#define GET_BOUNDING_BOX(box)                                                  \
-  GetBoundingBox(&(box).x, &(box).y, &(box).w, &(box).h, false)
-
-#define ZERO_4PC 0, 0, 0, 0
-
-typedef struct {
-  double x; // 左下角 x 坐标
-  double y; // 左下角 y 坐标
-  double w; // 宽度
-  double h; // 高度
-} BoundingBox;
-
 // 扩展边界框
 void expand_bounding_boxes(std::vector<BoundingBox>& boxes, double exp) {
     for (auto& box : boxes) {
@@ -202,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;
 }

+ 17 - 0
09_BoundaryGroup/cdrapp.h

@@ -19,6 +19,23 @@ bool BBox_DrawRectangle(corel *cdr, double exp = 0.0);
 
 void run_BoundaryGroup(corel *cdr);
 
+
+
 extern char infobuf[];
 
+#define GET_BOUNDING_BOX(box)                                                  \
+  GetBoundingBox(&(box).x, &(box).y, &(box).w, &(box).h, false)
+
+#define ZERO_4PC 0, 0, 0, 0
+ // 左下角坐标 x,y  w,h 宽高
+typedef struct {
+  double x;
+  double y; 
+  double w; 
+  double h; 
+} BoundingBox;
+
+bool isOverlapped(const BoundingBox &a, const BoundingBox &b);
+bool BoxGrouping(corel *cdr, IVGShapeRange *sr, IVGShapeRange *srs, double exp );
+
 #endif // CDRAPP_H_INCLUDED