Sesuaikan Bentuk Presentasi di Python melalui Java
Ikhtisar
Artikel ini menjelaskan cara menyesuaikan bentuk presentasi di Aspose.Slides dengan mengedit geometri bentuk melalui titik edit dan jalur geometri. Artikel ini menunjukkan cara menggunakan GeometryPath untuk memodifikasi bentuk yang ada, melakukan operasi penyuntingan jalur dasar, menambahkan atau menghapus titik, dan menerapkan geometri yang diperbarui kembali ke sebuah bentuk.
Artikel ini juga mendemonstrasikan cara membuat bentuk kustom dan komposit, membangun bentuk dengan sudut melengkung, menentukan apakah geometri bentuk tertutup, memeriksa elemen bentuk, dan mengonversi outline teks Java AWT menjadi jalur geometri.
Ubah Bentuk Menggunakan Titik Edit
Di PowerPoint, Anda dapat menggunakan Edit Points untuk memodifikasi sebuah persegi:
- Memindahkan sudut ke dalam atau ke luar.
- Menyesuaikan kelengkungan pada sebuah titik.
- Menambahkan titik baru.
Menyunting titik memungkinkan Anda mengubah kontur bentuk atau menggunakan bentuk yang ada sebagai dasar untuk bentuk baru.
Tips Penyuntingan Bentuk

Ketika menyunting bentuk PowerPoint, ingat 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 dengan sudut.
- Pada titik halus, dua pegangan kontrol sejajar dan berjarak sama dari titik jangkar.
- Pada titik lurus, dua pegangan kontrol sejajar tetapi dapat memiliki jarak berbeda dari titik jangkar.
- Memindahkan titik jangkar atau menyesuaikan pegangan mengubah kontur bentuk.
Untuk menyunting bentuk PowerPoint melalui titik edit, Aspose.Slides menyediakan kelas GeometryPath.
- Sebuah instance GeometryPath mewakili jalur geometri objek GeometryShape.
- Untuk mengambil GeometryPath dari instance GeometryShape, Anda dapat menggunakan metode GeometryShape.getGeometryPaths.
- Untuk menetapkan GeometryPath ke sebuah bentuk, Anda dapat menggunakan metode ini: GeometryShape.setGeometryPath untuk bentuk dengan satu jalur dan GeometryShape.setGeometryPaths untuk bentuk dengan beberapa jalur.
- Untuk menambahkan segmen, Anda dapat menggunakan metode di bawah GeometryPath.
- Dengan menggunakan metode GeometryPath.setStroke dan GeometryPath.setFillMode, Anda dapat mengatur tampilan sebuah jalur geometri.
- Dengan menggunakan metode GeometryPath.getPathData, Anda dapat mengambil jalur geometri sebuah GeometryShape sebagai array segmen jalur.
- Untuk mengakses opsi kustomisasi geometri bentuk tambahan, Anda dapat membaca sebuah java.awt.Shape melalui PathIterator‑nya dan memutar ulang segmen‑segmen pada sebuah GeometryPath.
Operasi Penyuntingan Sederhana
Gunakan metode berikut untuk menyunting sebuah jalur geometri. Overload yang menerima indeks menyisipkan segmen pada posisi berbasis nol 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 figur saat ini dengan menghubungkan titik akhirnya ke titik awalnya. | GeometryPath.closeFigure |
| Menetapkan titik awal sebuah figur. | GeometryPath.moveTo |
| Menghapus sebuah segmen pada indeks berbasis nol. | GeometryPath.removeAt |
Tambahkan Titik Kustom ke Sebuah Bentuk
Contoh ini menyisipkan dua titik ke dalam sebuah bentuk persegi panjang menggunakan GeometryPath.lineTo dan menerapkan jalur yang disunting dengan GeometryShape.setGeometryPath. Koordinat 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.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 200, 100)
geometry_path = shape.getGeometryPaths()[0]
geometry_path.lineTo(100, 50, 1)
geometry_path.lineTo(100, 50, 4)
shape.setGeometryPath(geometry_path)
finally:
presentation.dispose()

