프로그래밍 언어/OpenGL

[OpenGL] 스플라인_3차 함수 곡선 그리기(cubic spline)

sujo 2021. 12. 16. 00:49

[OpenGL] 스플라인_3차 함수 곡선 그리기(cubic spline)

 

개요

: 점을 지나는 자연스러운 곡선을 그린다.

: 참고로 y값의 좌표는 매번 랜덤으로 부여된다.

[ 결과 화면 ]

 

 

유도 공식

1. 첫 커브와 마지막 커브는 2차 스플라인으로 그림.

2. 나머지 커브들은 구간을 나눠서 3차 스플라인으로 그림.

 

※ 1번 참고.

https://wtg-study.tistory.com/101

 

[OpenGL] 스플라인_2차 함수 곡선 그리기 (quadratic function)

[OpenGL] 스플라인_2차 함수 곡선 그리기 (quadratic function) 개요 : 점 세 개를 지나는 2차 함수 곡선을 그린다. 유도 공식 이때, p(t) : 곡선을 그리는 함수 p1 ~ p2 : 각 세개의 점의 좌표 t : 0 <= t <= 1..

wtg-study.tistory.com

 

※ 2번

이때,

  • p(t) : 곡선을 그리는 함수
  • p1 ~ p4 : 각 4개의 점의 좌표
  • t : 0 <= t <= 1 인 실수
  • t를 0부터 1까지 실수 값으로 삽입하면 p2와 p3의 3차 곡선이 그려짐.
  • 즉, 좌표 4개가 있어야 두 번째, 세 번째 좌표 사이의 곡선을 그릴 수 있음.

 

※ 여기서 p(t)를 유도하는 방식은 앞서 2차 함수 스플라인을 그릴 때 설명했으므로 생략.

 

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <GL/glut.h>
#include <cstring>
#include <time.h>
#include <stdlib.h>
#define SIZE 10
using namespace std;
 
GLfloat point[10][2];
GLfloat matrix_2[3][3= { {2.0f, -4.0f, 2.0f}, {-3.0f, 4.0f, -1.0f}, {1.0f, 0.0f, 0.0f} };
GLfloat matrix_3[4][4= { {-1.0f, 3.0f, -3.0f, 1.0f}, 
                          {2.0f, -5.0f, 4.0f, -1.0f}, 
                          {-1.0f, 0.0f, 1.0f, 0.0f},
                          {0.0f, 2.0f, 0.0f, 0.0f} };
 
void reshape(GLint w, GLint h) {
    glViewport(00, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-10.010.0-10.010.0-1.030.0);
}
 
// 점 찍기
GLvoid drawPoints() {
    glPointSize(7.0f);
 
    glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
    glBegin(GL_POINTS);
    for (int i = 0; i < 10; i++)
        glVertex2f(point[i][0], point[i][1]);
    glEnd();
}
 
// cubic spline
GLvoid drawCardinal() {
    // init & variable
    glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
    GLfloat result[4][2];
    GLfloat t = 0.0f;
    GLfloat x, y;
 
    // Section 1.
    // quadratic function
    memset(result, 0sizeof(result));
 
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            result[i][0+= matrix_2[i][j] * point[j][0];
            result[i][1+= matrix_2[i][j] * point[j][1];
        }
    }
 
    glBegin(GL_LINE_STRIP);
    while (t < 0.5f) {
        x = result[2][0+ t * (result[1][0+ result[0][0* t);
        y = result[2][1+ t * (result[1][1+ result[0][1* t);
        glVertex2f(x, y);
        t += 0.01f;
    }
    glEnd();
 
    // Section 2.
    // cubic spline
    for (int cubic_case = 0; cubic_case < SIZE - 3; cubic_case++)
    {
        memset(result, 0sizeof(result));
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                result[i][0+= matrix_3[i][j] * point[j + cubic_case][0];
                result[i][1+= matrix_3[i][j] * point[j + cubic_case][1];
            }
        }
 
        t = 0.0f;
        glBegin(GL_LINE_STRIP);
        while (t < 1.0f) {
            x = (result[3][0+ t * (result[2][0+ t * (result[1][0+ result[0][0* t))) * 0.5f;
            y = (result[3][1+ t * (result[2][1+ t * (result[1][1+ result[0][1* t))) * 0.5f;
            glVertex2f(x, y);
            t += 0.01f;
        }
        glEnd();
    }
 
    // Section 3.
    // quadratic function
    memset(result, 0sizeof(result));
 
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            result[i][0+= matrix_2[i][j] * point[j + SIZE - 3][0];
            result[i][1+= matrix_2[i][j] * point[j + SIZE - 3][1];
        }
    }
 
    t = 0.5f;
    glBegin(GL_LINE_STRIP);
    while (t < 1.0f) {
        x = result[2][0+ t * (result[1][0+ result[0][0* t);
        y = result[2][1+ t * (result[1][1+ result[0][1* t);
        glVertex2f(x, y);
        t += 0.01f;
    }
    glEnd();
}
 
void rand_num() {
    srand(time(NULL));
 
    for (int i = 0; i < SIZE; i++)
    {
        point[i][0= i * 2.0f - 9.0f;
        point[i][1= rand() % 18 - 9.0f;
    }
}
 
GLvoid display() {
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
 
    rand_num();
 
    //점 찍기
    drawPoints();
 
    // 점을 기준으로 곡선 그리기
    drawCardinal();
 
    glutSwapBuffers();
}
 
int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(500500);
    glutInitWindowPosition(100100);
    glutCreateWindow("cubic spline");
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutMainLoop();
    return (0);
}
cs