文档库 最新最全的文档下载
当前位置:文档库 › 计算机图形学实验报告

计算机图形学实验报告

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

一、实验目的

1、掌握中点Bresenham直线扫描转换算法的思想。

2掌握边标志算法或有效边表算法进行多边形填充的基本设计思想。

3掌握透视投影变换的数学原理和三维坐标系中几何图形到二维图形的观察流程。

4掌握三维形体在计算机中的构造及表示方法

二、实验环境

Windows系统, VC6.0。

三、实验步骤

1、给定两个点的坐标P0(x0,y0),P1(x1,y1),使用中点Bresenham直线扫描转换算法画出连接两点的直线。

实验基本步骤

首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。

其次、使用中点Bresenham直线扫描转换算法实现自己的画线函数,函数原型可表示如下:

void DrawLine(CDC *pDC, int p0x, int p0y, int p1x, int p1y);

在函数中,可通过调用CDC成员函数SetPixel来画出扫描转换过程中的每个点。

COLORREF SetPixel(int x, int y, COLORREF crColor );

再次、找到文档视图程序框架视图类的OnDraw成员函数,调用DrawLine 函数画出不同斜率情况的直线,如下图:

最后、调试程序直至正确画出直线。

2、给定多边形的顶点的坐标P0(x0,y0),P1(x1,y1),P2(x2,y2),P3(x3,y3),P4(x4,y4)…使用边标志算法或有效边表算法进行多边形填充。

实验基本步骤

首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。

其次、实现边标志算法或有效边表算法函数,如下:

void FillPolygon(CDC *pDC, int px[], int py[], int ptnumb);

px:该数组用来表示每个顶点的x坐标

py :该数组用来表示每个顶点的y坐标

ptnumb:表示顶点个数

注意实现函数FillPolygon可以直接通过窗口的DC(设备描述符)来进行多边形填充,不需要使用帧缓冲存储。(边标志算法)首先用画线函数勾画出多边形,再针对每条扫描线,从左至右依次判断当前像素的颜色是否勾画的边界色,是就开始填充后面的像素直至再碰到边界像素。注意对顶点要做特殊处理。

通过调用GDI画点函数SetPixel来画出填充过程中的每个点。需要画线可以使用CDC的画线函数MoveTo和LineTo进行绘制,也可以使用实验一实现的画直线函数。

CPoint MoveTo(int x, int y );

BOOL LineTo(int x, int y );

实现边标志算法算法需要获取某个点的当前颜色值,可以使用CDC的成员函数

COLORREF GetPixel(int x, int y );

再次、找到文档视图程序框架视图类的OnDraw成员函数,调用FillPolygon 函数画出填充的多边形,如下:

void CTestView::OnDraw(CDC* pDC)

{

CTestcoodtransDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

//绘制之前先把整个窗口涂上背景色(白色)以便于下面的填充

RECT Rt;

GetClientRect(&Rt);

pDC->FillSolidRect(&Rt, RGB(255,255,255));

int ptx[] = {10, 100, 200, 150, 80};

int pty[] = {10, 50, 80, 120, 70};

FillPolygon(pDC, ptx, pty, 5);

}

截图如下

3.在世界坐标系中定义一个立方体(由6个面组成),并给定观察点在世界坐标系中的位置(a,b,c)以及观察坐标系的方位角θ,俯仰角φ和姿态角α,另外再给定投影面离观察点的距离D,在屏幕上画出立方体的透视投影图形。

实验基本步骤

首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。

其次、由给定观察点在世界坐标系中的位置(a,b,c)以及观察坐标系的方位角θ,俯仰角φ和姿态角α求出观察变换矩阵Tv.

再次、将立方体的每一个面的顶点坐标与变换矩阵Tv相乘得到观察坐标系中的坐标,再由式(1)求得二维投影坐标。并用直线连接这些二维投影坐标点形成每一个面在投影面的图形,依次将立方体的6个面画出即可。

核心代码如下:

void CTestView::OnDraw(CDC* pDC)

{

CTestDoc* pDoc = GetDocument();

ASSERT_V ALID(pDoc);

// TODO: add draw code for native data here

CRect Rect;

GetClientRect(&Rect);

int MaxX=Rect.right;

int MaxY=Rect.bottom;

pDC->SetMapMode(MM_ANISOTROPIC);

pDC->SetWindowExt(1, 1);

pDC->SetViewportExt(1, -1);

pDC->SetViewportOrg(MaxX/2, MaxY/2);//设置视点原点在屏幕中心DrawObject(pDC);

}

void CTestView::ReadPoint()//读入8个顶点坐标

{

//每一行代表正方体每个顶点的x,y,z坐标

int a=200;//正方体边长

P[1][1]=-a/2;P[1][2]=-a/2;P[1][3]=-a/2;

P[2][1]=-a/2;P[2][2]=a/2;P[2][3]=-a/2;

P[3][1]=-a/2;P[3][2]=a/2;P[3][3]=a/2;

P[4][1]=-a/2;P[4][2]=-a/2;P[4][3]=a/2;

P[5][1]=a/2;P[5][2]=-a/2;P[5][3]=-a/2;

P[6][1]=a/2;P[6][2]=a/2;P[6][3]=-a/2;

P[7][1]=a/2;P[7][2]=a/2;P[7][3]=a/2;

P[8][1]=a/2;P[8][2]=-a/2;P[8][3]=a/2;

}

void CTestView::ReadFace()//读入6个面坐标

{

//第一列为每个面的边数;其余列为面的顶点编号

F[1][0]=4;F[1][1]=1;F[1][2]=2;F[1][3]=3;F[1][4]=4;

F[2][0]=4;F[2][1]=1;F[2][2]=4;F[2][3]=8;F[2][4]=5;

F[3][0]=4;F[3][1]=5;F[3][2]=6;F[3][3]=7;F[3][4]=8;

F[4][0]=4;F[4][1]=6;F[4][2]=2;F[4][3]=3;F[4][4]=7;

F[5][0]=4;F[5][1]=8;F[5][2]=7;F[5][3]=3;F[5][4]=4;

F[6][0]=4;F[6][1]=5;F[6][2]=6;F[6][3]=2;F[6][4]=1; }

void CTestView::DrawObject(CDC *pDC)//绘制立方体{

int TotalEdge,PointNumber;

int xt,yt,zt,x,y,z;//边的点坐标

CPen MyPen,* OldPen;

double x2d,y2d;//屏幕坐标系的二维坐标点

MyPen.CreatePen(PS_SOLID,3,RGB(0,0,0));

OldPen=pDC->SelectObject(&MyPen);

for(face=1;face<=6;face++)

{

TotalEdge=F[face][0];//面的总边数

for(int edge=1;edge<=TotalEdge;edge++)//边循环

{

PointNumber=F[face][edge];//面的顶点号

x=P[PointNumber][1];//每个顶点的x,y,z坐标

y=P[PointNumber][2];

z=P[PointNumber][3];

Project(x2d, y2d, x,y,z);

if(edge==1)//保存起点用于闭合

{

pDC->MoveTo(ROUND(x2d),ROUND(y2d));

xt=x;yt=y;zt=z;

}

else

{

pDC->LineTo(ROUND(x2d),ROUND(y2d));

}

}

Project(x2d, y2d, xt,yt,zt);

pDC->LineTo(ROUND(x2d),ROUND(y2d));//封闭边

}

pDC->SelectObject(OldPen);

MyPen.DeleteObject();

}

void CTestView::Project(double &x2d, double &y2d, int x,int y,int z)//透视变换{

double x0,y0,z0;

//用户坐标变换为观察坐标系三维坐标,即用户坐标系坐标乘观察坐标变换矩阵(x,y,z,1)*Tv

x0 = x*Proj[0][0]+y*Proj[1][0]+z*Proj[2][0]+Proj[3][0];

