Sesuaikan Bentuk Presentasi di C++
Gambaran Umum
Artikel ini menjelaskan cara menyesuaikan bentuk presentasi di Aspose.Slides dengan mengedit geometri bentuk melalui titik edit dan jalur geometri. Artikel ini menunjukkan cara bekerja dengan GeometryPath dan IGeometryPath untuk memodifikasi bentuk yang ada, melakukan operasi edit jalur dasar, menambah atau menghapus titik, dan menerapkan geometri yang diperbarui kembali ke sebuah bentuk.
Artikel ini juga mendemonstrasikan cara membuat bentuk khusus dan komposit, membangun bentuk dengan sudut melengkung, serta menentukan apakah geometri sebuah bentuk tertutup.
Mengubah Bentuk dengan Titik Edit
Di PowerPoint, Anda dapat menggunakan Edit Points untuk memodifikasi sebuah kotak:
- Memindahkan sudut ke dalam atau ke luar.
- Menyesuaikan kelengkungan pada suatu titik.
- Menambahkan titik baru.
Mengedit titik memungkinkan Anda mengubah kontur sebuah bentuk atau menggunakan bentuk yang ada sebagai dasar untuk bentuk baru.
Tips Mengedit Bentuk

Saat mengedit bentuk PowerPoint, perhatikan konsep berikut:
- Sebuah bentuk (atau jalurnya) dapat berupa tertutup atau terbuka.
- Jalur bentuk terdiri dari titik jangkar yang dihubungkan oleh segmen.
- Sebuah segmen dapat lurus atau melengkung. Titik jangkar dan pegangan kontrol menentukan bentuknya.
- Titik jangkar dapat berupa titik sudut, titik lurus, atau titik halus:
- Pada titik sudut, segmen yang bersebelahan dapat bertemu pada suatu sudut.
- Pada titik halus, dua pegangan kontrol berada pada satu garis dan berjarak sama dari titik jangkar.
- Pada titik lurus, dua pegangan kontrol berada pada satu garis tetapi dapat memiliki jarak yang berbeda dari titik jangkar.
- Memindahkan titik jangkar atau menyesuaikan pegangannya mengubah kontur bentuk.
Untuk mengedit bentuk PowerPoint melalui titik edit, Aspose.Slides menyediakan kelas GeometryPath dan antarmuka IGeometryPath.
- Sebuah instance GeometryPath mewakili jalur geometri dari objek IGeometryShape.
- Untuk mengambil GeometryPath dari instance IGeometryShape, Anda dapat menggunakan metode IGeometryShape::GetGeometryPaths.
- Untuk menetapkan GeometryPath pada sebuah bentuk, Anda dapat menggunakan metode ini: IGeometryShape::SetGeometryPath untuk bentuk dengan satu jalur dan IGeometryShape::SetGeometryPaths untuk bentuk dengan banyak jalur.
- Untuk menambah segmen, Anda dapat menggunakan metode‑metode di bawah IGeometryPath.
- Dengan metode IGeometryPath::set_Stroke dan IGeometryPath::set_FillMode, Anda dapat mengatur tampilan jalur geometri.
- Dengan metode IGeometryPath::get_PathData, Anda dapat mengambil jalur geometri dari sebuah GeometryShape sebagai array segmen jalur.
Operasi Penyuntingan Sederhana
Gunakan metode berikut untuk menyunting sebuah jalur geometri. Overload yang menerima indeks menyisipkan segmen pada posisi nol‑based tersebut dalam array segmen jalur.
| Operasi | Metode |
|---|---|
| Menambahkan atau menyisipkan garis lurus. | GeometryPath::LineTo |
| Menambahkan atau menyisipkan kurva Bézier kubik dengan dua titik kontrol dan satu titik akhir. | GeometryPath::CubicBezierTo |
| Menambahkan atau menyisipkan kurva Bézier kuadratik dengan satu titik kontrol dan satu titik akhir. | GeometryPath::QuadraticBezierTo |
| Menambahkan busur elips dengan dimensi dan sudut yang ditentukan dalam derajat. | GeometryPath::ArcTo |
| Menutup gambar saat ini dengan menghubungkan titik akhir ke titik awal. | GeometryPath::CloseFigure |
| Menetapkan titik awal sebuah gambar. | GeometryPath::MoveTo |
| Menghapus segmen pada indeks nol‑based. | GeometryPath::RemoveAt |
Menambahkan Titik Khusus ke Bentuk
Contoh ini menyisipkan dua titik ke dalam bentuk persegi panjang menggunakan GeometryPath::LineTo dan menerapkan jalur yang telah diedit dengan IGeometryShape::SetGeometryPath. Koordinat tersebut bersifat lokal terhadap bentuk: kedua titik baru berada di tengahnya, 100 poin dari kiri dan 50 poin dari atas. Indeks segmen 1 dan 4 menempatkannya pada tepi atas dan bawah, menarik tepi‑tepi tersebut ke dalam.
#include <DOM/IAutoShape.h>
#include <DOM/IGeometryPath.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, 200.0f, 100.0f);
auto geometryPath = shape->GetGeometryPaths()->idx_get(0);
geometryPath->LineTo(100.0f, 50.0f, 1);
geometryPath->LineTo(100.0f, 50.0f, 4);
shape->SetGeometryPath(geometryPath);

