利用三角函数生成计算机图形.docx
- 文档编号:8651684
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:20
- 大小:720.11KB
利用三角函数生成计算机图形.docx
《利用三角函数生成计算机图形.docx》由会员分享,可在线阅读,更多相关《利用三角函数生成计算机图形.docx(20页珍藏版)》请在冰豆网上搜索。
利用三角函数生成计算机图形
利用三角函数生成计算机图形
吴占鹏
(辽宁省风沙地改良利用研究所阜新123000)
摘要:
利用三角函数,通过加倍、嵌入等修饰,以实现生成各种绚丽图形。
关键词:
计算机图形;三角函数;嵌入;修饰
计算机图形学自诞生以来,在辅助设计、美术、动画艺术、可视化计算、虚拟现实等方面得到了广泛应用。
计算机图形主要分为图像和图形。
图像一般是指自然生成的,如数码照片,扫描文件等。
图形一般是通过计算生成的。
在图形中,很多程序图形和三角函数有密切关系,利用三角函数创作曲线、着色、模型、动画可以产生意想不到的效果。
1曲线
1.1曲线细分与动画周期
三角函数曲线细分是把曲线一个圆周周期内分成n干段,即2*Math.PI/n,如果是旋转动画,简单曲线的动画周期是2*n。
后面有时会简化成Math.PI/n,那么周期是4*n。
1.2简单曲线
最简单曲线当属圆形,用javascript可表示成
moveTo(a,0);
for(i=0;i x=a*Math.cos(i*2*Math.PI/n); y=b*Math.sin(i*2*Math.PI/n); lineTo(x,y); } 这里a=b,为圆形,否则a≠b为椭圆。 如果把y=b*Math.sin(i*2*Math.PI/n)改成y=b*Math.sin(i*4*Math.PI/n),则圆形变成8字形。 如果写成 x=a*Math.cos(i*m*Math.PI/n); y=b*Math.sin(i*(n)*Math.PI/n); 其中m不能为偶数,n=m+1,或n=m-1。 则图形为: 图1变化m,n生成的曲线 1.3曲线修饰 1.3.1加修饰 如果定义一个常量x=Math.PI/n,循环变量i,可以写出他的绘图程序 for(i=0,i<2*n,i++){ x=a1*Math.cos(b1*i*x)+a2*Math.cos(b2*i*x); y=a1*Math.sin(b1*i*x)+a2*Math.sin(b2*i*x); lineTo(x,y); } 这里a1、a2为半径系数,是大于0的实数,b1、b2为周期系数,是大于0的正整数,且b2>b1,则图形会在圆形图案上形成b2-b1个突起。 如果把x、y的赋值写成 x=a1*Math.cos(b1*i*x)+a2*Math.sin(b2*i*x); y=a1*Math.sin(b1*i*x)+a2*Math.cos(b2*i*x); 或写成 x=a1*Math.cos(b1*i*x)-a2*Math.cos(b2*i*x); y=a1*Math.sin(b1*i*x)+a2*Math.sin(b2*i*x); 或写成 x=a1*Math.cos(b1*i*x)+a2*Math.cos(b2*i*x); y=a1*Math.sin(b1*i*x)-a2*Math.sin(b2*i*x); 则图案的突起是b1+b2个。 这里我们把 a1*Math.cos(b1*i*x) a1*Math.sin(b1*i*x) 称之为主函数,把 a2*Math.cos(b2*i*x) a2*Math.sin(b2*i*x) 称之为修饰函数。 修饰函数可随意增加,只要遵循突起规律,可以创造出无数个美丽图形,而且是对称图形。 如果把b1和b2换成b1,b2,b3,b4四个不等的正整数,生成的图形多数可能是不对称的。 图2通过加修饰生成的曲线 1.3.2乘修饰 可以写成 x=a*Math.cos(i*x)*Math.cos(b*i*x); y=a*Math.sin(i*x)*Math.cos(b*i*x); 或写成 x=a*Math.cos(i*x)*(c+Math.cos(b*i*x)); y=a*Math.sin(i*x)*(c+Math.cos(b*i*x)); b=5,c=1b=5,c=1.5b=5,c=0.3b=6,c=0.3 图3通过乘修饰生成的曲线 1.3.3嵌入修饰 如果周期系数出现非整数,曲线可能会产生无规则穿插。 当把小数部分定义成1/m,即b2*(1+1/m),这样曲线经过b2*(m+1)次又形成重合,产生嵌入效果,即嵌入修饰,其循环周期是2*n*m(n在前面定义过)。 也可写成b2*(k+s/m),这里s允许是负整数,嵌入次数为b2*(k*m+s)。 这种嵌入方式加修饰、乘修饰都适合。 图4利用嵌入修饰生成的花篮 1.3.4藤编效果 利用正弦余弦的嵌入方式只改变b2,在曲线的交汇点处产生偏移,避免重合,就像用一条藤子编织而成。 图5藤编效果曲线 2着色 利用三角函数可以使着色产生渐变效果。 2.1简单渐变 这种着色界限不是很明显,没有纯红、纯绿和纯蓝色: r=127.5*(1+Math.cos(t*p/n)); g=127.5*(1+Math.cos((t+c)*p/n)); b=127.5*(1+Math.cos((t+2*c)*p/n)); 2.2三色渐变 直接滤除曲线小于0部分,突出红、绿和蓝三颜色: Math.cos(t*p/n)<0? r=0: r=255*Math.cos(t*p/n); Math.cos((t+c)*p/n)<0? g=0: g=255*Math.cos((t+c)*p/n); Math.cos((t+2*c)*p/n)<0? b=0: b=255*Math.cos((t+2*c)*p/n); 2.3组合渐变 组合渐变更细分一些,可以组合成红、黄、绿、青、蓝、紫色: Math.cos(t*p/n)+0.5<0? r=0: (Math.cos(t*p/n)+0.5>1? r=255: r=255*(0.5+Math.cos(t*p/n)));Math.cos((t+c)*p/n)+0.5<0? g=0: (Math.cos((t+c)*p/n)+0.5>1? g=255: g=255*(0.5+Math.cos((t+c)*p/n)));Math.cos((t+2*c)*p/n)+0.5<0? b=0: (Math.cos((t+2*c)*p/n)+0.5>1? b=255: b=255*(0.5+Math.cos((t+2*c)*p/n))); 这里c=循环周期/3。 简单渐变着色曲线三色渐变着色曲线组合渐变着色曲线 图6三种渐变着色深度曲线 2.4周期渐变着色 有时动画涉及层深变化,采用周期渐变着色能增加透视效果(见图5)。 2.5uv渐变着色 有时曲线涉及交叉,为了使交叉处着色一致,需要uv方向渐变着色。 u向渐变着色也可理解成环形渐变着色,v向渐变着色可以理解成轴向渐变着色。 图7uv渐变着色效果 3模型 3.1简单模型 利用三角函数形成闭合曲线,填充颜色可以生成各种图形。 图8利用三角函数生成的多角星 3.2三维模型 利用三角函数生成点的三维坐标由相邻点构建平面生成三维图形。 图9利用三角函数生成的三维几何体 3.3螺旋线建模 螺旋线建模是选择螺旋线上四个或三个相邻的点,围城一个平面所构成的模型。 该模型说起来很简单,但如果生成一些比较复杂的模型,其意义也就显得非常重要了。 图10螺旋线原理图 图11利用螺旋线建模生成的几何体图形 3.4扭曲 有时需要扭曲,使效果更有变化,为了确保扭曲后交接处完全重合,其扭曲角度增量仍然遵循1/n规律,而且总面片数能被n整除。 图12扭曲与未扭曲效果比较 4动画 4.1旋转 很多旋转动画都需要三角函数,这里介绍一种乘修饰动画,只在主函数添加一个时间增量就可以产生旋转动画效果。 4.2变形 改变半径、周期、扭曲、弯曲,可以产生许多种变形动画。 4实例 最后用Flash的ActionScript编写的一段绘制小花程序,来揭示一下嵌入修饰和v向渐变着色,效果见图13。 图13用ActionScript代码编写的绘小花动画 ActionScript代码: [SWF(backgroundColor=0x888888)] varsp: Sprite=addChild(newSprite())asSprite; sp.x=275,sp.y=200; vart: uint,n: uint=0,m: uint=0,r: uint,g: uint,b: uint; varx1: Number,z1: Number,y1: Number,z2: Number,y2: Number; vark: int=2,w: int=4,h: Number=w+1/k,s: int=180,d: int=2*s*k+1,c: Number=(k*w+1)/k; varf: Number=900,p=Math.PI/s,angleX: Number=-0.6,q: Number=s/c; varcosX: Number,sinX: Number,cosY: Number,sinY: Number; varcos1: Number,cos2: Number,pp: Array=[]; varbbb: Boolean,dy: Number; for(t=0;t pp[t]=newMovieClip(); sp.addChild(pp[t]); pp[t].zz=-1000; } addEventListener(Event.ENTER_FRAME,fff); functionfff(e){ if(bbb){ angleX+=(dy-mouseY)/200; dy=mouseY; } m=m+1>d? d: m+1; cosX=Math.cos(angleX); sinX=Math.sin(angleX); x1=13*Math.cos(n*p/3)*4; z2=13*Math.sin(n*p/3)*4; y2=-90; y1=y2*cosX+z2*sinX; z1=z2*cosX-y2*sinX; for(t=0;t pp[t].graphics.clear(); r=255*col(0.5+Math.cos(t*p*c),z1); g=255*col(0.5+Math.cos((t+q)*p*c),z1); pp[t].graphics.moveTo(x1*f/(f+z1),y1*f/(f+z1)); pp[t].zz=z1; cos1=Math.cos(t*p*h),cos2=Math.cos(t*2*p*h); x1=13*Math.cos((t+n/3)*p)*(5-5*cos1+4*cos2); z2=13*Math.sin((t+n/3)*p)*(5-5*cos1+4*cos2); y2=30*(1-cos1-cos2-Math.cos(t*3*p*h))-30; y1=y2*cosX+z2*sinX; z1=z2*cosX-y2*sinX; pp[t].graphics.lineStyle(5*f/(f+z1),r<<16|g<<8|0); pp[t].graphics.lineTo(x1*f/(f+z1),y1*f/(f+z1)); pp[t].zz+=z1; } pp.sortOn("zz",18); for(t=0;t sp.setChildIndex(pp[t],t); } n=(n+1)%(4*s); } functioncol(xx: Number,xz: Number): Number{ varcz: Number,cx: Number; xx>1? cx=1: (xx<0? cx=0: cx=xx); 200/(280+xz)>1? cz=1: cz=200/(280+xz); returncx*cz; } stage.addEventListener(MouseEvent.MOUSE_UP,function(e){bbb=false;}); stage.addEventListener(MouseEvent.MOUSE_DOWN,function(e){dy=mouseY,bbb=true;}); 鼠标跟随的鱼 [SWF(backgroundColor=0x00eeff,width=640,height=480)] varsp: Sprite=addChild(newSprite())asSprite; sp.y=-200,sp.x=320; varpx: Array=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],pp: Array=[]; varpz: Array=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],yur: Array=[]; varx0: Array=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]; varz0: Array=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]; vary0: Array=[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]; varr: Array=[1,9,15,19.5,22,23,23.5,23,22,19.5,16.5,13,10,9,10,12,14,16]; varr1: Array=[0,8,12,14.5,16,17,17.5,17,15.5,13,10,7.5,5,3,1,0.2,0,0]; for(i=0;i<281;i++){ pp[i]=newMovieClip(); sp.addChild(pp[i]); } varf: Number=1800,i: uint,m: int,t: int,k: int,h: int,j: int,c1: uint,c2: uint,c3: uint,r2: Number; varmc: Sprite=newSprite(); varbox: Matrix=newMatrix(); box.createGradientBox(20,10,1.57,240,0); mc.graphics.beginGradientFill("linear",[0xddaaaa,0x882211,0xddaaaa],[1,1,1],[150,200,250],box,"reflect"); mc.graphics.drawRect(280,0,120,400); for(i=0;i<36;i++){ for(j=0;j<16;j++){ c1=255<<16|Math.abs(j-7.5)*20+20<<8|40; c2=255<<16|Math.abs(j-7.5)*20+60<<8|Math.abs(j-7.5)*20+30; c3=255<<16|Math.abs(j-7.5)*20<<8|0; r2=(5-Math.cos(i*Math.PI/40))/8; box.createGradientBox(56,40,0,270-i*9*r2,j*25-20+(i%2)*12.5); mc.graphics.beginGradientFill("radial",[c3,c1,c2],[1,1,1],[70,120,200],box); mc.graphics.moveTo(275-i*9*r2,j*25+(i%2)*12.5); mc.graphics.lineTo(315-i*9*r2,j*25-14+(i%2)*12.5); mc.graphics.curveTo(315+(20-i*9)*r2,j*25+(i%2)*12.5,315-i*9*r2,14+j*25+i%2*12.5); mc.graphics.lineTo(275-i*9*r2,j*25+(i%2)*12.5); mc.graphics.endFill(); } } for(i=0;i<2;i++){ box.createGradientBox(200,400,0,-30,i*400-200); mc.graphics.beginGradientFill("radial",[0xffddaa,0xff6633,0xff2200],[1,1,1],[50,150,205],box); mc.graphics.moveTo(0,i*200); mc.graphics.lineTo(60+i*10,i*200); mc.graphics.curveTo(125,110+i*180,70-i*10,200+i*200); mc.graphics.lineTo(0,200+i*200); mc.graphics.endFill(); } for(i=0;i<2;i++){ box.createGradientBox(20,40,0,45,i*200+80); mc.graphics.beginGradientFill("radial",[0,0xbbbbbb,0x555555],[1,1,1],[50,100,255],box); mc.graphics.drawEllipse(45,80+i*200,20,40); mc.graphics.endFill(); } for(i=0;i<2;i++){ mc.graphics.lineStyle(3,0xee6622,0.6); mc.graphics.moveTo(65+i*20,i*250+50); mc.graphics.curveTo(85,60+i*280,85-i*20,100+i*250); } varbmp1: BitmapData=newBitmapData(400,400); bmp1.draw(mc); addEventListener(Event.ENTER_FRAME,fff); functionfff(e: Event){ pz[0]+=(200*f/sp.mouseY-f-pz[0])/15;//高度坐标转换成深度坐标 px[0]+=(sp.mouseX*(f+pz[0])/f-px[0])/15; yur[0]=Math.atan2(pz[0]-200*f/sp.mouseY+f,px[0]-sp.mouseX*(f+pz[0])/f); for(i=1;i<18;i++){ i<=4? yur[i]=yur[0]: yur[i]=Math.atan2(pz[i]-pz[i-1],px[i]-px[i-1]); px[i]=px[i-1]+10*Math.cos(yur[i-1]); pz[i]=pz[i-1]+10*Math.sin(yur[i-1]); } for(i=0;i<18;i++){ for(m=0;m<17;m++){ z0[i][m]=pz[i]-r1[i]*Math.sin(m*Math.PI/8)*Math.cos(yur[i]); x0[i][m]=(px[i]+r1[i]*Math.sin(m*Math.PI/8)*Math.sin(yur[i]))*f/(f+z0[i][m]); y0[i][m]=(r[i]*Math.cos(m*Math.PI/8)+200)*f/(f+z0[i][m]); } } for(m=0;m<2;m++){ z0[18][m]=z0[4][2+m*12]+10*Math.sin(yur[4]-h*Math.PI/20*Math.pow(-1,m)); x0[18][m]=x0[4][2+m*12]+10*Math.cos(yur[4]-h*Math.PI/20*Math.pow(-1,m))*f/(f+z0[18][m]); y0[18][m]=217*f/(f+z0[18][m]); z0[18][m+2]=z0[4][3+m*10]+5*Math.sin(yur[4]-h*Math.PI/20*Math.pow(-1,m)); x0[18][m+2]=x0[4][3+m*10]+5*Math.cos(yur[4]-h*Math.PI/20*Math.pow(-1,m))*f/(f+z0[18][m+2]); y0[18][m+2]=207*f/(f+z0[18][m+2]); z0[18][m+4]=z0[8][1+m*14]+10*Math.sin(yur[8]-(9-h)*Math.PI/20*Math.pow(-1,m)); x0[18][m+4]=x0[8][1+m*14]+10*Math.cos(yur[8]-(9-h)*Math.PI/20*Math.pow(-1,m))*f/(f+z0[18][m+4]); y0[18][m+4]=221*f/(f+z0[18][m+4]); z0[18][m+6]=z0[8][2+m*12]+5*Math.sin(yur[8]-(9-h)*Math.PI/20*Math.pow(-1,m)); x0[18][m+6]=x0[8][2+m*12]+5*Math.cos(yur[8]-(9-h)*Math.PI/20*Math.pow(-1,m))*f/(f+z0[18][m+6]); y0[18][m+6]=214*f/(f+z0[18][m+6]); } t=0; for(i=0;i<17;i++){//鱼体 for(m=0;m<16;m++){ varvArr: Vector. varuArr: Vector. pp[t].Z=z0[i][m]+z0[i][m+1]+z0[i+1][m+1]+z0[i+1][m]; fce(t,vArr,uArr,"negative"); t++; } } for(i=5;i<9;i++){//背鳍 vary2: Number=(186+i-r[i+1])*f/(f+z0[i+1][7]),y3: Number=(187+i-r[i+2])*f/(f+z0[i+2][7]); vArr=Vector. uArr=Vector.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 利用 三角函数 生成 计算机 图形
![提示](https://static.bdocx.com/images/bang_tan.gif)