Hapus Titik dari Sebuah Bentuk
Contoh ini mengubah outline berbentuk hati dengan menghapus segmen pada indeks berbasis nol 2 menggunakan GeometryPath.removeAt. Menerapkan jalur yang dimodifikasi dengan GeometryShape.setGeometryPath memperbarui kontur bentuk.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Heart, 100, 100, 300, 300)
geometry_path = shape.getGeometryPaths()[0]
geometry_path.removeAt(2)
shape.setGeometryPath(geometry_path)
finally:
presentation.dispose()

Buat Bentuk Kustom
Contoh ini membangun bintang lima sudut menggunakan GeometryPath. Jari‑jari luar dan dalam yang bergantian sebesar 100 dan 50 poin menentukan ujung dan lekukan; langkah 72 derajat menempatkan lima ujung secara merata. Jalur ditutup dengan GeometryPath.closeFigure dan diterapkan ke bentuk persegi panjang menggunakan GeometryShape.setGeometryPath, menggantikan outline‑nya.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType, GeometryPath
import math
points = []
outer_radius = 100
inner_radius = 50
angle_step = 72
for angle in range(-90, 270, angle_step):
radians = math.radians(angle)
x = outer_radius * math.cos(radians)
y = outer_radius * math.sin(radians)
points.append((x + outer_radius, y + outer_radius))
radians = math.radians(angle + angle_step / 2)
x = inner_radius * math.cos(radians)
y = inner_radius * math.sin(radians)
points.append((x + outer_radius, y + outer_radius))
star_path = GeometryPath()
star_path.moveTo(*points[0])
for point in points[1:]:
star_path.lineTo(*point)
star_path.closeFigure()
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, outer_radius * 2, outer_radius * 2)
shape.setGeometryPath(star_path)
finally:
presentation.dispose()

Buat Bentuk Kustom Komposit
Contoh ini mendefinisikan dua GeometryPath tertutup untuk sepertiga atas dan bawah sebuah bentuk. Menerapkan kedua jalur dengan GeometryShape.setGeometryPaths menghasilkan satu bentuk komposit dengan celah di sepertiga tengahnya.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType, GeometryPath
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 200, 100)
top_path = GeometryPath()
top_path.moveTo(0, 0)
top_path.lineTo(shape.getWidth(), 0)
top_path.lineTo(shape.getWidth(), shape.getHeight() / 3)
top_path.lineTo(0, shape.getHeight() / 3)
top_path.closeFigure()
bottom_path = GeometryPath()
bottom_path.moveTo(0, shape.getHeight() / 3 * 2)
bottom_path.lineTo(shape.getWidth(), shape.getHeight() / 3 * 2)
bottom_path.lineTo(shape.getWidth(), shape.getHeight())
bottom_path.lineTo(0, shape.getHeight())
bottom_path.closeFigure()
shape.setGeometryPaths([top_path, bottom_path])
finally:
presentation.dispose()

