Anpassa presentationsformer på Android

Översikt

Denna artikel förklarar hur du anpassar presentationsformer i Aspose.Slides genom att redigera formgeometri via redigeringspunkter och geometri­vägar. Den visar hur du arbetar med GeometryPath och IGeometryPath för att ändra befintliga former, utföra grundläggande redigeringsoperationer för vägar, lägga till eller ta bort punkter och tillämpa den uppdaterade geometrin på en form.

Den visar också hur du skapar anpassade och sammansatta former, bygger former med rundade hörn, avgör om en formgeometri är sluten och inspekterar formelement med Android‑punktarrayer.

Ändra en form med redigeringspunkter

I PowerPoint kan du använda Edit Points för att ändra en fyrkant:

  • Flytta ett hörn inåt eller utåt.
  • Justera krökningen vid en punkt.
  • Lägg till nya punkter.

Genom att redigera punkter kan du ändra en forms kontur eller använda en befintlig form som grund för en ny.

Tips för formredigering

overview_image

När du redigerar PowerPoint‑former, ha dessa koncept i åtanke:

  • En form (eller dess bana) kan antingen vara sluten eller öppen.
  • En forms bana består av ankarpunkter som är sammankopplade av segment.
  • Ett segment kan vara rakt eller kurvat. Ankarlägen och kontrollhandtag bestämmer dess form.
  • Ankarlägen finns som hörnpunkter, raka punkter eller släta punkter:
    • Vid en hörnpunkt kan intilliggande segment mötas i en vinkel.
    • Vid en slät punkt är de två kontrollhandtagen i linje och lika långt från ankarläget.
    • Vid en rak punkt är de två kontrollhandtagen i linje men kan ha olika avstånd från ankarläget.
  • Att flytta ankarlägen eller justera deras handtag ändrar formens kontur.

För att redigera PowerPoint‑former via redigeringspunkter tillhandahåller Aspose.Slides klassen GeometryPath och gränssnittet IGeometryPath.

Enkla redigeringsoperationer

Använd följande metoder för att redigera en geometri­bana. Överlagringar som tar ett index sätter in ett segment på den nollbaserade positionen i bana­segment‑arrayen.

Operation Metod
Lägg till eller infoga en rak linje. GeometryPath.lineTo
Lägg till eller infoga en kubisk Bézier‑kurva med två kontrollpunkter och en slutpunkt. GeometryPath.cubicBezierTo
Lägg till eller infoga en kvadratisk Bézier‑kurva med en kontrollpunkt och en slutpunkt. GeometryPath.quadraticBezierTo
Lägg till en elliptisk båge med angivna dimensioner och vinklar i grader. GeometryPath.arcTo
Stäng den aktuella figur genom att koppla dess slutpunkt till dess startpunkt. GeometryPath.closeFigure
Ange startpunkten för en figur. GeometryPath.moveTo
Ta bort ett segment på en nollbaserad index. GeometryPath.removeAt

Lägg till anpassade punkter i en form

Detta exempel infogar två punkter i en rektangulär form med GeometryPath.lineTo och tillämpar den redigerade banan med IGeometryShape.setGeometryPath. Koordinaterna är lokala för formen: båda nya punkterna ligger i dess centrum, 100 punkter från vänster och 50 punkter från toppen. Segmentindex 1 och 4 placerar dem på de övre och nedre kanterna och drar dessa kanter inåt.

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

Ta bort punkter från en form

Detta exempel ändrar en hjärtformad kontur genom att ta bort segmentet på nollbaserad index 2 med GeometryPath.removeAt. Genom att tillämpa den modifierade banan med IGeometryShape.setGeometryPath uppdateras formens kontur.

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

Skapa en anpassad form

Detta exempel bygger en femspetsig stjärna med GeometryPath. Växlande yttre och inre radier på 100 respektive 50 punkter definierar spetsarna och indragningarna; ett 72‑gradigt steg placerar de fem spetsarna jämnt. Banam avslutas med GeometryPath.closeFigure och appliceras på en rektangulär form med IGeometryShape.setGeometryPath, vilket ersätter dess kontur.

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

Skapa en sammansatt anpassad form

Detta exempel definierar två sluta GeometryPath‑objekt för de övre och nedre tredjedelarna av en form. Genom att tillämpa båda banorna med IGeometryShape.setGeometryPaths skapas en enda sammansatt form med ett glapp över dess mittersta tredjedel.

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

Skapa en anpassad form med rundade hörn

