Personalizar formas de presentación en Java

Cambiar una forma usando puntos de edición

Considere un cuadrado. En PowerPoint, usando puntos de edición, puede

  • mover la esquina del cuadrado hacia adentro o hacia afuera
  • especificar la curvatura de una esquina o punto
  • agregar nuevos puntos al cuadrado
  • manipular puntos en el cuadrado, etc.

Esencialmente, puede realizar las tareas descritas en cualquier forma. Usando puntos de edición, puede cambiar una forma o crear una nueva forma a partir de una forma existente.

Consejos para la edición de formas

overview_image

Antes de comenzar a editar formas de PowerPoint mediante puntos de edición, quizá quiera considerar los siguientes aspectos sobre las formas:

  • Una forma (o su ruta) puede ser cerrada o abierta.
  • Cuando una forma es cerrada, carece de un punto de inicio o final. Cuando una forma es abierta, tiene un comienzo y un final.
  • Todas las formas constan de al menos 2 puntos de anclaje vinculados entre sí por líneas
  • Una línea puede ser recta o curva. Los puntos de anclaje determinan la naturaleza de la línea.
  • Los puntos de anclaje existen como puntos de esquina, puntos rectos o puntos suaves:
    • Un punto de esquina es un punto donde se unen 2 líneas rectas formando un ángulo.
    • Un punto suave es un punto donde existen 2 manejadores en una línea recta y los segmentos de la línea se unen en una curva suave. En este caso, todos los manejadores están separados del punto de anclaje por una distancia igual.
    • Un punto recto es un punto donde existen 2 manejadores en una línea recta y los segmentos de esa línea se unen en una curva suave. En este caso, los manejadores no tienen que estar separados del punto de anclaje por una distancia igual.
  • Al mover o editar los puntos de anclaje (lo que cambia el ángulo de las líneas), puede modificar la apariencia de una forma.

Para editar formas de PowerPoint mediante puntos de edición, Aspose.Slides ofrece la clase GeometryPath y la interfaz IGeometryPath.

Operaciones de edición simples

Este código Java le muestra cómo

Agregar una línea al final de una ruta

public void lineTo(java.awt.geom.Point2D.Float point);
public void lineTo(float x, float y);

Agregar una línea a una posición especificada en una ruta:

public void lineTo(java.awt.geom.Point2D.Float point, long index);
public void lineTo(float x, float y, long index);

Agregar una curva Bézier cúbica al final de una ruta:

public void cubicBezierTo(java.awt.geom.Point2D.Float point1, java.awt.geom.Point2D.Float point2, java.awt.geom.Point2D.Float point3);
public void cubicBezierTo(float x1, float y1, float x2, float y2, float x3, float y3);

Agregar una curva Bézier cúbica a la posición especificada en una ruta:

public void cubicBezierTo(java.awt.geom.Point2D.Float point1, java.awt.geom.Point2D.Float point2, java.awt.geom.Point2D.Float point3, long index);
public void cubicBezierTo(float x1, float y1, float x2, float y2, float x3, float y3, long index);

Agregar una curva Bézier cuadrática al final de una ruta:

public void quadraticBezierTo(java.awt.geom.Point2D.Float point1, java.awt.geom.Point2D.Float point2);
public void quadraticBez

ierTo(float x1, float y1, float x2, float y2);

Agregar una curva Bézier cuadrática a una posición especificada en una ruta:

public void quadraticBezierTo(java.awt.geom.Point2D.Float point1, java.awt.geom.Point2D.Float point2, long index);
public void quadraticBezierTo(float x1, float y1, float x2, float y2, long index);

Añadir un arco dado a una ruta:

public void arcTo(float width, float heigth, float startAngle, float sweepAngle);

Cerrar la figura actual de una ruta:

public void closeFigure();

Establecer la posición para el siguiente punto:

public void moveTo(java.awt.geom.Point2D.Float point);
public void moveTo(float x, float y);

Eliminar el segmento de ruta en un índice dado:

public void removeAt(int index);

