1、功能:最小化的畫圖系統實現的功能是能拖出直線、圓、三角形、矩形,通過右鍵菜單來控制所畫的圖形類型。
還可以通過右鍵菜單保存點集,將其存入txt文件中。也可以讀取文件將保存的圖畫出來,或者清除屏幕。
2、思路:首先創建一個結構體包含點的x和y座標,然後定義結構體數組來儲存鼠標點擊的點座標,畫直線,矩形以及圓時先點擊一個點按住不放拖動鼠標等到鼠標放開的時候畫出相應圖形,其中存儲的是點擊的那個點以及鼠標鬆開時的那個點。畫矩形時那兩個點作爲對角線的兩個端點,畫圓時那兩個點作爲一條直徑進行畫圓。畫三角形時,首先點擊一個點,再點擊第二個點這時用這兩個點畫出一條線段。然後移動鼠標進行第三個點的選擇,移動時使用鼠標所指的點作爲第三個點畫三角形,當點擊第三個點時確定三角形。
3、相關 函數 :
void glutMouseFunc(void(*func)(int button,int state,int x,int y)); 鼠標點擊函數,處理鼠標點擊事件的函數包含四個參數第一個button表示鼠標上的哪個鍵這個變量可以是下面的三個值中的一個:GLUT_LEFT_BUTTON,GLUT_MIDDLE_BUTTON,GLUT_RIGHT_BUTTON; 第二個參數是鼠標的狀態有被按下,或鬆開,可能取值如下:GLUT_DOWN,GLUT_UP;後兩個參數是鼠標所指位置的座標。
void glutMotionFunc(void(*func)(int x,int y)); 處理鼠標按住移動鼠標時的事件。
void glutPassiveMotionFunc(void (*func)(int x,int y) );
處理鼠標鬆開移動鼠標時的事件。
4、代碼實現:
#include <windows.h>
#define GLUT_DISABLE_ATEXIT_HACK
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
using namespace std;
#define Pi 3.1415926536f
struct point {
long x;
long y;
};//定義點的結構體
int count1 = 0;//點的個數
point point1[200];//點的數組集
int count2 = 0;//點的個數
point point2[200];//點的數組集
int count3 = 0;//點的個數
point point3[200];//點的數組集
int count4 = 0;//點的個數
point point4[200];//點的數組集
int n = 1000;//控制圓的精度
int shape=1;//記錄你想要畫的形狀類型
int color=1;//記錄你想要畫的顏色
int screenWidth=640;
int screenHeight=480;
//初始化
void init(void)
{
glClearColor(0.0,0.0,0.0,0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,640.0,0.0,480.0);
}
//畫線
void drawThread(int x1,int y1,int x2,int y2)
{
glBegin(GL_LINE_STRIP);
glVertex2i (x1, y1);
glVertex2i (x2, y2);
glEnd ();
}
//畫矩形
void drawRectangle(int x1,int y1,int x2,int y2)
{
glBegin(GL_LINE_LOOP);
glVertex2i(x1,y1);
glVertex2i(x1,y2);
glVertex2i(x2,y2);
glVertex2i(x2,y1);
glEnd();
}
//畫三角形
void drawTriangle(int x1,int y1,int x2,int y2,int x3,int y3)
{
glBegin(GL_LINE_LOOP);
glVertex2i(x1,y1);
glVertex2i(x2,y2);
glVertex2i(x3,y3);
glEnd();
}
//畫圓
void drawCircle(int x1,int y1,int x2,int y2)
{
GLfloat R = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))/2;//半徑
GLfloat x=(x1+x2)/2;//圓心橫座標
GLfloat y=(y1+y2)/2;//圓心縱座標
glBegin(GL_LINE_LOOP);
for(int i=0; i<n; ++i)
glVertex2f(x+R*cos(2*Pi/n*i), y+R*sin(2*Pi/n*i));
glEnd();
}
//顯示函數
void myDisplay()
{
glClear(GL_COLOR_BUFFER_BIT); //清屏
switch(color)
{
case 1:
glColor3f(1.0,0.0,0.0);
break;
case 2:
glColor3f(0.0,1.0,0.0);
break;
case 3:
glColor3f(0.0,0.0,1.0);
break;
}
if(count1>1)
{
for(int i=0; i<count1-1; i=i+2)
{
drawThread(point1[i].x,point1[i].y,point1[i+1].x,point1[i+1].y);
}
}
if(count2%3==0||count2%3==1)
{
for(int i=0; i+2<=count2-1; i=i+3)
{
drawTriangle(point2[i].x,point2[i].y,point2[i+1].x,point2[i+1].y,point2[i+2].x,point2[i+2].y);
}
}
if(count2%3==2)
{
for(int i=0; i+2<=count2-1; i=i+3)
{
drawTriangle(point2[i].x,point2[i].y,point2[i+1].x,point2[i+1].y,point2[i+2].x,point2[i+2].y);
}
drawThread(point2[count2-2].x,point2[count2-2].y,point2[count2-1].x,point2[count2-1].y);
}
if(count3>1)
{
for(int i=0; i<count3-1; i=i+2)
{
drawRectangle(point3[i].x,point3[i].y,point3[i+1].x,point3[i+1].y);
}
}
if(count4>1)
{
for(int i=0; i<count4-1; i=i+2)
{
drawCircle(point4[i].x,point4[i].y,point4[i+1].x,point4[i+1].y);
}
}
glFlush(); //送所有輸出到顯示設備
}
//顯示函數
void itDisplay()
{
glClear(GL_COLOR_BUFFER_BIT); //清屏
switch(color)
{
case 1:
glColor3f(1.0,0.0,0.0);
break;
case 2:
glColor3f(0.0,1.0,0.0);
break;
case 3:
glColor3f(0.0,0.0,1.0);
break;
}
for(int i=0; i<=count1-1; i=i+2)
{
drawThread(point1[i].x,point1[i].y,point1[i+1].x,point1[i+1].y);
}
for(int i=0; i+2<=count2; i=i+3)
{
drawTriangle(point2[i].x,point2[i].y,point2[i+1].x,point2[i+1].y,point2[i+2].x,point2[i+2].y);
}
if((count2+1)%3==2)
{
drawThread(point2[count2-1].x,point2[count2-1].y,point2[count2].x,point2[count2].y);
}
for(int i=0; i<=count3-1; i=i+2)
{
drawRectangle(point3[i].x,point3[i].y,point3[i+1].x,point3[i+1].y);
}
for(int i=0; i<=count4-1; i=i+2)
{
drawCircle(point4[i].x,point4[i].y,point4[i+1].x,point4[i+1].y);
}
glFlush(); //送所有輸出到顯示設備
}
//鼠標事件
void myMouse(int button,int state,int x,int y)
{
if(button==GLUT_LEFT_BUTTON)
{
if(state==GLUT_DOWN||state==GLUT_UP)
{
switch(shape)
{
case 1:
point1[count1].x=x;
point1[count1].y=screenHeight-y;
count1++;
myDisplay();
break;
case 3:
point3[count3].x=x;
point3[count3].y=screenHeight-y;
count3++;
myDisplay();
break;
case 4:
point4[count4].x=x;
point4[count4].y=screenHeight-y;
count4++;
myDisplay();
break;
}
}
}
if(button==GLUT_LEFT_BUTTON)
{
if(state==GLUT_DOWN&&shape==2)
{
point2[count2].x=x;
point2[count2].y=screenHeight-y;
count2++;
myDisplay();
}
}
}
//鼠標按住移動事件
void myMotion(int x,int y)
{
switch(shape)
{
case 1:
point1[count1].x=x;
point1[count1].y=screenHeight-y;
itDisplay();
break;
case 3:
point3[count3].x=x;
point3[count3].y=screenHeight-y;
itDisplay();
break;
case 4:
point4[count4].x=x;
point4[count4].y=screenHeight-y;
itDisplay();
break;
}
}
//鼠標鬆開移動事件
void myPassiveMotion(int x,int y)
{
point2[count2].x=x;
point2[count2].y=screenHeight-y;
itDisplay();
}
//加載點集
void LoadPoints()
{
FILE *fp;
fp = fopen("db1.txt","r");//讀取文件
if(fp == NULL)
{
printf("文件打開失敗\n");
exit(0);
}
fscanf(fp,"%d\n",&count1);//獲取點的個數
for(int i = 0; i < count1; i++)
{
fscanf(fp,"%d %d\n", &point1[i].x, &point1[i].y);
}
fclose(fp);
fp = fopen("db2.txt","r");//讀取文件
if(fp == NULL)
{
printf("文件打開失敗\n");
exit(0);
}
fscanf(fp,"%d\n",&count2);//獲取點的個數
for(int i = 0; i < count2; i++)
{
fscanf(fp,"%d %d\n", &point2[i].x, &point2[i].y);
}
fclose(fp);
fp = fopen("db3.txt","r");//讀取文件
if(fp == NULL)
{
printf("文件打開失敗\n");
exit(0);
}
fscanf(fp,"%d\n",&count3);//獲取點的個數
for(int i = 0; i < count3; i++)
{
fscanf(fp,"%d %d\n", &point3[i].x, &point3[i].y);
}
fclose(fp);
fp = fopen("db4.txt","r");//讀取文件
if(fp == NULL)
{
printf("文件打開失敗\n");
exit(0);
}
fscanf(fp,"%d\n",&count4);//獲取點的個數
for(int i = 0; i < count4; i++)
{
fscanf(fp,"%d %d\n", &point4[i].x, &point4[i].y);
}
fclose(fp);
}
//保存點集
void SavePoints()
{
FILE *fp;
fp = fopen("db1.txt","w");//寫入文件
if(fp == NULL)
{
printf("文件打開失敗\n");
exit(0);
}
fprintf(fp,"%d\n", count1);//寫入點的個數
for(int i=0;i<count1;i++)
{
fprintf(fp,"%d %d\n", point1[i].x,point1[i].y);
}
fclose(fp);
fp = fopen("db2.txt","w");//寫入文件
if(fp == NULL)
{
printf("文件打開失敗\n");
exit(0);
}
fprintf(fp,"%d\n", count2);//寫入點的個數
for(int i=0;i<count2;i++)
{
fprintf(fp,"%d %d\n", point2[i].x,point2[i].y);
}
fclose(fp);
fp = fopen("db3.txt","w");//寫入文件
if(fp == NULL)
{
printf("文件打開失敗\n");
exit(0);
}
fprintf(fp,"%d\n", count3);//寫入點的個數
for(int i=0;i<count3;i++)
{
fprintf(fp,"%d %d\n", point3[i].x,point3[i].y);
}
fclose(fp);
fp = fopen("db4.txt","w");//寫入文件
if(fp == NULL)
{
printf("文件打開失敗\n");
exit(0);
}
fprintf(fp,"%d\n", count4);//寫入點的個數
for(int i=0;i<count4;i++)
{
fprintf(fp,"%d %d\n", point4[i].x,point4[i].y);
}
fclose(fp);
}
//顏色菜單
void colorSubMenu(GLint colorOption)
{
color=colorOption;
}
//圖形菜單
void shapeSubMenu(GLint shapeOption)
{
shape=shapeOption;
}
//主菜單
void mainMenu (GLint renderingOption)
{
switch (renderingOption)
{
case 1:
count1=0;
count2=0;
count3=0;
count4=0;
LoadPoints();
myDisplay();
break;
case 2:
SavePoints();
break;
case 3:
count1=0;
count2=0;
count3=0;
count4=0;
myDisplay();
break;
}
}
int main(int argc, char *argv[])
{
GLint subMenu1; //定義子菜單
GLint subMenu2; //定義子菜單
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 100); //設置窗口在屏幕上的位置
glutCreateWindow("draw system");
init();
subMenu1=glutCreateMenu (shapeSubMenu);
glutAddMenuEntry ("直線", 1);
glutAddMenuEntry ("三角形", 2);
glutAddMenuEntry ("矩形", 3);
glutAddMenuEntry ("圓形", 4);
subMenu2=glutCreateMenu (colorSubMenu);
glutAddMenuEntry ("紅", 1);
glutAddMenuEntry ("綠", 2);
glutAddMenuEntry ("藍", 3);
glutCreateMenu (mainMenu); // 創建菜單
glutAddSubMenu ("圖形", subMenu1);
glutAddSubMenu ("顏色", subMenu2);
glutAddMenuEntry ("加載", 1);
glutAddMenuEntry ("保存", 2);
glutAddMenuEntry ("清除", 3);
glutAttachMenu (GLUT_RIGHT_BUTTON);
glutMouseFunc(myMouse);
glutMotionFunc(myMotion);
glutPassiveMotionFunc(myPassiveMotion);
glutDisplayFunc(myDisplay);
glutMainLoop();
}