تخصيص أشكال العرض التقديمي في C++

تغيير شكل باستخدام نقاط التحرير

تخيل مربعًا. في PowerPoint، باستخدام نقاط التحرير، يمكنك

  • نقل زاوية المربع إلى الداخل أو الخارج
  • تحديد الانحناء للزاوية أو النقطة
  • إضافة نقاط جديدة إلى المربع
  • التعامل مع النقاط على المربع، إلخ.

بشكل أساسي، يمكنك تنفيذ المهام الموضحة على أي شكل. باستخدام نقاط التحرير، يمكنك تغيير شكل أو إنشاء شكل جديد من شكل موجود.

نصائح تحرير الشكل

overview_image

قبل أن تبدأ في تحرير أشكال PowerPoint عبر نقاط التحرير، قد ترغب في النظر في هذه النقاط حول الأشكال:

  • يمكن أن يكون الشكل (أو مساره) مغلقًا أو مفتوحًا.
  • عندما يكون الشكل مغلقًا، لا يحتوي على نقطة بداية أو نهاية. عندما يكون الشكل مفتوحًا، يكون له بداية ونهاية.
  • تتكون جميع الأشكال من نقطتي تثبيت على الأقل مرتبطتين ببعضهما عبر خطوط
  • الخط إما مستقيم أو منحني. تحدد نقاط التثبيت طبيعة الخط.
  • نقاط التثبيت توجد ك نقاط زاوية، نقاط مستقيمة، أو نقاط ناعمة:
    • نقطة الزاوية هي نقطة يلتقي فيها خطان مستقيمان بزاوية.
    • نقطة ناعمة هي نقطة يكون فيها مقبضان في خط مستقيم وتلتقي أجزاء الخط بمنحنى ناعم. في هذه الحالة، يتم فصل جميع المقابض عن نقطة التثبيت بمسافة متساوية.
    • نقطة مستقيمة هي نقطة يكون فيها مقبضان في خط مستقيم وتلتقي أجزاء الخط بمنحنى ناعم. في هذه الحالة، لا يلزم أن تكون المقابض منفصلة عن نقطة التثبيت بمسافة متساوية.
  • عن طريق نقل أو تحرير نقاط التثبيت (التي تغير زاوية الخطوط)، يمكنك تغيير مظهر الشكل.

لتحرير أشكال PowerPoint عبر نقاط التحرير، توفر Aspose.Slides الفئة GeometryPath والواجهة IGeometryPath.

عمليات تحرير بسيطة

يظهر لك هذا الكود C++ كيفية

إضافة خط إلى نهاية المسار:

void LineTo(PointF point);
void LineTo(float x, float y);

إضافة خط إلى موقع محدد على المسار:

void LineTo(PointF point, uint32_t index);
void LineTo(float x, float y, uint32_t index);

إضافة منحنى بيزيه مكعب إلى نهاية المسار:

void CubicBezierTo(PointF point1, PointF point2, PointF point3);
void CubicBezierTo(float x1, float y1, float x2, float y2, float x3, float y3);

إضافة منحنى بيزيه مكعب إلى الموقع المحدد على المسار:

void CubicBezierTo(PointF point1, PointF point2, PointF point3, uint32_t index);
void CubicBezierTo(float x1, float y1, float x2, float y2, float x3, float y3, uint32_t index);

إضافة منحنى بيزيه رباعي إلى نهاية المسار:

void QuadraticBezierTo(PointF point1, PointF point2);
void QuadraticBezierTo(float x1, float y1, float x2, float y2);

إضافة منحنى بيزيه رباعي إلى موقع محدد على المسار:

void QuadraticBezierTo(PointF point1, PointF point2, uint32_t index);
void QuadraticBezierTo(float x1, float y1, float x2, float y2, uint32_t index);

إلحاق قوس محدد إلى مسار:

void ArcTo(float width, float heigth, float startAngle, float sweepAngle);

إغلاق الشكل الحالي للمسار:

void CloseFigure();

تحديد الموضع للنقطة التالية:

void MoveTo(PointF point);
void MoveTo(float x, float y);

إزالة جزء المسار عند فهرس معين:

void RemoveAt(int32_t index);

إضافة نقاط مخصصة إلى شكل

  1. إنشاء نسخة من فئة GeometryShape وتحديد النوع ShapeType.Rectangle.
  2. الحصول على نسخة من فئة GeometryPath من الشكل.
  3. إضافة نقطة جديدة بين النقطتين العلويتين على المسار.
  4. إضافة نقطة جديدة بين النقطتين السفليتين على المسار.
  5. تطبيق المسار على الشكل.

يظهر لك هذا الكود C++ كيفية إضافة نقاط مخصصة إلى شكل:

SharedPtr<Presentation> pres = System::MakeObject<Presentation>();

SharedPtr<IShapeCollection> shapes = pres->get_Slides()->idx_get(0)->get_Shapes();
SharedPtr<GeometryShape> shape = System::ExplicitCast<GeometryShape>(shapes->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, 200.0f, 100.0f));

