# Java에서 프레젠테이션 형상 맞춤화

> Aspose.Slides for Java를 사용하여 PowerPoint 프레젠테이션에서 형상을 만들고 맞춤화합니다: 기하학 경로, 곡선 모서리, 복합 형상.

Source: https://docs.aspose.com/slides/ko/java/custom-shape/
Updated: 2026-06-14

## **개요**

이 문서는 편집 포인트와 기하학 경로를 통해 형상 기하학을 편집하여 Aspose.Slides에서 프레젠테이션 형상을 사용자 지정하는 방법을 설명합니다. `GeometryPath`와 `IGeometryPath`를 사용하여 기존 형상을 수정하고, 기본 경로 편집 작업을 수행하며, 포인트를 추가하거나 제거하고, 업데이트된 기하학을 형상에 다시 적용하는 방법을 보여줍니다.

또한 사용자 정의 및 복합 형상을 만들고, 곡선 모서리를 가진 형상을 구성하며, 형상 기하학이 폐쇄된 것인지 여부를 확인하고, 추가적인 기하학 사용자 지정 시나리오를 위해 `GeometryPath`와 `java.awt.Shape` 간에 변환하는 방법을 시연합니다.

## **편집 포인트를 사용하여 형상 변경**

정사각형을 고려해 보십시오. PowerPoint에서 **edit points**를 사용하면

* 정사각형 모서리를 안쪽이나 바깥쪽으로 이동
* 모서리나 포인트의 곡률 지정
* 정사각형에 새로운 포인트 추가
* 정사각형의 포인트 조작 등

본질적으로, 이러한 작업을 모든 형상에 대해 수행할 수 있습니다. 편집 포인트를 사용하면 기존 형상에서 새로운 형상을 변경하거나 만들 수 있습니다.

## **형상 편집 팁**

![overview_image](custom_shape_0.png)

PowerPoint 형상을 편집 포인트를 통해 편집하기 전에 다음 형상에 대한 사항을 고려하십시오:

* 형상(또는 그 경로)은 폐쇄될 수도 있고 열릴 수도 있습니다.
* 형상이 폐쇄된 경우 시작점이나 끝점이 없습니다. 열려 있는 경우 시작점과 끝점이 있습니다.
* 모든 형상은 최소 2개의 앵커 포인트가 선으로 연결되어 구성됩니다.
* 선은 직선이거나 곡선일 수 있으며, 앵커 포인트가 선의 형태를 결정합니다.
* 앵커 포인트는 코너 포인트, 직선 포인트, 혹은 부드러운 포인트로 존재합니다:
  * 코너 포인트는 두 개의 직선이 각을 이루며 만나는 지점입니다.
  * 부드러운 포인트는 두 개의 핸들이 직선상에 존재하고 선분이 부드러운 곡선으로 연결되는 지점입니다. 이 경우 모든 핸들은 앵커 포인트와 같은 거리를 둡니다.
  * 직선 포인트는 두 개의 핸들이 직선상에 존재하지만 선분이 부드러운 곡선으로 연결되는 지점입니다. 이 경우 핸들은 앵커 포인트와 동일한 거리를 유지할 필요가 없습니다.
* 앵커 포인트를 이동하거나 편집하여(선의 각도를 변경) 형상의 모양을 바꿀 수 있습니다.

