Sesuaikan Bentuk Presentasi di Android

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 bekerja dengan GeometryPath dan IGeometryPath untuk memodifikasi bentuk yang ada, melakukan operasi penyuntingan jalur dasar, menambah atau menghapus titik, dan menerapkan geometri yang diperbarui kembali ke sebuah bentuk.

Artikel ini juga mendemonstrasikan cara membuat bentuk khusus dan gabungan, membangun bentuk dengan sudut melengkung, menentukan apakah geometri sebuah bentuk tertutup, dan memeriksa elemen bentuk menggunakan array titik Android.

Ubah Bentuk Menggunakan Titik Edit

Di PowerPoint, Anda dapat menggunakan Titik Edit untuk memodifikasi sebuah persegi:

  • Memindahkan sudut ke dalam atau ke luar.
  • Menyesuaikan kelengkungan pada sebuah titik.
  • Menambahkan titik baru.

Mengedit titik memungkinkan Anda memodifikasi kontur sebuah bentuk atau menggunakan bentuk yang ada sebagai dasar untuk bentuk baru.

Tips Penyuntingan Bentuk

overview_image

Saat menyunting bentuk PowerPoint, ingat konsep berikut:

  • Sebuah bentuk (atau jalurnya) dapat berupa tertutup atau terbuka.
  • Jalur sebuah bentuk terdiri dari titik jangkar yang dihubungkan oleh segmen.
  • Sebuah segmen dapat lurus atau melengkung. Titik jangkar dan pegangan kontrol menentukan bentuknya.
  • Titik jangkar ada sebagai titik sudut, titik lurus, atau titik halus:
    • Pada titik sudut, segmen yang berdekatan dapat bertemu pada 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 yang 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 dan antarmuka IGeometryPath.

Operasi Penyuntingan Sederhana

Gunakan metode berikut untuk menyunting jalur geometri. Overload yang menerima indeks menyisipkan segmen pada posisi berbasis nol dalam array segmen jalur.

Operasi Metode
Tambahkan atau sisipkan garis lurus. GeometryPath.lineTo
Tambahkan atau sisipkan kurva Bézier kubik dengan dua titik kontrol dan satu titik akhir. GeometryPath.cubicBezierTo
Tambahkan atau sisipkan kurva Bézier kuadratik dengan satu titik kontrol dan satu titik akhir. GeometryPath.quadraticBezierTo
Tambahkan busur elips dengan dimensi dan sudut yang ditentukan dalam derajat. GeometryPath.arcTo
Tutup gambar saat ini dengan menghubungkan titik akhirnya ke titik mulai. GeometryPath.closeFigure
Tetapkan titik mulai sebuah gambar. GeometryPath.moveTo
Hapus segmen pada indeks berbasis nol. GeometryPath.removeAt

Tambahkan Titik Kustom ke Bentuk

Contoh ini menyisipkan dua titik ke dalam bentuk persegi panjang menggunakan GeometryPath.lineTo dan menerapkan jalur yang diedit dengan IGeometryShape.setGeometryPath . Koordinat bersifat lokal terhadap bentuk: kedua titik baru berada di pusatnya, 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 com.aspose.slides.*;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 200, 100);

    IGeometryPath geometryPath = shape.getGeometryPaths()[0];
    geometryPath.lineTo(100, 50, 1);
    geometryPath.lineTo(100, 50, 4);

    shape.setGeometryPath(geometryPath);
} finally {
    presentation.dispose();
}

example1_image

Hapus Titik dari Bentuk

Contoh ini mengubah kontur berbentuk hati dengan menghapus segmen pada indeks berbasis nol 2 menggunakan GeometryPath.removeAt . Menerapkan jalur yang dimodifikasi dengan IGeometryShape.setGeometryPath memperbarui kontur bentuk.

import com.aspose.slides.*;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Heart, 100, 100, 300, 300);

    IGeometryPath path = shape.getGeometryPaths()[0];
    path.removeAt(2);

    shape.setGeometryPath(path);
} finally {
    presentation.dispose();
}

example2_image

Buat Bentuk Kustom

Contoh ini membangun bintang lima sudut dengan GeometryPath . Radius luar dan dalam yang bergantian masing‑masing 100 dan 50 poin menentukan puncak dan lekukan; langkah 72 derajat menempatkan lima puncak secara merata. Jalur ditutup dengan GeometryPath.closeFigure dan diterapkan ke bentuk persegi panjang menggunakan IGeometryShape.setGeometryPath , menggantikan konturnya.

import com.aspose.slides.*;
import android.graphics.PointF;
import java.util.ArrayList;
import java.util.List;

List<PointF> points = new ArrayList<>();

