圆中点Bresenham算法

圆中点Bresenham算法
圆中点Bresenham算法

第5章

本案例知识要点

掌握八分法中点Bresenham 算法绘制圆的原理 ●

设计八分法绘制圆的中点Bresenham 算法 ●

编写八分法绘制圆的CirclePoint(x,y) 子函数 ● 编写绘制整圆的Mbcircle()子函数

一、案例需求

1.案例描述

使用中点Bresenham 算法绘制圆心位于屏幕客户区中心的圆。

2.案例效果图

案例输入对话框及效果如图3-1所示。

(a )输入对话框 (b )效果

图3-1 圆中点Bresenham 算法效果图 3.功能说明

(1)要求使用对话框输入圆的半径。

(2)圆的颜色为蓝色。

三、算法设计

1. 输入圆的半径R 。

2. 定义圆当前点坐标x ,y 、定义中点偏差判别式d 、定义像素点颜色rgb 。

3. 计算R d -=25.1,x=0,y=R ,rgb =RGB(0,0,255)。

案例三 圆中点Bresenham 算法

4.绘制点(x,y)及其在八分圆中的另外7个对称点。

5.判断d的符号。若d<0,则(x,y)更新为(x+1,y),d更新为d+2x+3;否则(x,y)更新为(x+1,y-1),d更新为d+2(x-y)+5。

6.当x小于等于y,重复步骤⑷和⑸,否则结束。

四、案例实现

1.CTestView.h文件

// TestView.h : interface of the CTestView class

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

#if !defined(AFX_TESTVIEW_H__A75FDCFB_621C_4E38_A154_C344803E6372__INCLUDED_)

#define AFX_TESTVIEW_H__A75FDCFB_621C_4E38_A154_C344803E6372__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

#include "InputDlg.h"//包含对话框头文件

class CTestView : public CView

{

protected: // create from serialization only

CTestView();

DECLARE_DYNCREATE(CTestView)

// Attributes

public:

CTestDoc* GetDocument();

// Operations

public:

void GetMaxY();//获得屏幕的最大x值函数

void GetMaxX();//获得屏幕的最大y值函数

void CirclePoint(double x,double y);//八分法画圆子函数

void Mbcircle();//圆中点Bresenham算法

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CTestView)

public:

virtual void OnDraw(CDC* pDC); // overridden to draw this view

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

protected:

virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);

virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);

virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

//}}AFX_VIRTUAL

// Implementation

public:

virtual ~CTestView();

#ifdef _DEBUG

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

#endif

protected:

int MaxX,MaxY; //屏幕x和y的最大坐标

double R; //圆的半径

// Generated message map functions

protected:

//{{AFX_MSG(CTestView)

afx_msg void OnMENUMbcircle();

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

#ifndef _DEBUG // debug version in TestView.cpp

inline CTestDoc* CTestView::GetDocument()

{ return (CTestDoc*)m_pDocument; }

#endif

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

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_TESTVIEW_H__A75FDCFB_621C_4E38_A154_C344803E6372__INCLUDED_) 2.CTestView. cpp文件

// TestView.cpp : implementation of the CTestView class

#include "stdafx.h"

#include "Test.h"

#include "TestDoc.h"

#include "TestView.h"

#define ROUND(a) int(a+0.5) //四舍五入

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

///////////////////////////////////////////////////////////////////////////// // CTestView

IMPLEMENT_DYNCREATE(CTestView, CView)

BEGIN_MESSAGE_MAP(CTestView, CView)

//{{AFX_MSG_MAP(CTestView)

ON_COMMAND(ID_MENU_Mbcircle, OnMENUMbcircle)

//}}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()

///////////////////////////////////////////////////////////////////////////// // CTestView construction/destruction

CTestView::CTestView()

{

// TODO: add construction code here

}

CTestView::~CTestView()

{

}

BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs)

{

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

// the CREATESTRUCT cs

return CView::PreCreateWindow(cs);

}

///////////////////////////////////////////////////////////////////////////// // CTestView drawing

void CTestView::OnDraw(CDC* pDC)

{

CTestDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

}

///////////////////////////////////////////////////////////////////////////// // CTestView printing

BOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo)

{

// default preparation

return DoPreparePrinting(pInfo);

}

void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

// TODO: add extra initialization before printing

}

void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

// TODO: add cleanup after printing

}

///////////////////////////////////////////////////////////////////////////// // CTestView diagnostics

#ifdef _DEBUG

void CTestView::AssertValid() const

{

CView::AssertValid();

}

void CTestView::Dump(CDumpContext& dc) const

{

CView::Dump(dc);

}

CTestDoc* CTestView::GetDocument() // non-debug version is inline

{

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

return (CTestDoc*)m_pDocument;

}

#endif //_DEBUG

///////////////////////////////////////////////////////////////////////////// // CTestView message handlers

void CTestView::GetMaxX()//得到客户区的最大横坐标

{

CRect Rect;

GetClientRect(&Rect);

MaxX=Rect.right;

}

