求计算机图形学中的直线绘制函数法、DDA算法、中点法和Bresenham算法的优缺点以及比较.

求计算机图形学中的直线绘制函数法、DDA算法、中点法和Bresenham算法的优缺点以及比较.,第1张

DDA称为数值微分画线算法,是直线生成算法中最简单的一种原理相当简单,就是最直观的根据斜率的偏移程度,决定是以x为步进方向还是以y为步进方向然后在相应的步进方向上,步进变量每次增加一个像素,而另一个相关坐标变量则为Yk_1=Yk+m(以x为步进变量为例,m为斜率)假定直线斜率k在0~1之间,当前象素点为(xp,yp),则下一个象素点有两种可选择点P1(xp+1,yp)或P2(xp+1,yp+1)若P1与P2的中点(xp+1,yp+05)称为M,Q为理想直线与x=xp+1垂线的交点当M在Q的下方时,则取P2应为下一个象素点;当M在Q的上方时,则取P1为下一个象素点这就是中点画线法的基本原理Bresenham:过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线各垂直网格线的交点,然后确定该列像素中与此交点最近的像素该算法的优点在于可以采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列所求的像素大概就是这样,预知详细,

简单点就用TAB控件,把你要的各个功能的输入框放在不同的TAB上就行了(比如TAB1叫DDA画线,TAB2叫中点画线,依次类推)。或者先建一个主窗体,上面放上不同的按钮,比如DDA画线,中点画线等等,点击不同按钮d出不同窗体。用户输入两点那就随便了,比如说给四个输入框分别叫x1/y1 x2/y2

至于画图那是图形库的事了,用哪种图形库你可以自己选择,比如用GDI+,网上都能查到资料的。

DDA用来画线而不是一个像素点。当然因为其算法肯定要用到画像素点的函数。

DDA称为数值微分画线算法,是直线生成算法中最简单的一种。原理相当简单,就是最直观的根据斜率的偏移程度,决定是以x为步进方向还是以y为步进方向。然后在相应的步进方向上,步进变量每次增加一个像素,而另一个相关坐标变量则为Yk_1=Yk+m(以x为步进变量为例,m为斜率)

绘制一个像素点,java貌似没有相应函数,可以用1个像素的直线代替,或者其他图形,只要是大小一个像素,直线效率最高。

但是我觉得违背了DDA的本意。

不过,只是演示DDA的算法,那不需要考虑画着个像素点的方法,关键在于对前边描述的算法的表达式上

将DDA算法改成中点划线算法即可

// DDA画线Viewcpp : implementation of the CDDAView class

//

#include "stdafxh"

#include "DDA画线h"

#include "DDA画线Doch"

#include "DDA画线Viewh"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CDDAView

IMPLEMENT_DYNCREATE(CDDAView, CView)

BEGIN_MESSAGE_MAP(CDDAView, CView)

//{{AFX_MSG_MAP(CDDAView)

// NOTE - the ClassWizard will add and remove mapping macros here

// DO NOT EDIT what you see in these blocks of generated code!

//}}AFX_MSG_MAP

// Standard printing commands

ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CDDAView construction/destruction

CDDAView::CDDAView()

{

// TODO: add construction code here

}

CDDAView::~CDDAView()

{

}

BOOL CDDAView::PreCreateWindow(CREATESTRUCT& cs)

{

// TODO: Modify the Window class or styles here by modifying

// the CREATESTRUCT cs

return CView::PreCreateWindow(cs);

}

/////////////////////////////////////////////////////////////////////////////

// CDDAView drawing

void CDDAView::OnDraw(CDC pDC)

{

CDDADoc pDoc = GetDocument();

ASSERT_VALID(pDoc);

int xx,yy,x2,y2,m,n;

float dx,dy,k,x,y;

int x0=50,y0=500,x1=50,y1=50;

if(x0>x1)

{

m=x0;x0=x1;x1=m;

m=y0;y0=y1;y1=m;

}

dx=x1-x0;

dy=y1-y0;

k=dy/dx;

if(x0==x1)

{

if(y0>y1)

{

n=y0;

y0=y1;

y1=n;

}

for(y2=y0;y2<=y1;)

{

for(n=-10;n<11;)

{

pDC->SetPixel(x0+n,y2,255);

n++;

}

y2=y2+3;

}

}

if(k>=-1&&k<=10)

{

y=y0;

for(x2=x0;x2<=x1;)

{

yy=(int)(y+05);

for(n=-10;n<11;)

{

pDC->SetPixel(x2,yy+n,255);

n++;

}

y=y+k;

x2++;

}

}

else if(k>1)

{

x=x0;

k=dx/dy;

for(y2=y0;y2<=y1;)

{

xx=(int)(x+05);

for(n=-10;n<11;)

{

pDC->SetPixel(xx+n,y2,255);

n++;

}

x=x+k;

y2++;

}

}

else if(k<-1)

{

x=x1;

k=dx/dy;

for(y2=y1;y2<=y0;)

{

xx=(int)(x+05);

for(n=-10;n<11;)

{

pDC->SetPixel(xx+n,y2,255);

n++;

}

x=x+k;

y2++;

}

}

// TODO: add draw code for native data here

}

