Personalizar formas de presentación en .NET
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 los puntos del 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 editar formas

Antes de comenzar a editar formas de PowerPoint mediante puntos de edición, quizá desee considerar los siguientes aspectos sobre las formas:
- Una forma (o su ruta) puede ser cerrada o abierta.
- Todas las formas constan de al menos 2 puntos de anclaje vinculados entre sí por líneas
- Una línea es recta o curva. Los puntos de anclaje determinan la naturaleza de la línea.
- Los puntos de anclaje pueden ser 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 a 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 a 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 proporciona la clase GeometryPath y la interfaz IGeometryPath.
- Una instancia de GeometryPath representa una ruta geométrica del objeto IGeometryShape.
- Para obtener el
GeometryPathde la instanciaIGeometryShape, puede usar el método IGeometryShape.GetGeometryPaths. - Para establecer el
GeometryPathde una forma, puede usar estos métodos: IGeometryShape.SetGeometryPath para formas sólidas y IGeometryShape.SetGeometryPaths para formas compuestas. - Para agregar segmentos, puede usar los métodos bajo IGeometryPath.
- Usando las propiedades IGeometryPath.Stroke y IGeometryPath.FillMode, puede establecer la apariencia de una ruta geométrica.
- Con la propiedad IGeometryPath.PathData, puede obtener la ruta geométrica de un
GeometryShapecomo una matriz de segmentos de ruta. - Para acceder a opciones adicionales de personalización de geometría de forma, puede convertir GeometryPath a GraphicsPath
- Use los métodos GeometryPathToGraphicsPath y GraphicsPathToGeometryPath (de la clase ShapeUtil) para convertir GeometryPath a GraphicsPath y viceversa.
Operaciones de edición simples
Este código C# le muestra cómo
Agregar una línea al final de una ruta
void LineTo(PointF point);
void LineTo(float x, float y);
Agregar una línea a una posición especificada en una ruta:
void LineTo(PointF point, uint index);
void LineTo(float x, float y, uint index);
Agregar una curva cúbica de Bézier al final de una ruta:
void CubicBezierTo(PointF point1, PointF point2, PointF point3);
void CubicBezierTo(float x1, float y1, float x2, float y2, float x3, float y3);
Agregar una curva cúbica de Bézier a la posición especificada en una ruta:
void CubicBezierTo(PointF point1, PointF point2, PointF point3, uint index);
void CubicBezierTo(float x1, float y1, float x2, float y2, float x3, float y3, uint index);
Agregar una curva cuadrática de Bézier al final de una ruta:
void QuadraticBezierTo(PointF point1, PointF point2);
void QuadraticBezierTo(float x1, float y1, float x2, float y2);
Agregar una curva cuadrática de Bézier a la posición especificada en una ruta:
void QuadraticBezierTo(PointF point1, PointF point2, uint index);
void QuadraticBezierTo(float x1, float y1, float x2, float y2, uint index);
Adjuntar un arco dado a una ruta:
void ArcTo(float width, float heigth, float startAngle, float sweepAngle);
Cerrar la figura actual de una ruta:
void CloseFigure();
Establecer la posición para el siguiente punto:
void MoveTo(PointF point);
void MoveTo(float x, float y);
Eliminar el segmento de ruta en un índice dado:
void RemoveAt(int index);
Agregar puntos personalizados a una forma
- Crear una instancia de la clase GeometryShape y establecer el tipo ShapeType.Rectangle.
- Obtener una instancia de la clase GeometryPath de la forma.
- Agregar un nuevo punto entre los dos puntos superiores de la ruta.
- Agregar un nuevo punto entre los dos puntos inferiores de la ruta.
- Aplicar la ruta a la forma.
Este código C# le muestra cómo agregar puntos personalizados a una forma:
using (Presentation pres = new Presentation())
{
GeometryShape shape = pres.Slides[0].Shapes.AddAutoShape(ShapeType.Rectangle, 100, 100, 200, 100) as GeometryShape;
IGeometryPath geometryPath = shape.GetGeometryPaths()[0];
geometryPath.LineTo(100, 50, 1);
geometryPath.LineTo(100, 50, 4);
shape.SetGeometryPath(geometryPath);
}

Eliminar puntos de una forma
- Crear una instancia de la clase GeometryShape y establecer el tipo ShapeType.Heart.
- Obtener una instancia de la clase GeometryPath de la forma.
- Eliminar el segmento de la ruta.
- Aplicar la ruta a la forma.
Este código C# le muestra cómo eliminar puntos de una forma:
using (Presentation pres = new Presentation())
{
GeometryShape shape = pres.Slides[0].Shapes.AddAutoShape(ShapeType.Heart, 100, 100, 300, 300) as GeometryShape;
IGeometryPath path = shape.GetGeometryPaths()[0];
path.RemoveAt(2);
shape.SetGeometryPath(path);
}

