C++ 用Bresenham'绘制线条;s线算法
我的计算机图形学作业是只使用绘制点的能力来实现OpenGL算法 所以很明显,我需要先让C++ 用Bresenham'绘制线条;s线算法,c++,graphics,bresenham,C++,Graphics,Bresenham,我的计算机图形学作业是只使用绘制点的能力来实现OpenGL算法 所以很明显,我需要先让drawLine()工作,然后才能画其他东西drawLine()只能使用整数。没有浮点数 这就是我被教导的。基本上,直线可以分为4个不同的类别,正陡、正浅、负陡和负浅。这是我应该画的画: 这是我的程序正在绘制的图片: 这些颜色是为我们做的。我们得到了顶点,需要使用Bresenham的直线算法根据起点和终点绘制直线 这就是我到目前为止所做的: int dx = end.x - start.x; int dy
drawLine()
工作,然后才能画其他东西drawLine()
只能使用整数。没有浮点数
这就是我被教导的。基本上,直线可以分为4个不同的类别,正陡、正浅、负陡和负浅。这是我应该画的画:
这是我的程序正在绘制的图片:
这些颜色是为我们做的。我们得到了顶点,需要使用Bresenham的直线算法根据起点和终点绘制直线
这就是我到目前为止所做的:
int dx = end.x - start.x;
int dy = end.y - start.y;
//initialize varibales
int d;
int dL;
int dU;
if (dy > 0){
if (dy > dx){
//+steep
d = dy - 2*dx;
dL = -2*dx;
dU = 2*dy - 2*dx;
for (int x = start.x, y = start.y; y <= end.y; y++){
Vertex v(x,y);
drawPoint(v);
if (d >= 1){
d += dL;
}else{
x++;
d += dU;
}
}
} else {
//+shallow
d = 2*dy - dx;
dL = 2*dy;
dU = 2*dy - 2*dx;
for (int x = start.x, y = start.y; x <= end.x; x++) {
Vertex v(x,y);
drawPoint(v);
// if choosing L, next y will stay the same, we only need
// to update d by dL
if (d <= 0) {
d += dL;
// otherwise choose U, y moves up 1
} else {
y++;
d += dU;
}
}
}
} else {
if (-dy > dx){
cout << "-steep\n";
//-steep
d = dy - 2*dx;
//south
dL = 2*dx;
//southeast
dU = 2*dy - 2*dx;
for (int x = start.x, y = start.y; y >= end.y; --y){
Vertex v(x,y);
drawPoint(v);
//if choosing L, next x will stay the same, we only need
//to update d
if (d >= 1){
d -= dL;
} else {
x++;
d -= dU;
}
}
} else {
cout << "-shallow\n";
//-shallow
d = 2*dy - dx;
dL = 2*dy;
dU = 2*dy - 2*dx;
for (int x = start.x, y = start.y; x <= end.x; x++){
Vertex v(x,y);
drawPoint(v);
if (d >= 0){
d += dL;
} else {
--y;
d -= dU;
}
}
}
}
intdx=end.x-start.x;
int dy=end.y-start.y;
//初始化变量包
int d;
int-dL;
int dU;
如果(dy>0){
如果(dy>dx){
//+陡峭的
d=dy-2*dx;
dL=-2*dx;
dU=2*dy-2*dx;
对于(int x=start.x,y=start.y;y=1){
d+=dL;
}否则{
x++;
d+=dU;
}
}
}否则{
//+浅薄的
d=2*dy-dx;
dL=2*dy;
dU=2*dy-2*dx;
对于(int x=start.x,y=start.y;x=1){
d-=dL;
}否则{
x++;
d-=dU;
}
}
}否则{
cout如果有人想知道问题出在哪里,我仍然不知道问题出在哪里。我最终做的是重新分解我的代码,使-shall和-spink分别使用与+shall和+spink相同的算法。调整x,y坐标后(否定x或y坐标),当我去绘制它们时,我否定了我原来的否定,以便它绘制在正确的位置。/*BRESENHAAM算法用于线条绘制*/
/*BRESENHAAM ALGORITHM FOR LINE DRAWING*/
#include<iostream.h>
#include<graphics.h>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<math.h>
#include<dos.h>
void bhm_line(int,int,int,int,int);
void main()
{
int ghdriver=DETECT,ghmode,errorcode,x1,x2,y1,y2;
initgraph(&ghdriver,&ghmode,"..\\bgi");
errorcode = graphresult();
if(errorcode !=grOk)
{
cout<<"Graphics error:%s\n"<<grapherrormsg(errorcode);
cout<<"Press any key to halt:";
getch();
exit(1);
}
clrscr();
cout<<"Enter the coordinates (x1,y1): ";
cin>>x1>>y1;
cout<<"Enter the coordinates (x2,y2): ";
cin>>x2>>y2;
bhm_line(x1,y1,x2,y2,1);
getch();
}
void bhm_line(int x1,int y1,int x2,int y2,int c)
{
int x,y,dx,dy,dx1,dy1,px,py,xe,ye,i;
dx=x2-x1;
dy=y2-y1;
dx1=fabs(dx);
dy1=fabs(dy);
px=2*dy1-dx1;
py=2*dx1-dy1;
if(dy1<=dx1)
{
if(dx>=0)
{
x=x1;
y=y1;
xe=x2;
}
else
{
x=x2;
y=y2;
xe=x1;
}
putpixel(x,y,c);
for(i=0;x<xe;i++)
{
x=x+1;
if(px<0)
{
px=px+2*dy1;
}
else
{
if((dx<0 && dy<0) || (dx>0 && dy>0))
{
y=y+1;
}
else
{
y=y-1;
}
px=px+2*(dy1-dx1);
}
delay(0);
putpixel(x,y,c);
}
}
else
{
if(dy>=0)
{
x=x1;
y=y1;
ye=y2;
}
else
{
x=x2;
y=y2;
ye=y1;
}
putpixel(x,y,c);
for(i=0;y<ye;i++)
{
y=y+1;
if(py<=0)
{
py=py+2*dx1;
}
else
{
if((dx<0 && dy<0) || (dx>0 && dy>0))
{
x=x+1;
}
else
{
x=x-1;
}
py=py+2*(dx1-dy1);
}
delay(0);
putpixel(x,y,c);
}
}
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效bhm_线(int,int,int,int,int,int);
void main()
{
int ghdriver=检测、ghmode、错误代码x1、x2、y1、y2;
initgraph(&ghdriver,&ghmode,“..\\bgi”);
errorcode=graphresult();
如果(错误代码!=grOk)
{
CUT< P>我在C++中实现了原始Bresenham算法,并尽可能地优化(特别是从内部循环中移除IF)。
它在一个线性缓冲区而不是一个曲面中绘制,就这一点而言,这个实现几乎和(可能慢5%)一样快
#包括
#包括
使用名称空间std;
向量缓冲区;
int imageSide=2048;//曲面的宽度
结构点2di
{
int x;
int-y;
点2di(常数int&x,常数int&y):x(x),y(y){}
Point2Di(){}
};
无效绘制线(常数点2DI和p0、常数点2DI和p1)
{
intdx=p1.x-p0.x;
int-dy=p1.y-p0.y;
int-dLong=abs(dx);
int dShort=abs(dy);
int offsetLong=dx>0?1:-1;
int offsetShort=dy>0?图像侧:-图像侧;
if(长<短)
{
交换(短、长);
互换(冲销短、冲销长);
}
int error=dLong/2;
int指数=p0.y*imageSide+p0.x;
const int offset[]={offsetLong,offsetLong+offsetShort};
const int abs_d[]={dShort,dShort-dLong};
对于(int i=0;i=dLong;
索引+=偏移量[ErroristoBig];
error+=abs_d[ERRORSTOBIG];
}
}
我正在使用的EFLA实现是:
void drawLine(Point2Di p0, Point2Di p1)
{
bool yLonger=false;
int shortLen=p1.y-p0.y;
int longLen=p1.x-p0.x;
if (abs(shortLen)>abs(longLen)) {
swap(shortLen, longLen);
yLonger=true;
}
int decInc = longLen==0 ? decInc=0 : ((shortLen << 16) / longLen);
if (yLonger) {
p0.y*=imageSide;
p1.y*=imageSide;
if (longLen>0)
for (int j=0x8000+(p0.x<<16);p0.y<=p1.y;p0.y+=imageSide, j+=decInc)
buffer[p0.y + (j >> 16)] = 255; // or a call to your painting method
else
for (int j=0x8000+(p0.x<<16);p0.y>=p1.y;p0.y-=imageSide, j-=decInc)
buffer[p0.y + (j >> 16)] = 255; // or a call to your painting method
}
else
{
if (longLen>0)
for (int j=0x8000+(p0.y<<16);p0.x<=p1.x;++p0.x, j+=decInc)
buffer[(j >> 16) * imageSide + p0.x] = 255; // or a call to your painting method
else
for (int j=0x8000+(p0.y<<16);p0.x>=p1.x;--p0.x, j-=decInc)
buffer[(j >> 16) * imageSide + p0.x] = 255; // or a call to your painting method
}
}
void绘制线(点2di p0,点2di p1)
{
布尔-伊朗格=假;
int shortLen=p1.y-p0.y;
int longLen=p1.x-p0.x;
if(防抱死制动系统(短)>防抱死制动系统(长)){
掉期(短期、长期);
伊朗格=真;
}
int decInc=longLen==0?decInc=0:((shortLen 0)
for(int j=0x8000+(p0.x 16)]=255;//或调用您的绘制方法
}
其他的
{
如果(longLen>0)
对于(int j=0x8000+(p0.y 16)*imageSide+p0.x]=255;//或调用您的绘制方法
}
}
如果你看我代码上面段落中的两张图片,“第二象限”和“第四象限”画得不对。我把它们放在引号中,因为点(0,0)位于图片的左下角。基本上,第一个else语句包含工作不正常的代码,-浅和-陡。在两个简单示例上运行代码,一个有效,另一个无效。例如(0,0)、(5,5)和(0,5)、(5,0),跟踪这两个循环并查看它们是否存在分歧。这将是一个比有人在上面更好的练习,因此请为您执行此操作。我执行了此操作,但似乎仍然无法解决问题。发生的情况是,所有循环中的if语句if(d>=0)都没有按应有的方式切换。对于从(0,5)到(5,0)的行,它每次都应该减去y,这样它就可以在45度处形成一条直线,但不是。这是一个只包含链接的答案;请编辑您的答案,以包含实际代码,而不仅仅是链接。bhm_line()中的“延迟(0)”是什么?我不熟悉C语言,但可能一些数值必须转换成绝对值?
void drawLine(Point2Di p0, Point2Di p1)
{
bool yLonger=false;
int shortLen=p1.y-p0.y;
int longLen=p1.x-p0.x;
if (abs(shortLen)>abs(longLen)) {
swap(shortLen, longLen);
yLonger=true;
}
int decInc = longLen==0 ? decInc=0 : ((shortLen << 16) / longLen);
if (yLonger) {
p0.y*=imageSide;
p1.y*=imageSide;
if (longLen>0)
for (int j=0x8000+(p0.x<<16);p0.y<=p1.y;p0.y+=imageSide, j+=decInc)
buffer[p0.y + (j >> 16)] = 255; // or a call to your painting method
else
for (int j=0x8000+(p0.x<<16);p0.y>=p1.y;p0.y-=imageSide, j-=decInc)
buffer[p0.y + (j >> 16)] = 255; // or a call to your painting method
}
else
{
if (longLen>0)
for (int j=0x8000+(p0.y<<16);p0.x<=p1.x;++p0.x, j+=decInc)
buffer[(j >> 16) * imageSide + p0.x] = 255; // or a call to your painting method
else
for (int j=0x8000+(p0.y<<16);p0.x>=p1.x;--p0.x, j-=decInc)
buffer[(j >> 16) * imageSide + p0.x] = 255; // or a call to your painting method
}
}