Menghapus Titik dari Bentuk
Contoh ini mengubah kontur bentuk hati dengan menghapus segmen pada indeks nol‑based 2 menggunakan GeometryPath::RemoveAt. Menerapkan jalur yang dimodifikasi dengan IGeometryShape::SetGeometryPath memperbarui kontur bentuk.
#include <DOM/IAutoShape.h>
#include <DOM/IGeometryPath.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Heart, 100.0f, 100.0f, 300.0f, 300.0f);
auto path = shape->GetGeometryPaths()->idx_get(0);
path->RemoveAt(2);
shape->SetGeometryPath(path);

Membuat Bentuk Khusus
Contoh ini membangun bintang lima sudut dengan GeometryPath. Jari‑jari luar dan dalam yang bergantian sebesar 100 dan 50 poin menentukan ujung‑ujung dan lekukan; langkah 72 derajat menempatkan kelima ujung secara merata. Jalur ditutup dengan GeometryPath::CloseFigure dan diterapkan ke bentuk persegi panjang menggunakan IGeometryShape::SetGeometryPath, menggantikan kontur aslinya.
#include <DOM/GeometryPath.h>
#include <DOM/IAutoShape.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <drawing/point_f.h>
#include <system/collections/list.h>
#include <system/math.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Drawing;
auto points = System::MakeObject<List<PointF>>();
auto outerRadius = 100.0f;
auto innerRadius = 50.0f;
auto angleStep = 72;
for (auto angle = -90; angle < 270; angle += angleStep)
{
auto radians = angle * (Math::PI / 180.f);
auto x = outerRadius * Math::Cos(radians);
auto y = outerRadius * Math::Sin(radians);
points->Add(PointF((float)x + outerRadius, (float)y + outerRadius));
radians = Math::PI * (angle + angleStep / 2) / 180.0;
x = innerRadius * Math::Cos(radians);
y = innerRadius * Math::Sin(radians);
points->Add(PointF((float)x + outerRadius, (float)y + outerRadius));
}
auto starPath = System::MakeObject<GeometryPath>();
starPath->MoveTo(points->idx_get(0));
for (auto i = 1; i < points->get_Count(); i++)
{
starPath->LineTo(points->idx_get(i));
}
starPath->CloseFigure();
auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, outerRadius * 2, outerRadius * 2);
shape->SetGeometryPath(starPath);