PowerPoint 형상을 편집 포인트를 통해 편집하려면 **Aspose.Slides**가 [**GeometryPath**](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryPath) 클래스와 [**IGeometryPath**](https://reference.aspose.com/slides/ko/java/com.aspose.slides/IGeometryPath) 인터페이스를 제공합니다.

* A [GeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryPath) 인스턴스는 [IGeometryShape](https://reference.aspose.com/slides/ko/java/com.aspose.slides/IGeometryShape) 객체의 기하학 경로를 나타냅니다.
* `IGeometryShape` 인스턴스에서 `GeometryPath`를 가져오려면 [IGeometryShape.getGeometryPaths](https://reference.aspose.com/slides/ko/java/com.aspose.slides/IGeometryShape#getGeometryPaths--) 메서드를 사용할 수 있습니다.
* 형상의 `GeometryPath`를 설정하려면 *solid shapes* 에는 [IGeometryShape.setGeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/IGeometryShape#setGeometryPath-com.aspose.slides.IGeometryPath-) 를, *composite shapes* 에는 [IGeometryShape.setGeometryPaths](https://reference.aspose.com/slides/ko/java/com.aspose.slides/IGeometryShape#setGeometryPaths-com.aspose.slides.IGeometryPath:A-) 를 사용합니다.
* 세그먼트를 추가하려면 [IGeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/IGeometryPath) 아래의 메서드를 사용할 수 있습니다.
* [IGeometryPath.setStroke](https://reference.aspose.com/slides/ko/java/com.aspose.slides/IGeometryPath#setStroke-boolean-) 및 [IGeometryPath.setFillMode](https://reference.aspose.com/slides/ko/java/com.aspose.slides/IGeometryPath#setFillMode-byte-) 메서드를 사용하여 기하학 경로의 외관을 설정할 수 있습니다.
* [IGeometryPath.getPathData](https://reference.aspose.com/slides/ko/java/com.aspose.slides/IGeometryPath#getPathData--) 메서드를 사용하면 `GeometryShape`의 기하학 경로를 경로 세그먼트 배열로 가져올 수 있습니다.
* 추가 형상 기하학 사용자 지정 옵션에 액세스하려면 [GeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryPath)를 [java.awt.Shape](https://docs.oracle.com/javase/7/docs/api/java/awt/Shape.html)으로 변환할 수 있습니다.
* [ShapeUtil](https://reference.aspose.com/slides/ko/java/com.aspose.slides/ShapeUtil) 클래스의 [geometryPathToGraphicsPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/ShapeUtil#geometryPathToGraphicsPath-com.aspose.slides.IGeometryPath-) 및 [graphicsPathToGeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/ShapeUtil#graphicsPathToGeometryPath-java.awt.Shape-) 메서드를 사용하여 [GeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryPath)를 [java.awt.Shape](https://docs.oracle.com/javase/7/docs/api/java/awt/Shape.html)으로 왔다갔다 변환합니다.

## **간단한 편집 작업**

다음 Java 코드는 방법을 보여줍니다.

**선 추가**  
``` java
public void lineTo(java.awt.geom.Point2D.Float point);
public void lineTo(float x, float y);
```
**경로의 지정된 위치에 선 추가**:  
``` java    
public void lineTo(java.awt.geom.Point2D.Float point, long index);
public void lineTo(float x, float y, long index);
```
**경로 끝에 3차 베지에 곡선 추가**:  
``` java
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);
```
**경로의 지정된 위치에 3차 베지에 곡선 추가**:  
``` java
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);
```
**경로 끝에 2차 베지에 곡선 추가**:  
``` java
public void quadraticBezierTo(java.awt.geom.Point2D.Float point1, java.awt.geom.Point2D.Float point2);
public void quadraticBezierTo(float x1, float y1, float x2, float y2);
```
**경로의 지정된 위치에 2차 베지에 곡선 추가**:  
``` java
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);
```
**주어진 호를 경로에 추가**:  
``` java
public void arcTo(float width, float heigth, float startAngle, float sweepAngle);
```
**경로의 현재 도형 닫기**:  
``` java
public void closeFigure();
```
**다음 포인트의 위치 설정**:  
``` java
public void moveTo(java.awt.geom.Point2D.Float point);
public void moveTo(float x, float y);
```
**주어진 인덱스의 경로 세그먼트 제거**:  
``` java
public void removeAt(int index);
```

## **형상에 사용자 정의 포인트 추가**
1. [GeometryShape](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryShape) 클래스의 인스턴스를 생성하고 [ShapeType.Rectangle](https://reference.aspose.com/slides/ko/java/com.aspose.slides/ShapeType) 유형을 설정합니다.
2. 형상에서 [GeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryPath) 클래스의 인스턴스를 가져옵니다.
3. 경로의 상단 두 포인트 사이에 새로운 포인트를 추가합니다.
4. 경로의 하단 두 포인트 사이에 새로운 포인트를 추가합니다.
5. 경로를 형상에 적용합니다.

다음 Java 코드는 형상에 사용자 정의 포인트를 추가하는 방법을 보여줍니다:

``` java
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](custom_shape_1.png)

## **형상에서 포인트 제거**

1. [GeometryShape](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryShape) 클래스의 인스턴스를 생성하고 [ShapeType.Heart](https://reference.aspose.com/slides/ko/java/com.aspose.slides/ShapeType) 유형을 설정합니다.
2. 형상에서 [GeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryPath) 클래스의 인스턴스를 가져옵니다.
3. 경로의 세그먼트를 제거합니다.
4. 경로를 형상에 적용합니다.

다음 Java 코드는 형상에서 포인트를 제거하는 방법을 보여줍니다:

``` java
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](custom_shape_2.png)

## **사용자 정의 형상 만들기**
1. 형상의 포인트를 계산합니다.
2. [GeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryPath) 클래스의 인스턴스를 생성합니다.
3. 포인트를 사용하여 경로를 채웁니다.
4. [GeometryShape](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryShape) 클래스의 인스턴스를 생성합니다.
5. 경로를 형상에 적용합니다.

다음 Java 코드는 사용자 정의 형상을 만드는 방법을 보여줍니다:

``` java
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](custom_shape_3.png)


## **복합 사용자 정의 형상 만들기**

1. [GeometryShape](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryShape) 클래스의 인스턴스를 생성합니다.
2. [GeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryPath) 클래스의 첫 번째 인스턴스를 생성합니다.
3. [GeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryPath) 클래스의 두 번째 인스턴스를 생성합니다.
4. 경로들을 형상에 적용합니다.

다음 Java 코드는 복합 사용자 정의 형상을 만드는 방법을 보여줍니다:

``` java
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](custom_shape_4.png)

## **곡선 모서리를 가진 사용자 정의 형상 만들기**

다음 Java 코드는 내부로 굽은 곡선 모서리를 가진 사용자 정의 형상을 만드는 방법을 보여줍니다:

```java
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();
}
```

## **형상 기하학이 폐쇄되었는지 확인하기**

폐쇄된 형상은 모든 측면이 연결되어 틈 없이 단일 경계를 형성하는 형태로 정의됩니다. 이러한 형상은 단순한 기하학 형태일 수도 있고 복잡한 사용자 정의 윤곽일 수도 있습니다. 아래 코드 예제는 형상 기하학이 폐쇄되었는지 확인하는 방법을 보여줍니다:

```java
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;
}
```

## **GeometryPath를 java.awt.Shape로 변환**

1. [GeometryShape](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryShape) 클래스의 인스턴스를 생성합니다.
2. [java.awt.Shape](https://docs.oracle.com/javase/7/docs/api/java/awt/Shape.html) 클래스의 인스턴스를 생성합니다.
3. [ShapeUtil](https://reference.aspose.com/slides/ko/java/com.aspose.slides/ShapeUtil)을 사용하여 [java.awt.Shape](https://docs.oracle.com/javase/7/docs/api/java/awt/Shape.html) 인스턴스를 [GeometryPath](https://reference.aspose.com/slides/ko/java/com.aspose.slides/GeometryPath) 인스턴스로 변환합니다.
4. 경로를 형상에 적용합니다.

다음 Java 코드는 위 단계들을 구현한 것으로 **GeometryPath**를 **GraphicsPath**로 변환하는 과정을 시연합니다:

``` java
Presentation pres = new Presentation();
try {
    // 새 형상 만들기
    GeometryShape shape = (GeometryShape)pres.getSlides().get_Item(0).
            getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 300, 100);

    // 형상의 기하학 경로 가져오기
    IGeometryPath originalPath = shape.getGeometryPaths()[0];
    originalPath.setFillMode(PathFillModeType.None);

    // 텍스트가 포함된 새 그래픽 경로 만들기
    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();
    }

    // 그래픽 경로를 기하학 경로로 변환
    IGeometryPath textPath = ShapeUtil.graphicsPathToGeometryPath(graphicsPath);
    textPath.setFillMode(PathFillModeType.Normal);

    // 새 기하학 경로와 원래 기하학 경로의 조합을 형상에 설정
    shape.setGeometryPaths(new IGeometryPath[] { originalPath, textPath });
} finally {
    if (pres != null) pres.dispose();
}
```
![example5_image](custom_shape_5.png)

## **FAQ**

**기하학을 교체한 후 채우기와 외곽선은 어떻게 됩니까?**  
스타일은 형상에 그대로 유지되며, 윤곽선만 변경됩니다. 채우기와 외곽선은 새 기하학에 자동으로 적용됩니다.

**사용자 정의 형상과 그 기하학을 어떻게 올바르게 회전합니까?**  
형상의 [setRotation](https://reference.aspose.com/slides/ko/java/com.aspose.slides/shape/#setRotation-float-) 메서드를 사용하십시오; 기하학은 형상의 좌표계에 결합되어 있기 때문에 형상과 함께 회전합니다.

**결과를 '고정'하기 위해 사용자 정의 형상을 이미지로 변환할 수 있나요?**  
예. 필요한 [slide](/slides/ko/java/convert-powerpoint-to-png/) 영역이나 [shape](/slides/ko/java/create-shape-thumbnails/) 자체를 래스터 형식으로 내보내면 복잡한 기하학을 다루는 작업이 간소화됩니다.