float outerRadius = 100f;
float innerRadius = 50f;
int angleStep = 72;

for (int angle = -90; angle < 270; angle += angleStep)
{
    double radians = angle * (Math.PI / 180f);
    double x = outerRadius * Math.cos(radians);
    double y = outerRadius * Math.sin(radians);
    PointF point = new PointF((float)x + outerRadius, (float)y + outerRadius);
    points.add(point);

    radians = Math.PI * (angle + angleStep / 2) / 180.0;
    x = innerRadius * Math.cos(radians);
    y = innerRadius * Math.sin(radians);
    point = new PointF((float)x + outerRadius, (float)y + outerRadius);
    points.add(point);
}

GeometryPath starPath = new GeometryPath();
starPath.moveTo(points.get(0));

for (int i = 1; i < points.size(); i++)
{
    starPath.lineTo(points.get(i));
}

starPath.closeFigure();

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, outerRadius * 2, outerRadius * 2);
    shape.setGeometryPath(starPath);
} finally {
    presentation.dispose();
}

example3_image

Buat Bentuk Kustom Komposit

Contoh ini mendefinisikan dua GeometryPath tertutup untuk sepertiga atas dan sepertiga bawah sebuah bentuk. Menerapkan kedua jalur dengan IGeometryShape.setGeometryPaths menghasilkan satu bentuk komposit dengan celah di sepertiga tengahnya.

import com.aspose.slides.*;

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 200, 100);

    GeometryPath topPath = new GeometryPath();
    topPath.moveTo(0, 0);
    topPath.lineTo(shape.getWidth(), 0);
    topPath.lineTo(shape.getWidth(), shape.getHeight() / 3);
    topPath.lineTo(0, shape.getHeight() / 3);
    topPath.closeFigure();

    GeometryPath bottomPath = new GeometryPath();
    bottomPath.moveTo(0, shape.getHeight() / 3 * 2);
    bottomPath.lineTo(shape.getWidth(), shape.getHeight() / 3 * 2);
    bottomPath.lineTo(shape.getWidth(), shape.getHeight());
    bottomPath.lineTo(0, shape.getHeight());
    bottomPath.closeFigure();

    shape.setGeometryPaths(new GeometryPath[] { topPath, bottomPath });
} 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 IGeometryShape.setGeometryPath , dan presentasi disimpan dalam format PPTX.

import com.aspose.slides.*;
import android.graphics.PointF;

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

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

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Custom, shapeX, shapeY, shapeWidth, shapeHeight);

    PointF topLeft = new PointF(leftTopSize, 0);
    PointF topRight = new PointF(shapeWidth - rightTopSize, 0);
    PointF rightBottom = new PointF(shapeWidth, shapeHeight - rightBottomSize);
    PointF bottomLeft = new PointF(leftBottomSize, shapeHeight);
    PointF leftTop = new PointF(0, leftTopSize);

    GeometryPath geometryPath = new GeometryPath();
    geometryPath.moveTo(topLeft);
    geometryPath.lineTo(topRight);
    geometryPath.arcTo(rightTopSize, rightTopSize, 180, -90);
    geometryPath.lineTo(rightBottom);
    geometryPath.arcTo(rightBottomSize, rightBottomSize, -90, -90);
    geometryPath.lineTo(bottomLeft);
    geometryPath.arcTo(leftBottomSize, leftBottomSize, 0, -90);
    geometryPath.lineTo(leftTop);
    geometryPath.arcTo(leftTopSize, leftTopSize, 90, -90);
    geometryPath.closeFigure();

    shape.setGeometryPath(geometryPath);

    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 IGeometryPath.getPathData dan membandingkan perintah segmen terakhirnya IPathSegment.getPathCommand dengan PathCommandType.Close . Ia mengembalikan false bila tidak ada jalur yang tidak kosong. Pemeriksaan ini hanya memeriksa perintah akhir setiap jalur; tidak memeriksa setiap subgambar dalam sebuah jalur. Contoh mencetak true untuk sebuah persegi panjang.

import com.aspose.slides.*;

class GeometryInspector {
    boolean isGeometryClosed(IGeometryShape geometryShape) {
        boolean hasNonemptyPath = false;

        for (IGeometryPath geometryPath : geometryShape.getGeometryPaths()) {
            IPathSegment[] segments = geometryPath.getPathData();
            if (segments.length == 0) {
                continue;
            }

            hasNonemptyPath = true;
            IPathSegment lastSegment = segments[segments.length - 1];
            if (lastSegment.getPathCommand() != PathCommandType.Close) {
                return false;
            }
        }

        return hasNonemptyPath;
    }
}