Membuat Bentuk Khusus Komposit
Contoh ini mendefinisikan dua GeometryPath tertutup untuk sepertiga atas dan bawah sebuah bentuk. Menerapkan kedua jalur dengan IGeometryShape::SetGeometryPaths menciptakan satu bentuk komposit dengan celah pada sepertiga tengahnya.
#include <DOM/GeometryPath.h>
#include <DOM/IAutoShape.h>
#include <DOM/IGeometryPath.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 100.0f, 100.0f, 200.0f, 100.0f);
auto topPath = System::MakeObject<GeometryPath>();
topPath->MoveTo(0.0f, 0.0f);
topPath->LineTo(shape->get_Width(), 0.0f);
topPath->LineTo(shape->get_Width(), shape->get_Height() / 3);
topPath->LineTo(0.0f, shape->get_Height() / 3);
topPath->CloseFigure();
auto bottomPath = System::MakeObject<GeometryPath>();
bottomPath->MoveTo(0.0f, shape->get_Height() / 3 * 2);
bottomPath->LineTo(shape->get_Width(), shape->get_Height() / 3 * 2);
bottomPath->LineTo(shape->get_Width(), shape->get_Height());
bottomPath->LineTo(0.0f, shape->get_Height());
bottomPath->CloseFigure();
auto paths = System::MakeArray<SharedPtr<IGeometryPath>>({ topPath, bottomPath });
shape->SetGeometryPaths(paths);

