Hermite spline
- 퓨림노
- Module/Algorithm
- 2008. 11. 26.
< 참고 URL >
*참고한 공식 Site !
http://www.siggraph.org/education/materials/HyperGraph/modeling/splines/hermite.htm
http://blog.naver.com/millinya?Redirect=Log&logNo=40053907534
http://en.wikipedia.org/wiki/Catmull-Rom_spline#Interpolation_on_a_single_interval
*곡선의 데모를 볼수있는곳( Hermite, Bezier, B-Spline )
http://www.siggraph.org/education/materials/HyperGraph/modeling/splines/demoprog/curve.html
* API 로된 소스 & 자료
http://cstudy.co.kr/bbs/view.php?id=na_report&page=3&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=31
참고 URL 을 따라가면...상세한 공식 설명이 나옵니다.
그리고 중요한 공식하나...만!
x(t) = TMHGHx = P1x(2t^3 - 3t^2 + 1) + P4x(-2t^3 + 3t^2) + R1x(t^3 - 2t^2 + t) + R4X(t^3 - t^2)
이게 무슨말이냐!? 후훗..
첫 start point, end point 와 탄젠트 값 2개만 있으면 구할수 있습니다.
탄젠트의 값은 그냥 일반적으로 지정해주고 하네요...
다른예제들 보니 특별히 따로 계산하지 않은것 같더라구요. ㅎㅎㅎ
먼저 제가 site 를 보고 계산한 방법 부터 하겠습니다.
My Hermite Source 다운! ㅎ ->?
각 함수 4개를 만듭니다.
double HermiteF1( double t )
{
double result;
result = 1 -3*pow(t,2) + 2*pow(t,3);
return result;
}
double HermiteF2( double t )
{
double result;
result = 3*pow(t,2) - 2*pow(t,3);
return result;
}
double HermiteF3( double t )
{
double result;
result = t-2*pow(t,2) + pow(t,3);
return result;
}
double HermiteF4( double t )
{
double result;
result = -1 * pow(t,2) + pow(t,3);
return result;
}
// 각 점의 좌표를 가지고 아래의 공식으로 점의 좌표를 구합니다. ( 계속 그림...반복문을 돌며...)
/* x */ v[0] = CP[i][0]*HermiteF1(t) + CP[i+1][0]*HermiteF2(t) + 10*HermiteF3(t) + 10*HermiteF4(t);
/* y */ v[1] = CP[i][1]*HermiteF1(t) + CP[i+1][1]*HermiteF2(t) + 300*HermiteF3(t) + 300*HermiteF4(t);
v[1] = wh - v[1]; // 좌표 뒤집기
glVertex3dv(v);
t += 0.01;
if( CP[i+1][0] == 0 && CP[i+1][1] == 0 )
break;
참고 URL 을 따라가심 나온..소스! 아래 부붙 참조바랍니다.
API 소스 - 다운받기 ->
-
// Hermite Spline.cpp : Defines the entry point for the application.
-
//
-
-
#include "stdafx.h"
-
#include "resource.h"
-
-
// 좌표를 저장할 구조체 변수
-
// POINT형을 사용하면 되나 소수점 좌표도 처리하기 위해서 사용한다.
-
typedef struct Apt {
-
double x;
-
double y;
-
} Apt;
-
-
#define MAX_LOADSTRING 100
-
-
// 변수 선언 & 초기화 및 함수 선언
-
Apt HermiteSpline(Apt G[4], double t);
-
void DrawHermite(HDC hdc, Apt G[4]);
-
Apt G[4] = {{190, 230}, {570, 230}, {380, 115}, {380, 345}};
-
-
// Global Variables:
-
HINSTANCE hInst; // current instance
-
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
-
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
-
-
// Foward declarations of functions included in this code module:
-
ATOM MyRegisterClass(HINSTANCE hInstance);
-
BOOL InitInstance(HINSTANCE, int);
-
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
-
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
-
-
int APIENTRY WinMain(HINSTANCE hInstance,
-
HINSTANCE hPrevInstance,
-
LPSTR lpCmdLine,
-
int nCmdShow)
-
{
-
// TODO: Place code here.
-
MSG msg;
-
HACCEL hAccelTable;
-
-
// Initialize global strings
-
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
-
LoadString(hInstance, IDC_HERMITESPLINE, szWindowClass, MAX_LOADSTRING);
-
MyRegisterClass(hInstance);
-
-
// Perform application initialization:
-
if (!InitInstance (hInstance, nCmdShow))
-
{
-
return FALSE;
-
}
-
-
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_HERMITESPLINE);
-
-
// Main message loop:
-
while (GetMessage(&msg, NULL, 0, 0))
-
{
-
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
-
{
-
TranslateMessage(&msg);
-
DispatchMessage(&msg);
-
}
-
}
-
-
return msg.wParam;
-
}
-
-
-
-
//
-
// FUNCTION: MyRegisterClass()
-
//
-
// PURPOSE: Registers the window class.
-
//
-
// COMMENTS:
-
//
-
// This function and its usage is only necessary if you want this code
-
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
-
// function that was added to Windows 95. It is important to call this function
-
// so that the application will get 'well formed' small icons associated
-
// with it.
-
//
-
ATOM MyRegisterClass(HINSTANCE hInstance)
-
{
-
WNDCLASSEX wcex;
-
-
wcex.cbSize = sizeof(WNDCLASSEX);
-
-
wcex.style = CS_HREDRAW | CS_VREDRAW;
-
wcex.lpfnWndProc = (WNDPROC)WndProc;
-
wcex.cbClsExtra = 0;
-
wcex.cbWndExtra = 0;
-
wcex.hInstance = hInstance;
-
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_HERMITESPLINE);
-
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
-
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
-
wcex.lpszMenuName = (LPCSTR)IDC_HERMITESPLINE;
-
wcex.lpszClassName = szWindowClass;
-
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
-
-
return RegisterClassEx(&wcex);
-
}
-
-
//
-
// FUNCTION: InitInstance(HANDLE, int)
-
//
-
// PURPOSE: Saves instance handle and creates main window
-
//
-
// COMMENTS:
-
//
-
// In this function, we save the instance handle in a global variable and
-
// create and display the main program window.
-
//
-
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
-
{
-
HWND hWnd;
-
-
hInst = hInstance; // Store instance handle in our global variable
-
-
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
-
CW_USEDEFAULT, 0, 760, 460, NULL, NULL, hInstance, NULL);
-
-
if (!hWnd)
-
{
-
return FALSE;
-
}
-
-
ShowWindow(hWnd, nCmdShow);
-
UpdateWindow(hWnd);
-
-
return TRUE;
-
}
-
-
//
-
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
-
//
-
// PURPOSE: Processes messages for the main window.
-
//
-
// WM_COMMAND - process the application menu
-
// WM_PAINT - Paint the main window
-
// WM_DESTROY - post a quit message and return
-
//
-
//
-
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-
{
-
int wmId, wmEvent;
-
PAINTSTRUCT ps;
-
HDC hdc;
-
-
switch (message)
-
{
-
case WM_COMMAND:
-
wmId = LOWORD(wParam);
-
wmEvent = HIWORD(wParam);
-
// Parse the menu selections:
-
switch (wmId)
-
{
-
case IDM_ABOUT:
-
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
-
break;
-
case IDM_EXIT:
-
DestroyWindow(hWnd);
-
break;
-
default:
-
return DefWindowProc(hWnd, message, wParam, lParam);
-
}
-
break;
-
case WM_LBUTTONDOWN:
-
case WM_RBUTTONDOWN:
-
case WM_MOUSEMOVE:
-
// 마우스 왼쪽 버튼이나 오른쪽 버튼이 클릭되어 있는 동시에 control키나 shift키가
-
// 눌러졌을 시에
-
if (((wParam & MK_LBUTTON) && ((wParam & MK_CONTROL) || (wParam & MK_SHIFT)))
-
|| ((wParam & MK_RBUTTON) && ((wParam & MK_CONTROL) || (wParam & MK_SHIFT))))
-
{
-
hdc = GetDC (hWnd);
-
-
// 기존에 있던 그래프를 하얀펜으로 다시 그려서 지우는 효과를 낸다.
-
SelectObject (hdc, GetStockObject (WHITE_PEN));
-
DrawHermite (hdc, G);
-
-
// 마우스 왼쪽 버튼이 클릭되어 있을 시에
-
if (wParam & MK_LBUTTON)
-
{
-
// 마우스 왼쪽 버튼과 CONTROL키가 동시에 눌러졌을 때는
-
// 시작점의 좌표 값을 조정할 수 있도록 한다.
-
if (wParam & MK_CONTROL) {
-
G[0].x = LOWORD (lParam);
-
G[0].y = HIWORD (lParam);
-
}
-
// 마우스 왼쪽 버튼과 SHIFT키가 동시에 눌러졌을 때는
-
// 첫번 째 벡터값을 조정할 수 있도록 한다.
-
else if(wParam & MK_SHIFT) {
-
G[2].x = LOWORD (lParam);
-
G[2].y = HIWORD (lParam);
-
}
-
}
-
-
// 마우스 오른쪽 버튼이 클릭되어 있을 시에
-
if (wParam & MK_RBUTTON)
-
{
-
// 마우스 오른쪽 버튼과 CONTROL키가 동시에 눌러졌을 때는
-
// 끝점의 좌표 값을 조정할 수 있도록 한다.
-
if (wParam & MK_CONTROL) {
-
G[1].x = LOWORD (lParam);
-
G[1].y = HIWORD (lParam);
-
}
-
// 마우스 오른쪽 버튼과 SHIFT키가 동시에 눌러졌을 때는
-
// 두번 째 벡터값을 조정할 수 있도록 한다.
-
else if(wParam & MK_SHIFT) {
-
G[3].x = LOWORD (lParam);
-
G[3].y = HIWORD (lParam);
-
}
-
}
-
-
// 검정펜으로 다시 바꾸고 그려준다.
-
SelectObject (hdc, GetStockObject (BLACK_PEN));
-
DrawHermite (hdc, G);
-
ReleaseDC (hWnd, hdc);
-
}
-
break;
-
case WM_PAINT:
-
hdc = BeginPaint(hWnd, &ps);
-
// TODO: Add any drawing code here...
-
-
DrawHermite(hdc, G);
-
-
EndPaint(hWnd, &ps);
-
break;
-
case WM_DESTROY:
-
PostQuitMessage(0);
-
break;
-
default:
-
return DefWindowProc(hWnd, message, wParam, lParam);
-
}
-
return 0;
-
}
-
-
// Mesage handler for about box.
-
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
-
{
-
switch (message)
-
{
-
case WM_INITDIALOG:
-
return TRUE;
-
-
case WM_COMMAND:
-
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
-
{
-
EndDialog(hDlg, LOWORD(wParam));
-
return TRUE;
-
}
-
break;
-
}
-
return FALSE;
-
}
-
-
Apt HermiteSpline(Apt G[4], double t)
-
{
-
double t2, t3;
-
Apt Q;
-
-
// 이해하기 쉽기 위해서 t의 제곱, 세제곱의 값을 변수에 저장한다.
-
t2 = t * t;
-
t3 = t * t * t;
-
/* 시작점이 (x₁, y₁), 끝점이 (x₂, y₂)이고 벡터값이 (x₃, y₃), (x₄, y₄) 일 때
-
Hermite Spline을 구하기 위한 혼합함수는
-
x(t) = (2t³- 3t²+ 1)x₁+ (-2t³+ 3t²)x₂+ (t³- 2t²+ t)x₃+ (t³- t²)x₄
-
y(t) = (2t³- 3t²+ 1)y₁+ (-2t³+ 3t²)y₂+ (t³- 2t²+ t)y₃+ (t³- t²)y₄이다. */
-
Q.x = ((2 * t3 - 3 * t2 + 1) * G[0].x) + ((-2 * t3 + 3 * t2) * G[1].x)
-
+ ((t3 - 2 * t2 + t) * G[2].x) + ((t3 - t2) * G[3].x);
-
Q.y = ((2 * t3 - 3 * t2 + 1) * G[0].y) + ((-2 * t3 + 3 * t2) * G[1].y)
-
+ ((t3 - 2 * t2 + t) * G[2].y) + ((t3 - t2) * G[3].y);
-
-
return Q;
-
}
-
-
// Hermite Spline을 그리는 함수
-
void DrawHermite(HDC hdc, Apt G[4])
-
{
-
double t;
-
Apt Q;
-
-
// t가 0부터 1까지 변하는 값에 대해 곡선이 그려진다.
-
for(t=0; t<=1.0; t+=0.01) {
-
Q = HermiteSpline(G, t);
-
if(t==0) {
-
MoveToEx (hdc, (int) Q.x, (int) Q.y, NULL);
-
}
-
else {
-
LineTo (hdc, (int) Q.x, (int) Q.y);
-
}
-
}
-
}
그리고 참고했던 비주얼베이직으로 된 소스입니다.
Option Explicit
Dim u As Double
Dim x As Double
Dim y As Double
Dim x0 As Double, x1 As Double, y0 As Double, y1 As Double
Dim x0_p As Double, x1_p As Double, y0_p As Double, y1_p As Double
Dim k As Double
Private Sub Command1_Click()
setScaleMode
k = 3
x0 = 1: y0 = 1
x1 = 3: y1 = 1
x0_p = 1: y0_p = k
x1_p = 1: y1_p = k
u = 0
Do While u < 1
'x = x0 * f1(u) + x1 * f2(u) + x0_p * f3(u) + x1_p * f4(u)
'y = y0 * f1(u) + y1 * f2(u) + y0_p * f3(u) + y1_p * f4(u)
''x = 138 * f1(u) + 409 * f2(u) + x0_p * f3(u) + x1_p * f4(u)
''y = 322 * f1(u) + 248 * f2(u) + y0_p * f3(u) + y1_p * f4(u)
'x = 1 * f1(u) + 4 * f2(u) + x0_p * f3(u) + x1_p * f4(u)
'y = 3 * f1(u) + 2 * f2(u) + y0_p * f3(u) + y1_p * f4(u)
x = 1 * f1(u) + 3 * f2(u) + x0_p * f3(u) + x1_p * f4(u)
y = 1 * f1(u) + 1 * f2(u) + y0_p * f3(u) + y1_p * f4(u)
Debug.Print "u:" + CStr(u), "x:" + CStr(x), "y:" + CStr(y)
u = u + 0.01
If x > 5 Then Exit Do
Picture1.PSet (x, y)
Loop
End Sub
Private Function f1(u) As Double
f1 = 1 - 3 * (u ^ 2) + 2 * (u ^ 3)
End Function
Private Function f2(u) As Double
f2 = 3 * (u ^ 2) - 2 * (u ^ 3)
End Function
Private Function f3(u) As Double
f3 = u - 2 * (u ^ 2) + (u ^ 3)
End Function
Private Function f4(u) As Double
f4 = -1 * (u ^ 2) + (u ^ 3)
End Function
Private Sub Command2_Click()
setScaleMode
Picture1.Line (x0, y0)-(x0 + x0_p, y0 + y0_p)
Picture1.Line -(x1 - x1_p, y1 - y1_p)
Picture1.Line -(x1, y1)
End Sub
Private Sub setScaleMode()
With Picture1
.AutoRedraw = True
.ScaleWidth = 6
.ScaleHeight = 6
.ScaleMode = 0
.ScaleLeft = 0
.ScaleTop = 0
End With
End Sub
Private Sub Form_Load()
End Sub
'Module > Algorithm' 카테고리의 다른 글
[Algorithm] A star(A*) (0) | 2010.10.14 |
---|---|
Bellman Ford & Dijkstra Algorithm for Routing (0) | 2008.10.09 |
다익스트라(Dijkstra) 알고리즘 (0) | 2008.10.09 |