Detta exempel kombinerar raka segment med GeometryPath.arcTo för att skapa en form med inåtkurvade hörn. Varje hörnstorlek anger bågens bredd och höjd i punkter, och den -90‑gradiga svepningen ritar en moturs kvartselips. Den färdiga banan appliceras med IGeometryShape.setGeometryPath, och presentationen sparas i PPTX‑format.

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

Ta reda på om en formgeometri är sluten

Följande hjälpfunktion kontrollerar om varje icke‑tom geometri­bana avslutas med ett slutsegment. Den läser IGeometryPath.getPathData och jämför det sista segmentets IPathSegment.getPathCommand med PathCommandType.Close. Den returnerar false när det inte finns några icke‑tomma banor. Detta kontrollerar det sista kommandet för varje bana; den inspekterar inte varje subfigur inom en bana. Exemplet skriver ut true för en rektangel.

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

Extrahera och inspektera formelement

Använd IGeometryShape.createShapeElements för att inspektera en befintlig form som element som innehåller banapunkter och punt­typer. Kast varje returnerad IShapeElement till ShapeElement för att hämta punkt‑ och typ‑arrayerna via metoderna getPathPoints och getPathTypes . Denna representation är användbar för kontur‑analys eller för att skicka geometri till anpassade ritverktyg.

Exemplet öppnar input.pptx, hittar den första geometri‑formen direkt på den första bilden och skriver ut dess bansegment. Använd en presentation som innehåller en form med raka och kurviga segment för att se båda typerna av utskrift. Det söker inte i grupper.

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; // Behåll segmenttypen, exklusive flaggor.
                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; // Consume both control points and the endpoint.
                        break;
                }

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

Arrayerna korresponderar efter index: points[i] är en punkt och types[i] beskriver dess roll. Typ 0 startar en figur, och typ 1 ritar en linje från föregående punkt till den aktuella. Ett kubiskt Bézier‑segment startar vid föregående slutpunkt och använder tre på varandra följande typ‑3‑poster: två kontrollpunkter följda av den nya slutpunkten. Loopen konsumerar dessa tre poster tillsammans och kontrollerar om slutpunkten är sluten.

Punkt‑typer innehåller också flaggor. Maskera med 0x07 för att identifiera segmenttypen och testa 0x80 separat för att upptäcka en sluten delbana. Till exempel betyder 129 (0x81) en linjeslutpunkt som stänger en delbana, och 131 (0x83) betyder en Bézier‑slutpunkt som stänger en. Java lagrar dessa flaggor i signerade byte; maskering bevarar de avsedda bitvärdena. Att bara jämföra det råa värdet med 1 eller 3 skulle missa dessa fall. Andra flaggor, såsom streck (0x10) och markör (0x20), ändrar inte bassegmenttypen.

Koordinater och transformationer. Punkter mäts i punkter (1/72 tum), med X som ökar åt höger och Y som ökar nedåt. För en ogrupperad form inkluderar de extraherade koordinaterna redan positionen som returneras av getX och getY och reflekterar dess nuvarande bredd och höjd. Till exempel har en orotated rektangel på (100, 200) med storlek 120 × 80 konturbounderna (100, 200)–(220, 280). Lägg inte till formens position igen. Subtrahera dess X och Y för att få koordinater relativt till dess orotated ram.

De extraherade punkterna applicerar inte formens rotation, som returneras av getRotation, eller horisontella och vertikala speglingar. För att reproducera den visade konturen, applicera dessa transformationer runt formens centrum. För grupperade former, ta även hänsyn till gruppens koordinat‑mappning och transformationer; anta inte att de extraherade punkterna är de slutgiltiga renderade bild‑koordinaterna eller applicera en translation eller skala två gånger om den redan reflekteras i barnets ram.

Inspektion kontra redigering. Extraherade arrayer beskriver konturen; att förändra dem uppdaterar inte den ursprungliga formen. Välj detta tillvägagångssätt när din analys‑ eller ritkod behöver punkt‑/typ‑arrayer. Använd getGeometryPaths när du behöver geometrikommando i formens lokala koordinatsystem eller vill redigera dess geometri. Applicera redigerade banor via setGeometryPath eller setGeometryPaths.

FAQ

Vad händer med fyllning och kontur efter att geometrin har ersatts?

Stilen förblir på formen; endast konturen förändras. Fyllning och kontur appliceras automatiskt på den nya geometrin.

Hur roterar jag en anpassad form korrekt tillsammans med dess geometri?

Använd formens setRotation‑metod; geometrin roterar med formen eftersom den är bunden till formens eget koordinatsystem.

Kan jag konvertera en anpassad form till en bild för att “låsa” resultatet?

Ja. Exportera det önskade bildspel‑området eller själva form till ett rasterformat; detta förenklar vidare arbete med komplexa geometrier.