Presentation presentation = new Presentation();
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 200, 100);

    GeometryInspector inspector = new GeometryInspector();
    boolean closed = inspector.isGeometryClosed(shape);
    System.out.println(closed);
} finally {
    presentation.dispose();
}

Ekstrak dan Periksa Elemen Bentuk

Gunakan IGeometryShape.createShapeElements untuk memeriksa sebuah bentuk yang ada sebagai elemen yang berisi titik‑titik jalur dan tipe titik. Cast setiap IShapeElement yang dikembalikan ke ShapeElement untuk mendapatkan array titik dan tipe melalui metode getPathPoints dan getPathTypes . Representasi ini berguna untuk analisis kontur atau menyampaikan geometri ke alat gambar kustom.

Contoh membuka input.pptx, menemukan bentuk geometri pertama langsung pada slide pertama, dan mencetak segmen jalurnya. Gunakan presentasi yang berisi bentuk dengan segmen lurus dan melengkung untuk melihat kedua jenis output. Ia tidak mencari di dalam grup.

import com.aspose.slides.*;
import android.graphics.PointF;

Presentation presentation = new Presentation("input.pptx");
try {
    ISlide slide = presentation.getSlides().get_Item(0);

    IGeometryShape shape = null;
    for (IShape candidate : slide.getShapes()) {
        if (candidate instanceof IGeometryShape) {
            shape = (IGeometryShape) candidate;
            break;
        }
    }

    if (shape == null) {
        System.out.println("No geometry shape found on the first slide.");
    } else {
        for (IShapeElement element : shape.createShapeElements()) {
            ShapeElement shapeElement = (ShapeElement) element;
            PointF[] points = shapeElement.getPathPoints();
            byte[] types = shapeElement.getPathTypes();
            System.out.println("Shape element:");

            for (int i = 0; i < points.length; i++) {
                int pointType = types[i] & 0x07; // Simpan tipe segmen, kecuali flag.
                switch (pointType) {
                    case 0:
                        System.out.println("Start figure at " + points[i]);
                        break;
                    case 1:
                        System.out.println("Line to " + points[i]);
                        break;
                    case 3:
                        System.out.println("Cubic Bezier: controls " + points[i] + ", " + points[i + 1] + "; end " + points[i + 2]);
                        i += 2; // Konsumsi kedua titik kontrol dan titik akhir.
                        break;
                }

                if ((types[i] & 0x80) != 0) {
                    System.out.println("Close subpath back to its starting point.");
                }
            }
        }
    }
} finally {
    presentation.dispose();
}

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 mengonsumsi ketiga entri tersebut sekaligus dan memeriksa titik akhir untuk penutupan.

Tipe‑tipe titik juga mengandung flag. Lakukan mask dengan 0x07 untuk mengidentifikasi tipe segmen, dan uji 0x80 secara terpisah untuk mendeteksi sub‑jalur tertutup. Misalnya, 129 (0x81) berarti titik akhir garis yang menutup sub‑jalur, dan 131 (0x83) berarti titik akhir Bézier yang menutup satu. Java menyimpan flag ini dalam byte bertanda; masking mempertahankan nilai bit yang dimaksud. 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 bertambah ke kanan dan Y bertambah 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. Misalnya, sebuah persegi panjang yang tidak diputar 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 diputar.

Titik‑titik yang diekstrak tidak menerapkan rotasi bentuk, yang dikembalikan oleh getRotation , atau pembalikan horizontal dan vertikal. Untuk mereproduksi kontur yang ditampilkan, terapkan transformasi tersebut di sekitar pusat bentuk. Untuk bentuk dalam grup, juga perhitungkan pemetaan koordinat grup dan transformasinya; jangan mengasumsikan bahwa titik yang diekstrak adalah koordinat slide akhir 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 bila analisis atau kode gambar Anda memerlukan array titik/tipe. Gunakan getGeometryPaths bila Anda memerlukan perintah geometri dalam sistem koordinat lokal bentuk atau ingin menyunting geometriya. Terapkan jalur yang disunting melalui setGeometryPath atau setGeometryPaths .

FAQ

Apa yang terjadi pada isi dan garis tepi setelah mengganti geometri?

Gaya tetap melekat pada bentuk; hanya kontur yang berubah. Isi dan garis tepi secara otomatis diterapkan ke geometri baru.

Bagaimana cara memutar bentuk kustom bersama geometri secara benar?

Gunakan metode setRotation pada bentuk; geometri berputar bersama bentuk karena terikat pada sistem koordinat bentuk itu sendiri.

Bisakah saya mengonversi bentuk kustom ke gambar untuk “mengunci” hasilnya?

Ya. Ekspor area slide yang diperlukan atau shape itu sendiri ke format raster; ini menyederhanakan pekerjaan selanjutnya dengan geometri yang kompleks.