#include <iostream>
#include <GL/glut.h>
int detection(int x, int y);
void myMovedMouse(int x, int y);
double p_t(int n, int x, GLdouble t);
const int screenWidth = 600;
const int screenHeight = 480;
//顶点个数
static int length = 0;
//被检测到的顶点的位置
static int point_n = 0;
//--------------------数据结构部分---------------------
class Points;
//顶点类
class Point {
friend class Points;
public:
Point() {
this->x = NULL;
this->y = NULL;
this->next = NULL;
}
Point(GLfloat x, GLfloat y) {
this->x = x;
this->y = y;
this->next = NULL;
}
private:
GLfloat x;
GLfloat y;
Point* next;
};
//单链表类
class Points {
public:
Points() {
this->first = NULL;
}
void Add(GLfloat x, GLfloat y);
float Traverse(int n, int z);
void Alter(GLfloat x, GLfloat y, int n);
private:
Point* first;
};
//添加顶点
void Points::Add(GLfloat x, GLfloat y) {
Point* newPoint = new Point(x, y);
if (length == 0 || first == NULL) {
first = newPoint;
length++;
}
else
{
Point* q = first;
for (int i = 1; i < length; i++) {
q = q->next;
}
newPoint->next = q->next;
q->next = newPoint;
length++;
}
}
//遍历顶点
float Points::Traverse(int n, int z) {
if (n != 0) {
Point* q = first;
for (int i = 1; i < n; i++) {
q = q->next;
}
if (z == 0) {
//z=0时返回X
return q->x;
}
else
{
//z!=0时返回Y
return q->y;
}
}
}
//修改顶点
void Points::Alter(GLfloat x, GLfloat y, int n) {
if (n != 0) {
Point* q = first;
for (int i = 1; i < n; i++) {
q = q->next;
}
q->x = x;
q->y = y;
}
}
//-----------------------OpenGL部分--------------------------
static Points points;
//初始化
void SetupRC() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glPointSize(3.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-(GLdouble)screenWidth / 2, (GLdouble)screenWidth / 2, -(GLdouble)screenHeight / 2, (GLdouble)screenHeight / 2);
}
//绘制曲线和顶点
void draw() {
glColor3f(1.0f, 1.0f, 0.f);
glBegin(GL_LINE_STRIP);
for (int i = 1; i <= length; i++) {
GLfloat x = points.Traverse(i, 0);
GLfloat y = points.Traverse(i, 1);
glVertex2i(x, y);
}
glEnd();
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_POINTS);
for (int i = 1; i <= length; i++) {
GLfloat x = points.Traverse(i, 0);
GLfloat y = points.Traverse(i, 1);
glVertex2i(x, y);
}
glEnd();
glColor3f(0.0f, 1.0f, 1.0f);
glBegin(GL_LINE_STRIP);
for (GLdouble t = 0; t < 1; t = t + 0.01)
{
float x = p_t(length, 0, t);
float y = p_t(length, 1, t);
glVertex2i(x, y);
}
glEnd();
}
//渲染
void RenderScene() {
glClear(GL_COLOR_BUFFER_BIT);
draw();
glFlush();
}
//鼠标交互
void myMouse(int button, int state, int x, int y) {
if (state == GLUT_DOWN) {
if (button == GLUT_LEFT_BUTTON) {
if (point_n = detection(x - (GLdouble)screenWidth / 2, screenHeight / 2 - y)) {
std::cout << "检测到顶点:" << point_n << std::endl;
glutMotionFunc(myMovedMouse);
}
else if (!detection(x - (GLdouble)screenWidth / 2, screenHeight / 2 - y)) {
points.Add(x - (GLdouble)screenWidth / 2, screenHeight / 2 - y);
RenderScene();
}
}
}
}
//拖拽顶点
void myMovedMouse(int x, int y) {
points.Alter(x - (GLdouble)screenWidth / 2, screenHeight / 2 - y, point_n);
RenderScene();
}
//检测顶点
int detection(int x, int y) {
for (int i = 1; i <= length; i++) {
GLfloat p_x = points.Traverse(i, 0);
GLfloat p_y = points.Traverse(i, 1);
if (x - 10 < p_x && p_x < x + 10) {
if (y - 10 < p_y && p_y < y + 10) {
return i;
}
}
}
return 0;
}
//De Casteljau算法
double p_t(int n, int z, GLdouble t) {
double p[100][100];
for (int i = 0; i <= n - 1; i++) {
p[0][i] = points.Traverse(i + 1, z);
}
for (int r = 1; r <= n - 1; r++) {
for (int i = n - 1; i >= r; i--) {
p[r][i] = (1 - t) * p[r - 1][i - 1] + t * p[r - 1][i];
}
}
return p[n - 1][n - 1];
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
points.Add(0 * 20, 0 * 20);
points.Add(2 * 20, 2 * 20);
points.Add(2 * 20, -1 * 20);
points.Add(4 * 20, 0 * 20);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
//设置初始窗口的位置(窗口左上角相对于桌面坐标(x, y))
glutInitWindowPosition(100, 100);
//设置初始窗口的大小
glutInitWindowSize(screenWidth, screenHeight);
glutCreateWindow("Mouse Sierpinski");
glutMouseFunc(myMouse);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
如有疑问+QQ:307647252