C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[932] 여러가지 Spline 보간법(interpolation : 내삽법)의 도입
Nibble [gameover] 12267 읽음    2009-11-11 13:00
대표적인 Spline들은 다음과 같습니다.

복잡한 곡선을 분할해(spline) 3차 다항식의 근사를 이용하기 때문에 모두 4개의 샘플값을 인자로 받고(v0, v1, v2, v3), 추가적으로 주어진 구간중 어디를 원하는지를 t1을 통해 인자로 받게 됩니다.

inline float catmullRom(float t1, float v0, float v1, float v2, float v3)
{
    float t2 = t1 * t1;
    float t3 = t2 * t1;
    return ((      - t3 + 2.0f * t2        - t1       ) * v0 +
            ( 3.0f * t3 - 5.0f * t2             + 2.0f) * v1 +
            (-3.0f * t3 + 4.0f * t2        + t1       ) * v2 +
            (        t3        - t2                   ) * v3) / 2.0f;
}

inline float bSpline(float t1, float v0, float v1, float v2, float v3)
{
    float t2 = t1 * t1;
    float t3 = t2 * t1;
    return ((      - t3 + 3.0f * t2 - 3.0f * t1 + 1.0f) * v0 +
            ( 3.0f * t3 - 6.0f * t2             + 4.0f) * v1 +
            (-3.0f * t3 + 3.0f * t2 + 3.0f * t1 + 1.0f) * v2 +
            (        t3                               ) * v3) / 6.0f;
}

inline float hermite(float t1, float v0, float v1, float v2, float v3)
{
    float t2 = t1 * t1;
    float t3 = t2 * t1;
    return (( 2.0f * t3 - 3.0f * t2             + 1.0f) * v0 +
            (-2.0f * t3 + 3.0f * t2                   ) * v1 +
            (        t3 - 2.0f * t2       + t1        ) * v2 +
            (        t3        - t2                   ) * v3);
}

inline float bezier(float t1, float v0, float v1, float v2, float v3)
{
    float t2 = t1 * t1;
    float t3 = t2 * t1;
    return ((      - t3 + 3.0f * t2 - 3.0f * t1 + 1.0f) * v0 +
            ( 3.0f * t3 - 6.0f * t2 + 3.0f * t1       ) * v1 +
            (-3.0f * t3 + 3.0f * t2                   ) * v2 +
            (        t3                               ) * v3);
}


v0, v1, v2, v3 는 각각 4개의 점의 y좌표라 생각하시면 되고,
t1은 v1 과 v2사이의 어디를 보간할 것인가를 0과 1 사이의 값으로 전달한 인자입니다.
v1 v2사이의 t1거리에 해당하는 v값을 리턴합니다.

위 함수중 하나를 선택하셔서, x에 대해 보간하시고, y에 대해 보간하시면 2차원상의 보간이,
x, y, z 에 대해 보간하시면 3차원상의 보간이 되는거죠.
물론 1차원 보간이 필요할 뿐이라면 x에 대해서만 보간하시면 됩니다.

catmullRom 은 해당하는 v값들을 정확히 지나는 특성을 가지고,
bSpline이나 bezier는 그러지 못하며, bSpline은 가장 완만한 형태를 갖게 됩니다.
hermite는 위와 달리 인자로 v0, v1을 지날때의 기울기를 추가 인자로받게 되는데,
이를 0으로 셋팅하면 각점을 수평으로 지나는 곡선을 얻을 수 있고,
지그재그로 표현되는 주파수의 변곡점을 수평으로 보간할때 유용하게 사용하실 수 있을 뿐 아니라
변곡점의 기울기가 0일때는 당연히 표현도 줄어들게 됩니다.

inline float hermite0(float t1, float v0, float v1)
{
    float t2 = t1 * t1;
    float t3 = t2 * t1;
    return (( 2.0f * t3 - 3.0f * t2             + 1.0f) * v0 +
            (-2.0f * t3 + 3.0f * t2                   ) * v1);
}


많은 자료를 고속으로 처리해야 할 때 위에 열거한 spline 들의 atom 함수를 최적화 하기 위한 포인트는
v0, v1, v2, v3의 재사용입니다.
만약 등간격의 monotone 을 구현하신다면, (증가 또는 감소만 하는)
t1, t2, t3도 재사용해 보다 빠른 코드(곱하기 네 번, 더하기 세 번, 대입 한 번만 하는 코드)를 작성하실 수 있습니다.
이치고 [seokj777]   2014-11-22 12:21 X
각 점들의 앞/뒤로 일정간격만 직선 구간이 되고 나머지는 모두 보간 피팅 되도록 하는 방법은 없을까요?
계속 고민하고 있는 중인데 도움 부탁드립니다.
이치고 [seokj777]   2014-11-22 12:24 X
예를들어  2차원 상에 5개의 포인트(x,y)가 있고 이들의 점의 앞과 뒤에 각각 1만큼의 직선 구간이 (결국 포인트 3개의 연결되어 길이는 2가되는)
있고 앞/뒤에 있는 것을 제외한 나머지 포인트들만 곡선으로 보간되는 방법이 필요 합니다만...

+ -

관련 글 리스트
932 여러가지 Spline 보간법(interpolation : 내삽법)의 도입 Nibble 12267 2009/11/11
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.