Agregar puntos personalizados a una forma

  1. Cree una instancia de la clase GeometryShape y establezca el tipo ShapeType.Rectangle.
  2. Obtenga una instancia de la clase GeometryPath de la forma.
  3. Añada un nuevo punto entre los dos puntos superiores de la ruta.
  4. Añada un nuevo punto entre los dos puntos inferiores de la ruta.
  5. Aplique la ruta a la forma.

Este código Java le muestra cómo agregar puntos personalizados a una forma:

Presentation pres = new Presentation();
try {
    GeometryShape shape = (GeometryShape) pres.getSlides().get_Item(0).
            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 {
    if (pres != null) pres.dispose();
}

example1_image

Eliminar puntos de una forma

  1. Cree una instancia de la clase GeometryShape y establezca el tipo ShapeType.Heart.
  2. Obtenga una instancia de la clase GeometryPath de la forma.
  3. Elimine el segmento de la ruta.
  4. Aplique la ruta a la forma.

Este código Java le muestra cómo eliminar puntos de una forma:

Presentation pres = new Presentation();
try {
    GeometryShape shape = (GeometryShape) pres.getSlides().get_Item(0).
            getShapes().addAutoShape(ShapeType.Heart, 100, 100, 300, 300);

    IGeometryPath path = shape.getGeometryPaths()[0];
    path.removeAt(2);
    shape.setGeometryPath(path);
} finally {
    if (pres != null) pres.dispose();
}

example2_image

Crear una forma personalizada

  1. Calcule los puntos para la forma.
  2. Cree una instancia de la clase GeometryPath.
  3. Rellene la ruta con los puntos.
  4. Cree una instancia de la clase GeometryShape.
  5. Aplique la ruta a la forma.

Este Java le muestra cómo crear una forma personalizada:

List<Point2D.Float> points = new ArrayList<Point2D.Float>();

float R = 100, r = 50;
int step = 72;

for (int angle = -90; angle < 270; angle += step)
{
    double radians = angle * (Math.PI / 180f);
    double x = R * Math.cos(radians);
    double y = R * Math.sin(radians);
    points.add(new Point2D.Float((float)x + R, (float)y + R));

    radians = Math.PI * (angle + step / 2) / 180.0;
    x = r * Math.cos(radians);
    y = r * Math.sin(radians);
    points.add(new Point2D.Float((float)x + R, (float)y + R));
}

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 pres = new Presentation();
try {
    GeometryShape shape = (GeometryShape) pres.getSlides().get_Item(0).
            getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, R * 2, R * 2);

    shape.setGeometryPath(starPath);
} finally {
    if (pres != null) pres.dispose();
}

example3_image

Crear una forma personalizada compuesta

  1. Cree una instancia de la clase GeometryShape.
  2. Cree una primera instancia de la clase GeometryPath.
  3. Cree una segunda instancia de la clase GeometryPath.
  4. Aplique las rutas a la forma.

Este código Java le muestra cómo crear una forma personalizada compuesta:

Presentation pres = new Presentation();
try {
    GeometryShape shape = (GeometryShape) pres.getSlides().get_Item(0).
            getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 200, 100);

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

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

    shape.setGeometryPaths(new GeometryPath[] { geometryPath0, geometryPath1});
} finally {
    if (pres != null) pres.dispose();
}

example4_image

Crear una forma personalizada con esquinas curvas