void CTestView::GetMaxY()//得到客户区最大纵坐标

{

R=dlg.m_R;

}

AfxGetMainWnd()->SetWindowText("基本图形扫描转换:Mbcircle");

RedrawWindow();

GetMaxX();GetMaxY();

Mbcircle();

}

五、案例说明

因为设备坐标系的原点在屏幕左上角,所以为了在屏幕中心绘制圆,定义了GetMaxX()和GetMaxY()函数来获得屏幕的MaxX和MaxY,参见案例1的实现部分。在SetPixel函数中使用MaxX/2和MaxY/2来获得屏幕中心。

案例2-直线中点Bresenham算法

课程实验报告

步骤 为了规范颜色的处事,定义了CRGB类,重载了“+”,“-”、“*”、“\”、“+=”、“-=”、“*=”、“/=”运算符。成员函数Normalize()将颜色分量red,green,blue规范到[0,1]闭区间内。 RGB.h #pragma once class CRGB { public: CRGB(); CRGB(double, double, double); ~CRGB(); friend CRGB operator + (const CRGB&, const CRGB&); friend CRGB operator - (const CRGB&, const CRGB&); friend CRGB operator * (const CRGB&, const CRGB&); friend CRGB operator * (const CRGB&, double); friend CRGB operator * (double, const CRGB&); friend CRGB operator / (const CRGB&, double); friend CRGB operator += (const CRGB&, const CRGB&); friend CRGB operator -= (const CRGB&, const CRGB&); friend CRGB operator *= (const CRGB&, const CRGB&); friend CRGB operator /= (const CRGB&, double); void Normalize(); public: double red; double green; double blue; }; RGB.cpp #include"stdafx.h" #include"RGB.h" CRGB::CRGB() { red = 1.0; green = 1.0; blue = 1.0;

计算机图形学画圆实验报告

洛阳理工学院实验报告用纸

(2)画理想圆流程图如图-1: 图-1:画理想圆流程图 (3)中点画圆法 图-2 中点画圆法当前象素与下一象素的候选者

数,将乘法运算改成加法运算,即仅用整数实现中点画圆法。 (4)Bresenham画圆法 Bresenham画线法与中点画线法相似,,它通过每列象素中确定与理想直线最近的象素来进行直线的扫描的转换的。通过各行,各列的象素中心构造一组虚拟网格线的交点,然后确定该列象素中与此交点最近的的象素。该算法的巧妙之处在于可以采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列的所求对象。 假设x列的象素已确定,其行下标为y。那么下一个象素的列坐标必为x+1。而行坐标要么不变,要么递增1。是否递增1取决于如图所示的误差项d的值。因为直线的起始点在象素中心,所以误差项d的初始值为0。X下标每增加1,d的值相应递增直线的斜率值,即d=d+k(k=y/x为直线斜率)。一旦d>=1时,就把它减去,这样保证d始终在0、1之间。当d>0.5时,直线与x+1垂直网络线交点最接近于当前象素(x,y)的右上方象素(x+1,y+1);而当d<0.5时,更接近于象素(x+1,y),当d=0。5时,与上述二象素一样接近,约定取(x+1,y+1)。令e=d-0。5。则当e>=0时,下一象素的y下标增加1,而当e〈0时,下一象素的y下标不增。E的初始值为-0.5. (二)实验设计 画填充点流程图,如图-3: 图-3:圆的像素填充过程NS图 画理想圆,记录圆心坐标,计算半径大小,并记录 是否开始填充 否 是 初始化计数器、标志变量,设置最大计数值 调用Bresenha m画圆算法 否 是 填充标记是否为真 (While)计数变量小于最大计数值 循环变量temp + 1 填充计算出来的temp个坐 标点 计算需要填充坐标数组的 前temp个坐标

Bresenham的直线生成算法和整圆生成算法完整代码

以下是Bresenham的直线生成算法和整圆生成算法,已调试过,没有任何问题。Bresenham直线生成算法 #include "stdio.h" #include "graphics.h" Bresenham_line(x0,y0,x1,y1,color) int x0,y0,x1,y1,color; { int x,y,dx,dy, i; float k,e; dx=x1-x0;dy=y1-y0; k=(dy*1.0)/dx; e=-0.5; x=x0; y=y0; for (x=x0; x<=x1; x++) { putpixel(x,y,color); e=e+k; if(e>=0) { y++;e=e-1;} } } int main() { int x0,y0,x1,y1,c; int driver=DETECT,mode=0; initgraph(&driver,&mode,"c:\\tc"); setbkcolor(BLUE); setcolor(YELLOW); printf("input x0,y0,x1,y1,c"); scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&c); Bresenham_line(x0,y0,x1,y1,c); getch(); closegraph(); } 当取e=2*dy-dx时,可以消除浮点和除法运算 #include "stdio.h" #include "graphics.h" Bresenham_line(x0,y0,x1,y1,color)