Membuat Bentuk Khusus dengan Sudut Melengkung
Contoh ini menggabungkan segmen lurus dengan GeometryPath::ArcTo untuk membuat bentuk dengan sudut melengkung ke dalam. Setiap ukuran sudut menentukan lebar dan tinggi busur dalam poin, dan putaran –90 derajat menggambar seperempat elips berlawanan arah jarum jam. Jalur selesai diterapkan dengan IGeometryShape::SetGeometryPath, dan presentasi disimpan dalam format PPTX.
#include <DOM/GeometryPath.h>
#include <DOM/IAutoShape.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideCollection.h>
#include <DOM/Presentation.h>
#include <DOM/ShapeType.h>
#include <Export/SaveFormat.h>
#include <drawing/point_f.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System::Drawing;
auto shapeX = 20.f;
auto shapeY = 20.f;
auto shapeWidth = 300.f;
auto shapeHeight = 200.f;
auto leftTopSize = 50.f;
auto rightTopSize = 20.f;
auto rightBottomSize = 40.f;
auto leftBottomSize = 10.f;
auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Custom, shapeX, shapeY, shapeWidth, shapeHeight);
auto topLeft = PointF(leftTopSize, 0.0f);
auto topRight = PointF(shapeWidth - rightTopSize, 0.0f);
auto rightBottom = PointF(shapeWidth, shapeHeight - rightBottomSize);
auto bottomLeft = PointF(leftBottomSize, shapeHeight);
auto leftTop = PointF(0.0f, leftTopSize);
auto geometryPath = System::MakeObject<GeometryPath>();
geometryPath->MoveTo(topLeft);
geometryPath->LineTo(topRight);
geometryPath->ArcTo(rightTopSize, rightTopSize, 180.0f, -90.0f);
geometryPath->LineTo(rightBottom);
geometryPath->ArcTo(rightBottomSize, rightBottomSize, -90.0f, -90.0f);
geometryPath->LineTo(bottomLeft);
geometryPath->ArcTo(leftBottomSize, leftBottomSize, 0.0f, -90.0f);
geometryPath->LineTo(leftTop);
geometryPath->ArcTo(leftTopSize, leftTopSize, 90.0f, -90.0f);
geometryPath->CloseFigure();
shape->SetGeometryPath(geometryPath);
presentation->Save(u"output.pptx", SaveFormat::Pptx);
Menentukan Apakah Geometri Bentuk Tertutup
Pembantu berikut memeriksa apakah setiap jalur geometri yang tidak kosong berakhir dengan segmen penutup. Ia membaca IGeometryPath::get_PathData dan membandingkan perintah segmen terakhir IPathSegment::get_PathCommand dengan PathCommandType::Close. Ia mengembalikan false bila tidak ada jalur yang tidak kosong. Pemeriksaan ini melihat perintah akhir tiap jalur; ia tidak memeriksa setiap sub‑gambar di dalam jalur. Contoh mencetak True untuk sebuah persegi panjang.
#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IAutoShape.h>
#include <DOM/IGeometryShape.h>
#include <DOM/IGeometryPath.h>
#include <DOM/ShapeType.h>
#include <system/array.h>
#include <system/smart_ptr.h>
#include <system/console.h>
#include <DOM/IPathSegment.h>
#include <DOM/PathCommandType.h>
using namespace Aspose::Slides;
using namespace System;
auto isGeometryClosed = [](SharedPtr<IGeometryShape> geometryShape)
{
auto hasNonemptyPath = false;
for (auto&& geometryPath : geometryShape->GetGeometryPaths())
{
auto segments = geometryPath->get_PathData();
if (segments->get_Length() == 0)
{
continue;
}
hasNonemptyPath = true;
auto lastSegment = segments->idx_get(segments->get_Length() - 1);
if (lastSegment->get_PathCommand() != PathCommandType::Close)
{
return false;
}
}
return hasNonemptyPath;
};
auto presentation = MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shapes()->AddAutoShape(ShapeType::Rectangle, 100, 100, 200, 100);
Console::WriteLine(isGeometryClosed(shape));
Mengekstrak dan Memeriksa Elemen Bentuk
Gunakan IGeometryShape::CreateShapeElements untuk memeriksa bentuk yang ada sebagai elemen‑elemen yang berisi titik‑titik jalur dan tipe‑tipe titik. Cast setiap IShapeElement yang dikembalikan ke ShapeElement untuk membaca array yang dikembalikan oleh get_PathPoints dan get_PathTypes. Representasi ini berguna untuk analisis kontur atau untuk mengirim geometri ke alat‑alat menggambar khusus.
Contoh membuka sebuah presentasi, menemukan bentuk geometri pertama pada slide pertama, dan mencetak segmen‑segmen jalurnya. Gunakan presentasi yang berisi bentuk dengan segmen lurus dan melengkung untuk melihat kedua jenis output. Tidak dilakukan pencarian di dalam grup.
#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IAutoShape.h>
#include <DOM/IGeometryShape.h>
#include <DOM/IGeometryPath.h>
#include <DOM/ShapeType.h>
#include <system/array.h>
#include <system/smart_ptr.h>
#include <system/console.h>
#include <DOM/IShapeElement.h>
#include <DOM/ShapeElement.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = MakeObject<Presentation>(u"input.pptx");
auto slide = presentation->get_Slide(0);
SharedPtr<IGeometryShape> shape;
for (auto&& candidate : slide->get_Shapes())
{
shape = AsCast<IGeometryShape>(candidate);
if (shape != nullptr)
{
break;
}
}
if (shape == nullptr)
{
Console::WriteLine(u"No geometry shape found on the first slide.");
return;
}
for (auto&& element : shape->CreateShapeElements())
{
auto shapeElement = ExplicitCast<ShapeElement>(element);
auto points = shapeElement->get_PathPoints();
auto types = shapeElement->get_PathTypes();
Console::WriteLine(u"Shape element:");
for (auto i = 0; i < points->get_Length(); i++)
{
auto pointType = types[i] & 0x07; // Pertahankan tipe segmen, kecuali flag.
switch (pointType)
{
case 0:
Console::WriteLine(u"Start figure at {0}", points[i]);
break;
case 1:
Console::WriteLine(u"Line to {0}", points[i]);
break;
case 3:
Console::WriteLine(u"Cubic Bezier: controls {0}, {1}; end {2}", points[i], points[i + 1], points[i + 2]);
i += 2; // Gunakan kedua titik kontrol dan titik akhir.
break;
}
if ((types[i] & 0x80) != 0)
{
Console::WriteLine(u"Close subpath back to its starting point.");
}
}
}
Array‑array tersebut bersesuaian berdasarkan indeks: points[i] adalah sebuah titik dan types[i] menjelaskan perannya. Tipe 0 memulai sebuah gambar, dan tipe 1 menggambar garis dari titik sebelumnya ke titik saat ini. Sebuah segmen Bézier kubik dimulai dari titik akhir sebelumnya dan menggunakan tiga entri tipe‑3 berurutan: dua titik kontrol diikuti oleh titik akhir baru. Loop mengkonsumsi ketiga entri tersebut sekaligus dan memeriksa titik akhir untuk menutup.
Tipe titik juga mengandung flag. Mask dengan 0x07 untuk mengidentifikasi tipe segmen, dan uji 0x80 secara terpisah untuk mendeteksi sub‑path tertutup. Misalnya, 129 (0x81) berarti titik akhir garis yang menutup sub‑path, dan 131 (0x83) berarti titik akhir Bézier yang menutup satu sub‑path. Membandingkan nilai mentah hanya dengan 1 atau 3 akan melewatkan kasus‑kasus ini. Flag lain, seperti dash (0x10) dan marker (0x20), tidak mengubah tipe segmen dasar.
Koordinat dan transformasi. Titik diukur dalam poin (1/72 inci), dengan X meningkat ke kanan dan Y meningkat ke bawah. Untuk bentuk yang tidak berada dalam grup, koordinat yang diekstrak sudah mencakup posisi yang dikembalikan oleh get_X dan get_Y serta mencerminkan lebar dan tinggi saat ini. Misalnya, persegi panjang tidak berotasi pada (100, 200) dengan ukuran 120 × 80 memiliki batas kontur (100, 200)–(220, 280). Jangan menambahkan posisi bentuk lagi. Kurangi X dan Y‑nya untuk memperoleh koordinat relatif terhadap bingkai yang tidak berotasi.
Titik‑titik yang diekstrak tidak menerapkan rotasi yang diatur melalui set_Rotation atau pembalikan horizontal dan vertikal. Untuk mereproduksi kontur yang ditampilkan, terapkan transformasi tersebut di sekitar pusat bentuk. Untuk bentuk yang berada dalam grup, juga perhitungkan pemetaan koordinat grup serta transformasinya; jangan menganggap bahwa titik‑titik yang diekstrak adalah koordinat akhir slide yang dirender atau menerapkan translasi atau skala dua kali jika sudah tercermin dalam bingkai anak.
Pemeriksaan vs penyuntingan. Array yang diekstrak menggambarkan kontur; mengubahnya tidak memperbarui bentuk asli. Pilih pendekatan ini ketika analisis atau kode menggambar Anda membutuhkan array titik/tipe. Gunakan GetGeometryPaths bila Anda memerlukan perintah geometri dalam sistem koordinat lokal bentuk atau ingin menyunting geometri tersebut. Terapkan jalur yang telah diedit melalui SetGeometryPath atau SetGeometryPaths.
Mengonversi GeometryPath ke GraphicsPath
API publik Aspose.Slides untuk C++ saat ini tidak menyediakan konversi antara jalur geometri dan jalur grafis. Untuk memeriksa kontur, gunakan elemen bentuk seperti dijelaskan di atas. Untuk menyunting bentuk, gunakan jalur geometri dan terapkan jalur yang diperbarui ke bentuk.
FAQ
Apa yang terjadi pada isi dan kontur setelah mengganti geometri?
Gaya tetap melekat pada bentuk; hanya konturnya yang berubah. Isi dan kontur secara otomatis diterapkan ke geometri baru.
Bagaimana cara memutar bentuk khusus bersamaan dengan geometri secara benar?
Gunakan metode set_Rotation pada bentuk; geometri berotasi bersama bentuk karena terikat pada sistem koordinat bentuk itu sendiri.
Bisakah saya mengonversi bentuk khusus menjadi gambar untuk “mengunci” hasilnya?
Ya. Ekspor area slide yang diperlukan atau shape itu sendiri ke format raster; hal ini menyederhanakan pekerjaan lanjutan dengan geometri yang kompleks.