/*INTRODUCTION
// Mouse:
// - LEFT button:
// 1. draw a new line
// 2. choose the endpoint to modify a line
// Keyboard:
// - DELETE:
// clear the window
*/#include<GLFW/glfw3.h>#include<iostream>#include<vector>#include<cmath>#define WIDTH 960.f#define HEIGHT 600.fusingnamespace std;// hide the console window#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )struct Color {float r, g, b;Color(){}Color(float x,float y,float z):r(x),g(y),b(z){}}YELLOW(1,1,0),RED(1,0,0);struct Point {double x, y;Point(){}Point(double a,double b):x(a),y(b){}};
vector<Point> points;// drawing points
vector<vector<Point>> Line;bool Modifying =false;// To choose the end-point: dis<=10boolnear(double x1,double y1,double x2,double y2){// calculate the distance to judge whether chhoose the end-point or notdouble dis =sqrt(pow(x1 - x2,2)+pow(y1 - y2,2));if(dis <=10)returntrue;returnfalse;}// drawvoiddraw(double x,double y, Color color){// transform the coordinates to the drawing: (0, 0) == (width/2, height/2)
x =(x - WIDTH /2)/ WIDTH *2;
y =(HEIGHT /2- y)/ HEIGHT *2;glBegin(GL_POINTS);glColor3f(color.r, color.g, color.b);glVertex2f(x, y);// draw a pixelglEnd();}// use the window's coordinates: leftBottom(0,0), the drawing coordinates is differentvoidBresemhamLine(double x0,double y0,double x1,double y1, Color color){double x, y, dx, dy;double k, e;
dx = x1 - x0, dy = y1 - y0, k = dy / dx;
e =-0.5, x = x0, y = y0;// |k| <= 1if(abs(k)<=1){for(int i =0; i <=abs(dx); i++){draw(x, HEIGHT - y, color);// direction controlif(dx >=0) x +=1;else x -=1;
e +=abs(k);// e = d - 0.5if(e >=0){// direction controlif(dy >=0) y +=1;else y -=1;
e -=1;}}}// |k| > 1; change x and yelse{for(int i =0; i <=abs(dy); i++){draw(x, HEIGHT - y, color);// direction controlif(dy >=0) y +=1;else y -=1;
e +=abs(1/ k);if(e >=0){// direction controlif(dx >=0) x +=1;else x -=1;
e -=1;}}}}// Display the lines voiddisplayLine(){// display modifying line dynamicallyif(!points.empty()){int s = points.size();double x1 = points[0].x, y1 = points[0].y;double x2 = points[s -1].x, y2 = points[s -1].y;// display the painting lineBresemhamLine(x1, y1, x2, y2, RED);}// display the certain linesfor(int i =0; i < Line.size(); i++)BresemhamLine(Line[i][0].x, Line[i][0].y, Line[i][1].x, Line[i][1].y, YELLOW);}// mouse button callbackvoidgetMouseButton(GLFWwindow *window,int button,int action,int mods){switch(button){case GLFW_MOUSE_BUTTON_LEFT:// if release: add lineif(action == GLFW_RELEASE){
Modifying =false;// stop modifying the end-pointif(!points.empty()){// just finish drawing linesint s = points.size();// update the lines: keep old; add new
vector<Point> tmp;
tmp.push_back(points[0]);
tmp.push_back(points[s -1]);
Line.push_back(tmp);
points.clear();}}}}// Pressing left button to draw/modify a line with position of cursordynamicallyvoidleftButtonOP(double x,double y){int s = points.size();// transfer the coordinates
y = HEIGHT - y;// move the line: when the line is existed and choose the end-pointsfor(int i =0;!Modifying && i < Line.size(); i++){
Point tmp;bool start_near =near(x, y, Line[i][0].x, Line[i][0].y);bool end_near =near(x, y, Line[i][1].x, Line[i][1].y);// move the start pointif(!Modifying && start_near)
tmp.x = Line[i][1].x, tmp.y = Line[i][1].y;// move the end pointelseif(!Modifying && end_near)
tmp.x = Line[i][0].x, tmp.y = Line[i][0].y;if(start_near || end_near){// can move: modify the coresponding point
Line.erase(Line.begin()+ i);// earse the old line
points.push_back(tmp);// add the start point; not drawing, tmp is the first pointbreak;}}// preserve the drawing points
points.push_back(Point(x, y));
Modifying =true;// drawing new line or moving a line}// CursorPos callbackvoidcursorPosCallback(GLFWwindow *window,double x,double y){if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT)==1){// press button to add or modify a lineleftButtonOP(x, y);}}// keyboard callbackvoidkeyCallback(GLFWwindow *window,int key,int scancode,int action,int mods){if(key == GLFW_KEY_DELETE && action == GLFW_PRESS){// keep the clipped lines stay, erase the redundant parts
Line.clear();}}intmain(void){
GLFWwindow* window;/* Initialize the library */if(!glfwInit())return-1;/* Create a windowed mode window and its OpenGL context */
window =glfwCreateWindow(WIDTH, HEIGHT,"Bresemham",NULL,NULL);glfwSetWindowPos(window,600,200);if(!window){glfwTerminate();return-1;}/* Make the window's context current */glfwMakeContextCurrent(window);/* Loop until the user closes the window */while(!glfwWindowShouldClose(window)){/* Render here */glClearColor(0.2f,0.3f,0.3f,1.0f);glClear(GL_COLOR_BUFFER_BIT);// mouseglfwSetCursorPosCallback(window, cursorPosCallback);glfwSetMouseButtonCallback(window, getMouseButton);// keyboardglfwSetKeyCallback(window, keyCallback);// draw heredisplayLine();/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glfwTerminate();return0;}