Este código Java le muestra cómo crear una forma personalizada con esquinas curvas (hacia adentro);

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 pres = new Presentation();
try {
    IAutoShape childShape = pres.getSlides().get_Item(0).getShapes().addAutoShape(
            ShapeType.Custom, shapeX, shapeY, shapeWidth, shapeHeight);

    GeometryPath geometryPath = new GeometryPath();

    Point2D.Float point1 = new Point2D.Float(leftTopSize, 0);
    Point2D.Float point2 = new Point2D.Float(shapeWidth - rightTopSize, 0);
    Point2D.Float point3 = new Point2D.Float(shapeWidth, shapeHeight - rightBottomSize);
    Point2D.Float point4 = new Point2D.Float(leftBottomSize, shapeHeight);
    Point2D.Float point5 = new Point2D.Float(0, leftTopSize);

    geometryPath.moveTo(point1);
    geometryPath.lineTo(point2);
    geometryPath.arcTo(rightTopSize, rightTopSize, 180, -90);
    geometryPath.lineTo(point3);
    geometryPath.arcTo(rightBottomSize, rightBottomSize, -90, -90);
    geometryPath.lineTo(point4);
    geometryPath.arcTo(leftBottomSize, leftBottomSize, 0, -90);
    geometryPath.lineTo(point5);
    geometryPath.arcTo(leftTopSize, leftTopSize, 90, -90);

    geometryPath.closeFigure();

    childShape.setGeometryPath(geometryPath);

    pres.save("output.pptx", SaveFormat.Pptx);
} finally {
    if (pres!= null) pres.dispose();
}

Descubrir si la geometría de una forma está cerrada

Una forma cerrada se define como aquella en la que todos sus lados se conectan, formando un solo contorno sin huecos. Esa forma puede ser una forma geométrica simple o un contorno personalizado complejo. El siguiente ejemplo de código muestra cómo verificar si la geometría de una forma está cerrada:

boolean isGeometryClosed(IGeometryShape geometryShape)
{
    Boolean isClosed = null;

    for (IGeometryPath geometryPath : geometryShape.getGeometryPaths()) {
        int dataLength = geometryPath.getPathData().length;
        if (dataLength == 0)
            continue;

        IPathSegment lastSegment = geometryPath.getPathData()[dataLength - 1];
        isClosed = lastSegment.getPathCommand() == PathCommandType.Close;

        if (isClosed == false)
            return false;
    }

    return isClosed == true;
}

Convertir GeometryPath a java.awt.Shape

  1. Cree una instancia de la clase GeometryShape.
  2. Cree una instancia de la clase java.awt.Shape.
  3. Convierta la instancia java.awt.Shape a la instancia GeometryPath usando ShapeUtil.
  4. Aplique las rutas a la forma.

Este código Java—una implementación de los pasos anteriores—demuestra el proceso de conversión de GeometryPath a GraphicsPath:

Presentation pres = new Presentation();
try {
    // Crear nueva forma
    GeometryShape shape = (GeometryShape)pres.getSlides().get_Item(0).
            getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 300, 100);

    // Obtener la ruta de geometría de la forma
    IGeometryPath originalPath = shape.getGeometryPaths()[0];
    originalPath.setFillMode(PathFillModeType.None);

    // Crear nueva ruta gráfica con texto
    Shape graphicsPath;
    Font font = new java.awt.Font("Arial", Font.PLAIN, 40);
    String text = "Text in shape";
    BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = img.createGraphics();

    try
    {
        GlyphVector glyphVector = font.createGlyphVector(g2.getFontRenderContext(), text);
        graphicsPath = glyphVector.getOutline(20f, ((float) -glyphVector.getVisualBounds().getY()) + 10);
    }
    finally {
        g2.dispose();
    }

    // Convertir ruta gráfica a ruta de geometría
    IGeometryPath textPath = ShapeUtil.graphicsPathToGeometryPath(graphicsPath);
    textPath.setFillMode(PathFillModeType.Normal);

    // Establecer combinación de la nueva ruta de geometría y la ruta de geometría original en la forma
    shape.setGeometryPaths(new IGeometryPath[] { originalPath, textPath });
} finally {
    if (pres != null) pres.dispose();
}

example5_image

FAQ

¿Qué sucederá con el relleno y el contorno después de reemplazar la geometría?

El estilo permanece con la forma; solo el contorno cambia. El relleno y el contorno se aplican automáticamente a la nueva geometría.

¿Cómo rotar correctamente una forma personalizada junto con su geometría?

Utilice el método setRotation de la forma; la geometría gira con la forma porque está vinculada al propio sistema de coordenadas de la forma.

¿Puedo convertir una forma personalizada en una imagen para “bloquear” el resultado?

Sí. Exporte el área de la diapositiva requerida o la propia forma a un formato raster; esto simplifica el trabajo posterior con geometrías complejas.