y0 = x*Proj[0][1]+y*Proj[1][1]+z*Proj[2][1]+Proj[3][1];

z0 = x*Proj[0][2]+y*Proj[1][2]+z*Proj[2][2]+Proj[3][2];

//观察坐标系三维坐标透视变换为屏幕坐标系二维坐标,即(xv,yv,zv,1)*Ts,再转化为非其次坐标

x2d=D*x0/z0;

y2d=D*y0/z0;

}

void CTestView::InitParameter()//初始化观察坐标变换矩阵

{

double cosTheta = cos(PI*Theta/180);

double sinTheta = sin(PI*Theta/180);

double cosPhi = cos(PI*Phi/180);

double sinPhi = sin(PI*Phi/180);

double cosAlpha = cos(PI*Alpha/180);

double sinAlpha = sin(PI*Alpha/180);

Proj[0][0] = cosTheta*cosAlpha+sinTheta*cosPhi*sinAlpha;

Proj[0][1] = cosTheta*sinAlpha - cosPhi*sinTheta*cosAlpha;

Proj[0][2] = -sinPhi*sinTheta;

Proj[0][3] = 0;

Proj[1][0] = -sinPhi*sinAlpha;

Proj[1][1] = sinPhi*cosAlpha;

Proj[1][2] = -cosPhi;

Proj[1][3] = 0;

Proj[2][0] = -sinTheta*cosAlpha+cosTheta*cosPhi*sinAlpha;

Proj[2][1] = -sinTheta*sinAlpha-cosPhi*cosTheta*cosAlpha;

Proj[2][2] = -sinPhi*cosTheta;

Proj[2][3] = 0;

Proj[3][0] =

-(a*cosTheta-c*sinTheta)*cosAlpha-(-b*sinPhi+(a*sinTheta+c*cosTheta)*cosPhi)*si nAlpha;

Proj[3][1] = -(a*cosTheta-c*sinTheta)*sinAlpha+(-b*sinPhi+(a*sinTheta+c*cosTheta)*cosPhi)*c osAlpha;

Proj[3][2] = b*cosPhi+(a*sinTheta+c*cosTheta)*sinPhi;

Proj[3][3] = 1;

}

void CTestView::OnCustom()

{

// TODO: Add your command handler code here

AfxGetMainWnd()->SetWindowText("透视变换-任意观察坐标系透视");

//任意设定观察点

a = 200;

b = 0;

c = 500;

//观察角度

Theta=20;

Phi=90;

Alpha = 10;

//视距

D = 800;

InitParameter();

ReadPoint();

ReadFace();

RedrawWindow();

}

void CTestView::OnMENUOne() //一点透视

{

// TODO: Add your command handler code here

AfxGetMainWnd()->SetWindowText("透视变换-一点透视");

Theta=0;

Phi=90;

Alpha = 0;

//采用球面坐标设定观察点

double R= 700.0;

a = R*sin(PI*Phi/180)*sin(PI*Theta/180);

b = R*cos(PI*Phi/180);

c = R*sin(PI*Phi/180)*cos(PI*Theta/180);

D = 1000;//视距

InitParameter();

ReadPoint();

ReadFace();

RedrawWindow();

}

void CTestView::OnMENUTwo()//二点透视

{

// TODO: Add your command handler code here

AfxGetMainWnd()->SetWindowText("透视变换-二点透视");

Theta=30;

Phi=90;

Alpha =0;

//采用球面坐标设定观察点

double R= 700.0;

a = R*sin(PI*Phi/180)*sin(PI*Theta/180);

b = R*cos(PI*Phi/180);

c = R*sin(PI*Phi/180)*cos(PI*Theta/180);

D = 1000;//视距

InitParameter();

ReadPoint();

ReadFace();

RedrawWindow();

}

void CTestView::OnMENUThree() //三点透视

{

// TODO: Add your command handler code here

AfxGetMainWnd()->SetWindowText("透视变换-三点透视");

Theta=45;

Phi=45;

Alpha=0;

//采用球面坐标设定观察点

double R= 700.0;

a = R*sin(PI*Phi/180)*sin(PI*Theta/180);

b = R*cos(PI*Phi/180);

c = R*sin(PI*Phi/180)*cos(PI*Theta/180);

D = 1000;//视距

InitParameter();

ReadPoint();

ReadFace();

RedrawWindow();

}

实验截图

4、迭代剖分法生成球面。

首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。

其次、初始化生成正八面体的顶点表,和面表。

再次、对面表里的每一个三角形进行剖分,一个三角形变成四个三角形。将产生的新的顶点加入到顶点表,同时将产生的新三角形加入到面表里,并从面表里删除原来的三角形。迭代多次后即得一个逼近于球面的多面体。

最后、对面表里的每一个三角形进行透视投影,在屏幕上画出透视投影图,调试程序直至正确。

实验核心代码如下:

void CTestView::GenerateSphereFace()//生成球面表

{

//首先生成一个正八面体

int a=200;

P[0][0]=0; P[0][1]=a; P[0][2]=0;

P[1][0]=0; P[1][1]=-a; P[1][2]=0;

P[2][0]=a; P[2][1]=0; P[2][2]=0;

P[3][0]=0; P[3][1]=0; P[3][2]=-a;

P[4][0]=-a; P[4][1]=0; P[4][2]=0;

P[5][0]=0; P[5][1]=0; P[5][2]=a;

int ptNum = 6;

faceNum = 8;

F[0][0]=3;F[0][1]=0;F[0][2]=4;F[0][3]=5;

F[1][0]=3;F[1][1]=0;F[1][2]=5;F[1][3]=2;

F[2][0]=3;F[2][1]=0;F[2][2]=2;F[2][3]=3;

F[3][0]=3;F[3][1]=0;F[3][2]=3;F[3][3]=4;

F[4][0]=3;F[4][1]=1;F[4][2]=5;F[4][3]=4;

F[5][0]=3;F[5][1]=1;F[5][2]=2;F[5][3]=5;

F[6][0]=3;F[6][1]=1;F[6][2]=3;F[6][3]=2;

F[7][0]=3;F[7][1]=1;F[7][2]=4;F[7][3]=3;

//分割迭代

for(int times = 0; times < 3; times++)

{

int i, iNum = faceNum;

for(i = 0; i < iNum; i++)

{//一个三角形分割为四个三角形

// * *

// => * *

// * * * * *

//先求中点坐标,并添加到点表

int pt1 = F[i][1];

int pt2 = F[i][2];

int pt3 = F[i][3];

int mid12 = ptNum++;

double mx = (P[pt1][0] + P[pt2][0])/2;

double my = (P[pt1][1] + P[pt2][1])/2;

double mz = (P[pt1][2] + P[pt2][2])/2;

P[mid12][0] = a/sqrt(mx*mx+my*my+mz*mz)*mx;//坐标规范化

P[mid12][1] = a/sqrt(mx*mx+my*my+mz*mz)*my;

P[mid12][2] = a/sqrt(mx*mx+my*my+mz*mz)*mz;

int mid23 = ptNum++;

mx = (P[pt3][0] + P[pt2][0])/2;

my = (P[pt3][1] + P[pt2][1])/2;

mz = (P[pt3][2] + P[pt2][2])/2;

P[mid23][0] = a/sqrt(mx*mx+my*my+mz*mz)*mx;

P[mid23][1] = a/sqrt(mx*mx+my*my+mz*mz)*my;

P[mid23][2] = a/sqrt(mx*mx+my*my+mz*mz)*mz;

int mid13 = ptNum++;

mx = (P[pt1][0] + P[pt3][0])/2;

my = (P[pt1][1] + P[pt3][1])/2;

mz = (P[pt1][2] + P[pt3][2])/2;

P[mid13][0] = a/sqrt(mx*mx+my*my+mz*mz)*mx;

P[mid13][1] = a/sqrt(mx*mx+my*my+mz*mz)*my;

P[mid13][2] = a/sqrt(mx*mx+my*my+mz*mz)*mz;

//被分割的三角形改为其中一个小的三角形,新建另外三个小的三角形

F[i][2] = mid12;

F[i][3] = mid13;

F[faceNum][0] = 3;

F[faceNum][1] = mid12;

F[faceNum][2] = pt2;

F[faceNum][3] = mid23;

faceNum++;

F[faceNum][0] = 3;

F[faceNum][1] = mid13;

F[faceNum][2] = mid23;

F[faceNum][3] = pt3;

faceNum++;

F[faceNum][0] = 3;

F[faceNum][1] = mid12;

F[faceNum][2] = mid23;

F[faceNum][3] = mid13;

faceNum++;

}

}

}

