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

overview_image

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.

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()

example1_image

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()

example2_image

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()

example3_image

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()

example4_image

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()

example5_image

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.