SharedPtr<IGeometryPath> geometryPath = shape->GetGeometryPaths()->idx_get(0);

geometryPath->LineTo(100.0f, 50.0f, 1);
geometryPath->LineTo(100.0f, 50.0f, 4);
shape->SetGeometryPath(geometryPath);

example1_image

إزالة نقاط من شكل

  1. إنشاء نسخة من فئة GeometryShape وتحديد النوع ShapeType.Heart.
  2. الحصول على نسخة من فئة GeometryPath من الشكل.
  3. إزالة الجزء من المسار.
  4. تطبيق المسار على الشكل.

يظهر لك هذا الكود C++ كيفية إزالة نقاط من شكل:

SharedPtr<Presentation> pres = System::MakeObject<Presentation>();

SharedPtr<IShapeCollection> shapes = pres->get_Slides()->idx_get(0)->get_Shapes();
SharedPtr<GeometryShape> shape = System::ExplicitCast<GeometryShape>(shapes->AddAutoShape(ShapeType::Heart, 100.0f, 100.0f, 300.0f, 300.0f));

SharedPtr<IGeometryPath> path = shape->GetGeometryPaths()->idx_get(0);
path->RemoveAt(2);
shape->SetGeometryPath(path);

example2_image

إنشاء شكل مخصص

  1. احسب النقاط للشكل.
  2. إنشاء نسخة من فئة GeometryPath.
  3. املأ المسار بالنقاط.
  4. إنشاء نسخة من فئة GeometryShape.
  5. تطبيق المسار على الشكل.

يظهر لك هذا الكود C++ كيفية إنشاء شكل مخصص:

SharedPtr<List<PointF>> points = System::MakeObject<List<PointF>>();

float R = 100.0f, r = 50.0f;
int32_t step = 72;

for (int32_t angle = -90; angle < 270; angle += step)
{
    double radians = angle * (Math::PI / 180.f);
    double x = outerRadius * Math::Cos(radians);
    double y = outerRadius * Math::Sin(radians);
    points->Add(PointF((float)x + outerRadius, (float)y + outerRadius));

    radians = Math::PI * (angle + step / 2) / 180.0;
    x = innerRadiusr * Math::Cos(radians);
    y = innerRadiusr * Math::Sin(radians);
    points->Add(PointF((float)x + outerRadius, (float)y + outerRadius));
}

SharedPtr<GeometryPath> starPath = System::MakeObject<GeometryPath>();
starPath->MoveTo(points->idx_get(0));

for (int32_t i = 1; i < points->get_Count(); i++)
{
    starPath->LineTo(points->idx_get(i));
}

starPath->CloseFigure();

SharedPtr<Presentation> pres = System::MakeObject<Presentation>();

SharedPtr<IShapeCollection> shapes = pres->get_Slides()->idx_get(0)->get_Shapes();
SharedPtr<GeometryShape> shape = System::ExplicitCast<GeometryShape>(shapes->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, R * 2, R * 2));

shape->SetGeometryPath(starPath);

example3_image

إنشاء شكل مخصص مركب

  1. إنشاء نسخة من فئة GeometryShape.
  2. إنشاء النسخة الأولى من فئة GeometryPath.
  3. إنشاء النسخة الثانية من فئة GeometryPath.
  4. تطبيق المسارات على الشكل.

يظهر لك هذا الكود C++ كيفية إنشاء شكل مخصص مركب:

SharedPtr<Presentation> pres = System::MakeObject<Presentation>();

SharedPtr<IShapeCollection> shapes = pres->get_Slides()->idx_get(0)->get_Shapes();
SharedPtr<GeometryShape> shape = System::ExplicitCast<GeometryShape>(shapes->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, 200.0f, 100.0f));

SharedPtr<IGeometryPath> geometryPath0 = System::MakeObject<GeometryPath>();
geometryPath0->MoveTo(0.0f, 0.0f);
geometryPath0->LineTo(shape->get_Width(), 0.0f);
geometryPath0->LineTo(shape->get_Width(), shape->get_Height() / 3);
geometryPath0->LineTo(0.0f, shape->get_Height() / 3);
geometryPath0->CloseFigure();

SharedPtr<IGeometryPath> geometryPath1 = System::MakeObject<GeometryPath>();
geometryPath1->MoveTo(0.0f, shape->get_Height() / 3 * 2);
geometryPath1->LineTo(shape->get_Width(), shape->get_Height() / 3 * 2);
geometryPath1->LineTo(shape->get_Width(), shape->get_Height());
geometryPath1->LineTo(0.0f, shape->get_Height());
geometryPath1->CloseFigure();

shape->SetGeometryPaths(System::MakeArray<SharedPtr<IGeometryPath>>({ geometryPath0, geometryPath1 }));

example4_image

إنشاء شكل مخصص بزوايا منحنية

يظهر لك هذا الكود C++ كيفية إنشاء شكل مخصص بزوايا منحنية (للداخل);

float shapeX = 20.f;
float shapeY = 20.f;
float shapeWidth = 300.f;
float shapeHeight = 200.f;

