본문 바로가기
programming/Graphics

svg path 패스 3차 베지에곡선 이해 Cubic Bézier Curve

by 개코 - 개발과 코딩 2021. 9. 17.

3차 베지에곡선은 조절점을 2개를 이용해 점의 이동경로를 선으로 그리게 된다. 조절점이 하나만 있는 베지어곡선보다 조금 더 복잡한 곡선을 그릴 수 있다. 조절점을 위치시키면서 곡선의 형태를 다양하게 변형할 수 있다. 3차베지에 곡선까지 개념만 충분히 이해하면 그 이상의 베지에곡선을 이해하는 것은 어렵지 않다.

svg path 패스 3차 베지에곡선 이해
Cubic Bézier Curve

2차 베지어곡선은 시작점과 끝점 조절점이 1개지만 3차 베지에곡선은 큐빅 베지에곡선으로 시작점과 끝점이 존재하고 조절점이 2개가 존재한다.

차수가 점차 증가할 수록 베지에곡선은 복잡해지며 점차 정교해 진다.

2차와 3차 베지에곡선을 이해하면 차수가 증가하더라도 베지에곡선의 이해가 쉽다.

3차 큐빅 베지에곡선의 인자값의 사용은 아래와 같다.

  • M 시작점 좌표
  • C 첫번째 조절점 좌표, 두번재 조절점 좌표, 끝점 좌표

 

svg path 베지어곡선 그리기

3차 베지에곡선을 그려본다.

3차 베지에곡선의 인자값은 위에서도 언급했다.

  • M 시작점좌표, C 첫번째 조절점 좌표, 두번째 조절점 좌표, 끝점 좌표

위의 좌표구성만 이해하면 쉽다.

<html>
    <body>

        <h1>SVG 3차 베지에곡선 그리기</h1>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 50,50 250,50 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="50" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="250" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 50,250 250,250 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="50" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="250" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

    </body>
</html>

2개의 베지에곡선을 그렸다.

빨간색 점은 조절점이다.

검은색 점은 각각 시작점과 끝점이다.

위의 코드에서 중요한 곳은 path d="" 부분이다.

조절점의 위치만 바꾸더라도 전혀 새로운 곡선이 생성된다.

 

조절점 위치 변경하기

위에서 그린 3차 베지어곡선에서 조절점의 간격을 줄여보자.

곡선이 조금 뾰족해 보이는 것을 알 수 있다.

<html>
    <body>

        <h1>SVG 3차 베지에곡선 그리기</h1>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 100,50 200,50 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 100,250 200,250 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

    </body>
</html>

조절점의 간격을 줄인 것만으로도 곡선의 간격 또한 줄어드는 것을 알 수 있다.

조절점의 위치가 어디에 있는가에 따라 곡선의 형태는 당연히 달라진다.

 

조절점 위치를 다양하게 변경하기

바로 위의 결과를 이용해 조절점을 위에서 아래로 하나씩 위치를 변경해 보도록 하자.

곡선의 형태가 물결을 이루는 것을 알 수 있다.

<html>
    <body>

        <h1>SVG 3차 베지에곡선 그리기</h1>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 100,50 200,50 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 100,150 200,50 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="150" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 100,250 200,50 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 100,250 200,50 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 100,250 200,150 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="150" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 100,250 200,250 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

    </body>
</html>

첫번째 조절점을 위에서 아래로 이동시킬 때마다 선 또한 아래로 내려가고 있다.

두번째 조절점을 위에서 아래로 이동시킬 때마다 선 또한 아래로 내려가고 있다.

점의 간격이 클 수록 곡선은 급격해지고, 간격이 좁을 수록 완만해 진다.

이런 곡선 또한 조절점의 위치를 반대로 위치시켜도 전혀 다른 결과를 보여준다.

<html>
    <body>

        <h1>SVG 3차 베지에곡선 그리기</h1>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 200,50 100,50 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 200,50 100,150 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="150" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 200,50 100,250 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 200,50 100,250 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="50" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 200,150 100,250 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="150" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

        <svg height="300" width="300" style="border:1px solid black;">

            <path d="M 50,150 C 200,250 100,250 250,150" 
                stroke="#ff0000" fill="none" stroke-width="1" stroke-linecap="round" />

            <circle cx="50" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="250" cy="150" r="3" stroke="black" stroke-width="0" fill="black" />
            <circle cx="100" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />
            <circle cx="200" cy="250" r="3" stroke="black" stroke-width="0" fill="red" />

        </svg>

    </body>
</html>

위의 결과와 전혀 다르다.

조절점의 위치만 바꿔줬을 뿐이다.

 

베지어곡선이 그려지는 과정

베지어곡선이 그려지는 과정은 이전 포스팅에서도 거론했다.

하지만, 이 곡선이 어떻게 이렇게 정교하게 그려지는 것은 이해하는 것이 쉽지는 않다.

점이 모여 선을 이룬다.

점이 모여 만들어진 선을 지나는 점의 이동경로를 연속하여 연결하면 곡선처럼 보인다.

이 관점을 토대로 아래의 이미지를 보도록 하자.

베지어곡선이 어떻게 그려지는 것인지 이해가 될 것이다.

반응형

댓글