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
- canvas繪製sin正弦曲線Canvas
- WPF隨筆收錄-實時繪製心率曲線
- 使用opengl繪製yuv
- 解析csv資料繪製曲線圖
- ROC曲線繪製與AUC計算
- Origin教程:DSC曲線的描述和繪製
- flutter 自定義view 繪製曲線統計圖FlutterView
- MPAndroidChart繪製曲線圖、柱狀圖總結Android
- Android繪圖最終篇之大戰貝塞爾三次曲線Android繪圖
- caffe的python介面繪製loss和accuracy曲線示例Python
- 函式的遞迴及科赫曲線繪製函式遞迴
- webGL入門-四階貝塞爾曲線繪製Web
- OpenGL 繪製你的 github skyline 模型Github模型
- pyqt5+matplotlib繪製動態雙y軸曲線QT
- WPF開發隨筆收錄-心電圖曲線繪製
- 基於 matplotlib 的抽象網格和能量曲線繪製程式抽象
- canvas bezierCurveTo() 三次貝塞爾曲線Canvas
- Android OpenGL ES 開發(二):繪製圖形Android
- OpenGL 學習系列--基礎的繪製流程
- OpenGL 學習系列---基本形狀的繪製
- Flutter 實現平滑曲線折線圖Flutter
- R語言ggsurvplot繪製生存曲線報錯 : object of type ‘symbol‘ is not subsettableR語言ObjectSymbol
- 4次Bezier曲線--計算機圖形學 opengl計算機
- ECharts,付費求教,有人能繪製出文中的 曲線圖表嘛!Echarts
- canvas實現手動繪製矩形Canvas
- Android動畫實現繪製原理Android動畫
- 基於react的錄音及音訊曲線繪製的元件開發React音訊元件
- Android 身高體重曲線的實現Android
- 基於面繪製的MC演算法以及基於體繪製的 Ray-casting 實現Dicom影像的三維重建(python實現)演算法ASTPython
- canvas 繪製線條Canvas
- canvas繪製直線Canvas
- SVG 繪製直線SVG
- OpenGL 繪圖移動繪圖
- Android OpenGL ES 2.0 手把手教學(5)- 繪製模式Android模式
- 學習OpenGL ES之繪製三角形
- Android模擬器繪製實現概述Android
- 使用python matplotlib實現動圖繪製Python
- QT OPENGL 與 shader 繪製展示視訊程式碼例項 OPenGL直接顯示YUV資料QT