float leftTopSize = 50.f;
float rightTopSize = 20.f;
float rightBottomSize = 40.f;
float leftBottomSize = 10.f;

auto presentation = System::MakeObject<Presentation>();

auto childShape = presentation->get_Slides()->idx_get(0)->get_Shapes()->AddAutoShape(ShapeType::Custom, shapeX, shapeY, shapeWidth, shapeHeight);

auto geometryPath = System::MakeObject<GeometryPath>();

PointF point1(leftTopSize, 0.0f);
PointF point2(shapeWidth - rightTopSize, 0.0f);
PointF point3(shapeWidth, shapeHeight - rightBottomSize);
PointF point4(leftBottomSize, shapeHeight);
PointF point5(0.0f, leftTopSize);

geometryPath->MoveTo(point1);
geometryPath->LineTo(point2);
geometryPath->ArcTo(rightTopSize, rightTopSize, 180.0f, -90.0f);
geometryPath->LineTo(point3);
geometryPath->ArcTo(rightBottomSize, rightBottomSize, -90.0f, -90.0f);
geometryPath->LineTo(point4);
geometryPath->ArcTo(leftBottomSize, leftBottomSize, 0.0f, -90.0f);
geometryPath->LineTo(point5);
geometryPath->ArcTo(leftTopSize, leftTopSize, 90.0f, -90.0f);

geometryPath->CloseFigure();

childShape->SetGeometryPath(geometryPath);

presentation->Save(u"output.pptx", SaveFormat::Pptx);

اكتشف ما إذا كان شكل الهندسة مغلقًا

يُعرّف الشكل المغلق بأنه الشكل الذي تتصل جميع جهاته لتكوّن حدًا واحدًا دون فراغات. يمكن أن يكون هذا الشكل شكلًا هندسيًا بسيطًا أو مخططًا مخصصًا معقدًا. يوضح المثال البرمجي التالي كيفية التحقق مما إذا كان شكل الهندسة مغلقًا:

bool IsGeometryClosed(SharedPtr<IGeometryShape> geometryShape)
{
    bool isClosed = false;

    for (auto&& geometryPath : geometryShape->GetGeometryPaths())
    {
        auto dataLength = geometryPath->get_PathData()->get_Length();
        if (dataLength == 0)
            continue;

        auto lastSegment = geometryPath->get_PathData()[dataLength - 1];
        isClosed = lastSegment->get_PathCommand() == PathCommandType::Close;

        if (!isClosed)
            return false;
    }

    return isClosed;
}

تحويل GeometryPath إلى GraphicsPath

  1. إنشاء نسخة من فئة GeometryShape.
  2. إنشاء نسخة من فئة GraphicsPath في مساحة الأسماء System.Drawing.Drawing2D.
  3. تحويل نسخة GraphicsPath إلى نسخة GeometryPath باستخدام ShapeUtil.
  4. تطبيق المسارات على الشكل.

هذا الكود C++—تنفيذ للخطوات أعلاه—يُظهر عملية التحويل من GeometryPath إلى GraphicsPath:

SharedPtr<Presentation> pres = System::MakeObject<Presentation>();

SharedPtr<IShapeCollection> shapes = pres->get_Slides()->idx_get(0)->get_Shapes();
SharedPtr<GeometryShape> shape = System::ExplicitCast<GeometryShape>(shapes->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, 300.0f, 100.0f));

SharedPtr<IGeometryPath> originalPath = shape->GetGeometryPaths()->idx_get(0);
originalPath->set_FillMode(PathFillModeType::None);

SharedPtr<Drawing2D::GraphicsPath> graphicsPath = System::MakeObject<Drawing2D::GraphicsPath>();
graphicsPath->AddString(u"Text in shape", System::MakeObject<FontFamily>(u"Arial"), 1, 40.0f, PointF(10.0f, 10.0f), StringFormat::get_GenericDefault());

SharedPtr<IGeometryPath> textPath = ShapeUtil::GraphicsPathToGeometryPath(graphicsPath);
textPath->set_FillMode(PathFillModeType::Normal);

shape->SetGeometryPaths(System::MakeArray<SharedPtr<IGeometryPath>>({ originalPath, textPath }));

example5_image

FAQ

ماذا سيحدث للملء والمخطط بعد استبدال الهندسة؟
تبقى الأنماط مع الشكل؛ يتغير الحد فقط. يتم تطبيق الملء والمخطط تلقائيًا على الهندسة الجديدة.

كيف أدوّر الشكل المخصص مع الهندسة بشكل صحيح؟
استخدم خاصية rotation لل形؛ تدور الهندسة مع الشكل لأنها مرتبطة بنظام إحداثيات الشكل نفسه.

هل يمكنني تحويل الشكل المخصص إلى صورة لتثبيت النتيجة؟
نعم. صدّر الشريحة المطلوبة slide أو shape نفسها إلى تنسيق نقطي؛ هذا يُبسّط العمل اللاحق مع الهندسات الثقيلة.