OpenGL實現Hermite演算法繪製三次曲線
首先是推導:節省功夫我就直接貼照片了。
程式加了滑鼠的監聽器,可以移動控制點和型值點。
注意:圖片中矩陣第二行第二列應該為3,當時筆誤
程式效果:
程式碼如下:
#include<gl/glut.h>
#include<math.h>
#include<windows.h>
#include<algorithm>
using namespace std;
struct Vertex
{
int x, y;
Vertex(int tx, int ty)
{
x = tx;
y = ty;
}
};
Vertex p0(100, 250); //型值點
Vertex p1(400, 250);
Vertex c0(150, 200); //控制點
Vertex c1(350, 300);
bool mouseLeftIsDown = false;
bool mouseRightIsDown = false;
int caculateSquareDistance(Vertex a, Vertex b)
{
return (a.x - b.x)*(a.x - b.x) + (a.y - b.y);
}
void Hermite(int n) //精度
{
//求出相對於控制點的向量(切線)
//這裡把切點的長度人為擴大4倍,劃線的效果更為明顯(實際上不符合計算出的公式)
Vertex tempC0((c0.x - p0.x)<<2, (c0.y - p0.y)<<2);
Vertex tempC1((c1.x - p1.x)<<2, (c1.y - p1.y)<<2);
double delTa = 1.0 / n;
glBegin(GL_LINE_STRIP);
for (int i = 0; i < n; i++)
{
double t = i * delTa;
double t1 = 2 * pow(t, 3) - 3 * pow(t, 2) + 1;
double t2 = -2 * pow(t, 3) + 3 * pow(t, 2);
double t3 = pow(t, 3) - 2 * pow(t, 2) + t;
double t4 = pow(t, 3) - pow(t, 2);
glVertex2d(p0.x*t1 + p1.x*t2 + tempC0.x*t3 + tempC1.x*t4, p0.y*t1 + p1.y*t2 + tempC0.y*t3 + tempC1.y*t4);
}
glEnd();
}
void myDisplay()
{
glClear(GL_COLOR_BUFFER_BIT); //清除。GL_COLOR_BUFFER_BIT表示清除顏色
glPointSize(10.0f);
glColor3f(0, 0, 1);
//畫出型值點和控制點(藍色)
glBegin(GL_POINTS);
glVertex2d(p0.x, p0.y);
glVertex2d(p1.x, p1.y);
glVertex2d(c0.x, c0.y);
glVertex2d(c1.x, c1.y);
glEnd();
//畫出控制點與型值點的連線(紅色)
glColor3f(1, 0, 0);
glLineWidth(3);
glBegin(GL_LINES);
glVertex2d(p0.x, p0.y); glVertex2d(c0.x, c0.y);
glVertex2d(p1.x, p1.y); glVertex2d(c1.x, c1.y);
glEnd();
Hermite(200);
glFlush();
glutSwapBuffers();
}
void mouse(int button,int state,int x, int y) //監聽滑鼠動作
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
mouseLeftIsDown = true;
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
{
mouseLeftIsDown = false;
}
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
{
mouseRightIsDown = true;
}
if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
{
mouseRightIsDown = false;
}
}
void motion(int x, int y) //移動點
{
if (mouseLeftIsDown) //左鍵移動控制點
{
if (caculateSquareDistance(Vertex(x, y), c0) < 400) //防止滑鼠移動過快點位無法及時讀取,經測試,400為一個較適合的值
{
c0.x = x;
c0.y = y;
}
else if (caculateSquareDistance(Vertex(x, y), c1) < 400)
{
c1.x = x;
c1.y = y;
}
}
else if (mouseRightIsDown) //右鍵移動型值點
{
if (caculateSquareDistance(Vertex(x, y), p0) < 400)
{
p0.x = x;
p0.y = y;
}
else if (caculateSquareDistance(Vertex(x, y), p1) < 400)
{
p1.x = x;
p1.y = y;
}
}
glutPostRedisplay(); //重新構圖
}
void Reshape(int w, int h) //兩個引數:視窗被移動後大小
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void initWindow(int &argc, char *argv[], int width, int height, char *title) //初始化並顯示到螢幕中央
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowPosition((GetSystemMetrics(SM_CXSCREEN) - width) >> 1, (GetSystemMetrics(SM_CYSCREEN) - height) >> 1); //指定視窗位置
glutInitWindowSize(width, height); //指定視窗大小
glutCreateWindow(title);
glClearColor(1, 1, 1, 0.0);
glShadeModel(GL_FLAT);
}
int main(int argc, char *argv[])
{
initWindow(argc, argv, 500, 500, "Hermite");
puts("\n\t使用Hermite演算法,用兩頂點兩控制點繪製三次曲線。");
puts("\t左鍵移動控制點,右鍵移動型值點");
glutDisplayFunc(myDisplay);
glutReshapeFunc(Reshape);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutMainLoop();
return 0;
}
相關文章
- Android日常學習:OpenGL 實踐之貝塞爾曲線繪製Android
- iOS 波浪曲線的繪製iOS
- canvas繪製sin正弦曲線Canvas
- 怎麼用java繪製曲線Java
- WPF隨筆收錄-實時繪製心率曲線
- 解析csv資料繪製曲線圖
- ROC曲線繪製與AUC計算
- JavaScript繪製sin正弦函式曲線JavaScript函式
- JavaScript 繪製sin正弦函式曲線JavaScript函式
- 體繪製RayCasting(光線投影演算法)C++/OpenGL原始碼AST演算法C++原始碼
- 用canvas繪製一個曲線動畫——深入理解貝塞爾曲線Canvas動畫
- flutter 自定義view 繪製曲線統計圖FlutterView
- Origin教程:DSC曲線的描述和繪製
- webGL入門-四階貝塞爾曲線繪製Web
- html5中canvas繪製貝塞爾曲線HTMLCanvas
- Android繪圖最終篇之大戰貝塞爾三次曲線Android繪圖
- 函式的遞迴及科赫曲線繪製函式遞迴
- MPAndroidChart繪製曲線圖、柱狀圖總結Android
- canvas繪製貝濟埃曲線程式碼例項Canvas線程
- html5中canvas貝塞爾曲線繪製菊花HTMLCanvas
- 曲線點抽稀演算法- Python 實現演算法Python
- caffe的python介面繪製loss和accuracy曲線示例Python
- canvas bezierCurveTo() 三次貝塞爾曲線Canvas
- pyqt5+matplotlib繪製動態雙y軸曲線QT
- WPF開發隨筆收錄-心電圖曲線繪製
- 包教包會-貝塞爾曲線的繪製原理與應用
- OpenGL ES繪製3D圖形3D
- 使用html5實現的繪製直線效果HTML
- Flutter 實現平滑曲線折線圖Flutter
- 基於 matplotlib 的抽象網格和能量曲線繪製程式抽象
- OpenGL應用——實現DDA演算法演算法
- SVG <path> C 指令 三次貝塞爾曲線SVG
- OpenGL 學習系列---基本形狀的繪製
- OpenGL 學習系列--基礎的繪製流程
- Opengl ES 3.0 on iOS--- HelloWord(繪製彩色矩形)iOS
- R語言ggsurvplot繪製生存曲線報錯 : object of type ‘symbol‘ is not subsettableR語言ObjectSymbol
- 自定義 View 梳理:用貝塞爾曲線繪製酷炫輪廓背景View
- Unity3d 繪製並獲取通過任意點的曲線Unity3D