Buat Bentuk Kustom 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 ayunan -90 derajat menggambar seperempat elips berlawanan arah jarum jam. Jalur yang selesai diterapkan dengan GeometryShape.setGeometryPath, dan presentasi disimpan dalam format PPTX.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType, GeometryPath, SaveFormat
shape_x = 20
shape_y = 20
shape_width = 300
shape_height = 200
left_top_size = 50
right_top_size = 20
right_bottom_size = 40
left_bottom_size = 10
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Custom, shape_x, shape_y, shape_width, shape_height)
geometry_path = GeometryPath()
geometry_path.moveTo(left_top_size, 0)
geometry_path.lineTo(shape_width - right_top_size, 0)
geometry_path.arcTo(right_top_size, right_top_size, 180, -90)
geometry_path.lineTo(shape_width, shape_height - right_bottom_size)
geometry_path.arcTo(right_bottom_size, right_bottom_size, -90, -90)
geometry_path.lineTo(left_bottom_size, shape_height)
geometry_path.arcTo(left_bottom_size, left_bottom_size, 0, -90)
geometry_path.lineTo(0, left_top_size)
geometry_path.arcTo(left_top_size, left_top_size, 90, -90)
geometry_path.closeFigure()
shape.setGeometryPath(geometry_path)
presentation.save("output.pptx", SaveFormat.Pptx)
finally:
presentation.dispose()
Temukan Apakah Geometri Bentuk Tertutup
Pembantu berikut memeriksa apakah setiap jalur geometri yang tidak kosong diakhiri dengan segmen penutup. Ia membaca GeometryPath.getPathData dan membandingkan perintah segmen terakhir PathSegment.getPathCommand dengan PathCommandType.Close. Ia mengembalikan False ketika tidak ada jalur yang tidak kosong. Pemeriksaan ini memperhatikan perintah akhir tiap jalur; tidak memeriksa setiap sub‑figur dalam sebuah jalur. Contoh menampilkan True untuk persegi panjang.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType, PathCommandType
def is_geometry_closed(geometry_shape):
has_nonempty_path = False
for geometry_path in geometry_shape.getGeometryPaths():
path_data = geometry_path.getPathData()
if len(path_data) == 0:
continue
last_segment = path_data[-1]
has_nonempty_path = True
if last_segment.getPathCommand() != PathCommandType.Close:
return False
return has_nonempty_path
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 200, 100)
closed = is_geometry_closed(shape)
print(closed)
finally:
presentation.dispose()
Ekstrak dan Periksa Elemen Bentuk
Gunakan GeometryShape.createShapeElements untuk memeriksa sebuah bentuk yang ada sebagai elemen‑elemen yang berisi titik‑titik jalur dan jenis titik. Cast setiap elemen yang dikembalikan ke ShapeElement dengan jpype.JObject untuk mengambil array titik dan tipe melalui metode getPathPoints dan getPathTypes. Representasi ini berguna untuk analisis kontur atau mengirim geometri ke alat gambar kustom.
Contoh membuka input.pptx, menemukan bentuk geometri pertama langsung pada slide pertama, dan mencetak segmen‑segmen jalurnya. Gunakan presentasi yang berisi bentuk dengan segmen lurus dan melengkung untuk melihat kedua jenis output. Ia tidak mencari di dalam grup.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, GeometryShape, ShapeElement
presentation = Presentation("input.pptx")
try:
slide = presentation.getSlides().get_Item(0)
shape = None
for candidate in slide.getShapes():
if isinstance(candidate, GeometryShape):
shape = candidate
break
if shape is None:
print("No geometry shape found on the first slide.")
else:
for element in shape.createShapeElements():
shape_element = jpype.JObject(element, ShapeElement)
points = shape_element.getPathPoints()
types = shape_element.getPathTypes()
print("Shape element:")
i = 0
while i < len(points):
point_type = types[i] & 0x07 # Keep the segment type, excluding flags.
if point_type == 0:
print(f"Start figure at {points[i]}")
elif point_type == 1:
print(f"Line to {points[i]}")
elif point_type == 3:
print(f"Cubic Bezier: controls {points[i]}, {points[i + 1]}; end {points[i + 2]}")
i += 2 # Consume both control points and the endpoint.
if types[i] & 0x80:
print("Close subpath back to its starting point.")
i += 1
finally:
presentation.dispose()
Array‑array tersebut bersesuaian berdasarkan indeks: points[i] adalah sebuah titik dan types[i] menggambarkan perannya. Tipe 0 memulai sebuah figur, dan tipe 1 menggambar garis dari titik sebelumnya ke titik saat ini. Sebuah segmen Bézier kubik dimulai pada ujung titik sebelumnya dan menggunakan tiga entri tipe 3 berurutan: dua titik kontrol diikuti oleh titik akhir baru. Loop mengonsumsi ketiga entri tersebut secara bersamaan dan memeriksa titik akhir untuk penutupan.
Jenis titik juga mengandung flag. Lakukan masking 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. Java menyimpan flag ini dalam byte bertanda; masking mempertahankan nilai bit yang dimaksud. Membandingkan nilai mentah hanya dengan 1 atau 3 akan melewatkan 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 getX dan getY serta mencerminkan lebar dan tinggi saat ini. Contohnya, sebuah persegi panjang tidak berotasi pada (100, 200) dengan ukuran 120 × 80 mempunyai batas kontur (100, 200)–(220, 280). Jangan menambahkan posisi bentuk lagi. Kurangi X dan Y untuk memperoleh koordinat relatif terhadap bingkai tak berotasi.
Titik‑titik yang diekstrak tidak menerapkan rotasi bentuk, yang dikembalikan oleh getRotation, atau flip horizontal dan vertikal. Untuk mereproduksi kontur yang ditampilkan, terapkan transformasi tersebut di sekitar pusat bentuk. Untuk bentuk yang berada dalam grup, perhitungkan pula pemetaan koordinat grup dan transformasinya; jangan mengasumsikan bahwa titik yang diekstrak adalah koordinat akhir slide yang dirender atau menerapkan translasi atau skala dua kali bila sudah tercermin dalam bingkai anak.
Inspeksi vs penyuntingan. Array yang diekstrak menggambarkan kontur; mengubahnya tidak memperbarui bentuk asli. Pilih pendekatan ini ketika analisis atau kode gambar Anda memerlukan array titik/tipe. Gunakan getGeometryPaths ketika Anda memerlukan perintah geometri dalam sistem koordinat lokal bentuk atau ingin menyunting geometri tersebut. Terapkan jalur yang disunting melalui setGeometryPath atau setGeometryPaths.
Konversi Java AWT Shape ke GeometryPath
Contoh ini menggabungkan outline persegi panjang dengan teks yang dikonversi menjadi geometri. Metode setFillMode pada outline menonaktifkan isinya. Sebuah GlyphVector membuat outline teks dalam sebuah java.awt.Shape. PathIterator‑nya menyediakan segmen move, line, quadratic, cubic, dan closing, yang kemudian diputar ulang pada sebuah GeometryPath.
Teks menggunakan font Arial 40 poin. Outline dipindahkan 20 poin secara horizontal dan diposisikan dengan bagian atas visualnya 10 poin di bawah tepi atas bentuk. Jalur teks diisi, sementara persegi panjang asli tetap menjadi outline. Menerapkan kedua jalur dengan GeometryShape.setGeometryPaths menghasilkan satu bentuk yang berisi persegi panjang dan teks.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType, GeometryPath, PathFillModeType
from java.awt import Font
from java.awt.geom import PathIterator
from java.awt.image import BufferedImage
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 300, 100)
# Dapatkan jalur geometri dari bentuk.
original_path = shape.getGeometryPaths()[0]
original_path.setFillMode(PathFillModeType.None_)
# Buat jalur grafis baru dengan teks.
font = Font("Arial", Font.PLAIN, 40)
text = "Text in shape"
image = BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB)
graphics = image.createGraphics()
try:
font_context = graphics.getFontRenderContext()
glyph_vector = font.createGlyphVector(font_context, text)
text_bounds = glyph_vector.getVisualBounds()
baseline = -text_bounds.getY() + 10
graphics_path = glyph_vector.getOutline(20.0, baseline)
finally:
graphics.dispose()
# Konversi jalur grafis ke jalur geometri.
text_path = GeometryPath()
path_iterator = graphics_path.getPathIterator(None)
points = jpype.JArray(jpype.JFloat)(6)
while not path_iterator.isDone():
segment_type = path_iterator.currentSegment(points)
if segment_type == PathIterator.SEG_MOVETO:
text_path.moveTo(points[0], points[1])
elif segment_type == PathIterator.SEG_LINETO:
text_path.lineTo(points[0], points[1])
elif segment_type == PathIterator.SEG_QUADTO:
text_path.quadraticBezierTo(points[0], points[1], points[2], points[3])
elif segment_type == PathIterator.SEG_CUBICTO:
text_path.cubicBezierTo(points[0], points[1], points[2], points[3], points[4], points[5])
elif segment_type == PathIterator.SEG_CLOSE:
text_path.closeFigure()
path_iterator.next()
text_path.setFillMode(PathFillModeType.Normal)
# Terapkan jalur teks bersama dengan jalur geometri asli.
shape.setGeometryPaths([original_path, text_path])
finally:
presentation.dispose()

FAQ
Apa yang terjadi pada isian dan outline setelah mengganti geometri?
Gaya tetap pada bentuk; hanya kontur yang berubah. Isian dan outline secara otomatis diterapkan pada geometri baru.
Bagaimana cara memutar bentuk kustom bersama geometrinya secara benar?
Gunakan metode setRotation pada bentuk; geometri berotasi bersama bentuk karena terikat pada sistem koordinat bentuk itu sendiri.
Bisakah saya mengonversi bentuk kustom menjadi gambar untuk “mengunci” hasilnya?
Ya. Ekspor area slide yang diperlukan atau shape itu sendiri ke format raster; ini mempermudah pekerjaan selanjutnya dengan geometri yang kompleks.