BoundaryGroup.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "cdrapp.h"
  2. #define GET_BOUNDING_BOX(box) \
  3. GetBoundingBox(&(box).x, &(box).y, &(box).w, &(box).h, false)
  4. #define ZERO_4PC 0, 0, 0, 0
  5. typedef struct {
  6. double x; // 左下角 x 坐标
  7. double y; // 左下角 y 坐标
  8. double w; // 宽度
  9. double h; // 高度
  10. } BoundingBox;
  11. bool isDPCurve(IVGShapePtr s) {
  12. auto dpc = (s->Type == cdrRectangleShape) || (s->Type == cdrEllipseShape) ||
  13. (s->Type == cdrCurveShape) || (s->Type == cdrPolygonShape) ||
  14. (s->Type == cdrBitmapShape);
  15. return dpc;
  16. }
  17. IVGShapePtr CreateBoundary(corel *cdr, IVGShapePtr s) {
  18. auto scp = s->CreateBoundary(0, 0, true, false);
  19. // 这个 API X7 以上才支持,所以现在直接画矩形
  20. // BoundingBox box;
  21. // s->GET_BOUNDING_BOX(box);
  22. // auto scp = cdr->ActiveLayer->CreateRectangle2(box.x, box.y, box.w, box.h,
  23. // ZERO_4PC);
  24. return scp;
  25. }
  26. // VGCore::IVGShapePtr VGCore::IVGShape::CreateBoundary ( double x, double y,
  27. // VARIANT_BOOL PlaceOnTop, VARIANT_BOOL DeleteSource ); VGCore::IVGShapePtr
  28. // VGCore::IVGShapeRange::CreateBoundary ( double x, double y, VARIANT_BOOL
  29. // PlaceOnTop, VARIANT_BOOL DeleteSource ); VARIANT_BOOL
  30. // VGCore::IVGCurve::IntersectsWith ( struct IVGCurve * Curve )
  31. bool isIntWith(corel *cdr, IVGShape *s1, IVGShape *s2) {
  32. bool isIn = false;
  33. if (isDPCurve(s1) && isDPCurve(s2)) {
  34. isIn = s1->GetDisplayCurve()->IntersectsWith(s2->GetDisplayCurve());
  35. } else if (isDPCurve(s1)) {
  36. // 群组文字和OLE等其他类型,创建一个临时边界范围
  37. auto scp = CreateBoundary(cdr, s2);
  38. isIn = s1->GetDisplayCurve()->IntersectsWith(scp->GetDisplayCurve());
  39. scp->Delete();
  40. } else if (isDPCurve(s2)) {
  41. auto scp = CreateBoundary(cdr, s1);
  42. isIn = scp->GetDisplayCurve()->IntersectsWith(s2->GetDisplayCurve());
  43. scp->Delete();
  44. } else {
  45. auto scp = CreateBoundary(cdr, s1);
  46. auto scp2 = CreateBoundary(cdr, s2);
  47. isIn = scp->GetDisplayCurve()->IntersectsWith(scp2->GetDisplayCurve());
  48. scp->Delete();
  49. scp2->Delete();
  50. }
  51. return isIn;
  52. }
  53. // 从矩形边界坐标 获得中心坐标
  54. void calculate_center(const BoundingBox *box, double *cx, double *cy) {
  55. *cx = box->x + (box->w / 2);
  56. *cy = box->y + (box->h / 2);
  57. }
  58. // VGCore::cdrPositionOfPointOverShape VGCore::IVGShape::IsOnShape ( double x,
  59. // double y, double HotArea ); VGCore::cdrPositionOfPointOverShape
  60. // VGCore::IVGCurve::IsOnCurve ( double x, double y, double HotArea );
  61. bool BoundaryGroup(corel *cdr, IVGShapeRange *sr, IVGShapeRange *srs) {
  62. if (sr->Count < 2)
  63. return false;
  64. BoundingBox box;
  65. double x, y;
  66. int OnSh = 0;
  67. auto bounds = sr->CreateBoundary(0, 0, true, false); // 建立异性边界物件
  68. bounds->Fill->UniformColor->RGBAssign(255, 0, 0); // 填充红色
  69. auto sbox = bounds->BreakApartEx(); // 把边界 拆分为多个边界 用来分组
  70. auto srgp = cdr->CreateShapeRange();
  71. for (int k = 0; k < sbox->Count; k++) {
  72. for (int i = 0; i < sr->Count; i++) {
  73. auto sh = sr->Shapes->Item[i + 1];
  74. sh->GET_BOUNDING_BOX(box); // 获得物件矩形边界坐标
  75. calculate_center(&box, &x, &y); // 获得物件中心坐标
  76. OnSh = sbox->Shapes->Item[k + 1]->IsOnShape(x, y, -1);
  77. if (OnSh) {
  78. srgp->Add(sh);
  79. } else if (isIntWith(cdr, sbox->Shapes->Item[k + 1], sh)) {
  80. srgp->Add(sh);
  81. }
  82. }
  83. // 从Range中移除已分组的图形
  84. sr->RemoveRange(srgp);
  85. srs->Add(srgp->Group());
  86. srgp->RemoveAll();
  87. }
  88. sbox->Delete();
  89. return true;
  90. }
  91. // 测试运行 异形群组
  92. void run_BoundaryGroup(corel *cdr) {
  93. auto start = std::chrono::high_resolution_clock::now(); // 开始时间
  94. BeginOpt(cdr);
  95. auto sr = cdr->ActiveSelectionRange;
  96. auto srs = cdr->CreateShapeRange();
  97. int cnt = sr->Count;
  98. cdr->ActiveDocument->ClearSelection();
  99. BoundaryGroup(cdr, sr, srs);
  100. srs->CreateSelection();
  101. // 计算持续时间
  102. double runtime = 0.0;
  103. auto end = std::chrono::high_resolution_clock::now();
  104. std::chrono::duration<double> duration = end - start;
  105. runtime = duration.count();
  106. sprintf(infobuf, "选择物件: %d 个进行异形群组\n群组: %d 组, 时间: %.2f秒",
  107. cnt, srs->Count, runtime);
  108. EndOpt(cdr);
  109. }