Přizpůsobení tvarů prezentace na Androidu

Přehled

Tento článek vysvětluje, jak přizpůsobit tvary prezentací v Aspose.Slides úpravou geometrie tvaru pomocí editačních bodů a geometrických cest. Ukazuje, jak pracovat s GeometryPath a IGeometryPath k úpravě existujících tvarů, provádění základních operací úpravy cesty, přidávání nebo odebírání bodů a aplikaci aktualizované geometrie zpět na tvar.

Také ukazuje, jak vytvořit vlastní a složené tvary, vytvořit tvary s zakřivenými rohy, určit, zda je geometrie tvaru uzavřená, a prozkoumat elementy tvaru pomocí Android pole bodů.

Změna tvaru pomocí editačních bodů

V PowerPointu můžete použít Edit Points k úpravě čtverce:

  • Posunout roh dovnitř nebo ven.
  • Upravit zakřivení v bodě.
  • Přidat nové body.

Úprava bodů vám umožní měnit obrys tvaru nebo použít existující tvar jako základ pro nový.

Tipy pro úpravu tvarů

overview_image

Při úpravě tvarů v PowerPointu mějte na paměti následující pojmy:

  • Tvar (nebo jeho cesta) může být buď uzavřený, nebo otevřený.
  • Cesta tvaru se skládá z kotevních bodů spojených segmenty.
  • Segment může být přímý nebo zakřivený. Kotevní body a ovládací úchyty určují jeho tvar.
  • Kotevní body existují jako rohové body, přímé body nebo hladké body:
    • U rohového bodu se sousední segmenty mohou setkat pod úhlem.
    • U hladkého bodu jsou dva ovládací úchyty zarovnané a ve stejné vzdálenosti od kotevního bodu.
    • U přímého bodu jsou dva ovládací úchyty zarovnané, ale mohou být od kotevního bodu ve různých vzdálenostech.
  • Posun kotevních bodů nebo úprava jejich úchytných úchytů mění obrys tvaru.

Pro úpravu tvarů v PowerPointu pomocí editačních bodů poskytuje Aspose.Slides třídu GeometryPath a rozhraní IGeometryPath.

Jednoduché operace úprav

Použijte následující metody pro úpravu geometrické cesty. Přetížení, která přijímají index, vloží segment na danou nulovou pozici v poli segmentů cesty.

Operace Metoda
Přidat nebo vložit přímou čáru. GeometryPath.lineTo
Přidat nebo vložit kubickou Bézierovu křivku se dvěma řídícími body a koncovým bodem. GeometryPath.cubicBezierTo
Přidat nebo vložit kvadratickou Bézierovu křivku s jedním řídícím bodem a koncovým bodem. GeometryPath.quadraticBezierTo
Přidat eliptický oblouk se zadanými rozměry a úhly ve stupních. GeometryPath.arcTo
Uzavřít aktuální útvar spojením jeho koncového bodu s počátečním bodem. GeometryPath.closeFigure
Nastavit počáteční bod útvaru. GeometryPath.moveTo
Odstranit segment na nulovém indexu. GeometryPath.removeAt

Přidání vlastních bodů do tvaru

Tento příklad vloží dva body do obdélníkového tvaru pomocí GeometryPath.lineTo a použije upravenou cestu metodou IGeometryShape.setGeometryPath. Souřadnice jsou lokální k tvaru: oba nové body jsou ve středu, 100 bodů od levého okraje a 50 bodů od horního. Indexy segmentů 1 a 4 je umístí na horní a dolní hranu, čímž tyto hrany stáhnou dovnitř.

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

Odstranění bodů ze tvaru

Tento příklad mění obrys ve tvaru srdce odstraněním segmentu na nulovém indexu 2 pomocí GeometryPath.removeAt. Použití upravené cesty metodou IGeometryShape.setGeometryPath aktualizuje konturu tvaru.

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

Vytvoření vlastního tvaru

Tento příklad vytvoří pěticípou hvězdu pomocí GeometryPath. Střídavé vnější a vnitřní poloměry 100 a 50 bodů definují špičky a zapuštění; krok 72 stupňů rovnoměrně rozmístí pět špiček. Cesta je uzavřena pomocí GeometryPath.closeFigure a aplikována na obdélníkový tvar pomocí IGeometryShape.setGeometryPath, čímž nahradí jeho obrys.

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

Vytvoření složeného vlastního tvaru

Tento příklad definuje dva uzavřené objekty GeometryPath pro horní a dolní třetinu tvaru. Použití obou cest pomocí IGeometryShape.setGeometryPaths vytvoří jeden složený tvar s mezerou napříč jeho střední třetinou.

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

Vytvoření vlastního tvaru se zakřivenými rohy

Tento příklad kombinuje přímé segmenty s GeometryPath.arcTo k vytvoření tvaru se zakřivenými rohy dovnitř. Každá velikost rohu určuje šířku a výšku oblouku v bodech a úhel -90 stupňů vykreslí proti směru hodinových ručiček čtvrtkružnici. Dokončená cesta je použita pomocí IGeometryShape.setGeometryPath a prezentace je uložena ve formátu 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();
}