/////////////////////////////////////////////////////////////////////////////

// CDDAView printing

BOOL CDDAView::OnPreparePrinting(CPrintInfo pInfo)

{

// default preparation

return DoPreparePrinting(pInfo);

}

void CDDAView::OnBeginPrinting(CDC /pDC/, CPrintInfo /pInfo/)

{

// TODO: add extra initialization before printing

}

void CDDAView::OnEndPrinting(CDC /pDC/, CPrintInfo /pInfo/)

{

// TODO: add cleanup after printing

}

/////////////////////////////////////////////////////////////////////////////

// CDDAView diagnostics

#ifdef _DEBUG

void CDDAView::AssertValid() const

{

CView::AssertValid();

}

void CDDAView::Dump(CDumpContext& dc) const

{

CView::Dump(dc);

}

CDDADoc CDDAView::GetDocument() // non-debug version is inline

{

ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDDADoc)));

return (CDDADoc)m_pDocument;

}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////

// CDDAView message handlers

C++ JAVA 或其它语言, 他们的+-/ if else while 这些都几乎一样, API和数据类型有差异, 但不影响读懂算法,还是去试着看懂吧,

而且我搜了一下, 网上有很多这些算法的文字描述, 理解起来不难;

研究算法还是自己动手吧;

LZ加油;

DDA称为数值微分画线算法,是直线生成算法中最简单的一种。原理相当简单,就是最直观的根据斜率的偏移程度,决定是以x为步进方向还是以y为步进方向。然后在相应的步进方向上,步进变量每次增加一个像素,而另一个相关坐标变量则为Yk_1=Yk+m(以x为步进变量为例,m为斜率)

假定直线斜率k在0~1之间,当前象素点为(xp,yp),则下一个象素点有两种可选择点P1(xp+1,yp)或P2(xp+1,yp+1)。若P1与P2的中点(xp+1,yp+05)称为M,Q为理想直线与x=xp+1垂线的交点。当M在Q的下方时,则取P2应为下一个象素点;当M在Q的上方时,则取P1为下一个象素点。这就是中点画线法的基本原理

Bresenham:过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。该算法的优点在于可以采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列所求的像素。

大概就是这样,预知详细,可以参考图形学的书籍

 void DDALine(int x0,int y0,int x1,int y1,int color) {

 int x;

 float dx, dy, y, k;

 dx = x1-x0; dy=y1-y0;

 k=dy/dx,;y=y0;

 for (x=x0;x< x1;x++) {

drawpixel (x, int(y+05), color);

y=y+k;

 }

}

…… top↑

 如上面代码所示,DDA算法中的y和k都必须用浮点数表示,并且每一步运算都要对y进行舍入取整,这不利于硬件实现。中点画线法只包含整数变量,并且不含乘除法,因而解决了上述问题

首先给定两个点(x1,y1)(x2,y2)

那么可以算出斜率:k=(y2-y1)/(x2-x1)

直线公式:y = k(x-x1) + y1

先假设斜率小于1。

从(x1,y1)开始,使用画点函数在该处画点。

然后将x1自增1,计算y的值。调用画点函数画点,位置是(x1+1,k+y1),然后再把x1自增1,计算y的值……循环下去,直到x1已经自增到了与x2同样大小。

当然在实际 *** 作时,我们不应改变x1,x2,y1,y2的值,而是应该另设变量初始化为这四个量,然后改变这几个变量的值。

如果斜率小于1,就把方程中y和x的位置互换,改为每次y1自增1,计算x的取值……

若斜率等于1,y=x,最容易了……

但是,当直线非常长时,误差就比较大了,建议使用Bresenham算法……详见《计算机图形学》。

以上就是关于求计算机图形学中的直线绘制函数法、DDA算法、中点法和Bresenham算法的优缺点以及比较.全部的内容,包括:求计算机图形学中的直线绘制函数法、DDA算法、中点法和Bresenham算法的优缺点以及比较.、visualc++怎么用一个程序实现多个代码、如何用java实现在一个画布上画一个像素等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/zz/10637458.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-10
下一篇2023-05-10

发表评论

登录后才能评论

评论列表(0条)

    保存