BoundaryGroup.cpp 4.7 KB

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