123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- #include "cdrapp.h"
- #include <cerrno>
- #include <cmath>
- #include <cstddef>
- bool isDPCurve(IVGShapePtr s) {
- auto dpc = (s->Type == cdrRectangleShape) || (s->Type == cdrEllipseShape) ||
- (s->Type == cdrCurveShape) || (s->Type == cdrPolygonShape) ||
- (s->Type == cdrBitmapShape);
- return dpc;
- }
- IVGShapePtr CreateBoundary(corel *cdr, IVGShapePtr s) {
- IVGShapePtr scp;
- if (cdr->VersionMajor < 17) {
- // s->CreateSelection();
- // cdr->FrameWork->Automation->InvokeItem( _bstr_t("b0491566-5ffe-450a-b17e-f2f496b4eb22"));
- // scp = cdr->ActiveSelectionRange->Shapes->Item[1];
- BoundingBox box;
- s->GET_BOUNDING_BOX(box);
- scp = cdr->ActiveLayer->CreateRectangle2(box.x, box.y, box.w, box.h, ZERO_4PC);
- } else {
- // 这个 API X7 以上才支持,所以现在直接画矩形
- scp = s->CreateBoundary(0, 0, true, false);
- }
- return scp;
- }
- // VGCore::IVGShapePtr VGCore::IVGShape::CreateBoundary ( double x, double y, VARIANT_BOOL PlaceOnTop, VARIANT_BOOL DeleteSource ); VGCore::IVGShapePtr
- // VGCore::IVGShapeRange::CreateBoundary ( double x, double y, VARIANT_BOOL PlaceOnTop, VARIANT_BOOL DeleteSource );
- // VARIANT_BOOL VGCore::IVGCurve::IntersectsWith ( struct IVGCurve * Curve )
- bool isIntWith(corel *cdr, IVGShape *s1, IVGShape *s2) {
- bool isIn = false;
- if (isDPCurve(s1) && isDPCurve(s2)) {
- isIn = s1->GetDisplayCurve()->IntersectsWith(s2->GetDisplayCurve());
- } else if (isDPCurve(s1)) {
- // 群组文字和OLE等其他类型,创建一个临时边界范围
- auto scp = CreateBoundary(cdr, s2);
- isIn = s1->GetDisplayCurve()->IntersectsWith(scp->GetDisplayCurve());
- scp->Delete();
- } else if (isDPCurve(s2)) {
- auto scp = CreateBoundary(cdr, s1);
- isIn = scp->GetDisplayCurve()->IntersectsWith(s2->GetDisplayCurve());
- scp->Delete();
- } else {
- auto scp = CreateBoundary(cdr, s1);
- auto scp2 = CreateBoundary(cdr, s2);
- isIn = scp->GetDisplayCurve()->IntersectsWith(scp2->GetDisplayCurve());
- scp->Delete();
- scp2->Delete();
- }
- return isIn;
- }
- // 从矩形边界坐标 获得中心坐标
- 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, double y, double HotArea );
- // VGCore::cdrPositionOfPointOverShape VGCore::IVGCurve::IsOnCurve ( double x, double y, double HotArea );
- bool BoundaryGroup(corel *cdr, IVGShapeRange *sr, IVGShapeRange *srs) {
- if (sr->Count < 2)
- return false;
- BoundingBox box, bound_box;
- double x, y;
- int OnSh = 0;
- auto red = cdr->CreateCMYKColor(0, 100, 100, 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 stmp = sr->CreateBoundary(0, 0, true, false); // 建立异性边界物件
- // auto ef1 = stmp->CreateContour(
- // cdrContourOutside, 0.2, 1, cdrDirectFountainFillBlend, red, NULL, NULL, 0,
- // 0, cdrContourSquareCap, cdrContourCornerMiteredOffsetBevel, 15);
- // auto bounds = ef1->Separate();
- // stmp->Delete();
- // // bounds->SetOutlineProperties(0.076, NULL, cdr->CreateCMYKColor(100, 50, 0,
- // // 0), NULL, NULL, cdrUndefined, cdrUndefined, cdrOutlineUndefinedLineCaps,
- // // cdrOutlineUndefinedLineJoin, NULL, NULL, NULL, NULL, NULL);
- // auto sbox = bounds->BreakApartEx();
- // sbox->ApplyUniformFill(red);
- // 建立辅助的异性边界物件,需要填充颜色,搞了半天才搞定
- IVGShapePtr bounds;
- if (cdr->VersionMajor < 17) {
- sr->CreateSelection();
- cdr->FrameWork->Automation->InvokeItem( _bstr_t("b0491566-5ffe-450a-b17e-f2f496b4eb22"));
- bounds = cdr->ActiveSelectionRange->Shapes->Item[1];
- bounds->OrderToFront();
- } else {
- bounds = sr->CreateBoundary(0, 0, true, false); // 建立异性边界物件
- }
- bounds->Fill->UniformColor->RGBAssign(255, 0, 0);
- auto sbox = bounds->BreakApartEx(); // 把边界 拆分为多个边界 用来分组
- if (sbox->Count > 2) {
- // VGCore::IVGShapeRange::Sort ( _bstr_t CompareExpression, long
- // StartIndex, long EndIndex, const _variant_t & Data );
- sbox->Sort(bstr_t( "@shape1.width * @shape1.height > @shape2.width * @shape2.height"), 1, sbox->Count, _variant_t());
- }
- // 删除文字添加的方框
- if (sr_text->Count > 0) {
- sr->RemoveRange(txtbox);
- txtbox->Delete();
- }
- // 按照边界框异形范围进行分组群组
- auto srgp = cdr->CreateShapeRange();
- for (int k = 0; k < sbox->Count && sr->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); // 获得物件中心坐标
- OnSh = sbox->Shapes->Item[k + 1]->IsOnShape(x, y, -1);
- if (OnSh) {
- srgp->Add(sh);
- } else if (isOverlapped(box, bound_box)) {
- if (isIntWith(cdr, sbox->Shapes->Item[k + 1], sh))
- srgp->Add(sh);
- }
- }
- // 从Range中移除已分组的图形
- sr->RemoveRange(srgp);
- if (srgp->Count > 1) {
- srs->Add(srgp->Group());
- } else {
- srs->AddRange(srgp);
- }
- srgp->RemoveAll();
- }
- // 删除辅助的异性边界物件
- if(!debug_flg)
- 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();
- if (cnt > 300) {
- // 调用矩形分组,分步执行异形群组
- if (BoxGrouping(cdr, sr, sr_box, 0.1)) {
- 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();
- // 计算持续时间
- double runtime = 0.0;
- auto end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double> duration = end - start;
- runtime = duration.count();
- // sprintf(infobuf, "选择物件: %d 个进行异形群组\n群组: %d 组, 时间: %.2f秒", cnt, srs->Count, runtime);
- sprintf(infobuf, "Selected objects: %d, Grouping time: %.2f seconds\nTotal groups: %d, Total time: %.2f seconds", cnt, srs->Count, runtime);
- EndOpt(cdr);
- }
|