int x0,y0,x1,y1,color; { int x,y,dx,dy, i,e; float k; dx=x1-x0;dy=y1-y0; k=(dy*1.0)/dx; e=2*dy-dx; x=x0; y=y0; for (x=x0; x<=x1; x++) { putpixel(x,y,color); e=e+2*dy; if(e>=0) { y++;e=e-2*dx;} } } int main() { int x0,y0,x1,y1,c; int driver=DETECT,mode=0; initgraph(&driver,&mode,"c:\\tc"); setbkcolor(BLUE); setcolor(YELLOW); printf("input x0,y0,x1,y1,c"); scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&c); Bresenham_line(x0,y0,x1,y1,c); getch(); closegraph(); }

Bresenham算法

Course Page
Page 1 of 6
课程首页 > 第二章 二维图形的生成 > 2.1 直线的生成 > 2.1.2 生成直线的Bresenham算法
全部隐藏
2.1.2 生成直线的Bresenham算法
从上面介绍的DDA算法可以看到,由于在循环中涉及实型数据的加减运算,因此直线的生成速度较慢。 在生成直线的算法中,Bresenham算法是最有效的算法之一。Bresenham算法是一种基于误差判别式来生成直线的方法。 一、直线Bresenham算法描述: 它也是采用递推步进的办法,令每次最大变化方向的坐标步进一个象素,同时另一个方向的坐标依据误差判别式的符号来决定是否也要步进一 个象素。 我们首先讨论m=△ y/△x,当0≤m≤1且x1有两种Bresenham算法思想,它们各自从不同角度介绍了Bresenham算法思想,得出的误差判别式都是一样的。 二、直线Bresenham算法思想之一: 由于显示直线的象素点只能取整数值坐标,可以假设直线上第i个象素点坐标为(xi,yi),它是直线上点(xi,yi)的最佳近似,并且xi=xi(假设 m<1),如下图所示。那么,直线上下一个象素点的可能位置是(xi+1,yi)或(xi+1,yi+1)。
由图中可以知道,在x=xi+1处,直线上点的y值是y=m(xi+1)+b,该点离象素点(xi+1,yi)和象素点(xi+1,yi+1)的距离分别是d1和d2:
d1=y-yi=m(xi+1)+b-yi d2=(yi+1)-y=(yi+1)-m(xi+1)-b 这两个距离差是 d1-d2=2m(xi+1)-2yi+2b-1
(2-8) (2-9)
(2-10)
我们来分析公式(2-10): (1)当此值为正时,d1>d2,说明直线上理论点离(xi+1,yi+1)象素较近,下一个象素点应取(xi+1,yi+1)。 (2)当此值为负时,d1mhtml:file://C:\Documents and Settings\Administrator\桌面\Course Page.mht
2011-7-12

实验1 中点画线和Bresenham画线算法的实现

计算机图形学实验报告 实验1 使用画线算法,绘制直线段 一.实验目的及要求 (1)掌握图形学中常用的三种画线算法:数值微分法、中点画线法和Bresenham画线算法。 (2)掌握绘制直线的程序设计方法。 (3)掌握使用文件来保存直线段的方法。 (4)掌握从文本文件中恢复出直线的方法。 二.实验内容 使用VC++ 6.0开发环境,分别实现中点画线算法和Bresenham画线算法,绘制直线(注意,不能使用VC中已有的绘制直线的函数),并以文本文件的形式保存绘制的结果,可以从文本文件中恢复出以前绘制过的直线。 三.算法设计与分析 Bresenham算法绘制直线的程序(仅包含整数运算)。 void MidBresenhamLine(int x0,int y0,int x1,int y1,int color) { int dx,dy,d,UpIncre,DownIncre,x,y; if(x0>x1){ x=x1;x1=x0;x0=x;

y=y1;y1=y0;y0=y; } x=x0;y=y0; dx=x1-x0;dy=y1-y0; d=dx-2*dy; UpIncre=2*dx-2*dy;DownIncre=-2*dy; while(x<=x1){ putpixel(x,y,color); X++; if(d<0){ y++; d+=UpIncre; } else d+=DownIncre; } } 四.程序调试及运行结果的自我分析与自我评价 // testView.cpp : implementation of the CTestView class #include "stdafx.h" #include "test.h" #include "testDoc.h" #include "testView.h" #include // ifstream、ofstream等位于其中 #include #include // string类型需要 #include "DlgInput.h" //CDlgInput类的头文件 using namespace std; #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // CTestView IMPLEMENT_DYNCREATE(CTestView, CView) BEGIN_MESSAGE_MAP(CTestView, CView) //{{AFX_MSG_MAP(CTestView) ON_COMMAND(ID_MENUITEM32771, OnMenuitem32771) ON_COMMAND(ID_MENUBRESENHAMLINE, OnMenubresenhamline) ON_COMMAND(ID_MENUCLEARVIEW, OnMenuclearview) ON_COMMAND(ID_FILE_OPEN, OnFileOpen) ON_COMMAND(ID_FILE_SA VE, OnFileSave) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)

直线中点Bresenham算法