void CTestView::GenerateEllipsoidFace()//生成椭球面表

{

int a = 200, b = 100, c = 100;

P[0][0]=0; P[0][1]=b; P[0][2]=0;

P[1][0]=0; P[1][1]=-b; P[1][2]=0;

P[2][0]=a; P[2][1]=0; P[2][2]=0;

P[3][0]=0; P[3][1]=0; P[3][2]=-c;

P[4][0]=-a; P[4][1]=0; P[4][2]=0;

P[5][0]=0; P[5][1]=0; P[5][2]=c;

int ptNum = 6;

faceNum = 8;

F[0][0]=3;F[0][1]=0;F[0][2]=4;F[0][3]=5;

F[1][0]=3;F[1][1]=0;F[1][2]=5;F[1][3]=2;

F[2][0]=3;F[2][1]=0;F[2][2]=2;F[2][3]=3;

F[3][0]=3;F[3][1]=0;F[3][2]=3;F[3][3]=4;

F[4][0]=3;F[4][1]=1;F[4][2]=5;F[4][3]=4;

F[5][0]=3;F[5][1]=1;F[5][2]=2;F[5][3]=5;

F[6][0]=3;F[6][1]=1;F[6][2]=3;F[6][3]=2;

F[7][0]=3;F[7][1]=1;F[7][2]=4;F[7][3]=3;

//分割迭代

for(int times = 0; times < 3; times++)

{

int i, iNum = faceNum;

for(i = 0; i < iNum; i++)

{//一个三角形分割为四个三角形

// * *

// => * *

// * * * * *

//先求中点坐标,并添加到点表

int pt1 = F[i][1];

int pt2 = F[i][2];

int pt3 = F[i][3];

int mid12 = ptNum++;

double mx = (P[pt1][0] + P[pt2][0])/2;

double my = (P[pt1][1] + P[pt2][1])/2;

double mz = (P[pt1][2] + P[pt2][2])/2;

double scale = 1.0/sqrt(mx*mx/(a*a)+my*my/(b*b)+mz*mz/(c*c));

P[mid12][0] = scale*mx;//坐标规范化

P[mid12][1] = scale*my;

P[mid12][2] = scale*mz;

int mid23 = ptNum++;

mx = (P[pt3][0] + P[pt2][0])/2;

my = (P[pt3][1] + P[pt2][1])/2;

mz = (P[pt3][2] + P[pt2][2])/2;

scale = 1.0/sqrt(mx*mx/(a*a)+my*my/(b*b)+mz*mz/(c*c));

P[mid23][0] = scale*mx;

P[mid23][1] = scale*my;

P[mid23][2] = scale*mz;

int mid13 = ptNum++;

mx = (P[pt1][0] + P[pt3][0])/2;

my = (P[pt1][1] + P[pt3][1])/2;

mz = (P[pt1][2] + P[pt3][2])/2;

scale = 1.0/sqrt(mx*mx/(a*a)+my*my/(b*b)+mz*mz/(c*c));

P[mid13][0] = scale*mx;

P[mid13][1] = scale*my;

P[mid13][2] = scale*mz;

//被分割的三角形改为其中一个小的三角形,新建另外三个小的三角形

F[i][2] = mid12;

F[i][3] = mid13;

F[faceNum][0] = 3;

F[faceNum][1] = mid12;

F[faceNum][2] = pt2;

F[faceNum][3] = mid23;

faceNum++;

F[faceNum][0] = 3;

F[faceNum][1] = mid13;

F[faceNum][2] = mid23;

F[faceNum][3] = pt3;

faceNum++;

F[faceNum][0] = 3;

F[faceNum][1] = mid12;

F[faceNum][2] = mid23;

F[faceNum][3] = mid13;

faceNum++;

}

}

}

void CTestView::DrawObject(CDC *pDC)//绘制

{

int TotalEdge,pt;

int xt,yt,zt,x,y,z;//边的点坐标

double x2d,y2d;//屏幕坐标系的二维坐标点

for(int face=0;face

{

TotalEdge=F[face][0];//面的总边数

if(!IsFaceVisible(F[face]))//判定从视线方向看过去,该面是否可见

continue;

for(int edge=1;edge<=TotalEdge;edge++)//边循环

{

pt=F[face][edge];//面的顶点号

x=P[pt][0];//每个顶点的x,y,z坐标

y=P[pt][1];

z=P[pt][2];

Project(x2d, y2d, x,y,z);

if(edge==1)//保存起点用于闭合

{

pDC->MoveTo(ROUND(x2d),ROUND(y2d));

xt=x;yt=y;zt=z;

}

else

{

pDC->LineTo(ROUND(x2d),ROUND(y2d));

}

}

Project(x2d, y2d, xt,yt,zt);

pDC->LineTo(ROUND(x2d),ROUND(y2d));//封闭边

}

}

void CTestView::Project(double &x2d, double &y2d, int x,int y,int z)//透视变换{

double x0,y0,z0;

//用户坐标变换为观察坐标系三维坐标,即用户坐标系坐标乘观察坐标变换矩阵(x,y,z,1)*Tv

x0 = x*Proj[0][0]+y*Proj[1][0]+z*Proj[2][0]+Proj[3][0];

y0 = x*Proj[0][1]+y*Proj[1][1]+z*Proj[2][1]+Proj[3][1];

z0 = x*Proj[0][2]+y*Proj[1][2]+z*Proj[2][2]+Proj[3][2];

//观察坐标系三维坐标透视变换为屏幕坐标系二维坐标,即(xv,yv,zv,1)*Ts,再转化为非其次坐标

x2d=D*x0/z0;

y2d=D*y0/z0;

}

void CTestView::InitParameter()//初始化观察坐标变换矩阵

{

double cosTheta = cos(PI*Theta/180);

double sinTheta = sin(PI*Theta/180);

double cosPhi = cos(PI*Phi/180);

double sinPhi = sin(PI*Phi/180);

double cosAlpha = cos(PI*Alpha/180);

double sinAlpha = sin(PI*Alpha/180);

Proj[0][0] = cosTheta*cosAlpha+sinTheta*cosPhi*sinAlpha;

Proj[0][1] = cosTheta*sinAlpha - cosPhi*sinTheta*cosAlpha;

Proj[0][2] = -sinPhi*sinTheta;

Proj[0][3] = 0;

Proj[1][0] = -sinPhi*sinAlpha;

Proj[1][1] = sinPhi*cosAlpha;

Proj[1][2] = -cosPhi;

Proj[1][3] = 0;

Proj[2][0] = -sinTheta*cosAlpha+cosTheta*cosPhi*sinAlpha;

Proj[2][1] = -sinTheta*sinAlpha-cosPhi*cosTheta*cosAlpha;

Proj[2][2] = -sinPhi*cosTheta;

Proj[2][3] = 0;

Proj[3][0] = -(a*cosTheta-c*sinTheta)*cosAlpha-(-b*sinPhi+(a*sinTheta+c*cosTheta)*cosPhi)*si nAlpha;

Proj[3][1] = -(a*cosTheta-c*sinTheta)*sinAlpha+(-b*sinPhi+(a*sinTheta+c*cosTheta)*cosPhi)*c osAlpha;

Proj[3][2] = b*cosPhi+(a*sinTheta+c*cosTheta)*sinPhi;

Proj[3][3] = 1;

}

