I am using C++ to write a CPG plugin,when using ShapeRange.Group in CorelDRAW to group 2,000 objects, it takes 30 seconds.

I am using C++ to write a CPG plugin. There are tens of thousands of overlapping objects that need to be grouped. The C++ algorithm runs very quickly, in less than 0.25 seconds. However, when using ShapeRange.Group in CorelDRAW to group 2,000 objects, it takes 30 seconds. How can I solve the software bottleneck?

  • Not sure how to implement it but with macros this code speeds things up greatly

    Somewhere in the beginning

    Optimization = True

        whatever code here
        then

    Optimization=False: Refresh

    • void BeginOpt(corel *cdr)

      {

        auto name = _bstr_t("Undo");

        cdr->EventsEnabled = false;

        cdr->ActiveDocument->BeginCommandGroup(name);

        cdr->ActiveDocument->Unit = cdrMillimeter;

        cdr->Optimization = true;

      }

      void EndOpt(corel *cdr)

      {

        cdr->EventsEnabled = true;

        cdr->Optimization = false;

        cdr->EventsEnabled = true;

        cdr->ActiveDocument->ReferencePoint = cdrBottomLeft;

        cdr->Application->Refresh();

        cdr->ActiveDocument->EndCommandGroup();

      }

      I have already used window refresh optimization and called the above optimization function. The current bottleneck is the 2,000 times execution of the ShapeRange.Group traversal, which is causing CorelDRAW to hang. Is it possible to solve this problem through multi-threading or by calling similar APIs through the SDK?

    • Also you can use ActiveDocument.BeginCommandGroup

      your routine

      ActiveDocument.EndCommandGroup

      • Using multi-threading to call ShapeRange.Group() in batches. The good result is that the program does not crash. The bad result is that it did not improve the speed.

        •   // Output the grouping results
            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 number starts from 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)  {    
                  srgp->GET_BOUNDING_BOX(box);
                  // al->CreateRectangle2(box.x, box.y, box.w, box.h, ZERO_4PC); // Create a rectangle using the bounding box
                  // Convert the bounding box to top-left and bottom-right coordinates: box.x, box.y + box.h, box.x + box.w, box.y
                  auto sh = cdr->ActivePage->SelectShapesFromRectangle(box.x, box.y + box.h, box.x + box.w, box.y, false);
                  sh->Group();

                  // srgp->Group();  // Grouping the selected shapes is actually 10 times faster than using ShapeRange->Group() directly
                  }
                srgp->RemoveAll();
            }

          // =================================

          My algorithm hasn't changed, I just took a detour. Previously, I would group the shapes in one step using srgp.Group().

          Now, I first get the bounding box of the srgp, then use the bounding box to select the shapes, and then group them.

          However, I'm not sure why ShapeRange->Group() is so slow. It could be a bug in CorelDRAW.