实验一基本图形生成算法 实验目的: 掌握中点Bresenham绘制直线的原理 设计中点Bresenham算法 编程实现中点Bresenham算法 实验描述: 使用中点Bresenham算法绘制斜率为0≤k≤1的直线。 算法设计: 直线中点Bresenham算法 1. 输入直线的起点坐标P0(x0,y0)和终点坐标P1(x1,y1)。 2. 定义直线当前点坐标x,y、定义中点偏差判别式d、定义直线斜率k、定义像素点颜色 rgb。 3. x=x0,y=y0,计算d=0.5-k,k=(y1-y0)/(x1-x0),rgb=RGB(0,0,255)。 4. 绘制点(x,y),判断d的符号。若d<0,则(x,y)更新为(x+1,y+1),d 更新为 d+1-k;否则(x,y)更新为(x+1,y),d更新为d-k。 5. 如果当前点x 小于x1,重复步骤4,否则结束。 源程序: 1)// TestView.h #include "InputDlg.h"//对话框头文件 #define ROUND(a) int(a+0.5) class CTestView : public CView { ….. } 2)//TestView.cpp void CTestView::OnMENUMbline()//菜单函数 { InputDlg dlg; if(dlg.DoModal()==IDOK) { AfxGetMainWnd()->SetWindowText(":直线中点Bresenham算法"); RedrawWindow(); Mbline(dlg.m_x0, dlg.m_y0, dlg.m_x1, dlg.m_y1); } } void CTestView::Mbline(double x0, double y0,double x1,double y1) //直线中点Bresenham函数 { CClientDC dc(this); COLORREF rgb=RGB(255,0,0); //定义直线颜色为红色 double x,y,d,k; x=x0;y=y0;k=(y1-y0)/(x1-x0);d=0.5-k;

DDA算法 中点画线算法 Bresenham算法

