欢迎来到我的图形学实验一展示~

 

在第一个实验中,我们希望通过自己的实践利用OpenGL来完成画线和画圆,体会Bresenham画线画圆算法的精妙之处,亲自动手把该算法实现一下。

在实现过程中,画线算法我使用了Bresenham的方法,首先考虑一些special case,比如没有斜率的情况等等。接下来画的时候,由于没有要求用户的输入的两点有什么要求,所以我分了四种情况来讨论,但是基本的画法其实只写一种就可以了,其他的情况通过坐标转换,将求出的坐标在映射回去就可以了。画的时候注意在斜率大于一与小于一时从哪个方向画,具体的Bresenham方法是啥就不在赘述啦!

画圆方法也是差不多,但是只需要画出来第一象限八分之一个圆的基本情况,其他的根据对称就可以画出来。

实验的效果图如下:

源代码附在下边啦,供大家参考。

#include "stdafx.h"
#include "graphics.h"

void draw_line(int x0, int y0, int x1, int y1){
if (x1-x0== 0){//没有斜率的情况
if (y1-y0 > 0){
for (int y = y0; y <= y1; y++){
putpixel(x0, y, ege::YELLOW);
}
}
else{
for (int y = y1; y <= y0; y++){
putpixel(x0, y, ege::YELLOW);
}
}
}
else{
int dx = 2 * (x1 - x0), dy = 2 * (y1 - y0);
if ((dy / dx) >= -1 && (dy / dx <= 1)){//以x为基准来画
if (x0 < x1){
if (y0 <= y1){//最基本情况
int x=x0, y=y0;
int dydx = dy - dx;
int F = dy - dx / 2;
for (x; x <= x1; x++){
putpixel(x, y, ege::YELLOW);
if (F < 0)
F += dy;
else{
y++;
F += dydx;
}
}
}
else{//做一次关于y=y0对称
int x = x0;
int y = y0;
dy = 2*(y0-y1);
int dydx = dy - dx, F = dy - dx / 2;
for (x; x <= x1; x++){
putpixel(x, 2 * y0 - y, ege::YELLOW);
if (F < 0)
F += dy;
else{
y++;
F += dydx;
}
}
}
}
else{
if (y0 <= y1){
int x = x0;
int y = y0;
dx = 2 * (x0 - x1);
int dydx = dy - dx, F = dy - dx / 2;
for (x; x <= 2*x0-x; x++){
putpixel(2*x0-x, y, ege::YELLOW);
if (F < 0)
F += dy;
else{
y++;
F += dydx;
}
}
}
else{
int x = x0;
int y = y0;
dy = 2 * (y0 - y1);
dx = 2 * (x0 - x1);
int dydx = dy - dx, F = dy - dx / 2;
for (x; x <= 2 * x0 - x; x++){
putpixel(2 * x0 - x, 2*y0-y, ege::YELLOW);
if (F < 0)
F += dy;
else{
y++;
F += dydx;
}
}
}
}
}
else{//以y为基准来画
if (y0 <= y1){
if (x0 < x1){
int x = y0;
int y = x0;
dy = 2 * (x1 - x0);
dx = 2 * (y1 - y0);
int dydx = dy - dx, F = dy - dx / 2;
for (x; x <= y1; x++){
putpixel(y, x, ege::YELLOW);
if (F < 0)
F += dy;
else{
y++;
F += dydx;
}
}
}
else{
int x = y0;
int y = x0;
dy = 2 * (x0-x1);
dx = 2 * (y1 - y0);
int dydx = dy - dx, F = dy - dx / 2;
for (x; x <= y1; x++){
putpixel(2 * x0 - y, x, ege::YELLOW);
if (F < 0)
F += dy;
else{
y++;
F += dydx;
}
}
}
}
else{
if (x0 < x1){
int x = y0;
int y = x0;
dx = 2 * (y0 - y1);
dy = 2 * (x1 - x0);
int dydx = dy - dx, F = dy - dx / 2;
for (x; x <= 2 * y0 - y1; x++){
putpixel(y, 2 * y0 - x, ege::YELLOW);
if (F < 0)
F += dy;
else{
y++;
F += dydx;
}
}
}
else{
int x = y0;
int y = x0;
dx = 2 * (y0 - y1);
dy = 2 * (x0 - x1);
int dydx = dy - dx, F = dy - dx / 2;
for (x; x <= 2 * y0 - y1; x++){
putpixel(2 * x0 - y, 2 * y0 - x, ege::YELLOW);
if (F < 0)
F += dy;
else{
y++;
F += dydx;
}
}
}
}
}
}
}

void draw_circle(int radius,int x0,int y0){
int x =0, y = radius;
int d = 1 - radius;
while (y > x){
if (d < 0)
d += 2 * x + 3;
else{
d += 2 * (x - y) + 5;
y--;
}
x++;
putpixel(x+x0,y+y0,ege::YELLOW);//依次画出八个部分的圆,利用平移挪动到指定的像素点
putpixel(y+x0,x+y0,ege::YELLOW);
putpixel(-x+x0,y+y0,ege::YELLOW);
putpixel(-y+x0,x+y0,ege::YELLOW);
putpixel(x+x0,-y+y0,ege::YELLOW);
putpixel(y+x0,-x+y0,ege::YELLOW);
putpixel(-x+x0,-y+y0,ege::YELLOW);
putpixel(-y+x0,-x+y0,ege::YELLOW);
}
}
int main()
{ initgraph(300, 300);
draw_line(20, 280, 20, 20);
draw_line(280, 20, 280, 280);
draw_line(20, 20, 280, 20);
draw_line(20, 280, 280, 280);

draw_line(20, 280, 280, 20);
draw_line(20, 20, 280, 280);

draw_line(20, 280, 150, 20);
draw_line(150,20,280,280);
draw_line(20, 20, 150, 280);
draw_line(150, 280, 280, 20);

draw_circle(50,150,150);
draw_circle(80, 150, 150);
draw_circle(100, 150, 150);
getch();
closegraph();
return 0;
}