实验题目:
利计算机编程语言绘制图形实现容:
(1)中点算法生成意斜率直线设置线型线宽
(2)中点算法生成圆
(3)中点算法生成椭圆
(4)扫描算法实现意边形填充
(5)Cohen_Sutherland裁剪
(6)曲线曲面绘制
(7)二维图形变换
(8)三视图变换
二系统分析设计
实验采C语言编程运行环境TurboC
三算法思想程序实现
1中点算法生成意斜率直线设置线型线宽
(1).算法思想
假定直线斜率k0~1间(k取值类似处理)前象素点(xpyp)象素点两种选择点P1(xp+1yp)P2(xp+1yp+1)P1P2中点(xp+1yp+05)称MQ理想直线xxp+1垂线交点MQ方时取P2应象素点MQ方时取P1象素点中点画线法基原理
面讨中点画线法实现点(x0y0)(x1 y1)直线段L方程式F(x y)ax+by+c0中ay0y1 bx1x0 cx0y1x1y0欲判断中点MQ点方方M代入F(xy)判断符号构造判式
dF(M)F(xp+1 yp+05)a(xp+1)+b(yp+05)+c
d<0时ML(Q点)方取P2象素
d>0时ML(Q点)方取P1象素
d0时选P1P2均约定取P1象素
注意dxp yp线性函数采增量计算提高运算效率
前象素处d³0情况取正右方象素P1(xp+1 yp)判象素位置应计算 d1F(xp+2 yp+05)a(xp+2)+b(yp+05)d+a增量a
d<0时取右方象素P2(xp+1 yp+1)判断象素计算d2 F(xp+2 yp+15)a(xp+2)+b(yp+15)+cd+a+b 增量a+b画线(x0 y0)开始d初值 d0F(x0+1 y0+05)F(x0 y0)+a+05b F(x0 y0)0d0a+05b
d符号d增量整数初始值包含数2d代d摆脱数
(2)程序实现
void putpixels(int xint yint colorint n)
{ int ij
for(in2i
}
void Midpointline(int x0int y0int x1int y1int colorint n)
{
int abdxdydxyincrP1incrP2
if(x0x1)
{
if(y0
else
for(yy0y>y1y)
putpixel(x0ycolor)
}
else if(x0
if(y0
dy y1y0 dx x1x0
d dx2*dy
incrP1 2*dy incrP2 2*(dxdy)
x x0 y y0
putpixels(xycolorn)
while (x
if (d<0)
{y++ d +incrP2}
else
d +incrP1
x++
putpixels(xycolorn)
}
}
else
{
dy y1y0 dx x1x0
d2*dydx
incrP1 2*(dx+dy) incrP2 2*dy
x x0 y y0
putpixels(xycolorn)
while(x
if (d>0)
{ yd +incrP1}
else
d +incrP2
x++
putpixels(xycolorn)
}
}
}
else
if(x0>x1)
{ if(y0
dy y0y1 dx x0x1
d2*dydx
incrP1 2*(dx+dy) incrP2 2*dy
x x1 y y1
putpixels(xycolorn)
while (x
if(d>0)
{ yd +incrP1}
else
d +incrP2
x++
putpixels(xycolorn)
}
}
else
{
dy y0y1 dx x0x1
d dx2*dy
incrP1 2*dy incrP2 2*(dxdy)
x x1 y y1
putpixels(xycolorn)
while (x
if (d<0)
{y++ d +incrP2}
else
d +incrP1
x++
putpixels(xycolorn)
}
}
}}
2中点算法实现画圆
(1) 算法思想
果构造函数 F(xy)x2+y2R2圆点F(xy)0圆外点F(xy)>0圆点F(xy)<0 中点画线法样构造判式:
dF(M)F(xp+1yp05)(xp+1)2+(yp05)2R2
d<0应取P1象素象素判式:
dF(xp+2yp05)(xp+2)2+(yp05)2R2d+2xp+3
d≥0应取P2象素象素判式
dF(xp+2yp15)(xp+2)2+(yp15)2R2d+2(xpyp)+5
里讨第象素(0R)判式d初始值:
d0F(1R05)125R
进步提高算法效率面算法中浮点数改写成整数法运算改成加法运算仅整数实现中点画圆法
(2)程序实现:
void midpointcircle(int R)
{
int xydeltaxdeltayd
x0yRd1R
deltax3
deltay5RR
putpixel(x+300y+300GREEN)
while(x
if(d<0)
{
d+deltax
deltax+2
x++
}
else
{
d+deltax+deltay
deltax+2
deltay+2
x++
y
}
putpixel(x+300y+300RED)
putpixel(y+300x+300GREEN)
putpixel(x+300y+300BLUE)
putpixel(y+300x+300WHITE)
putpixel(x+300y+300YELLOW)
putpixel(y+300x+300CYAN)
putpixel(x+300y+300MAGENTA)
putpixel(y+300x+300BROWN)
}
}
3中点算法实现椭圆:
(1)算法思想
生成椭圆弧中点算法直线中点算法类似初始化条件判式递推公式确定判式时候消浮点运算量减少法次数椭圆注意第限斜率1情况直线|m|>1时相y变量详细叙述椭圆:考虑分界点部弧段段斜率素递推出继素根条件
初始条件分界点方弧段类似求
(2)程序实现
void putpixels(int xint yint colorint n)
{ int ij
for(in2i
}
void ellipsepoint(long x0long y0long xlong ylong colorint n)
{
putpixels((int)(x0+x)(int)(y0+y)(int)colorn)
putpixels((int)(x0x)(int)(y0+y)(int)colorn)
putpixels((int)(x0+x)(int)(y0y)(int)colorn)
putpixels((int)(x0x)(int)(y0y)(int)colorn)
}
void midpointellipse(long x0long y0long along blong colorint n)
{
long xydsasbxpyp
saa*asbb*b
xp(long)((float)sa(float)sqrt((float)(sa+sb)))
yp(long)((float)sb(float)sqrt((float)(sa+sb)))
x0ybdsa+4*sb4*sa*b
while(x
if(d<0)
{
dd+4*sb*(2*x+3)
x++
}
else
{
dd+4*sb*(2*x+3)+4*sa*(22*y)
x++
y
}
ellipsepoint(x0y0xycolorn)
}
xay0d4*sa+sb4*a*sb
while(y
if(d<0)
{
dd+4*sa*(2*y+3)
y++
}
else
{
dd+4*sa*(2*y+3)+4*sb*(22*x)
y++
x
}
ellipsepoint(x0y0xycolorn)
}
}
4扫描线算法实现边形填充:
(1)算法思想:
水扫描线扫描点线段构成段定义边形根扫描线边形边产生系列交点交点x坐标进行排序排序交点成取出作两端点需填充色彩画水直线边形扫描完毕填充结束
实现步骤:
(1) 建立边分类表ET
(2) 扫描线坐标y初值ET中非空元素序号
(3) 置活化边表AEL空
(4) 执行列步骤直ETAEL空
A 果ET中第y类非空中边取出插入AEL中插入程忠进行排序
B AEL中边两两配边中x坐标规取整获效填充区段填充
C 前扫描线坐标y值递增1y1
D AEL中满足yymax边删
E AEL中剩条边x递增deltaxxx+deltax
(2)程序实现
typedef struct
{
int y_top
float x_int
int delta_y
float x_change_per_scan }EACH_ENTRY
EACH_ENTRY sides[MAX_POINT]
int x[MAX_POINT]y[MAX_POINT]
int side_countfirst_slast_sscanbottomscanx_int_count
void fill_area(int count)
{
sort_on_bigger_y(count) first_s1 last_s1
for(scansides[1]y_topscan>bottomscanscan)
{ update_first_and_last(countscan)
process_x_intersections(first_slast_s)
draw_lines(scanx_int_countfirst_s)
update_sides_list() } }
sort_on_bigger_y(int n)
{ int kx1y1int tem
side_count0 y1y[n]
x1x[n] bottomscany[n]
for(k1k
{ side_count++ if(kn) temy[k+1]
else temy[1]
put_in_sides_list(side_countx1y1x[k]y[k]tem)
}
else { setcolor(13) line(x1y1x[k]y[k]) }
if(y[k]
}
put_in_sides_list(int entryint x1int y1int x2int y2int next_y)
{ int maxy float x2_tempx_change_temp
x_change_temp(float)(x2x1)(float)(y2y1)
x2_tempx2 if((y2>y1)&&(y2
else { if((y2
{ y2++ x2_temp+x_change_temp } }
maxy(y1>y2) y1y2
while((entry>1)&&(maxy>sides[entry1]y_top))
{ sides[entry]sides[entry1]
entry }
sides[entry]y_topmaxy
sides[entry]delta_yabs(y2y1)+1
if(y1>y2) sides[entry]x_intx1
else sides[entry]x_intx2_temp
sides[entry]x_change_per_scanx_change_temp
}
update_first_and_last(int countint scan)
{
while((sides[last_s+1]y_top>scan)&&(last_s
first_s++ }
process_x_intersections(int first_sint last_s)
{ int k x_int_count0
for(kfirst_sk
{ x_int_count++
sort_on_x(kfirst_s)
}
}
}
sort_on_x(int entryint first_s)
{ while((entry>first_s)&&(sides[entry]x_int
}
}
swap(EACH_ENTRY *xEACH_ENTRY *y)
{ int i_temp
float f_temp
i_tempx>y_top
x>y_topy>y_top
y>y_topi_temp
f_tempx>x_int
x>x_inty>x_inty>x_intf_temp
i_tempx>delta_yx>delta_yy>delta_y
y>delta_yi_temp
f_tempx>x_change_per_scan
x>x_change_per_scany>x_change_per_scan
y>x_change_per_scanf_temp
}
draw_lines(int scanint x_int_countint index)
{
int kxx1x2 for(k1k<(int)(x_int_count2+15)k++)
{ while(sides[index]delta_y0)
index++ x1(int)(sides[index]x_int+05)
index++
while(sides[index]delta_y0)
index++
x2(int)(sides[index]x_int+05)
setcolor(13)
line(x1scanx2scan) index++
}
}
update_sides_list() {
int k
int temp
for(kfirst_sk
{ sides[k]delta_y
sides[k]x_intsides[k]x_change_per_scan
}
}
}
5CohenSutherland裁剪算法实现直线段裁剪:
51编码算法:
511算法思想:
算法分三步骤:判断线段两端否窗口果线段完全见否判断线段否显然见果裁剪结束否求线段窗口边延长线交点线段线段分两段中段见舍弃余线段继续进行递裁剪算法编码进行二进制位运算顶点窗口二进制编码0000否进行编码
512实现步骤:
(1) 种算法利编码方法延长窗口边线包含未裁剪图形窗口面区域分成九区域:
(2)区域4位编码CtCbCrCl表示代码中位分01窗口边线确定面出具体编码规中右边位Cl第位次Cr第二Cb第三Ct第四位
A两端点P1(x1y1)P2(x2y2)区域0000中满足点裁剪 等式:
B两端点窗口边线外侧位置四位代码中相位时位1显然两端点代码C1C2位运算 C1&C2≠0 检查判断直线窗口外应全部舍弃
C果直线两端点满足述两种情况简单全部保留全部舍弃直线时需计算出直线窗口边线交点直线分段继续进行检查判断样逐段舍弃位窗口外线段保留剩余窗口线段
513程序实现
*********定义裁剪函数************
void line_clip(int x1 int y1 int x2 int y2 int leftint topint right int bottom)
{
void getcode(int xint yint d[4]) *定义获端点代码函数*
int ix11y11 *定义交点坐标*
int aa1
getcode(x1y1a)
getcode(x2y2b)
*1:裁剪循环开始*
while(aa0)
{
if((a[0]+a[1]+a[2]+a[3]0)&&(b[0]+b[1]+b[2]+b[3]0)) *第种情况线段完全见*
{
aa0
return
}
else if((a[0]&&b[0])+(a[1]&&b[1])+(a[2]&&b[2])+(a[3]&&b[3])0) *线段完全见*
{
setcolor(0)
setwritemode(0) *设置画线输出模式覆盖方式*
line(x1y1x2y2) *进行裁剪 进行覆盖*
aa0
return
}
*2:线段完全见完全见边交点线段裁剪处理*
else
{
if(a[0]+a[1]+a[2]+a[3]0) *寻找见点*
{
for(i0i<4i++)
c[i]b[i]*x2y2见点*
}
else
{
for(i0i<4i++)
c[i]a[i]*x1y1见点*
}
*3:直线窗口边作求交运算求出交点赋值x11y11*
if(c[0]1)
{
x11left
y11(int)((y2y1)*(leftx1)(x2x1)+y1)
}
else if(c[1]1)
{
x11right
y11(int)((y2y1)*(rightx1)(x2x1)+y1)
}
else if(c[2]1)
{
x11(int)((x2x1)*(bottomy1)(y2y1)+x1)
y11bottom
}
else if(c[3]1)
{
x11(int)((x2x1)*(topy1)(y2y1)+x1)
y11top
} *3:求交运算结束*
if((c[0]a[0])&&(c[1]a[1])&&(c[2]a[2])&&(c[3]a[3]))
{
setcolor(0)
setlinestyle(003)
setwritemode(0)
line(x1y1x11y11)
x1x11 y1y11
getcode(x11y11a)
}
else if((c[0]b[0])&&(c[1]b[1])&&(c[2]b[2])&&(c[3]b[3]))
{
setcolor(0)
setlinestyle(003)
setwritemode(0)
line(x2y2x11y11)
x2x11y2y11
getcode(x11y11b)
}
} *2:边交点线段裁剪处理结束*
} *1:裁剪循环结束*
}
*获端点代码*
void getcode(int xint yint d[4])
{
d[0]0d[1]0d[2]0d[3]0
if(x
if(y>bottom) d[2]1
if(y
}
6曲线曲面绘制
61生成Bezier曲线
(1)算法思想
利Bezier曲线造型时果次数太高固然表示复杂形状时造成计算复杂度增加二次Bezier曲线表示力限面仅讨三次Bezier曲线矩阵表示计算机生成
(1) 矩阵表示
三次Bezier曲线定义式:
分解两矢量点积:
取Bezier曲线矩阵:
三次Bezier曲线基矩阵:
(2) 三次Bezier曲线生成
Bezier曲线参数表示法区间[01]分成N等份确定控制点取应三维点样两间画条直线该直线段投影二维面需Bezier曲线
(2)程序实现:
void bezier_3(int color double p[4][2])
{
double tt1t2xtyt
int rate200xy
setcolor(color)
moveto(p[0][0]p[0][1])
for (t0t<1t+10rate)
{
yt1t
t1yt*yt
t23*yt*t
xtp[0][0]*t1*yt+p[1][0]*t2*yt+p[2][0]*t2*t+p[3][0]*t*t*t
ytp[0][1]*yt*t1+p[1][1]*t2*yt+p[2][1]*t2*t+p[3][1]*t*t*t
x(int)(xt)
y(int)(yt)
lineto(xy)
}
}
62绘制Bezier曲面
(1)算法思想:
Bezier曲线条控制边形顶点位置严格关系曲线 Bezier曲线形状趋特征边形形状阶数控制边形顶点数决定Bezier曲面Bezier曲线拓广Bernstein函数作基函数Bernstein基函数构造空间点阵列位置控制
(2)算法实现步骤:
1 出控制顶点
2根公式编程绘制Bezier曲面
计算点坐标
3 画直线方法首尾相接画直线
(3)程序实现:
main()
{
char str[80]
int drivermode
int ikmj
int x0300y0300
int p[4][4][3]{{{1214550}{2412050}{4511750}{6514050}}
{{246534}{564534}{875634}{997534}}
{{4312020}{659820}{8710020}{11111520}}
{{151600}{341200}{551350}{751700}}}
float u0u1u2u3v0v1v2v3
float q10q11q12q13dudv
float q[n+1][n+1][3]q20[3]q21[3]q22[3]q23[3]q30[3]q31[3]q32[3]q33[3]
float xy
printf(input j(0bezier 1B_spline)\n)
scanf(d&j)
driverDETECTmode0
initgraph(&driver&modeD\\TC)
setbkcolor(1)
setcolor(15)
for(i0i<3i++)
{for(k0k<3k++)
{x(07071*p[i][k][0]+07071*p[i][k][1]+200)*2300
y(04082*p[i][k][0]+04082*p[i][k][1]08165*p[i][k][2]+200)*2300
if(k0)moveto(xy)lineto(xy)
}
}
for(i0i<3i++)
{for(k0k<3k++)
{x(07071*p[k][i][0]+07071*p[k][i][1]+200)*2300
y(04082*p[k][i][0]+04082*p[k][i][1]08165*p[k][i][2]+200)*2300
if(k0)moveto(xy)lineto(xy)
}
}
dudv10n
for(i0i
u0(i*du)*(i*du)*(i*du)u1(i*du)*(i*du)u2i*duu31
if(j0)
{q10u0*(1)+u1*3+u2*(3)+u3*1q11u0*3+u1*(6)+u2*3
q12u0*(3)+u1*3q13u0*1}
if(j1)
{q10(u0*(1)+u1*3+u2*(3)+u3*1)6 q11(u0*3+u1*(6)+u3*4)6
q12(u0*(3)+u1*3+u2*3+u3*1)6q13(u0*1)6}
for(k0k<2k++)
{
q20[k]q10*p[0][0][k]+q11*p[1][0][k]+q12*p[2][0][k]+q13*p[3][0][k]
q21[k]q10*p[0][1][k]+q11*p[1][1][k]+q12*p[2][1][k]+q13*p[3][1][k]
q22[k]q10*p[0][2][k]+q11*p[1][2][k]+q12*p[2][2][k]+q13*p[3][2][k]
q23[k]q10*p[0][3][k]+q11*p[1][3][k]+q12*p[2][3][k]+q13*p[3][3][k]
if(j0)
{q30[k]q20[k]*(1)+q21[k]*3+q22[k]*(3)+q23[k]*1
q31[k]q20[k]*3+q21[k]*(6)+q22[k]*3
q32[k]q20[k]*(3)+q21[k]*3
q33[k]q20[k]*1}
if(j1)
{q30[k](q20[k]*(1)+q21[k]*3+q22[k]*(3)+q23[k]*1)6
q31[k](q20[k]*3+q21[k]*(6)+q22[k]*3)6
q32[k](q20[k]*(3)+q22[k]*3)6
q33[k](q20[k]*1+q21[k]*4+q22[k]*1)6}
}
for(m0m
v0(m*dv)*(m*dv)*(m*dv)v1(m*dv)*(m*dv)v2m*dvv31
for(k0k<2k++)
{q[i][m][k]q30[k]*v0+q31[k]*v1+q32[k]*v2+q33[k]*v3}
}
}
setcolor(4)
for(i0i
y(04082*q[i][m][0]+04082*q[i][m][1]08165*q[i][m][2]+200)*2300
if(m0)moveto(xy)
lineto(xy)
}
}
for(m0m
y(04082*q[i][m][0]+04082*q[i][m][1]08165*q[i][m][2]+200)*2300
if(m0)moveto(xy)
lineto(xy)
}
}
if(j0)
{ printf(3Bezier curved surface)}
if(j1)
{ printf(3B_Splline curved surface)}
outtextxy(270270this is zhouman's homework)
setcolor(3)
settextstyle(TRIPLEX_FONTHORIZ_DIR1)
sprintf(strsgraphicszhoumantime20091230)
outtextxy(120430str)
getch()
closegraph()
}
7 二维图形缩放旋转移组合变换
(1)思想算法:
齐次坐标理二维图形变换矩阵式表示:
移变换:[x* y* 1] [x y 1] * [t*x s*y 1]
例变换:[x* y* 1][x y 1] * [m+x n+y 1]
旋转变换: 面二维图形饶原点逆时针旋转Ө角变换矩阵
[x* y* 1][x y 1] * [x*cosөy*sinө]
复合变换:种变换矩阵原点参点意参点进行变换时
候复合变换矩阵
(2)程序实现:
直线命令画出齿(六边形半)→利旋转变换称变换矩阵 实现余部分绘制→调试运行程序→输出图形→分析结果→结束
void tf1(float sqfloat cqint xpint yp)
{ t[0][0]cq t[0][1]sq t[0][2]0
t[1][0]sqt[1][1]cq t[1][2]0
t[2][0]xp t[2][1]yp t[2][2]1
}
void tf2()
{ float xy
xpp[j][0]ypp[j][1]
pp[j][0]x*t[0][0]+y*t[1][0]+t[2][0]
pp[j][1]x*t[0][1]+y*t[1][1]+t[2][1]
}
main()
{
int gdrivergmodexp300yp200
float p[][2]{{801}{808}{9917}{9726}{7626}}
float it[3][3]
gdriverDETECT
registerbgidriver(EGAVGA_driver)
initgraph(&gdriver&gmoded\\tc)
setbkcolor(3)
cleardevice()
setcolor(9)
circle(xpyp70)
circle(xpyp20)
circle(xpyp40)
circle(xpyp5)
circle(xpyp2)
circle(xpyp45)
setlinestyle(006)
for(i0i<6ii+03142)
{tf1(sin(i)cos(i)xpyp)
for(j0j<5j++)
{pp[j][0]p[j][0]pp[j][1]p[j][1]tf2()}
for(j0j<4j++)
line(pp[j][0]pp[j][1]pp[j+1][0]pp[j+1][1])
delay(10000)
}
getch()
closegraph()
}
8. 图形三视图变换
编写三维变换算法程序→检查程序正确性→分段调试程序→输入出三维形体顶点坐标→执行变换→算法程序进行必调整→更换形体数继续变换→结束
程序实现:
#include
#include
int a[14][4]{{30001}{304001}{04001}{040101}{030301}
{00301}{300301}{3010301}{1010301}{1030301}{1040101}
{1010101}{3010101}{3040101}}
float t[4][4]p[14][4]
void a400()
{int ij
for(i0i<4i++)
for(j0j<4j++)
t[i][j]0
}
void a500()
{ int kij
for(i0i<14i++)
{for(j0j<4j++)
{p[i][j]0
for(k0k<4k++)
p[i][j]p[i][j]+a[i][k]*t[k][j]}
p[i][0]p[i][0]+280
p[i][1]p[i][1]+180
}
setcolor(9)
moveto(p[0][0]p[0][1])
for(i0i<14i++)
lineto(p[i][0]p[i][1])
line(p[6][0]p[6][1]p[0][0]p[0][1])
line(p[7][0]p[7][1]p[12][0]p[12][1])
line(p[8][0]p[8][1]p[11][0]p[11][1])
line(p[9][0]p[9][1]p[4][0]p[4][1])
line(p[10][0]p[10][1]p[3][0]p[3][1])
line(p[13][0]p[13][1]p[10][0]p[10][1])
line(p[1][0]p[1][1]p[13][0]p[13][1])
getch()
}
main()
{int drivermodeij
driverDETECT
initgraph(&driver&moded\\tc)
setbkcolor(3)
a400()
t[0][0]07071*3
t[0][1]04082*3
t[1][0]07071*3
t[1][1]04082*3
t[2][1]08165*3
t[3][3]1
a500()
closegraph()
}
四实验总结
实验程中程中许会方提高改进加深书知识理解掌握时学书没东西积累宝贵验学工作裨益
实验采C语言编程C语言图形界面制作方面较面
象语言言没优势实验基图形绘制方面选择算法加实施够实现实验完成部分功种功选中种算法完成程中深刻解认识种算法留印象未实现整画图板界面遗憾继续努力完善
需完成功点:
(1)汉字编写功
(2)投影变换
(3)隐藏面消隐
(4)三维图形变换等
参考文献
[1] 倪明田吴良芝 计算机图形学 北京:北京学出版社2000
[2] 孙家广等 计算机图形学 北京: 清华学出版社 2002
[3] 王飞 计算机图形学基础北京:北京邮电学出版社 2002
[4] 王汝传邹北骥计算机图形学北京:民邮电出版社2003
[5] 杨钦计算机图形学清华学出版社2005(3)
[6] 郭玲文精通AutoCAD科学出版社2001(8)
文档香网(httpswwwxiangdangnet)户传
《香当网》用户分享的内容,不代表《香当网》观点或立场,请自行判断内容的真实性和可靠性!
该内容是文档的文本内容,更好的格式请下载文档