BOOL CTestView::IsFaceVisible(int Face[5])

{

//求视矢量

int pt0 = Face[1];

int pt1 = Face[2];

int pt2 = Face[3];

//视点坐标减面的某个顶点的坐标(这里取第一个顶点),即得视矢量int Vx=a-P[pt0][0];

int Vy=b-P[pt0][1];

int Vz=c-P[pt0][2];

//求法矢量

//先求第一条边的分量

int Fx1=P[pt1][0]-P[pt0][0];

int Fy1=P[pt1][1]-P[pt0][1];

int Fz1=P[pt1][2]-P[pt0][2];

//先求第二条边的分量

int Fx2=P[pt2][0]-P[pt0][0];

int Fy2=P[pt2][1]-P[pt0][1];

int Fz2=P[pt2][2]-P[pt0][2];

//法矢量为第一和第二个矢量的叉积

int Nx=Fy1*Fz2-Fy2*Fz1;

int Ny=Fz1*Fx2-Fz2*Fx1;

int Nz=Fx1*Fy2-Fx2*Fy1;

//法矢量与视矢量点积>0表示夹角小于90

return Vx*Nx+Vy*Ny+Vz*Nz > 0;

}

void CTestView::OnCustom()

{

// TODO: Add your command handler code here

AfxGetMainWnd()->SetWindowText("球");

Theta=45;

Phi=90;

Alpha = 0;

//采用球面坐标设定观察点

double R= 700.0;

a = R*sin(PI*Phi/180)*sin(PI*Theta/180);

b = R*cos(PI*Phi/180);

c = R*sin(PI*Phi/180)*cos(PI*Theta/180);

D = 800;//视距

InitParameter();

GenerateSphereFace();

RedrawWindow();

}

void CTestView::OnMENUOne()

{

// TODO: Add your command handler code here

AfxGetMainWnd()->SetWindowText("椭球");

Theta=0;

Phi=90;

Alpha = 0;

//采用球面坐标设定观察点

double R= 700.0;

a = R*sin(PI*Phi/180)*sin(PI*Theta/180);

b = R*cos(PI*Phi/180);

c = R*sin(PI*Phi/180)*cos(PI*Theta/180);

D = 800;//视距

InitParameter();

GenerateEllipsoidFace();

RedrawWindow();

}

实验截图

实验总结:

这次试验在指导书的引导下,将每个环节逐步完成,最终顺利完成实验。通过该实验,总的来说,还有不少收获,比如进一步熟悉了Bresenham直线扫描转换算法的思想,同时,在实验中也培养了自己的耐心,总归,有不少收获。

研究生计算机图形学课程室内场景OpenGL--实验报告Word版

《高级计算机图形学》实验报告 姓名:学号:班级: 【实验报告要求】 实验名称:高级计算机图形学室内场景 实验目的:掌握使用OpenGL生成真实感复杂对象的方法,进一步熟练掌握构造实体几何表示法、扫描表示法、八叉树法、BSP树法等建模方法。 实验要求:要求利用OpenGL生成一个真实感的复杂对象及其周围场景,并显示观测点变化时的几何变换,要具备在一个纹理复杂的场景中漫游功能。要求使用到光线跟踪算法、 纹理映射技术以及实时绘制技术。 一、实验效果图 图1:正面效果图

图2:背面效果图 图4:背面效果图

图4:室内场景细节效果图 图5:场景角度转换效果图

二、源文件数据代码: 共6个文件,其实现代码如下: 1、DlgAbout.cpp #include "StdAfx.h" #include "DlgAbout.h" CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() 2、FormCommandView.cpp #include "stdafx.h" #include "Tool.h" #include "MainFrm.h" #include "FormCommandView.h" #include "ToolDoc.h" #include "RenderView.h" // Download by https://www.wendangku.net/doc/8f5585161.html, #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // CFormCommandView IMPLEMENT_DYNCREATE(CFormCommandView, CFormView) CFormCommandView::CFormCommandView() : CFormView(CFormCommandView::IDD) { //{{AFX_DATA_INIT(CFormCommandView)

计算机图形学实验报告 (2)

中南大学信息科学与工程学院 实验报告实验名称 实验地点科技楼四楼 实验日期2014年6月 指导教师 学生班级 学生姓名 学生学号 提交日期2014年6月

实验一Window图形编程基础 一、实验类型:验证型实验 二、实验目的 1、熟练使用实验主要开发平台VC6.0; 2、掌握如何在编译平台下编辑、编译、连接和运行一个简单的Windows图形应用程序; 3、掌握Window图形编程的基本方法; 4、学会使用基本绘图函数和Window GDI对象; 三、实验内容 创建基于MFC的Single Document应用程序(Win32应用程序也可,同学们可根据自己的喜好决定),程序可以实现以下要求: 1、用户可以通过菜单选择绘图颜色; 2、用户点击菜单选择绘图形状时,能在视图中绘制指定形状的图形; 四、实验要求与指导 1、建立名为“颜色”的菜单,该菜单下有四个菜单项:红、绿、蓝、黄。用户通过点击不同的菜单项,可以选择不同的颜色进行绘图。 2、建立名为“绘图”的菜单,该菜单下有三个菜单项:直线、曲线、矩形 其中“曲线”项有级联菜单,包括:圆、椭圆。 3、用户通过点击“绘图”中不同的菜单项,弹出对话框,让用户输入绘图位置,在指定位置进行绘图。