Crear una forma personalizada
- Calcular los puntos para la forma.
- Crear una instancia de la clase GeometryPath.
- Rellenar la ruta con los puntos.
- Crear una instancia de la clase GeometryShape.
- Aplicar la ruta a la forma.
Este C# le muestra cómo crear una forma personalizada:
List<PointF> points = new List<PointF>();
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 PointF((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 PointF((float)x + R, (float)y + R));
}
GeometryPath starPath = new GeometryPath();
starPath.MoveTo(points[0]);
for (int i = 1; i < points.Count; i++)
{
starPath.LineTo(points[i]);
}
starPath.CloseFigure();
using (Presentation pres = new Presentation())
{
GeometryShape shape = pres.Slides[0].Shapes.AddAutoShape(ShapeType.Rectangle, 100, 100, R * 2, R * 2) as GeometryShape;
shape.SetGeometryPath(starPath);
}

Crear una forma personalizada compuesta
- Crear una instancia de la clase GeometryShape.
- Crear una primera instancia de la clase GeometryPath.
- Crear una segunda instancia de la clase GeometryPath.
- Aplicar las rutas a la forma.
Este código C# le muestra cómo crear una forma personalizada compuesta:
using (Presentation pres = new Presentation())
{
GeometryShape shape = pres.Slides[0].Shapes.AddAutoShape(ShapeType.Rectangle, 100, 100, 200, 100) as GeometryShape;
GeometryPath geometryPath0 = new GeometryPath();
geometryPath0.MoveTo(0, 0);
geometryPath0.LineTo(shape.Width, 0);
geometryPath0.LineTo(shape.Width, shape.Height/3);
geometryPath0.LineTo(0, shape.Height / 3);
geometryPath0.CloseFigure();
GeometryPath geometryPath1 = new GeometryPath();
geometryPath1.MoveTo(0, shape.Height/3 * 2);
geometryPath1.LineTo(shape.Width, shape.Height / 3 * 2);
geometryPath1.LineTo(shape.Width, shape.Height);
geometryPath1.LineTo(0, shape.Height);
geometryPath1.CloseFigure();
shape.SetGeometryPaths(new GeometryPath[] { geometryPath0, geometryPath1});
}

Crear una forma personalizada con esquinas curvas
Este código C# le muestra cómo crear una forma personalizada con esquinas curvas (hacia adentro);
var shapeX = 20f;
var shapeY = 20f;
var shapeWidth = 300f;
var shapeHeight = 200f;
var leftTopSize = 50f;
var rightTopSize = 20f;
var rightBottomSize = 40f;
var leftBottomSize = 10f;
using (var presentation = new Presentation())
{
var childShape = presentation.Slides[0].Shapes.AddAutoShape(
ShapeType.Custom, shapeX, shapeY, shapeWidth, shapeHeight);
var geometryPath = new GeometryPath();
var point1 = new PointF(leftTopSize, 0);
var point2 = new PointF(shapeWidth - rightTopSize, 0);
var point3 = new PointF(shapeWidth, shapeHeight - rightBottomSize);
var point4 = new PointF(leftBottomSize, shapeHeight);
var point5 = new PointF(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);
presentation.Save("output.pptx", SaveFormat.Pptx);
}
Descubrir si la geometría de una forma está cerrada
Una forma cerrada se define como aquella donde todos sus lados se conectan, formando un único 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 comprobar si la geometría de una forma está cerrada:
bool IsGeometryClosed(IGeometryShape geometryShape)
{
bool? isClosed = null;
foreach (var geometryPath in geometryShape.GetGeometryPaths())
{
var dataLength = geometryPath.PathData.Length;
if (dataLength == 0)
continue;
var lastSegment = geometryPath.PathData[dataLength - 1];
isClosed = lastSegment.PathCommand == PathCommandType.Close;
if (isClosed == false)
return false;
}
return isClosed == true;
}
Convertir GeometryPath a GraphicsPath (System.Drawing.Drawing2D)
- Crear una instancia de la clase GeometryShape.
- Crear una instancia de la clase GraphicsPath del espacio de nombres System.Drawing.Drawing2D.
- Convertir la instancia GraphicsPath a la instancia GeometryPath usando ShapeUtil.
- Aplicar las rutas a la forma.
Este código C#—una implementación de los pasos anteriores—demuestra el proceso de conversión de GeometryPath a GraphicsPath:
using (Presentation pres = new Presentation())
{
GeometryShape shape = pres.Slides[0].Shapes.AddAutoShape(ShapeType.Rectangle, 100, 100, 300, 100) as GeometryShape;
IGeometryPath originalPath = shape.GetGeometryPaths()[0];
originalPath.FillMode = PathFillModeType.None;
GraphicsPath gPath = new GraphicsPath();
gPath.AddString("Text in shape", new FontFamily("Arial"), 1, 40, new PointF(10, 10), StringFormat.GenericDefault);
IGeometryPath textPath = ShapeUtil.GraphicsPathToGeometryPath(gPath);
textPath.FillMode = PathFillModeType.Normal;
shape.SetGeometryPaths(new[] {originalPath, textPath}) ;
}

Preguntas frecuentes
¿Qué ocurrirá 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 la propiedad rotation 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 a 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.