Zjištění, zda je geometrie tvaru uzavřená

Následující pomocná metoda kontroluje, zda každá neprázdná geometrická cesta končí uzavíracím segmentem. Načte IGeometryPath.getPathData a porovná příkaz posledního segmentu IPathSegment.getPathCommand s PathCommandType.Close. Vrátí false, pokud neexistují neprázdné cesty. Toto kontroluje poslední příkaz každé cesty; neprozkoumává každou subfiguru uvnitř cesty. Příklad vypíše true pro obdélník.

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

Extrahování a inspekce elementů tvaru

Použijte IGeometryShape.createShapeElements k prozkoumání existujícího tvaru jako elementů obsahujících body cesty a typy bodů. Přetypujte každý vrácený IShapeElement na ShapeElement a získejte pole bodů a typů pomocí metod getPathPoints a getPathTypes . Toto znázornění je užitečné pro analýzu kontury nebo předání geometrie vlastním kreslícím nástrojům.

Příklad otevře soubor input.pptx, najde první geometrický tvar přímo na první snímku a vypíše jeho segmenty cesty. Použijte prezentaci obsahující tvar s přímými i zakřivenými segmenty, abyste viděli oba typy výstupu. Neprohledává skupiny.

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; // Zachovat typ segmentu, vyjma příznaků.
                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; // Spotřebovat oba řídící body a koncový bod.
                        break;
                }

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

Pole odpovídají podle indexu: points[i] je bod a types[i] popisuje jeho roli. Typ 0 zahajuje útvar a typ 1 kreslí čáru od předchozího bodu k aktuálnímu. Kubický Bézierův segment začíná na předchozím koncovém bodě a používá tři po sobě jdoucí položky typu 3: dva řídící body následované novým koncovým bodem. Smyčka spotřebuje tyto tři položky najednou a kontroluje koncový bod pro uzavření.

Typy bodů také obsahují příznaky. Maskujte pomocí 0x07 k určení typu segmentu a testujte 0x80 samostatně k detekci uzavřeného podcesty. Například 129 (0x81) znamená koncový bod čáry, který uzavírá podcestu, a 131 (0x83) znamená koncový bod Bézieru, který uzavírá podcestu. Java ukládá tyto příznaky do podepsaných bytů; maskování zachovává zamýšlené bitové hodnoty. Porovnání surové hodnoty jen s 1 nebo 3 by tyto případy prošvihlo. Další příznaky, jako čárka (0x10) a značka (0x20), nemění základní typ segmentu.

Souřadnice a transformace.
Bodů se měří v bodech (1/72 palce), přičemž X roste doprava a Y dolů. Pro netvořený (ne‑skupinový) tvar již extrahované souřadnice zahrnují pozici vrácenou metodami getX a getY a odrážejí jeho aktuální šířku a výšku. Například neotočený obdélník na (100, 200) s velikostí 120 × 80 má obrysové meze (100, 200)–(220, 280). Nepřidávejte pozici tvaru znovu. Odečtěte jeho X a Y, abyste získali souřadnice relativní k jeho neotočenému rámu.

Extrahované body neaplikují rotaci tvaru, vrácenou metodou getRotation, ani horizontální a vertikální převrácení. Pro reprodukci zobrazeného obrysu aplikujte tyto transformace kolem středu tvaru. Pro seskupené tvary také zohledněte mapování souřadnic skupiny a transformace; nepředpokládejte, že extrahované body jsou finální vykreslené souřadnice snímku, ani neaplikujte translační nebo škálovací transformaci dvakrát, pokud už jsou ve rámu dítěte zahrnuty.

Inspekce versus úprava. Extrahovaná pole popisují obrys; jejich změna neaktualizuje původní tvar. Zvolte tento přístup, když vaše analytické nebo kreslicí kódy potřebují pole bodů/typů. Použijte getGeometryPaths pokud potřebujete geometrické příkazy v lokálním souřadnicovém systému tvaru nebo chcete upravit jeho geometrii. Aplikujte upravené cesty pomocí setGeometryPath nebo setGeometryPaths.

Často kladené otázky

Co se stane s výplní a obrysem po nahrazení geometrie?
Styl zůstává u tvaru; mění se pouze obrys. Výplň a obrys jsou automaticky aplikovány na novou geometrii.

Jak správně otočit vlastní tvar spolu s jeho geometrií?
Použijte metodu setRotation tvaru; geometrie se otáčí spolu s tvarem, protože je vázána na jeho vlastní souřadnicový systém.

Mohu převést vlastní tvar na obrázek, aby byl výsledek „uzamčen“?
Ano. Exportujte požadovanou oblast slide nebo samotný shape do rastrového formátu; toto usnadní další práci s komplexními geometriemi.