五、实验结果: 六、实验主要代码 1、画直线:CClientDC *m_pDC;再在OnDraw函数里给变量初始化m_pDC=new CClientDC(this); 在OnDraw函数中添加: m_pDC=new CClientDC(this); m_pDC->MoveTo(10,10); m_pDC->LineTo(100,100); m_pDC->SetPixel(100,200,RGB(0,0,0)); m_pDC->TextOut(100,100); 2、画圆: void CMyCG::LineDDA2(int xa, int ya, int xb, int yb, CDC *pDC) { int dx = xb - xa; int dy = yb - ya; int Steps, k; float xIncrement,yIncrement; float x = xa,y= ya; if(abs(dx)>abs(dy))

计算机图形学实验一

实验一二维基本图元的生成与填充 实验目的 1.了解并掌握二维基本图元的生成算法与填充算法。 2.实现直线生成的DDA算法、中点算法和Bresenham算法。 3.实现圆和椭圆生成的DDA和中点算法, 对几种算法的优缺点有感性认识。 二.实验内容和要求 1.选择自己熟悉的任何编程语言, 建议使用VC++6.0。 2.创建良好的用户界面,包括菜单,参数输入区域和图形显示区域。 3.实现生成直线的DDA算法、中点算法和Bresenham算法。 4.实现圆弧生成的中点算法。 5.实现多边形生成的常用算法, 如扫描线算法,边缘填充算法。 6.实现一般连通区域的基于扫描线的种子填充算法。 7.将生成算法以菜单或按钮形式集成到用户界面上。 8.直线与圆的坐标参数可以用鼠标或键盘输入。 6. 可以实现任何情形的直线和圆的生成。 实验报告 1.用户界面的设计思想和框图。 2.各种实现算法的算法思想。 3.算法验证例子。 4.上交源程序。 直线生成程序设计的步骤如下: 为编程实现上述算法,本程序利用最基本的绘制元素(如点、直线等),绘制图形。如图1-1所示,为程序运行主界面,通过选择菜单及下拉菜单的各功能项分别完成各种对应算法的图形绘制。 图1-1 基本图形生成的程序运行界面 2.创建工程名称为“基本图形的生成”单文档应用程序框架

(1)启动VC,选择“文件”|“新建”菜单命令,并在弹出的新建对话框中单击“工程”标签。 (2)选择MFC AppWizard(exe),在“工程名称”编辑框中输入“基本图形的生成”作为工程名称,单击“确定”按钮,出现Step 1对话框。 (3)选择“单个文档”选项,单击“下一个”按钮,出现Step 2对话框。 (4)接受默认选项,单击“下一个”按钮,在出现的Step 3~Step 5对话框中,接受默认选项,单击“下一个”按钮。 (5)在Step 6对话框中单击“完成”按钮,即完成“基本图形的生成”应用程序的所有选项,随后出现工程信息对话框(记录以上步骤各选项选择情况),如图1-2所示,单击“确定”按钮,完成应用程序框架的创建。 图1-2 信息程序基本 3.编辑菜单资源 设计如图1-1所示的菜单项。在工作区的ResourceView标签中,单击Menu项左边“+”,然后双击其子项IDR_MAINFRAME,并根据表1-1中的定义编辑菜单资源。此时VC已自动建好程序框架,如图1-2所示。 表1-1菜单资源表 菜单标题菜单项标题标示符ID 直线DDA算法生成直线ID_DDALINE Bresenham算法生成直线ID_BRESENHAMLINE 中点算法生成直线ID_MIDPOINTLINE 4.添加消息处理函数 利用ClassWizard(建立类向导)为应用程序添加与菜单项相关的消息处理函数,ClassName栏中选择CMyView,根据表1-2建立如下的消息映射函数,ClassWizard会自动完成有关的函数声明。 表1-2菜单项的消息处理函数 菜单项ID消息消息处理函数ID_DDALINE CONMMAN OnDdaline

计算机图形学课程设计报告

一、设计内容与要求 1.1、设计题目 算法实现时钟运动 1.2、总体目标和要求 (1)目标:以图形学算法为目标,深入研究。继而策划、设计并实现一个能够表现计算机图形学算法原理的或完整过程的演示系统,并能从某些方面作出评价和改进意见。通过完成一个完整程序,经历策划、设计、开发、测试、总结和验收各阶段,达到巩固和实践计算机图形学课程中的理论和算法;学习表现计算机图形学算法的技巧;培养认真学习、积极探索的精神。 (2)总体要求:策划、设计并实现一个能够充分表现图形学算法的演示系统,界面要求美观大方,能清楚地演示算法执行的每一个步骤。(3)开发环境:Viusal C++ 6.0 1.3、设计要求 内容: (1)掌握动画基本原理; (2)实现平面几何变换; 功能要求: (1)显示时钟三个时针,实现三根时针间的相互关系;

(2)通过右键菜单切换时钟背景与时针颜色; 1.4设计方案 通过使用OpenGL提供的标准库函数,综合图形学Bresenham画线和画圆的算法,OpenGL颜色模型中颜色表示模式等实现指针式时钟运动,并通过点击右键菜单实习时钟背景与时针颜色的转换。根据Bresenham画线和画圆的算法,画出时钟的指针和表盘。再根据OpenGL颜色模型定义当前颜色。设置当时钟运行时交换的菜单,运行程序时可变换时钟背景与时针的颜色。最后再设置一个恢复菜单恢复开始时表盘与指针的颜色。

二、总体设计 2.1、过程流程图

2.2、椭圆的中点生成算法 1、椭圆对称性质原理: (1)圆是满足x轴对称的,这样只需要计算原来的1/2点的位置;(2)圆是满足y轴对称的,这样只需要计算原来的1/2点的位置; 通过上面分析可以得到实际上我们计算椭圆生成时候,只需要计算1/4个椭圆就可以实现对于所有点的生成了。 2、中点椭圆算法内容: (1)输入椭圆的两个半径r1和r2,并且输入椭圆的圆心。设置初始点(x0,y0)的位置为(0,r2); (2)计算区域1中央决策参数的初始值 p = ry*ry - rx*rx*ry + 1/4*(rx*rx); (3)在区域1中的每个Xn为止,从n = 0 开始,直到|K|(斜率)小于-1时后结束; <1>如果p < 0 ,绘制下一个点(x+1,y),并且计算 p = p + r2*r2*(3+2*x); <2>如果P >=0 ,绘制下一个点(x+1,y-1),并且计算 p = p + r2*r2*(3+2*point.x) - 2*r1*r1*(y-1) (4)设置新的参数初始值; p = ry*ry(X0+1/2)*(X0+1/2) + rx*rx*(Y0-1) - rx*rx*ry*ry; (5)在区域2中的每个Yn为止,从n = 0开始,直到y = 0时结束。 <1>如果P>0的情况下,下一个目标点为(x,y-1),并且计算 p = p - 2rx*rx*(Yn+1) + rx*rx;

计算机图形学实验报告,DOC

欢迎共阅

目录

实验一直线的DDA算法 一、【实验目的】 1.掌握DDA算法的基本原理。 2.掌握 3. 1.利用 2.加强对 四 { glClearColor(1.0f,1.0f,1.0f,1.0f); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0,200.0,0.0,150.0); } voidDDALine(intx0,inty0,intx1,inty1) { glColor3f(1.0,0.0,0.0); intdx,dy,epsl,k; floatx,y,xIncre,yIncre; dx=x1-x0;dy=y1-y0;

x=x0;y=y0; if(abs(dx)>abs(dy))epsl=abs(dx); elseepsl=abs(dy); xIncre=(float)dx/(float)epsl; yIncre=(float)dy/(float)epsl; for(k=0;k<=epsl;k++) { glPointSize(3); glBegin(GL_POINTS); glEnd(); } } { } { } { glutInitWindowSize(400,300); glutInitWindowPosition(100,120); glutCreateWindow("line"); Initial(); glutDisplayFunc(Display); glutReshapeFunc(winReshapeFcn); glutMainLoop(); return0; }

计算机图形学实验

实验1 直线的绘制 实验目的 1、通过实验,进一步理解和掌握DDA和Bresenham算法; 2、掌握以上算法生成直线段的基本过程; 3、通过编程,会在TC环境下完成用DDA或中点算法实现直线段的绘制。实验环境 计算机、Turbo C或其他C语言程序设计环境 实验学时 2学时,必做实验。 实验内容 用DDA算法或Besenham算法实现斜率k在0和1之间的直线段的绘制。 实验步骤 1、算法、原理清晰,有详细的设计步骤; 2、依据算法、步骤或程序流程图,用C语言编写源程序; 3、编辑源程序并进行调试; 4、进行运行测试,并结合情况进行调整; 5、对运行结果进行保存与分析; 6、把源程序以文件的形式提交; 7、按格式书写实验报告。 实验代码:DDA: # include # include