实验1直接绘制实验 (提示:#表示Project的编号,##表示Project题目) 学号姓名上交时间 1.问题描述 如何利用OpenGL实现直线光栅化的DDA算法、中点画线算法和Bresenham算法2.算法描述 DDA算法:据直线公式y = kx + b来推导出来的,其关键之处在于如何设定单位步进,即一个方向的步进为单位步进,另一个方向的步进必然是小于1。 中点划线法:在画直线段的过程中,当前像素点为(xp ,yp ),下一个像素点有两种可选择点P1(xp +1,yp )或P2(xp +1,yp +1)。若M=(xp +1,yp +0.5)为P1与P2之中点,Q 为P理想直线与x=xp +1垂线的交点。当M在Q的下方,则P2应为下一个像素点; M在Q的上方,应取P1为下一个像素点。 Bresenham算法:过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线各垂直网格线的交点,然后确定该列像素中与此交点最近 的像素。 实验结果 成功运行三个算法,并且能转换出通用Bresenham算法。 3.分析与评论 (分析每个算法的运行时间,对你的本实验的工作进行评论,同时也可以对老师提出建议。) 附录: Source Code(in C)

#include //需要正确安装GLUT,安装方法如预备知识中所述void myDisplay(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glColor3f (1.0f, 1.0f, 1.0f); glRectf(-0.5f, -0.5f, 0.5f, 0.5f); glBegin (GL_TRIANGLES); glColor3f (1.0f, 0.0f, 0.0f); glVertex2f (0.0f, 1.0f); glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (0.8f, -0.5f); glColor3f (0.0f, 0.0f, 1.0f); glVertex2f (-0.8f, -0.5f); glEnd (); glColor3f(1,0,0); glBegin(GL_LINE_LOOP); glVertex2f (0.0f, 0.5f); glVertex2f (0.4f, -0.25f); glVertex2f (-0.4f, -0.25f); glEnd (); glPointSize(3); glBegin (GL_POINTS); glColor3f (1.0f, 0.0f, 0.0f); glVertex2f (-0.4f, -0.4f); glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (0.0f, 0.0f); glColor3f (0.0f, 0.0f, 1.0f); glVertex2f (0.4f, 0.4f); glEnd (); glFlush(); } int main(intargc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);

bresenham画线算法详解

给定两个点起点P1(x1, y1), P2(x2, y2),如何画它们直连的直线呢,即是如何得到上图所示的蓝色的点。假设直线的斜率00,直线在第一象限,Bresenham算法的过程如下: 1.画起点(x1, y1). 2.准备画下一个点,X坐标加1,判断如果达到终点,则完成。否则找下一个点,由图可知要画的点要么为当前点的右邻接点,要么是当前点的右上邻接点。 2.1.如果线段ax+by+c=0与x=x1+1的交点y坐标大于(y+*y+1))/2则选右上那个点 2.2.否则选右下那个点。 3.画点 4.跳回第2步 5.结束 具体的算法如下,原理就是比较目标直线与x+1直线交点的纵坐标,哪个离交点近就去哪个void Bresenhamline(int x0, int y0, int x1, int y1, int color) { int x, y, dx, dy; float k, e; dx = x1 - x0; dy = y1 - y0; k = dy / dx; e = -0.5; x = x0; y = y0; for (x= x0;x < x1; x++) { drawpixel(x, y, color);//这个是画点子函数

e = e + k; if (e > 0) { y++; e = e - 1; } } } 上述Bresenham算法在计算直线斜率与误差项时用到小数与除法。可以改用整数以避免除法。等式两边同时乘以2*dx,得到2*e*dx = 2*e*dx + 2dy, 2*e*dx = 2*e*dx - 2*dx.由于算法中只用到误差项的符号,因此可作如下替换:2*e*dx.改进的Bresenham画线算法程序:将e统一乘以2*dx即变成了整数的Bresenhan算法了,^_^ void InterBresenhamline (int x0, int y0, int x1, int y1, int color) { int dx = x1 - x0; int dy = y1 - y0; int dx2 = dx << 1;//乘2 int dy2 = dy<< 1;//乘2 int e = -dx; int x = x0; int y = y0; for (x = x0; x < x1; x++) { drawpixel (x, y, color); e=e + dy2; if (e > 0) { y++; e = e - dx2; } } }

实验1:Bresenham算法

实验1:Bresenham算法 实验题目: Bresenham直线扫描算法的实现 实验内容及要求: 实现绘制各种情况直线的Bresenham算法,并将实现的算法应用于任意多边形的绘制,要求多边形的顶点由键盘输入或鼠标拾取,绘制的多边形顶点要准确,图形应该封闭。要求掌握Bresenham算法的基本原理和算法设计,画出算法实现的程序流程图,使用C或者VC++实现算法,并演示。 实验原理: 1、Bresenham基本算法: 过各行各列象素中心构造一组虚拟网格线。按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后根据误差项的符号确定该列象素中与此交点最近的象素。 设直线方程为: 其中k=dy/dx。因为直线的起始点在象素中心,所以误差项d的初值d0=0。 X下标每增加1,d的值相应递增直线的斜率值k,即d=d+k。一旦d≥1, 就把它减去1,这样保证d在0、1之间。 当d≥0.5时,最接近于当前象素的右上方象素() 当d<0.5时,更接近于右方象素()。 为方便计算,令e=d-0.5,e的初值为-0.5,增量为k。 当e≥0时,取当前象素(x i,y i)的右上方象素(); 而当e<0时,更接近于右方象素()。 可以改用整数以避免除法。 d d d d k y x x k y y i i i i i + = - + = + + ) ( 1 1 1 1 , + +i i y x i i y x, 1+ 1 1 , + +i i y x i i y x, 1+

Bresenham算法代码如下: void Bresenhamline(int x1, int y1, int x2, int y2,CDC *pDC) { //对于所有直线均按照从左至右的方向绘制 int x,y,d,dx,dy,right,rightleft; if(x1>x2){ int tempx,tempy; tempx=x1;x1=x2;x2=tempx; tempy=y1;y1=y2;y2=tempy; } //根据斜率的情况不同而绘制 if(y1==y2){//斜率为0的情况 for(x=x1;x<=x2;x++) pDC->SetPixel(x,y1,2); } else if(x1==x2){//直线为垂直的情况 if(y1>y2){ //使直线按从下往上画 int tempy=y1; y1=y2;y2=tempy; } for(y=y1;y<=y2;y++) pDC->SetPixel(x1,y,2); } else{ dy=y2-y1; dx=x2-x1; if(abs(dy)==abs(dx)){////斜率为1或-1时 x=x1;y=y1; if(dy<0){//斜率为1 for(;y>=y2;y--){ x++; pDC->SetPixel(x,y,2); } }//斜率为1 else{//斜率为-1 for(;y<=y2;y++){ x++; pDC->SetPixel(x,y,2); } }//斜率为-1 } else if(abs(dy)0&&dx>0){//斜率为正时 right=-2*dy; rightleft=2*dx-2*dy; d=dx-2*dy; x=x1;y=y1; while(x<=x2){ pDC->SetPixel(x,y,2); x++; if(d<0){ y++; d=d+rightleft; }else{ d=d+right; } } }//斜率为正时 else {//斜率为负时 right=2*dy; rightleft=2*dy-2*dx; d=2*dy-dx; x=x1;y=y1; while(x<=x2){ pDC->SetPixel(x,y,2); x++; if(d<0){ y++;

计算机图形学画圆算法源程序

#include void CirclePoint(int x, int y, int color, int m ) { putpixel(x+m, y+m, color); putpixel(y+m, x+m, color); putpixel(-y+m, x+m, color); putpixel(-x+m, y+m, color); putpixel(-x+m, -y+m, color); putpixel(-y+m, -x+m, color); putpixel(y+m, -x+m, color); putpixel(x+m, -y+m, color); } void MidBresenhamCircle(int r,int color, int m) { int x, y, d; x=0; y=r; d=1-r; while(x<=y) { CirclePoint(x, y, color, m); if(d<0) d+=2*x+3; else { d+=2*(x-y)+5; y--; } x++; } } void main() { int gdriver,gmode,a,b,c; gdriver=DETECT; initgraph(&gdriver,&gmode,"C:\\TC20\\BGI"); printf("qing shu ru\n"); scanf("%d,%d,%d",&a,&b,&c) setbkcolor(0); MidBresenhamCircle(a, b, c); getch(); closegraph(); }

计算机图形学 实验 数值微分(DDA)法、中点画线法、Bresenham算法

XXXXXXXX 大学(计算机图形学)实验报告 实验名称 数值微分(DDA )法、中点画线法、Bresenham 算法 实验时间 年 月 日 专 业 姓 名 学 号 预 习 操 作 座 位 号 教师签名 总 评 一、实验目的: 1.了解数值微分(DDA )法、中点画线法、Bresenham 算法的基本思想; 2.掌握数值微分(DDA )法、中点画线法、Bresenham 算法的基本步骤; 二、实验原理: 1.数值微分(DDA)法 已知过端点 的直线段L :y=kx+b,直线斜率为 从x 的左端点 开始,向x 右端点步进。步长=1(个象素),计算相应的y 坐标y=kx+b ;取象素点(x, round(y))作为当前点的坐标。 2.中点画线法 当前象素点为(x p , y p ) 。下一个象素点为P 1 或P 2 。 设M=(x p +1, y p +0.5),为p 1与p 2之中点,Q 为理想直线与x=x p +1垂线的交点。将Q 与 M 的y 坐标进行比较。 当M 在Q 的下方,则P 2 应为下一个象素点; 当M 在Q 的上方,应取P 1为下一点。 构造判别式:d=F(M)=F(x p +1,y p +0.5)=a(x p +1)+b(y p +0.5)+c ,其中a=y 0-y 1, b=x 1-x 0, c=x 0y 1-x 1y 0。 当d<0,M 在L(Q 点)下方,取右上方P 2为下一个象素; 当d>0,M 在L(Q 点)上方,取右方P 1为下一个象素; 当d=0,选P 1或P 2均可,约定取P 1为下一个象素; 但这样做,每一个象素的计算量是4个加法,两个乘法。 d 是x p , y p 的线性函数,因此可采用增量计算,提高运算效率。 若当前象素处于d ≥0情况,则取正右方象素P 1 (x p +1, y p), 要判下一个象素位置,应计算 d 1=F(x p +2, y p +0.5)=a(x p +2)+b(y p +0.5)=d+a ; 增量为a 。 若d<0时,则取右上方象素P 2 (x p +1, y p +1)。要判断再下一象素,则要计算 d 2= F(x p +2, y p +1.5)=a(x p +2)+b(y p +1.5)+c=d+a+b ;增量为a +b 。 3.Bresenham 算法 过各行各列象素中心构造一组虚拟网格线。按直线从起点到终点的顺序计算直线与各垂 ),(),,(111000y x P y x P 0101x x y y k --=0x

Bresenham直线算法与画圆算法

Bresenham直线算法与画圆算法 文章分类:Java编程 计算机是如何画直线的?简单来说,如下图所示,真实的直线是连续的,但我们的计算机显示的精度有限,不可能真正显示连续的直线,于是我们用一系列离散化后的点(像素)来近似表现这条直线。 (上图来自于互联网络,《计算机图形学的概念与方法》柳朝阳,郑州大学数学系) 接下来的问题就是如何尽可能高效地找到这些离散的点,Bresenham直线算法就是一个非常不错的算法。 Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。是计算机图形学中最先发展出来的算法。 (引自wiki百科布雷森漢姆直線演算法) 这个算法的流程图如下:

可以看到,算法其实只考虑了斜率在 0 ~ 1 之间的直线,也就是与 x 轴夹角在 0 度到 45 度的直线。只要解决了这类直线的画法,其它角度的直线的绘制全部可以通过简单的坐标变换来实现。 下面是一个C语言实现版本。 Java代码 1.view sourceprint? 2. // 交换整数 a 、b 的值 3. 4.inline void swap_int(int *a, int *b) 5.{ 6. *a ^= *b; 7. *b ^= *a; 8. *a ^= *b;

9.} 10. 11.// Bresenham's line algorithm 12. 13.void draw_line(IMAGE *img, int x1, int y1, int x2, int y2, unsi gned long c) 14.{ 15. // 参数 c 为颜色值 16. int dx = abs(x2 - x1), 17. dy = abs(y2 - y1), 18. yy = 0; 19. 20. if(dx < dy) 21. { 22. yy = 1; 23. swap_int(&x1, &y1); 24. swap_int(&x2, &y2); 25. swap_int(&dx, &dy); 26. } 27. 28. int ix = (x2 - x1) > 0 ? 1 : -1, 29. iy = (y2 - y1) > 0 ? 1 : -1, 30. cx = x1, 31. cy = y1, 32. n2dy = dy * 2, 33. n2dydx = (dy - dx) * 2, 34. d = dy * 2 - dx; 35. 36.// 如果直线与 x 轴的夹角大于45度 37. if(yy) 38. { 39. while(cx != x2) 40. { 41. if(d < 0) 42. { 43. d += n2dy; 44. } 45. else 46. { 47. cy += iy; 48. d += n2dydx; 49. } 50. 51. putpixel(img, cy, cx, c);

Bresenham画圆算法

GIS专业实验报告(计算机图形学) 实验2 使用Bresenham画圆算法,绘制一个圆 姓名系别班级学号实验日期指导教师实验成绩 殷悦10级4班2010203482 2013.06.20肖燕 一.实验目的及要求 根据Bresenham画圆算法,掌握绘制圆的程序设计方法。在绘制时应利用圆的对称性。注意,不能使用语言库中的画圆函数。 二.理论基础 1.Bresenham画圆算法: 在Bresenham画线算法的基础之上,根据输入的圆心点坐标和半径,每次绘制出八分之一圆弧,进而逐步绘制出整个圆形。 三.算法设计与分析 算法代码: void drawcircle(int xc,int yc,int radius) { int x,y,p; x=0; y=radius; p=3-2*radius; glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_POINTS); while(x

计算机图形学实验报告-直线中点bresenham算法的实现资料

计算机图形学实验报告 实验内容直线中点Bresenham算法的实现专业计算机科学与技术 班级 学号 姓名 指导教师刘长松 年月日

一、实验题目 直线中点Bresenham算法的实现 二、实验要求 学习Visual C++ 6.0集成编程环境的使用、图形设备接口和常用图形程序设计、鼠标编程以及菜单设计等基础知识,从而掌握利用Visual C++进行图形程序设计的方法以及简单的图形画法,并编程实现Bresenham直线扫描转换程序,得出相应的输出图形。 三、实验内容 1.学习Visual C++ 6.0集成编成环境的使用; 2.掌握Visual C++ 6.0图形设备接口和常用图形程序设计、菜单设计等方法; 3.编程实现Bresenham直线扫描转换程序,得出相应的输出图形;

四、实验过程 1、实验原理 Bresenham 算法思想: 0≤d≤1 当d<0.5:下一个象素应取右光栅点(xi+1,yi) 当d≥0.5:下一个象素应取右上光栅点(xi+1,yi+1) e=d-0.5 假定直线斜率|k|≤1。e0= -0.5,x每次加1,e = e + k;e<0时,下一像素取(xi+1,yi),e = e + k ;e>0时,下一像素取(xi+1,yi+1); e = e + k -1 ;e=0时,可任取上、下光栅点显示。 当斜率|k|>1时,同理,只是y每次加1,x是否变化取决于增量e。 中点算法 d =2F(M)=2F(Xp+1,Yp+0.5)=2(a(Xp+1)+b(Yp+0.5)+c) 其中a=y0-y1, b=x1-x0, c=x0y1-x1y0 当d<0,M在L(Q点)下方,取右上方T为下一个象素; 此时再下一个象素的判别式为: d’= 2F(Xp+2,Yp+0.5)=2(a(Xp+2)+b(Yp+0.5)+c) = 2(a(Xp+1)+b(Yp+0.5)+c) +2a = d + 2a; 当d>0,M在L(Q点)上方,取右方B为下一个象素; 此时下一个象素的判别式为: d’= 2F(Xp+2,Yp+1.5)=2(a(Xp+2)+b(Yp+1.5)+c) = 2(a(Xp+1)+b(Yp+0.5)+c) +2(a +b) = d + 2(a + b); 当d=0,选T或B均可,约定取B为下一个象素;d0 = 2F(X0+1,Y0+0.5) = 2(a(X0+1)+b(Y0+0.5)+c) = 2(F(X0,Y0)+a+0.5b) 2、案例分析 MFC提供的CDC类的成员函数MoveTo()和LineTo()函数用于绘制傻

§3.2圆、圆弧的生成—Bresenham算法

§3.2圆的生成——Bresenham算法 条件:给定圆心(x c,y c)和半径R 约定:只考虑圆心在原点,半径为整数R的圆x2+y2.=R2。对于圆心不在原点的圆,可先通过平移转换,化为圆心在原点的圆,再进行扫 描转换,把所得到的像素集合加上一个位移量,就可以把目标圆光 栅化。 在众多圆的生成算法,如逐点比较法、角度DDA法、Bresenham算法中,Bresenham画圆法是一种最简单有效的的方法。 首先注意到只要生成一个八分圆,那么,圆的其它部分就可以通过一系列的对成变换得到。 1 2 3 4 5 6 7 8 由算法生成 y=x 第一八分圆关于y=x对称变换 第一四分圆关于x=0对称变换 上半圆关于y=0对称变换 如果以点x=0,y=R为起点按顺时针方向生成圆,则在第一象限内y是x 的单调递减函数。 要在这三个像素中选择一个使其与理想圆的距离的平方达到最小,即下 列数值中的最小者。 R

(0,R) (R,0) x y 这样,从圆上任一点出发,按顺时针方向生成圆时,为了最佳逼近该圆,对于下一像素的取法只有三种可能的选择,即正右方像素、正下方像素和右下角像素,分别记作:m H、m V、m D。 (x i,y i) (x i,y i-1) (x i+1,y i) (x i+1,y i-1) m H m D m V m H=|(x i+1)2+(y i)2-R2| m V=|(x i)2+(y i+1)2-R2| m D=|(x i+1)2+(y I-1)2-R2| m H (x i,y i) (x i+1,y i) (x i+1,y i+1) (x i+1,y i-1) (x i-1,y i-1) (x i,y i-1) m V m D 1 2 3 5 4 圆与点(x i,y i)附近光栅格网的相交关系只有五种可能。

DDA算法 中点画线算法 Bresenham算法

实验1 直接绘制实验 (提示:#表示Project的编号,##表示Project题目) 学号姓名上交时间 1.问题描述 如何利用OpenGL实现直线光栅化的DDA算法、中点画线算法和Bresenham算法2.算法描述 DDA算法:据直线公式y = kx + b来推导出来的,其关键之处在于如何设定单位步进,即一个方向的步进为单位步进,另一个方向的步进必然是小于1。 中点划线法:在画直线段的过程中,当前像素点为(xp ,yp ),下一个像素点有两种可选择点P1(xp +1,yp )或P2(xp +1,yp +1)。若M=(xp +1,yp +为P1与P2之中点,Q为P理想直线与x=xp +1垂线的交点。当M在Q的下方,则P2应为下一个像素点;M在Q 的上方,应取P1为下一个像素点。 Bresenham算法:过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线各垂直网格线的交点,然后确定该列像素中与此交点最近 的像素。 实验结果 成功运行三个算法,并且能转换出通用Bresenham算法。 3.分析与评论 (分析每个算法的运行时间,对你的本实验的工作进行评论,同时也可以对老师提出建议。) 附录: Source Code(in C)

#include //需要正确安装GLUT,安装方法如预备知识中所述void myDisplay(void) { glClearColor, , , ; glClear(GL_COLOR_BUFFER_BIT); glColor3f , , ; glRectf, , , ; glBegin (GL_TRIANGLES); glColor3f , , ; glVertex2f , ; glColor3f , , ; glVertex2f , ; glColor3f , , ; glVertex2f , ; glEnd (); glColor3f(1,0,0); glBegin(GL_LINE_LOOP); glVertex2f , ; glVertex2f , ; glVertex2f , ; glEnd (); glPointSize(3); glBegin (GL_POINTS); glColor3f , , ; glVertex2f , ; glColor3f , , ; glVertex2f , ; glColor3f , , ; glVertex2f , ; glEnd (); glFlush(); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);

3种画圆算法的优劣分析

三种画圆算法的优劣分析 学生姓名:杨晓瑜指导教师:张俊花 摘要 通过对Bresenham画圆法、正负画圆法、中点画圆法的算法分析,以及实现算法的程序运行速度和程序存储空间分析的比较。对此3种算法进行综合的优劣分析。 关键词 Bresenham 画圆法;正负画圆法;中点画圆法 Abstract By analysing the algorithms of Bresenham drawcirclc right-and-lose drawcircle and midpoint drawcircle,comparing their proceduze,run speeds and the small circle radiuses they display,the virtues and defects of the three algorithms are analysed synthetically. Key words Bresenham drawcircle;right—and—lose drawcircle,o midpoint drawcircle

1、引言 图形通常是由点、线、面、体等几何元素和灰度、色彩、线型、线宽等非几何属性组成.直线与曲线是组成图形的基本元素.其生成算法的优劣对整个图形系统的效率是至关重要的,因为在产生一幅图形的过程中要反复多次调用这些算法程序.曲线的生成算法可分为线生成和像素级(或称点)生成两类.所谓线生成就是以小的直线段来逼近和代替实际曲线而显示之;而点生成则是逐个像素地选择距离实际曲线最近的点而显示之.圆是一种基本的、常用的元素,其生成算法也有很多,围绕这些算法人们进行了讨论和探索,其核心无非是为了节省时间和空间。本文仅以Bresenham 画圆、正负画圆、中点画圆3种方法讨论圆的点生成算法,并对此3种算法进行优劣分析. 2、3种圆的点生成算法 2.1 Bresenham画圆法 (1)只要画出圆上的1/8弧AB(设圆心在原点,A点是y轴正向与圆弧的交点,B点在第一限的圆弧上),根据圆的对称性,即可画出整个圆. (2)在AB弧上取任一点。像素为p i-1=(x i-1,y i-1),按顺时针方向生成圆时,为了最佳逼近该圆,根据圆弧的走向,下一点像素的取法只有两种可能的选择:正右方像素和右下方像素,分别记为H i和L i,H i点特征:( X hi=x i,Y hi=y i-1),L i点特征:(X li=x i,Y Li=y i-1-1) (3)判断选择点 由圆的方程标准形式(x-x c) 2+(y-y c) 2 =R2可知,圆周上的实际位置的y值可由y2=R2-(x i-1+1)2=R2-x i2得到,这个y值和整数坐标值y i –1之间

相关文档
最新文档