void DDALine(int x0,int y0,int x1,int y1,int color) { int dx,dy,epsl,k; float x,y,xIncre,yIncre; dx=x1-x0; dy=y1-y0; x=x0; y=y0; if(abs(dx)>abs(dy)) epsl=abs(dx); else epsl=abs(dy); xIncre=(float)dx/(float)epsl; yIncre=(float)dy/(float)epsl; for(k=0;k<=epsl;k++) { putpixel((int)(x+0.5),(int)(y+0.5),4); x+=xIncre; y+=yIncre; } } main(){ int gdriver ,gmode ;

计算机图形学实验二

实验报告 课程名称:计算机图形学 实验项目:区域填充算法 实验仪器:计算机 系别:计算机学院 专业:计算机科学与技术 班级姓名:计科1602/ 学号:2016011 日期:2018-12-8 成绩: 指导教师:

一.实验目的(Objects) 1.实现多边形的扫描线填充算法。 二.实验内容 (Contents) 实现多边形的扫描线填充算法,通过鼠标,交互的画出一个多边形,然后利用种子填充算法,填充指定的区域。不能使用任何自带的填充区域函数,只能使用画点、画线函数或是直接对图像的某个像素进行赋值操作;

三.实验内容 (Your steps or codes, Results) //widget.cpp //2016CYY Cprogramming #include"widget.h" #include #include #include using namespace std; #define H 1080 #define W 1920 int click = 0; //端点数量 QPoint temp; QPoint first; int result = 1; //判断有没有结束 int sign = 1; //2为画线 int length = 5; struct edge { int ymax; float x; float dx; edge *next; }; edge edge_; QVector edges[H]; QVector points;//填充用 bool fin = false; QPoint *Queue = (QPoint *)malloc(length * sizeof(QPoint)); //存放端点的数组 Widget::Widget(QWidget *parent) : QWidget(parent) { } Widget::~Widget() { } void Widget::mouseMoveEvent(QMouseEvent *event) { setMouseTracking(true); if (click > 0 && result != 0) { startPt = temp; endPt =event->pos(); sign = 2; update(); } } void Widget::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { } else if (event->button() == Qt::RightButton) { sign = 2;

计算机图形学实验报告记录

计算机图形学实验报告记录

————————————————————————————————作者:————————————————————————————————日期:

计算机图形学实验报告 姓名:___ __________ 学号:_____ ________ 班级:______ _______ 时间:_____2016年12月_________

实验一OpenGL编程与图形绘制 1.实验目的 了解OpenGL编程,并熟悉OpenGL的主要功能、绘制流程和基本语法。学会配置OpenGL环境,并在该环境中编程绘图。 2.实验内容 OpenGL的主要功能:模型绘制、模型观察、颜色模式、光照应用、图像效果增强、位图和图像处理、纹理映射、实时动画和交互技术。 OpenGL的绘制流程分为两个方面:一个完整的窗口系统的OpenGL图形处理系统的结构为:最底层为图形硬件,第二层为操作系统,第三层为窗口系统,第四层为OpenGL,最上面的层为应用软件;OpenGL命令将被放在一个命令缓冲区中,这样命令缓冲区中包含了大量的命令、顶点数据和纹理数据。当缓冲区被清空时,缓冲区中的命令和数据都将传递给流水线的下一个阶段。 OpenGL的基本语法中相关库有:OpenGL核心库:gl、OpenGL实用程序库:glu、OpenG 编程辅助库:aux、OpenGL实用程序工具包(OpenGL utility toolkit,GLUT):glut、Windows 专用库:wgl。 OpenGL的基本语法中命名规则为:OpenGL函数都遵循一个命名约定,即采用以下格式:<库前缀><根命令><可选的参数个数><可选的参数类型>。 了解了上述基础知识后,配置好OpenGL环境,然后在该环境中编程练习图形的绘制,本次实验主要是对点的绘制、直线的绘制和多边形面的绘制。 3.实验代码及结果 3.1点的绘制: #include void Initial(void) { glClearColor(1.0f,1.0f,1.0f,1.0f); //设置窗口背景颜色为白色 glMatrixMode(GL_PROJECTION); //指定设置投影参数 gluOrtho2D(0.0,200.0,0.0,150.0); //设置投影参数 } void Display(void) {

计算机图形学实验指导书1

佛山科学技术学院计算机图形学实验指导书 李晓东编 电信学院计算机系 2011年11月

实验1 直线段的扫描转换 实验类型:设计性 实验类别:专业实验 实验目的 1.通过实验,进一步理解直线段扫描转换的DDA算法、中点bresenham算法及 bresenham算法的基本原理; 2.掌握以上算法生成直线段的基本过程; 3.通过编程,会在C/C++环境下完成用DDA算法、中点bresenham算法及 bresenham算法对任意直线段的扫描转换。 实验设备及实验环境 计算机(每人一台) VC++6.0或其他C/C++语言程序设计环境 实验学时:2学时 实验内容 用DDA算法中点bresenham算法及bresenham算法实现任意给定两点的直线段的绘制(直线宽度和线型可自定)。 实验步骤: 1、复习有关算法的基本原理,明确实验目的和要求; 2、依据算法思想,绘制程序流程图; 3、设计程序界面,要求操作方便; 4、用C/C++语言编写源程序并调试、执行; 5、分析实验结果 6、对程序设计过程中出现的问题进行分析与总结; 7、打印源程序或把源程序以文件的形式提交; 8、按格式要求完成实验报告。 实验报告要求: 1、各种算法的基本原理; 2、各算法的流程图 3、实验结果及分析(比较三种算法的特点,界面插图并注明实验条件) 4、实验总结(含问题分析及解决方法)

实验2 圆的扫描转换 实验类型:设计性 实验类别:专业实验 实验目的 1、通过实验,进一步理解和掌握中点bresenham画圆算法的基本原理; 2、掌握以上算法生成圆和圆弧的基本过程; 3、掌握在C/C++环境下完成用中点bresenham算法圆或圆弧的绘制方法。实验设备及实验环境 计算机(每人一台) VC++6.0或其他C/C++语言程序设计环境 实验学时:2学时 实验内容 用中点(Besenham)算法实现圆或圆弧的绘制。 实验步骤 1.复习有关圆的生成算法,明确实验目的和要求; 2.依据算法思想,绘制程序流程图(注意圆弧生成时的输入条件); 3.设计程序界面,要求操作方便; 4.用C/C++语言编写源程序并调试、执行; 5.分析实验结果 6.对程序设计过程中出现的问题进行分析与总结; 7.打印源程序或把源程序以文件的形式提交; 8.按格式要求完成实验报告。 实验报告要求: 1.分析算法的工作原理; 2.画出算法的流程图 3.实验结果及分析(比较圆与圆弧生成算法的不同) 4.实验总结(含问题分析及解决方法)

计算机图形学实验报告

《计算机图形学》实验报告姓名:郭子玉 学号:2012211632 班级:计算机12-2班 实验地点:逸夫楼507 实验时间:15.04.10 15.04.17

实验一 1 实验目的和要求 理解直线生成的原理;掌握典型直线生成算法;掌握步处理、分析实验数据的能力; 编程实现DDA 算法、Bresenham 中点算法;对于给定起点和终点的直线,分别调用DDA 算法和Bresenham 中点算法进行批量绘制,并记录两种算法的绘制时间;利用excel 等数据分析软件,将试验结果编制成表格,并绘制折线图比较两种算法的性能。 2 实验环境和工具 开发环境:Visual C++ 6.0 实验平台:Experiment_Frame_One (自制平台) 3 实验结果 3.1 程序流程图 (1)DDA 算法 是 否 否 是 是 开始 计算k ,b K<=1 x=x+1;y=y+k; 绘点 x<=X1 y<=Y1 绘点 y=y+1;x=x+1/k; 结束

(2)Mid_Bresenham 算法 是 否 否 是 是 是 否 是 否 开始 计算dx,dy dx>dy D=dx-2*dy 绘点 D<0 y=y+1;D = D + 2*dx - 2*dy; x=x+1; D = D - 2*dy; x=x+1; x

3.2程序代码 //-------------------------算法实现------------------------------// //绘制像素的函数DrawPixel(x, y); (1)DDA算法 void CExperiment_Frame_OneView::DDA(int X0, int Y0, int X1, int Y1) { //----------请实现DDA算法------------// float k, b; float d; k = float(Y1 - Y0)/float(X1 - X0); b = float(X1*Y0 - X0*Y1)/float(X1 - X0); if(fabs(k)<= 1) { if(X0 > X1) { int temp = X0; X0 = X1; X1 = temp; }

计算机图形学课程参考文献

《计算机图形学》课程参考文献 [1 Kenneth R. Castleman, “Digital Image Processing”, Prentice-Hall International,Inc, 1996 [2] James Sharman. The Marching Cubes Algorithm[EB]. https://www.wendangku.net/doc/8f5585161.html,/. [3] William E. Lorensen, Harvey E. Cline. Marching Cubes: A High Resolution 3D Surface Construction Algrorithm[J].Computer Graphics, 1987, 21(4). [4] Jan Horn. Metaballs程序[CP]. http://www.sulaco.co.za. [5] 唐泽圣,等.三维数据场可视化[M].北京:清华大学出版社,1999.177-179. [6] 白燕斌,史惠康,等.OpenGL三维图形库编程指南[M].北京:机械工业出版社,1998. [7] 费广正,芦丽丹,陈立新.可视化OpenGL程序设计[M].北京:清华大学出版社,2001. [8] 田捷,包尚联,周明全.医学影像处理与分析[M].北京:电子工业出版社,2003. [9] 三维表面模型的重构、化简、压缩及其在计算机骨科手术模拟中的应用[R]. https://www.wendangku.net/doc/8f5585161.html,/~yike/uthesis.pdf ; [10] 首套中国数字化可视人体二维图像[DB]. http://www.chinesevisiblehuman. com/ pic/pictype.asp [11] 季雪岗,王晓辉,张宏林,等.Delphi编程疑难详解[M].北京:人民邮电出版社,2000. [12] 郑启华.PASCAL程序设计(第二版)[M].北京:清华大学出版社,1996. [13] 涂晓斌,谢平,陈海雷,蒋先刚.实用微机工程绘图实验教程[M].西南交通大学出版社,2004,4. [14] David F.Rogers.计算机图形学算法基础[M].北京:电子工业出版社,2002. [15] 李信真,车刚明,欧阳洁,封建湖.计算方法[M].西安:西北工业大学出版社,2000. [16] Paul Bourke Polygonising a scalar field [CP]. http://astronomy. https://www.wendangku.net/doc/8f5585161.html,.au/ ~pbourke/ modelling/polygonise/ [17] 刘骏.Delphi数字图像处理及高级应用[M].北京:科学出版社,2003. [18] 李弼程,彭天强,彭波,等.智能图像处理技术[M].北京:电子工业出版社,2004. [19] Kenneth R.Castleman著,朱志刚,石定机,等译.数字图像处理[M].北京:电子工业出版社,2002. [20] Milan Sonka, Vaclav Hlavac, Roger Boyle.Image Processing, Analysis, and Machine Vision [M].北京:人民邮电出版社,2003. [21] 阮秋奇.数字图像处理学[M]. 北京:电子工业出版社, 2001. [22] 刘宏昆,等.Delphi应用技巧与常见问题[M]. 北京:机械工业出版社, 2003. [23] 张增强,李鲲程,等.专家门诊—Delphi开发答疑300问[M].北京:人民邮电出版社,2003.6.

一种基于计算几何方法的最小包容圆求解算法.kdh

2007年 工 程 图 学 学 报2007 第3期 JOURNAL OF ENGINEERING GRAPHICS No.3一种基于计算几何方法的最小包容圆求解算法 张 勇, 陈 强 (清华大学机械工程系先进成形制造重点实验室,北京 100084) 摘要:为实现点集最小包容圆(最小外接圆)的求解,将计算几何中的α-壳的概 念应用到最小包容圆的计算过程,提出了一种精确有效的最小包容圆求解算法。根据α-壳定 义及最小包容圆性质,证明当1/α等于最小包容圆半径时点集的α-壳顶点共圆,1/α小于最小 包容圆半径时α-壳不存在,1/α大于最小包容圆半径时随着1/α减小α-壳顶点数逐渐减小的规 律。将α-壳顶点数目作为搜索最小包容圆半径的依据,实现了最小包容圆半径的搜索和最小包容圆的求解。 关键词:计算机应用;优化算法;计算几何;最小包容圆;α-壳 中图分类号:TP 391 文献标识码:A 文章编号:1003-0158(2007)03-0097-05 Algorithm for Minimum Circumscribed Circle Detection Based on Computational Geometry Technique ZHANG Yong, CHEN Qiang ( Key Laboratory for Advanced Manufacturing by Materials Processing Technology, Department of Mechanical Engineering, Tsinghua University, Beijing 100084, China ) Abstract: α-hulls are applied to calculate the minimum circumscribed circle (MCC) of point set and an accurate and effective method for MCC detection is established through finding the least squares circle of the point set and iteratively approaching the MCC with recursive subdivision. Several theorems concerning the properties of α-hulls are presented. If 1/α is equal to the radius of points’ MCC, all vertices of the α-hull will be on the same circle. When 1/α is larger than the MCC’s radius, the number of vertices of α-hulls will decrease with decreasing of 1/α, and the number of vertices’ number will reach zero when 1/α is smaller than MCC’s radius. From the above rules, an algorithm for detecting MCC is developed, and experimental results show this algorithm is reliable. Key words: computer application; optimized algorithm; computational geometry; minimum circumscribed circle; α-hull 收稿日期:2005-12-20 基金项目:国家自然科学基金资助项目(50275083);高校博士点基金资助项目(20020003053)

计算机图形学课程设计报告简单图形的绘制-

《计算机图形学》课程设计 报告 学生姓名:学号: 学院: 班级: 题目: 简单图形的绘制 职称2015年7月1日

目录 目录............................................................................................... I 一、选题背景 (1) 二、算法设计 (2) 2.1 绘制直线、圆、椭圆、抛物线 (2) 2.1.1 绘制直线 (2) 2.1.2 绘制圆 (2) 2.1.3 绘制椭圆 (2) 2.1.4 绘制抛物线 (2) 2.2 三维几何变换 (2) 三、程序及功能说明 (5) 3.1 绘制直线、圆、椭圆、抛物线...... (5) 3.1.1 绘制直线 (5) 3.1.2 绘制圆 (5) 3.1.3 绘制椭圆 (5) 3.1.4 绘制抛物线 (6) 3.2 图形的平移 (6) 3.3 图形的旋转 (6) 3.4 图形的缩放 (7) 四、结果分析 (7) 4.1 绘制直线、圆、椭圆、抛物线 (7) 4.1.1 直线 (7) 4.1.2 圆 (8)

4.1.3 椭圆 (8) 4.1.4 抛物线 (8) 4.2 图形的平移 (9) 4.3 图形的旋转 (10) 4.4 图形的缩放 (11) 五、总结 (10) 六、课程设计心得体会 (14) 参考文献 (15) 源程序 (16)

一、选题背景

二、算法设计 2.1 绘制直线、圆、椭圆、抛物线 2.1.1 绘制直线 通过两个点的坐标来绘制直线。计算机图形学中二维图形在显示输出之前需要扫描转换,生成直线的算法一般有DDA 算法和中点算法。 2.1.2 绘制圆 通过运用圆的参数方程cos ;sin x a r y b r θθ=+=+来绘制圆的图形,其中[0,2]θπ∈, (a,b )为圆心,r 为半径,运用参数方程,只需要确定半径的长度和圆心的位置,即可绘制出圆。 2.1.3 绘制椭圆 通过运用椭圆的参数方程cos ;sin x a y b θθ==来绘制椭圆的图形,其中 [0,2]θπ∈,是已知的变量,a ,b 分别为长半轴,短半轴,当确定a 和b 后,通过参数方程即可得到这个椭圆的方程。 2.1.4 绘制抛物线 根据点绘制抛物线图像是通过拟合完成,根据三个点的坐标,通过数据拟合,得到经过这三个点的函数关系式,从而再根据这个函数关系式绘制出抛物线上其他的点,形成一条连续的抛物线;或直接根据已知函数绘制图像是通过已知函数画出图像。 2.2 三维几何变换 三维几何变换是二维几何变换的推广。二维几何变换在齐次坐标空间中 可用3?3的变换矩阵表示,类似的,三维几何变换在齐次坐标空间中可用4?4的变换矩阵表示。三维空间中的点(),,x y z 的齐次坐标定义为(),,h h h x y z ,其中,h 为不等与零的任意常数,h x hx =,h y hy =,h z hz =。亦即点(),,x y z 对应4维齐次坐标空间的一条直线:

计算机图形学上机实验指导

计算机图形学上机实验指导 指导教师:张加万老师 助教:张怡 2009-10-10

目录 1.计算机图形学实验(一) – OPENGL基础 ..................................... - 1 - 1.1综述 (1) 1.2在VC中新建项目 (1) 1.3一个O PEN GL的例子及说明 (1) 2.计算机图形学实验(二) – OPENGL变换 ..................................... - 5 - 2.1变换 (5) 3.计算机图形学实验(三) - 画线、画圆算法的实现....................... - 9 - 3.1MFC简介 (9) 3.2VC6的界面 (10) 3.3示例的说明 (11) 4.计算机图形学实验(四)- 高级OPENGL实验...................... - 14 - 4.1光照效果 (14) 4.2雾化处理 (16) 5.计算机图形学实验(五)- 高级OPENGL实验........................ - 20 - 5.1纹理映射 (20) 5.2反走样 (24) 6.计算机图形学实验(六) – OPENGL IN MS-WINDOWS .......... - 27 - 6.1 实验目标: (27) 6.2分形 (28)

1.计算机图形学实验(一) – OpenGL基础 1.1综述 这次试验的目的主要是使大家初步熟悉OpenGL这一图形系统的用法,编程平台是Visual C++,它对OpenGL提供了完备的支持。 OpenGL提供了一系列的辅助函数,用于简化Windows操作系统的窗口操作,使我们能把注意力集中到图形编程上,这次试验的程序就采用这些辅助函数。 本次实验不涉及面向对象编程,不涉及MFC。 1.2在VC中新建项目 1.2.1新建一个项目 选择菜单File中的New选项,弹出一个分页的对话框,选中页Projects中的Win32 Console Application项,然后填入你自己的Project name,如Test,回车即可。VC为你创建一个工作区(WorkSpace),你的项目Test就放在这个工作区里。 1.2.2为项目添加文件 为了使用OpenGL,我们需要在项目中加入三个相关的Lib文件:glu32.lib、glaux.lib、opengl32.lib,这三个文件位于c:\program files\microsoft visual studio\vc98\lib目录中。 选中菜单Project->Add To Project->Files项(或用鼠标右键),把这三个文件加入项目,在FileView中会有显示。这三个文件请务必加入,否则编译时会出错。或者将这三个文件名添加到Project->Setting->Link->Object/library Modules 即可。 点击工具条中New Text File按钮,新建一个文本文件,存盘为Test.c作为你的源程序文件,再把它加入到项目中,然后就可以开始编程了。 1.3一个OpenGL的例子及说明 1.3.1源程序 请将下面的程序写入源文件Test.c,这个程序很简单,只是在屏幕上画两根线。 #include

《计算机图形学实验报告》

一、实验目的 1、掌握中点Bresenham直线扫描转换算法的思想。 2掌握边标志算法或有效边表算法进行多边形填充的基本设计思想。 3掌握透视投影变换的数学原理和三维坐标系中几何图形到二维图形的观察流程。 4掌握三维形体在计算机中的构造及表示方法 二、实验环境 Windows系统, VC6.0。 三、实验步骤 1、给定两个点的坐标P0(x0,y0),P1(x1,y1),使用中点Bresenham直线扫描转换算法画出连接两点的直线。 实验基本步骤 首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。 其次、使用中点Bresenham直线扫描转换算法实现自己的画线函数,函数原型可表示如下: void DrawLine(CDC *pDC, int p0x, int p0y, int p1x, int p1y); 在函数中,可通过调用CDC成员函数SetPixel来画出扫描转换过程中的每个点。 COLORREF SetPixel(int x, int y, COLORREF crColor ); 再次、找到文档视图程序框架视图类的OnDraw成员函数,调用DrawLine 函数画出不同斜率情况的直线,如下图:

最后、调试程序直至正确画出直线。 2、给定多边形的顶点的坐标P0(x0,y0),P1(x1,y1),P2(x2,y2),P3(x3,y3),P4(x4,y4)…使用边标志算法或有效边表算法进行多边形填充。 实验基本步骤 首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。 其次、实现边标志算法或有效边表算法函数,如下: void FillPolygon(CDC *pDC, int px[], int py[], int ptnumb); px:该数组用来表示每个顶点的x坐标 py :该数组用来表示每个顶点的y坐标 ptnumb:表示顶点个数 注意实现函数FillPolygon可以直接通过窗口的DC(设备描述符)来进行多边形填充,不需要使用帧缓冲存储。(边标志算法)首先用画线函数勾画出多边形,再针对每条扫描线,从左至右依次判断当前像素的颜色是否勾画的边界色,是就开始填充后面的像素直至再碰到边界像素。注意对顶点要做特殊处理。 通过调用GDI画点函数SetPixel来画出填充过程中的每个点。需要画线可以使用CDC的画线函数MoveTo和LineTo进行绘制,也可以使用实验一实现的画直线函数。 CPoint MoveTo(int x, int y ); BOOL LineTo(int x, int y ); 实现边标志算法算法需要获取某个点的当前颜色值,可以使用CDC的成员函数 COLORREF GetPixel(int x, int y ); 再次、找到文档视图程序框架视图类的OnDraw成员函数,调用FillPolygon 函数画出填充的多边形,如下: void CTestView::OnDraw(CDC* pDC) { CTestcoodtransDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc);

计算机图形学实验报告

计算机图形学 实验报告 学号:20072115 姓名: 班级:计算机 2班 指导老师:何太军 2010.6.19

实验一、Windows 图形程序设计基础 1、实验目的 1)学习理解Win32 应用程序设计的基本知识(SDK 编程); 2)掌握Win32 应用程序的基本结构(消息循环与消息处理等); 3)学习使用VC++编写Win32 Application 的方法。 4)学习MFC 类库的概念与结构; 5)学习使用VC++编写Win32 应用的方法(单文档、多文档、对话框); 6)学习使用MFC 的图形编程。 2、实验内容 1)使用WindowsAPI 编写一个简单的Win32 程序,调用绘图API 函数绘制若干图形。(可选任务) 2 )使用MFC AppWizard 建立一个SDI 程序,窗口内显示"Hello,This is my first SDI Application"。(必选任务) 3)利用MFC AppWizard(exe)建立一个SDI 程序,在文档视口内绘制基本图形(直线、圆、椭圆、矩形、多边形、曲线、圆弧、椭圆弧、填充、文字等),练习图形属性的编程(修改线型、线宽、颜色、填充样式、文字样式等)。定义图形数据结构Point\Line\Circle 等保存一些简单图形数据(在文档类中),并在视图类OnDraw 中绘制。 3、实验过程

1)使用MFC AppWizard(exe)建立一个SDI 程序,选择单文档; 2)在View类的OnDraw()函数中添加图形绘制代码,说出字符串“Hello,This is my first SDI Application”,另外实现各种颜色、各种边框的线、圆、方形、多边形以及圆弧的绘制; 3)在类视图中添加图形数据point_pp,pp_circle的类,保存简单图形数据,通过在OnDraw()函数中调用,实现线、圆的绘制。 4、实验结果 正确地在指定位置显示了"Hello,This is my first SDI Application"字符串,成功绘制了圆,椭圆,方形,多边形以及曲线圆弧、椭圆弧,同时按指定属性改绘了圆、方形和直线。成功地完成了实验。 结果截图: 5、实验体会 通过实验一,了解了如用使用基本的SDI编程函数绘制简单的图

相关文档
相关文档 最新文档