÷ƒ’À;è TeX output 1998.04.09:1417‹ÿÿÿÿ ¨ ýF ¬ŽóKñ`y cmr10²274’)§TUGbGoat,–UUV‘ÿ*ªolume“18“(1997),“No.“4ŽŽ œ ý™šŸè‰™šáŸ$„$™šŸô‘9óñkAHG® cmssbx10¹Graphics‘U>ApplicationsŽŽ’ßÌÌ„$™šŽŸ™š‰™šáŽŽŽŽŸ ‹aóò"V cmbx10ºCreating–Õ93D“animations“with“ó{#ºõ logod10»METÄDAPwwOSTŽ¤‘²Denis‘U>RoGegelŽ©ºAbstractŽ¡óø”o> logo10¼METÇAPqÆOST‘²can–Î8bGe“used“to“create“animations.‘ÜqW‘ÿ*ªeŽ¤ sho¸ãw–ª¦here“an“example“of“animation“of“pGolyhedra,Ž¡inš¸ãtroGducing–UUthe“óßêŸÓVEŽ‘ãxX“distribution.Ž¡‘Unfortunately‘ÿ*ª,‘‡r¼METÇAPqÆOST‘Oé²is–still“quite“bareŽ¡and–—the“user“is“only“o ered“the“raš¸ãw“pGo˜w˜er–ª®|“a‘—littleŽ¡bit–¼tlik¸ãe“the“T‘þU>ŸÓVEŽ›ãxX“user“who“only“has“plain“T‘þU>ŸÓVEŽ˜X“atŽ¡his/her–^ÎdispGosal.‘Ž1The“lac¸ãk“of“libraries“is“certainlyŽ¡due–N8to“the“infancy“of‘U¼METÇAPqÆOST‘‡²(whic¸ãh“came“inŽ¡the–Ünpublic“domain“at“the“bGeginning“of“1995)“andŽ¡thš¸ãus–UUto“the“small“n˜um˜bGer“of“its“users.Ž¡‘In–e³this“papGer,‘éËwš¸ãe“presen˜t“a“w˜a˜y“to“proGduceŽ¡animations–Ÿ}using‘à ¼METÇAPqÆOST8ã².‘ P@The“tec¸ãhnique“isŽ¡quite–ýSgeneral“and“w¸ãe“illustrate“it“through“the“½3dŽ¡²pac¸ãk‘ÿqÇage.Ž¦ºAnimationsŽŸ²The–RW›ÿ*ªorld“Wide“W˜eb“has“accustomed“us“to“v‘ÿqÇariousŽ¡animations,‘½$espGecially‘˜»½java‘u.²animations.‘ÑRCommonŽ¡compGonenš¸ãts–áof“w˜eb“pages“are“animated“GIF‘àçimages.Ž¡‘ProGducing–™˜animations“in“¼METÇAPqÆOST‘Ò{²is“actu-Ž¡ally–§mquite“easy‘ÿ*ª.‘ hA‘¦Ôn•¸ãum“bšGer–§mof“ó  b> cmmi10µn“²images“will“b˜eŽ¡computed–#Šand“their“sequence“proGduces“the“anima-Ž¡tion.‘ ®The–/¢animation“will“bGe“similar“to“a“mo¸ãvie,Ž¡with–^Ìno“in¸ãteraction.‘Ž-More“precisely‘ÿ*ª,‘a*if“½an_image(µi½)Ž¡²proGduces–?ka“picture“parameterized“b¸ãy“µi²,‘CÍit“suces“toŽ¡wrap–UUthis“macro“bGet•¸ãw“een–UU½beginfig“²and“½endfig²:Ž©žW½def–?ýone_image_out(expr“i)=Ž¡‘ úbeginfig();Ž¡‘ÿôan_image(i);Ž¡‘ úendfig;Ž¡enddef;Ž¦²and–UUto“loGop“o•¸ãv“er‘UU½one_image_out²:Ž¦½for–?ýj:=1“upto“100:one_image_out(j);endfor;ŽŽŽ ý‚’²Assuming–Sïthat“½“²is“equal“toŽ¤ ’óthe–€}parameter“of“½an_image²,‘‹Gthe“compilation“of“thisŽ¡’óprogram–M1will“proGduce“a“h¸ãundred“ les“with“extensionsŽ¡’ó½.1²,–P0½.2²,“.–ªª.“.“,‘P0½.100².‘o¢All–Nçthese“ les“are“P¸ãostScript“ lesŽ¡’óand–«Øall“wš¸ãe“need“to“do“is“to“ nd“a“w˜a˜y“to“collateŽ¡’óthem–Ïfin“one“piece.‘ßúHo¸ãw“to“do“this“depGends“on“theŽ¡’óopGerating–bsystem.‘ŸîOn“UNIX‘2for“instance,‘=åone“canŽ¡’óuse–W½Ghostscript“²to“transform“a“Pš¸ãostScript“ le“in˜toŽ¡’ó½ppm–9I²and“then“transform“eacš¸ãh“½ppm“² le“in˜to“GIF‘9BwithŽ¡’ó½ppmtogif².‘ã—These–Кprograms“are“part“of“the“½NETPBMŽ¡’ó²pac•¸ãk‘ÿqÇage›´±(Da“vidsen,–̈1993).‘ÚFinally‘ÿ*ª,“a˜program˜suc¸ãhŽ¡’óas–…½gifmerge“²(MG‘ú¸âuller,‘1996)“creates“an“animatedŽ¡’óGIF–¼ le›+(GIF89A)“out˜of˜the˜h¸ãundred˜individualŽ¡’ósimple›?¢GIFs.‘7Ho•¸ãw“ev“er,‘w-v‘ÿqÇarious˜details˜m“ust˜bGe˜tak“enŽ¡’ócare–\øof.‘ˆ°F‘ÿ*ªor“instance,‘^áonly“a“part“of‘$½Ghostscript²'sŽ¡’óoutput–¬ois“needed“and“selection“can“bGe“made“withŽ¡’ó½pnmcut².Ž¡’The–žÍwhole“proGcess“of“creating“an“animationŽ¡’óout–—of‘^8¼METÇAPqÆOST8ã²'s“outputs“can“bGe“summed“up“inŽ¡’óa–ëshell“script,‘Pˆsimilar“to“the“one“in“ gure“1.‘ 3AsŽ¡’ówš¸ãe–Íÿwill“see,‘ì)this“script“(including“the“argumen˜ts“ofŽ¡’ó½awk–Ùf²and“½pnmcut²)“can“bGe“generated“automatically“b¸ãyŽ¡’ó¼METÇAPqÆOST‘Ž8²itself.ŽŸ’óºOb‘£Žjects–Õ9in“spaceŽŸ’óIn®9troQÇduction‘K¯²The–¡author“applied“this“idea“to“theŽ¡’óanimation–PXof“ob‘Ž8jects“in“space.‘bÑThe“macros“in“theŽ¡’ó½3d.mp›ûm²pac•¸ãk‘ÿqÇageŸü^ÿóÙ“ Rcmr7±1ŽŽ‘wà²pro“vide˜a˜basis˜for˜the˜represen“ta-Ž¡’ótion–Gýof“three-dimensional“ob‘Ž8jects.‘I¾The“basic“com-Ž¡’ópšGonen¸ãts–9of“the“ob‘Ž8jects“are“the“p˜oinš¸ãts“or“the“v˜ectors.Ž¡’óBoth–Caare“stored“as“triplets.‘kËMore“precisely‘ÿ*ª,‘Føwš¸ãe“ha˜v˜eŽ¡’óthree–UUarraš¸ãysŸü^ÿ±2ŽŽ‘ÑȲof“t˜ypGe“½numeric²:Ž¤2ƒ’ó½numeric‘?ývect[]x,vect[]y,vect[]z;Ž¡’²V‘ÿ*ªector–¡µi²'s“compGonen¸ãts“are“½vect[µi½]x²,‘´ ½vect[µi½]yŽ¤ ’ó²and–á½vect[µi½]z².‘‰lIt“is“then“straigh•¸ãtforw“ard–áto“de neŽ¡’óthe–<ðusual“opGerations“on“vš¸ãectors“using“this“con˜v˜en-Ž¡’ótion.‘qÇF‘ÿ*ªor–UUinstance,“v¸ãector“addition“is“de ned“as:ŽŸ2ƒ’ó½def–?ývect_sum(expr“k,i,j)=Ž¡’ýúvect[k]x:=vect[i]x+vect[j]x;Ž¡’ýúvect[k]y:=vect[i]y+vect[j]y;Ž¡’ýúvect[k]z:=vect[i]z+vect[j]z;Ž¡’óenddef;Ž’óŸ“ý‰ffYÿ¦Ÿ J=‘ ÕiŸý-:ó¹Aa¨cmr6À1ŽŽŽ‘\„ó|{Ycmr8¿On–9ÅCT‘ÿJªAN,“under“óßCÊscmtt8Ågraphics/metapost/macros/3d¿.‘ôhTheŽ¤ €coš‘ ÕiŸý-:À2ŽŽŽ‘\„ÆMETÑZAP]LOST‘ð¿has–ëJa“few“simple“tšÃŽyp“$i.psŽ¡#–?ýproduce“ppm“format:Ž¡gs–?ý-sDEVICE=ppmraw“-sPAPERSIZE=a4“-dNOPAUSE“-r36“-sOutputFile=$i.ppm“-q“--“$i.psŽ¡/bin/rm–?ý-f“$i.psŽ¡#–?ýproduce“gif:Ž¡ppmquant–?ý32“$i.ppm“|“pnmcut“15“99“141“307“|“ppmtogif“>“`expr“$i.ppm“:“'\(.*\)ppm'`gifŽ¡/bin/rm–?ý-f“$i.ppmŽ¡doneŽ¡/bin/rm–?ý-f“animpoly.gifŽ¡#–?ýmerge“the“gif“files:Ž¡gifmerge–?ý-10“-l1000“animpoly.*.gif“>“animpoly.gifŽ¡/bin/rm–?ý-f“animpoly.*.gifŽŸ‘E åºFigure‘ÕT1²:‘qÇScript–UUcreated“bš¸ãy‘xâ¼METÇAPqÆOST‘Ž8²(with“some“additional“commen˜ts)ŽŽŽ Ž9 þqÇ‘Often,‘S§wš¸ãe–S;need“some“scratc˜h“v˜ectors“or“v˜ectorsŽ¤ lošGcal–§Òto“a“macro.‘i=A‘§¼simple“v¸ãector“allo˜cation“mec¸ãh-Ž¡anism–Iœsolvš¸ães“the“problem:‘këw˜e“use“a“stac˜k“of“v˜ectorsŽ¡and–ìwš¸ãe“reserv˜e“and“free“v˜ectors“only“on“top“of“theŽ¡stacš¸ãk.‘ 7yF‘ÿ*ªor–ìinstance,‘R_the“alloGcation“of“a“v˜ector“isŽ¡de ned‘UUb¸ãy:Ž¤‘l½def–?ýnew_vect=incr(last_vect_)“enddef;Ž¡²where–íÕ½last_vect_“²is“the“index“of“the“top“of“theŽ¤ stac•¸ãk.‘qHence,‘ü±a›Û8v“ector˜is˜manipulated˜b“y˜its˜indexŽ¡on–³the“stac¸ãk.‘‚àW‘ÿ*ªriting“½v:=new_vect;“²lets“½v“²bGe“theŽ¡index–UUof“the“newly“alloGcated“v¸ãector.Ž¡‘F‘ÿ*ªreeing–ÚÛa“vš¸ãector“is“also“easy“and“is“only“allo˜w˜edŽ¡at–UUthe“top“of“the“stac¸ãk:Ž©‘l½def–?ýfree_vect(expr“i)=Ž¡‘ úif‘?ýi=last_vect_:Ž¡‘?ñlast_vect_:=last_vect_-1;Ž¡‘ úelse:–?ýerrmessage("Vector“"“&Ž¡‘?ñdecimal–?ýi“&“"“can't“be“freed!");Ž¡‘ úfi;Ž¡enddef;Ž¦‘²Ho¸ãw–®6these“macros“are“used“is“made“explicit“inŽ¡the–¢¬½vect_rotate“²macro“whic¸ãh“doGes“a“rotation“of“aŽ¡vš¸ãector–½v“²around“a“v˜ector“½axis“²b˜y“an“angle“½alpha².Ž¡This–o¬rotation“is“illustrated“in“ gure“2.‘ÁÒµ~Ž‘%:vŽŽ‘ É£²is“written“asŽ¡the–¼-sum“ofŸý\q‘¨µ~ŽŸ£“hŽŽ‘ ;Q²and‘âµ~Ž“aŽŽ‘ ÁŠ²whereŸý\q‘¨µ~ŽŸ£“hŽŽ‘ F<ó !",š cmsy10¸?‘&͵~Ž‘ÇaŽŽ‘H².‘>ºIfŸý\q‘œŸµ~ŽŸ£“bŽŽ‘ òisŸúgž“¸ŽŽ‘iÁ‘þ㎎Ž‘t«!ŽŽŸ˜b“µaxisŽŽŽŽ‘Þm=¸kŸúgžŽŽ‘­”‘þ㎎Ž‘t«!ŽŽŸ˜bµaxisŽŽŽŽ‘"@¸kŽ‘"B²,ŽŸ H‰‘ÿsDµ~ŽcŽŽ‘¾È²is–jícomputed“as“the“v¸ãector“proGduct“ofŸý\q‘K_µ~ŽŸ£“bŽŽ‘ „²and‘Ê¢µ~Ž“aŽŽ‘  ²andŽ¡‘ÿ_µµ~ŽaŽŽ‘ž…²is–UUthen“rotated“in“a“simple“w•¸ãa“y–UUresulting“inŸý\q‘·“µ~ŽŸ£“fŽŽ‘ N;².Ž¡‘The–!1v¸ãectors“declared“with“½new_vect“²are“freedŽ¡in–x&the“in•¸ãv“erse–x&order.‘( The“½vect_rotate“²macro“mak¸ãesŽ¡use–”‹of“a“few“other“macros:‘ð4½vect_mod“²computes“theŽŽŽ þqÇ’ómoGdulus–qËof“a“v¸ãector;‘½vect_dprod(a,b)“²is“the“dotŽ¤ ’óproGduct–`»of“v¸ãectors“½a“²and“½b²;‘fn½vect_mult(b,a,x)“²letsŽ¡’óvš¸ãector–‹Œ½b“²equal“v˜ector“½a“²m˜ultiplied“b˜y“the“scalarŽ¡’ó½x²;‘-‹½vect_sum–åy²and“½vect_diff“²compute“as“their“ rstŽ¡’óargumenš¸ãt– xthe“sum“or“the“di erence“of“the“t˜w˜o“otherŽ¡’óvš¸ãectors;‘,X½vect_prod(c,a,b)–䬲lets“v˜ector“½c“²equal“theŽ¡’óvš¸ãectorial–zNproGduct“of“v˜ectors“½a“²and“½b².‘à±These“macrosŽ¡’óare–UUdescribšGed“in“app˜endix“A.Ž©Ç’ó½vardef–?ývect_rotate(expr“v,axis,alpha)=Ž¡’ýúsave‘?ýv_a,v_b,v_c,v_d,v_e,v_f;Ž¡’ýúv_a:=new_vect;v_b:=new_vect;Ž¡’ýúv_c:=new_vect;v_d:=new_vect;Ž¡’ýúv_e:=new_vect;v_f:=new_vect;Ž¡’ýúv_g:=new_vect;v_h:=new_vect;Ž¡’ýúvect_mult(v_b,axis,1/vect_mod(axis));Ž¡’ýúvect_mult(v_h,v_b,vect_dprod(v_b,v));Ž¡’ýúvect_diff(v_a,v,v_h);Ž¡’ýúvect_prod(v_c,v_b,v_a);Ž¡’ýúvect_mult(v_d,v_a,cosd(alpha));Ž¡’ýúvect_mult(v_e,v_c,sind(alpha));Ž¡’ýúvect_sum(v_f,v_d,v_e);Ž¡’ýúvect_sum(v,v_f,v_h);Ž¡’ýúfree_vect(v_h);free_vect(v_g);Ž¡’ýúfree_vect(v_f);free_vect(v_e);Ž¡’ýúfree_vect(v_d);free_vect(v_c);Ž¡’ýúfree_vect(v_b);free_vect(v_a);Ž¡’óenddef;Ž¦’²The–.¹½3d“²pac¸ãk‘ÿqÇage“de nes“other“macros“in“orderŽ¡’óto–£Âset“the“observ¸ãer,‘·^to“compute“a“reference“matrix,Ž¡’óetc.‘qÇProš¸ãvision–UUis“giv˜en“for“manipulating“ob‘Ž8jects.ŽŽŽŽŽŽŽŒ‹Ý ¨ ýF ¬Ž²276’)§TUGbGoat,–UUV‘ÿ*ªolume“18“(1997),“No.“4ŽŽ œ ýûUŸå9‘fU¼ï;PSfile="vect-fig.9" llx=-23 lly=-6 urx=112 ury=86 rwi=1350 Ž’ K<ï;PSfile="vect-fig.10" llx=-13 lly=-18 urx=86 ury=86 rwi=990 ŽŽŸ’¯ò­ºFigure‘ÕT2²:‘qÇV‘ÿ*ªector‘UUrotationŽŽŽ ªc þUºOb‘£Žjects–Õ9and“classes‘²The–²š½3d“²pac¸ãk‘ÿqÇage“understandsŽ¤ a–Þnotion“of“¾class².‘\JA‘ξclass‘æÿ²is“a“parameterized“ob‘Ž8ject.Ž¡F‘ÿ*ªor–u instance,‘¡èwš¸ãe“ha˜v˜e“the“class“of“regular“tetrahedra,Ž¡the–ÖFclass“of“regular“cubGes,‘ö‚etc.‘ô›Our“classes“are“theŽ¡lo•¸ãw“est›¯lev“el˜of˜abstraction˜and˜classes˜can˜not˜bGeŽ¡compšGosed.‘/[They–Žcan“only“b˜e“¾instanciate‘ÿ}'d².‘/[When“w¸ãeŽ¡need–ÒNa“spGeci c“tetrahedron,‘ñw¸ãe“call“a“generic“func-Ž¡tion–Áíto“create“a“tetrahedron,‘Ýbut“with“an“iden¸ãti erŽ¡spGeci c–UUto“one“instance.Ž¡‘A‘œ‡class–œÛis“a“set“of“v¸ãertices“in“space,‘î½togetherŽ¡with–Úa“w•¸ãa“y–Úto“dra¸ãw“faces,‘«»and“therefore“edges.Ž¡The–*§author's“foGcus“w¸ãas“to“manipulate“(and“laterŽ¡animate)–ApGolyhedra.‘6LAs“an“example,‘|Œthe“½poly.mpŽ¡²pac•¸ãk‘ÿqÇage›wýpro“vides˜the˜de nition˜of˜eac“h˜of˜the˜ v“eŽ¡regular›UUcon•¸ãv“ex˜pGolyhedra.Ž¡‘Eacš¸ãh–ÑÅclass“consists“of“t˜w˜o“macros:‘j¦one“de nesŽ¡the–zUpGoin¸ãts,‘¦"the“other“calls“the“ rst“macro“and“de nesŽ¡the–à´faces.‘ ãEacš¸ãh“macro“has“a“parameter“whic˜h“isŽ¡a–Bstring“iden¸ãtifying“the“particular“instance“of“thatŽ¡class.Ž¡‘The–¥“pGoin¸ãts“of“a“regular“tetrahedron“are“de-Ž¡ ned–vÙin“½set_tetrahedron_points²,‘9an“exampleŽ¡of–v´the“general“macro“name“½set_¸h¾class‘Ò!¸i½_points².Ž¡Fiv•¸ãe› ‘pGoin“ts˜are˜de ned,‘ …žfour˜of˜them˜withŽ¡½set_obj_point²,‘´ïa–¡Ðmacro“whicš¸ãh“de nes“pGoin˜ts“¾lo–ÿ}'c“alŽ¡²to–USan“ob‘Ž8ject.‘ qÂThe“ rst“four“pGoinš¸ãts“are“the“v˜er-Ž¡tices–Öand“the“ fth“is“the“cen¸ãter“of“the“tetrahedron.Ž¡½set_obj_point²'s–¸ç rst“parameter“is“the“pGoinš¸ãt“n˜um-Ž¡bšGer–çand“the“other“three“are“the“cartesian“co˜ordi-Ž¡nates.‘ÌlThe–sŒ rst“three“pGoin¸ãts“are“in“a“plane“and“theŽ¡fourth–ÞÔis“obtained“with“the“½new_face_point“²macro,Ž¡whic¸ãh–Ônfolds“a“face“(see“the“description“in“appGendixŽ¡A‘for–cmore“details).‘IñThe“½new_face_point“²macroŽ¡is–sZused“with“the“angle“½an“²whic¸ãh“is“computed“inŽ¡adv‘ÿqÇance.‘uŒOnce–V—the“four“pGoin¸ãts“are“set,‘Vçthe“ob‘Ž8ject“isŽ¡normalized,‘êwhicš¸ãh–ÏNmeans“that“it“is“cen˜tered“with“re-Ž¡spGect–üÔto“the“list“of“vš¸ãertices“giv˜en“as“parameter“(hereŽ¡½1,2,3,4²)–Û¼and“the“last“v¸ãertex“is“put“on“a“sphere“ofŽ¡radius–y81,›‚0cen¸ãtered“on“the“origin.‘ÝoTherefore,˜pGoin¸ãt“5Ž¡is–˜šthe“cen¸ãter“of“the“tetrahedron,‘¾Yand“the“tetrahedronŽ¡is–UUset“symmetrically“with“respGect“to“the“origin.ŽŽŽ þU’All–õÓ vš¸ãe“con˜v˜ex“regular“pGolyhedra“are“de ned“inŽ¤ ’óthis›w•¸ãa“y˜and˜ma“y˜therefore˜b•Ge˜inscrib“ed˜in˜a˜sphereŽ¡’óof–UUradius“1.Ž©U’ó½def–?ýset_tetrahedron_points(expr“inst)=Ž¡’ýúset_obj_point(1,0,0,0);Ž¡’ýúset_obj_point(2,1,0,0);Ž¡’ýúset_obj_point(3,cosd(60),sind(60),0);Ž¡’ýúsinan=1/sqrt(3);Ž¡’ýúcosan=sqrt(1-sinan**2);Ž¡’ýúan=180-2*angle((cosan,sinan));Ž¡’ýúnew_face_point(4,1,2,3,an);Ž¡’ýúnormalize_obj(inst)(1,2,3,4);Ž¡’ýúset_obj_point(5,0,0,0);Ž¡’óenddef;Ž¦’²The–)Üsecond“macro,‘žþ½def_tetrahedron“²de nesŽ¡’óthe›ý=n•¸ãum“b•Ger˜of˜p“oin¸ãts˜and˜faces˜of˜the˜instance,‘ÜcallsŽ¡’óthe–Gprevious“macro“and“de nes“the“faces“with“theŽ¡’ómacro–x½set_obj_face².‘ÙÎThe“ rst“argumen¸ãt“of“thatŽ¡’ómacro–oàis“a“¾lo–ÿ}'c“al‘xi²face›oàn•¸ãum“bGer,‘vƒthe˜second˜is˜a˜list˜ofŽ¡’óv•¸ãertices›ôosuc“h˜that˜the˜list˜go•Ges˜clo“c¸ãkwise˜when˜theŽ¡’óface–/:is“visible.‘eThe“last“argumen¸ãt“is“the“color“of“theŽ¡’óface–UUin“R¸ãGB.Ž¦’ó½vardef–?ýdef_tetrahedron(expr“inst)=Ž¡’ýúnew_obj_points(inst,5);Ž¡’ýúnew_obj_faces(inst,4);Ž¡’ýúset_tetrahedron_points(inst);Ž¡’ýúset_obj_face(1,"1,2,4","b4fefe");Ž¡’ýúset_obj_face(2,"2,3,4","b49bc0");Ž¡’ýúset_obj_face(3,"1,4,3","b4c8fe");Ž¡’ýúset_obj_face(4,"1,3,2","b4fe40");Ž¡’óenddef;Ž¦’²The–UUresult“of“the“dra¸ãwing“is:ŽŸVQ’BàÎï6PSfile="tetra.ps" llx=-42 lly=8 urx=23 ury=84 rwi=650 ŽŽŽŽŽŽŽŽŒ‹*¿ ¨ ýF ¬Ž²TUGbGoat,–UUV‘ÿ*ªolume“18“(1997),“No.“4’)§277ŽŽ œ ý‚‘A‘cmore–c¡complex“example“is“the“icosahedronŽ¤ whicš¸ãh–UUis“de ned“bGelo˜w.Ž©ª«½def–?ýset_icosahedron_points(expr“inst)=Ž¡‘ úset_obj_point(1,0,0,0);Ž¡‘ úset_obj_point(2,1,0,0);Ž¡‘ úset_obj_point(3,cosd(60),sind(60),0);Ž¡‘ úcosan=1-8/3*cosd(36)*cosd(36);Ž¡‘ úsinan=sqrt(1-cosan*cosan);Ž¡‘ úan=180-angle((cosan,sinan));Ž¡‘ únew_face_point(4,1,2,3,an);Ž¡‘ únew_face_point(5,2,3,1,an);Ž¡‘ únew_face_point(6,3,1,2,an);Ž¡‘ únew_face_point(7,2,4,3,an);Ž¡‘ únew_face_point(8,3,5,1,an);Ž¡‘ únew_face_point(9,1,6,2,an);Ž¡‘ únew_face_point(10,3,4,7,an);Ž¡‘ únew_face_point(11,3,7,5,an);Ž¡‘ únew_face_point(12,1,8,6,an);Ž¡‘ ú%–?ý1“and“10“are“opposite“verticesŽ¡‘ únormalize_obj(inst)(1,10);Ž¡‘ ú%–?ýcenter“of“icosahedronŽ¡‘ úset_obj_point(13,0,0,0);Ž¡enddef;Ž¦vardef–?ýdef_icosahedron(expr“inst)=Ž¡‘ úsave‘?ýcosan,sinan,an;Ž¡‘ únew_obj_points(inst,13);Ž¡‘ únew_obj_faces(inst,20);Ž¡‘ úset_icosahedron_points(inst);Ž¡‘ úset_obj_face(1,"3,2,1","b40000");Ž¡‘ úset_obj_face(2,"2,3,4","ff0fa1");Ž¡‘ úset_obj_face(3,"3,7,4","b49b49");Ž¡‘ úset_obj_face(4,"3,5,7","b49bc0");Ž¡‘ úset_obj_face(5,"3,1,5","b4c8fe");Ž¡‘ úset_obj_face(6,"1,8,5","b4fefe");Ž¡‘ úset_obj_face(7,"1,6,8","b4fe40");Ž¡‘ úset_obj_face(8,"1,2,6","45d040");Ž¡‘ úset_obj_face(9,"2,9,6","45a114");Ž¡‘ úset_obj_face(10,"2,4,9","45a1d4");Ž¡‘ úset_obj_face(11,"9,4,10","4569d4");Ž¡‘ úset_obj_face(12,"4,7,10","112da1");Ž¡‘ úset_obj_face(13,"7,5,11","b4fefe");Ž¡‘ úset_obj_face(14,"5,8,11","b49bc0");Ž¡‘ úset_obj_face(15,"8,6,12","45a114");Ž¡‘ úset_obj_face(16,"6,9,12","b49b49");Ž¡‘ úset_obj_face(17,"8,12,11","b40000");Ž¡‘ úset_obj_face(18,"7,11,10","45a1d4");Ž¡‘ úset_obj_face(19,"12,10,11","b4c8fe");Ž¡‘ úset_obj_face(20,"9,10,12","ff0fa1");Ž¡enddef;Ž¦‘²Since–KØall“pGoin¸ãts“of“the“ob‘Ž8jects“are“stored“in“aŽ¡unique–jæglobal“arraš¸ãy‘ÿ*ª,‘pJthey“are“in˜ternally“accessed“b˜yŽ¡the–krlošGcal“n•¸ãum“b˜ers–krand“an“o set“de ned“b¸ãy“the“macroŽ¡½new_obj_points².‘ÃœThe–Gicosahedron“example“sho¸ãwsŽŽŽ ý‚’óa–'¢systematic“use“of“the“½new_face_point“²macro“toŽ¤ ’ócompute–«qa“pGoinš¸ãt“on“an“adjacen˜t“face.‘tDispla˜yingŽ¡’ósuc¸ãh–UUan“icosahedron“results“in“the“ gure“3.Ž ŒééŸå9’6TÍï7PSfile="icosa.ps" llx=-45 lly=-9 urx=45 ury=74 rwi=900 ŽŽŸ’)tºFigure‘ÕT3²:‘qÇAn‘UUicosahedronŽŽŽŸ&Äç’The–UUother“three“regular“con•¸ãv“ex–UUpGolyhedra“are:ŽŸO‹„’CáÃï5PSfile="cube.ps" llx=-33 lly=0 urx=30 ury=65 rwi=630 ŽŽŸh³¨’óï6PSfile="octa.ps" llx=-39 lly=-8 urx=36 ury=84 rwi=750 Ž’w§°ï8PSfile="dodeca.ps" llx=-46 lly=-8 urx=46 ury=74 rwi=920 ŽŽ©[W’The–WHdošGdecahedron“co˜de“is“a“bit“sp˜ecial,‘—ÅsinceŽ¡’óthe–I!vš¸ãertices“are“built“using“ten“additional“pGoin˜tsŽ¡’ócorrespšGonding–ž6to“face“cen¸ãters.‘ LjThese“p˜oin¸ãts“areŽ¡’óde ned–Dqas“an“arra¸ãy“of“v‘ÿqÇariables“½fc1“²through“½fc10Ž¡’ó²with‘…p½new_points(fc)(10)².‘½free_points(fc)(10)Ž¡’ó²frees–ÿþthem“when“they“are“no“longer“necessary‘ÿ*ª.‘qÁAnŽ¡’óexcerpt–UUof“the“došGdecahedron“co˜de“is:Ž¦’ó½def–?ýset_dodecahedron_points(expr“inst)=Ž¡’ýúnew_points(fc)(10);%–?ýface“centersŽ¡’ýúset_point(fc1,0,0,0);Ž¡’ýúset_obj_point(1,1,0,0);Ž¡’ýúset_obj_point(2,cosd(72),sind(72),0);Ž¡’ýúrotate_in_plane(3,fc1,1,2);Ž¡’ýú...Ž¡’ýúfree_points(fc)(10);Ž¡’óenddef;Ž¦’²Finally‘ÿ*ª,‘βwire–¶ldraš¸ãwings“can“bGe“obtained“b˜y“set-Ž¡’óting–UUthe“b•Go“olean–UU½filled_faces“²to“false:ŽŽŽŽŽŽŒ‹;Ë ¨ ýF ¬Ž²278’)§TUGbGoat,–UUV‘ÿ*ªolume“18“(1997),“No.“4ŽŽ œ þšŽ‘*ï=PSfile="icosa-w.ps" llx=-117 lly=-31 urx=61 ury=130 rwi=1780 ŽŽŸºAnimating‘Õ9ob‘£Žjects‘j²The–i¿animation“of“one“or“sev-Ž¤ eral–¥“ob›Ž8jects“in•¸ãv“olv“es–¥“the“ob˜ject(s)“and“an“observ¸ãer.Ž¡The–ûanimation“is“a“set“of“images“and“from“an“imageŽ¡to–ŒÔthe“next“one,‘š³the“observš¸ãer“as“w˜ell“as“the“ob‘Ž8jectsŽ¡can›àfmo•¸ãv“e.‘ úF‘ÿ*ªor˜instance˜the˜macro˜½one_image˜²inŽ¡½3d.mp‘UU²is:Ž©2¹½def–?ýone_image(expr“name,i,a,rd,ang)=Ž¡‘ úbeginfig(i);Ž¡‘ÿôset_point(Obs,Ž¡‘?ñ-rd*cosd(a*ang),-rd*sind(a*ang),1);Ž¡‘ÿôObs_phi:=90;Obs_dist:=2;Ž¡‘ÿô%–?ýfix“point“1“of“object“|name|Ž¡‘ÿôpoint_of_view_obj(name,1,Obs_phi);Ž¡‘ÿôdraw_obj(name);Ž¡‘ÿôrotate_obj_pv(name,1,vect_I,ang);Ž¡‘ÿô%–?ýshow“the“rotation“pointŽ¡‘ÿôdraw_point(name,1);Ž¡‘ÿôdraw_axes(red,green,blue);Ž¡‘ úendfig;Ž¡enddef;Ž¦‘²The–˜parameters“of“this“macro“are“a“name“of“anŽ¡ob‘Ž8ject–D|(½name²),›GÛan“image“index“(½i²),˜and“three“v‘ÿqÇaluesŽ¡de ning–¬orienš¸ãtation“of“the“observ˜er“is“de ned“b˜yŽ¡three–†gangles“(see“ gure“5).‘üThe“½Obs_phi“²angle“isŽ¡givš¸ãen–‹^and“the“t˜w˜o“others“are“computed“with“a“call“toŽ¡½point_of_view_obj(name,1,Obs_phi)–÷²whic¸ãh“con-Ž¡strains–n›the“observš¸ãer“to“loGok“to˜w˜ards“pGoin˜t“1“of“ob‘Ž8jectŽ¡½name².‘´_Therefore,‘Fithis–2pGoin¸ãt“will“seem“ xed“on“theŽ¡animation–°band“½draw_point(name,1)“²dra¸ãws“it“laterŽ¡so–)Íthat“this“feature“can“bGe“observ¸ãed.‘cDThere“is“noth-Ž¡ing–G¤spšGecial“ab˜out“that“p˜oin¸ãt,‘Jaexcept“that“it“remainsŽŽŽ ý‚’ó x–^`when“the“ob›Ž8ject“is“rotated.‘ŒèThe“ob˜ject“is“dra¸ãwnŽ¤ ’ówith–g.½draw_obj(name)“²and“½rotate_obj_pv“²rotatesŽ¡’óthe– eob‘Ž8ject“½name“²b¸ãy“½ang“²degrees“around“an“axis“goingŽ¡’óthrough–¢™pGoinš¸ãt“1“and“directed“b˜y“v˜ector“½vect_I‘¢…²(‘þžøµ~Ž{ŽŽ‘9}²).ŽŸ H‰’óThe–bsreference“vš¸ãectors“(‘þžøµ~Ž{ŽŽ‘9}²,‘á½µ~Ž‘eº|ŽŽ‘ ŸK²andŸý\q‘à;µ~ŽŸ£“kŽŽ‘çɲ)“are“dra˜wn“in“red,Ž¡’ógreen–UUand“blue“with“½draw_axes².Ž¡’Finally‘ÿ*ª,‘œëa–nÐcomplete“animation“of“an“icosahedronŽ¡’óis–UUobtained“withŽ¤âS’ó½animate_object("icosahedron",1,100,100);Ž¡’ó²whic¸ãh–/Cgenerates“ les“½anim.101²,›6à.–ªª.“.“,˜½anim.200‘/C²fromŽ¤ ’óthe–-Ômain“ le“½anim.mp².‘ ûCThe“ rst“parameter“ofŽ¡’ó½animate_object–|u²is“the“name“of“the“ob‘Ž8ject“to“an-Ž¡’óimate,‘êeacš¸ãh“image“is“dra˜wn,‘ŽÜthe“v‘ÿqÇalues“of“the“cur-Ž¡’óren¸ãt–cŠbšGounding“b˜o¸ãx“are“used“to“compute“the“b˜ound-Ž¡’óing–ŒbGoš¸ãx“of“the“sequence“of“images.‘ |kThe“in˜ternalŽ¡’óv‘ÿqÇalues›oè½xmin_²,–öŒ½ymin_²,“½xmax_˜²and˜½ymax_˜²hold˜theŽ¡’óminimal–9ãand“maximal“v‘ÿqÇalues“of“the“coGordinates“ofŽ¡’óthe–ߘpast“images'“corners.‘ They“are“upGdated“justŽ¡’óbšGefore–UUeac¸ãh“image“is“shipp˜ed“out.ŽŸ’óºPutting–Õ9the“pieces“together‘h²Once–½\all“the“viewsŽ¡’óha•¸ãv“e–lÜbšGeen“computed,‘²½they“can“b˜e“used“separatelyŽ¡’ó(see–œofor“instance“the“ v¸ãe“views“of“ gure“6)“or“moreŽ¡’óin¸ãterestingly‘ÿ*ª,‘9Bthey–¥Fcan“bGe“merged.‘ a›This“task“isŽ¡’ómade–Ûalmost“straigh•¸ãtforw“ard‘Ûb“y‘þ‘¼METÇAPqÆOST‘ç²itself.Ž¡’óIndeed,›]¦ev¸ãery–[ütime“½animate_object“²is“used,˜a“shellŽ¡’óscript–`named“½create_animation.sh“²is“generated,Ž¡’óas–Ka“side-e ect“of“a“call“to“½show_animation_bbox².Ž¡’óThe–Ì¢script“is“similar“to“that“sho¸ãwn“in“ gure“1.Ž¡’óThis–ýscript“uses“the“v‘ÿqÇalues“computed“for“the“globalŽ¡’ób•Gounding›/eb“o¸ãx˜of˜the˜sequence˜of˜images,‘eèfor˜theseŽ¡’óv‘ÿqÇalues–ÑÄare“necessary“in“order“to“extract“the“righ¸ãtŽ¡’óparts–ýof“the“images“and“get“correct“alignmen¸ãts;‘•QtheŽ¡’óparts–ÿ¤are“extracted“with“½pnmcut².Ÿü^ÿ±3ŽŽ‘ í(²If“yš¸ãou“ha˜v˜e“theŽ¡’óprograms–ÌÏused“in“this“script“(½Ghostscript²,‘*­etc.),Ž¡’óy¸ãou–qcan“just“run“it“with“½sh‘?ýcreate_animation.shŽ¡’ó²on–o¢UNIX.“Y‘ÿ*ªou“maš¸ãy“need“to“adapt“it“to“y˜our“needs,Ž¡’óand–÷]for“that“purpšGose,‘_ßy¸ãou“can“mo˜dify“the“macroŽ¡’ó½write_script–UU²in“½3d.mp².Ž¡’Some–´Ñexamples“are“included“in“the“½3d“²distri-Ž¡’óbution,‘à¼and–‘¨they“can“bGe“view¸ãed“for“instance“withŽ¡’ó½netscape–UU²or“spGecial“programs“suc¸ãh“as“½xanim².Ž’óŸ(•‰ffYÿ¦Ÿ J=‘ ÕiŸý-:À3ŽŽŽ‘\„¿One–NžmighÃŽt“think“of“using‘l×ÅGhostscript“¿for“generating“anŽ¤ €excerpt–,“of“an“image,‘Bbbut“if‘ÎZÅGhostscript“¿is“used“to“generateŽ¡the–¨=bšA˜T&T‘bÙBell“LabGoratories,Ž¡‘Murra¸ãy–UUHill,“New“Jersey‘ÿ*ª,“1992.Ž¦Knš¸ãuth,‘¡SDonald–’!E.“\MFT,“v˜ersion“2.0".“1989.“Stan-Ž¡‘dard–UUT‘þU>ŸÓVEŽ‘ãxX“distribution.ŽŽŽ ý‚’óKn¸ãuth,‘ZÇDonald–&}E.“¾The–TTA¾“rt“of“Computer“Pr–ÿ}'o“gr“am-Ž¤ ’ming,–ivolumes›^b1,“2˜and˜3².–)Addison-W‘ÿ*ªesley“Pub-Ž¡’lishing–UUCompan¸ãy‘ÿ*ª,“1997.“New“editions.ŽŸ ·w’óMG‘ú¸âuller,› n Ren¸ã‘ûGe– Ï€K.“\GIFMerge,˜v¸ãersion“1.33".Ž¡’1996.–­Av‘ÿqÇailable“at“½http://www.iis.ee.ethz.Ž¡’ch/~kiwi/GIFMerge/².ŽŸ’óºAppQÇendix‘Õ9AŽ¡’óSummary–Õ9of“the“½3d“ºpac®9k‘ÿ\rageŽŸ’óT®9ypQÇes‘…¼²The–Ûcommands“in“the“½3d“²pacš¸ãk‘ÿqÇage“tak˜e“pa-Ž¡’órameters–_˜of“sevš¸ãeral“di eren˜t“t˜ypGes.‘‘The“t˜ypGes“areŽ¡’ódescribGed‘UUhere.ŽŸ·w’ý¸ŽŽŽ’²An–ú¸h¾avn‘Äc¸i“²(¾A¾“bsolute–+wV‘ÿ;¼e›ÿ}'ctor“Numb˜er‘²)–úis“the“in-Ž¡’ternal›“Kn•¸ãum“bGer˜iden“tifying˜a˜v“ector˜in˜the˜½vectŽ¡’²arraš¸ãy–UU(an“in˜teger).Ž© nî’ý¸ŽŽŽ’²An–¸È¸h¾apn‘Äc¸i“²(¾A¾“bsolute–ïePoint“Numb‘ÿ}'er‘²)–¸Èrefers“to“aŽ¡’vš¸ãector–“Bin“the“same“w˜a˜y“as“an“¸h¾avn‘Äc¸i“²(an“in˜teger).Ž¦’ý¸ŽŽŽ’²A‘y°¸h¾lpn‘Äc¸i›yè²(¾L–ÿ}'o“c“al–Ê Point“Numb‘ÿ}'er‘²)˜is˜a˜n•¸ãum“bGer˜iden-Ž¡’tifying–´1a“pGoinš¸ãt“¾within‘x”²an“ob‘Ž8ject“(an“in˜teger).Ž¡’Tw¸ão–×V¸h¾lpn‘Äc¸i²s“with“the“same“v‘ÿqÇalue“can“correspGondŽ¡’to–UUdi erenš¸ãt“pGoin˜ts“in“di eren˜t“ob‘Ž8jects.Ž¦’ý¸ŽŽŽ’²An–9'¸h¾afn‘Äc¸i“²(¾A¾“bsolute–ŽwF‘ÿ;¼ac›ÿ}'e“Numb˜er‘²)–9'is“the“in¸ãternalŽ¡’n•¸ãum“bGer›UUiden“tifying˜a˜face.Ž¦’ý¸ŽŽŽ’²A‘J}¸h¾lfn‘Äc¸i‘J²(¾L–ÿ}'o“c“al›‰ïF‘ÿ;¼ac“e˜Numb“er‘²)–Jis“a“n•¸ãum“bGer‘Jiden-Ž¡’tifying–‰†a“face“¾within‘Mé²an“ob‘Ž8ject“(an“in¸ãteger).Ž¡’As–_Ofor“pGoin•¸ãts,‘¡Ít“w“o–_O¸h¾lfn‘Äc¸i²s“with“the“same“v‘ÿqÇalueŽ¡’can–UQcorrespGond“to“di erenš¸ãt“faces“in“di eren˜tŽ¡’ob‘Ž8jects.Ž¦’ý¸ŽŽŽ’²A‘3¸h¾cl‘‰¸i–`²(¾Class‘Ò!²)“is“a“string“represen¸ãting“a“class,Ž¡’for–¥Xinstance“½"tetrahedron"².‘aÏIt“ma¸ãy“only“con-Ž¡’tain–UUletters“and“underscores.Ž¦’ý¸ŽŽŽ’²An–Ãl¸h¾obj‘r]¸i“²(¾Obje‘ÿ}'ct‘òز)“is“a“string“represen¸ãting“anŽ¡’ob‘Ž8ject,‘’ôthat–Snis“an“instance“of“a“class.‘lSuc¸ãh“aŽ¡’string–Zmaš¸ãy“only“con˜tain“letters“and“underscores.Ž¦’ý¸ŽŽŽ’²A‘œY¸h¾vl‘‰¸i–œk²(¾V‘ÿ;¼ertex‘ÕMList‘òز)“is“a“list“of“in¸ãtegers,‘®0whereŽ¡’eac•¸ãh›gin“teger˜iden“ti es˜a˜v“ertex.‘§F‘ÿ*ªor˜instance,Ž¡’½1,7–UU²is“the“list“of“v¸ãertices“1“and“7.Ž¦’ý¸ŽŽŽ’²A‘i@¸h¾vsl‘‰¸i›i‡²(¾V‘ÿ;¼ertex–’String“List‘òز)˜is˜a˜string˜corre-Ž¡’spGonding–i2to“a“list“of“inš¸ãtegers,‘˜lwhere“eac˜h“in˜tegerŽ¡’idenš¸ãti es–Áña“v˜ertex.‘·œF‘ÿ*ªor“instance,‘ݽ"1,2,6,5"“²isŽ¡’the–UUlist“of“v¸ãertices“1,“2,“6“and“5.Ž¦’ý¸ŽŽŽ’h¾hc‘¶¸i–›c²(¾Hex‘èÖColor‘²)“is“a“string“represen¸ãting“a“colorŽ¡’with–áÔthe“three“R•¸ãGB‘áncompGonen“ts–áÔin“hexadec-Ž¡’imal–W±and“in“the“range“0µ::²255.‘ xÛF‘ÿ*ªor“instance,Ž¡’½"b4fe40"².Ž¦’ý¸ŽŽŽ’h¾c‘ÿ}'ol‘‰¸i–Àw²(¾Color‘²)“is“a“standard“¼METÇAPqÆOST‘ùZ²color“(aŽ¡’triplet–ñGof“R•¸ãGB‘ñcompGonen“ts–ñGin“the“range“0µ::²1),Ž¡’suc¸ãh–UUas“½red².Ž¦’ý¸ŽŽŽ’h¾str‘¸i–UU²(¾String‘â}²)“is“a“string.Ž¦’ý¸ŽŽŽ’h¾p‘ÿ}'air–¸i›UU²(¾Pair“²)˜is˜a˜pair˜of˜n¸ãumerics.Ž¦’ý¸ŽŽŽ’h¾num‘Äc¸i–UU²(¾Numeric‘¶²)“is“a“n•¸ãum“bGer.Ž¦’ý¸ŽŽŽ’h¾b–ÿ}'o“ol‘‰¸i›UU²(¾Bo“ole“an‘Äc²)˜is˜a˜b•Go“olean.ŽŽŽŽŽŽŒ‹cˆ ¨ ýF ¬Ž²TUGbGoat,–UUV‘ÿ*ªolume“18“(1997),“No.“4’)§281ŽŽ œ ý‚ºLo•®9w›Õ9lev“el˜v“ector˜commands‘¢B²The–÷—loš¸ãw“lev˜el“v˜ec-Ž¤ tor–ï»commands“de ne“the“classical“opGerations“in“v¸ãec-Ž¡tor‘UUalgebra.ŽŸ‘ ¸ŽŽŽ‘½vect_def(¸h¾avn›Äc¸i½,µx½,µy[Ù½,µzp—½)²:‘ÝÃde nes– Sv¸ãector“¸h¾avn˜¸iŽ¡‘²as‘UU(µx;–ª¨y[Ù;“zp—²);Ž© ‘ ¸ŽŽŽ‘½set_point²;‘çÙsynonš¸ãym–a­of“½vect_def²:‘Šwa“pGoin˜t“isŽ¡‘stored–UUin“the“same“arraš¸ãy“as“v˜ectors.Ž¦‘ ¸ŽŽŽ‘½set_obj_point(¸h¾lpn‘Äc¸i½,µx½,µy[Ù½,µzp—½)²:‘Fˆthis–þÖde nes“theŽ¡‘pGoin¸ãt–UU¸h¾lpn‘Äc¸i“²as“(µx;–ª¨y[Ù;“zp—²);Ž¦‘ ¸ŽŽŽ‘½vect_def_vect(¸h¾avn–Äc¸iŸÿ±1Ž›|s½,¸h¾avn“¸iŸÿ±2Ž˜½)²:‘ÿ=v¸ãector‘pA¸h¾avn“¸iŸÿ±1ŽŽ¡‘²bGecomes–UUequal“to“v¸ãector“¸h¾avn‘Äc¸iŸÿ±2Ž‘|s²;Ž¦‘ ¸ŽŽŽ‘½vect_sum(¸h¾avn–Äc¸iŸÿ±1Ž›|s½,¸h¾avn“¸iŸÿ±2Ž˜½,¸h¾avn“¸iŸÿ±3Ž˜½)²:‘JKthe‘A—v¸ãectorŽ¡‘¸h¾avn›Äc¸iŸÿ±1Ž‘ª²bGecomes–7the“sum“of“v¸ãectors“¸h¾avn˜¸iŸÿ±2Ž‘ª²andŽ¡‘¸h¾avn‘Äc¸iŸÿ±3Ž‘|s².Ž¦‘ ¸ŽŽŽ‘½vect_translate(¸h¾avn–Äc¸iŸÿ±1Ž›|s½,¸h¾avn“¸iŸÿ±2Ž˜½)²:‘7éadd‘8fv¸ãectorŽ¡‘¸h¾avn›Äc¸iŸÿ±2Ž‘ôh²to–wõv¸ãector“¸h¾avn˜¸iŸÿ±1Ž‘|s²;‘‰Ev¸ãector“¸h¾avn˜¸iŸÿ±2Ž‘ôh²remainsŽ¡‘unc¸ãhanged.Ž¦‘ ¸ŽŽŽ‘½vect_diff(¸h¾avn–Äc¸iŸÿ±1Ž›|s½,¸h¾avn“¸iŸÿ±2Ž˜½,¸h¾avn“¸iŸÿ±3Ž˜½)²:‘ÊMthe‘˜v¸ãectorŽ¡‘¸h¾avn‘Äc¸iŸÿ±1Ž‘G¦²bšGecomes–Ë3the“di erence“b˜et•¸ãw“een‘Ë3v“ectorsŽ¡‘¸h¾avn–Äc¸iŸÿ±2Ž‘ÑȲand‘UU¸h¾avn“¸iŸÿ±3Ž‘|s².Ž¦‘ ¸ŽŽŽ‘½vect_dprod(¸h¾avn–Äc¸iŸÿ±1Ž›|s½,¸h¾avn“¸iŸÿ±2Ž˜½)–8ã¸!“h¾num‘Äc¸i²:‘ãŽreturnsŽ¡‘the–UUdot“proGduct“of“v¸ãectors“¸h¾avn›Äc¸iŸÿ±1Ž‘ÑȲand“¸h¾avn˜¸iŸÿ±2Ž‘|s².Ž¦‘ ¸ŽŽŽ‘½vect_mod(¸h¾avn›Äc¸i½)–Êh¸!“h¾num˜¸i²:‘[íreturns“the“moGd-Ž¡‘ulus–UUof“v¸ãector“¸h¾avn‘Äc¸i².Ž¦‘ ¸ŽŽŽ‘½vect_prod(¸h¾avn–Äc¸iŸÿ±1Ž›|s½,¸h¾avn“¸iŸÿ±2Ž˜½,¸h¾avn“¸iŸÿ±3Ž˜½)²:‘ÊMthe‘˜v¸ãectorŽ¡‘¸h¾avn‘Äc¸iŸÿ±1Ž‘ðs²bšGecomes–tthe“v¸ãector“pro˜duct“of“v¸ãectorsŽ¡‘¸h¾avn–Äc¸iŸÿ±2Ž‘ÑȲand‘UU¸h¾avn“¸iŸÿ±3Ž‘|s².Ž¦‘ ¸ŽŽŽ‘½vect_mult(¸h¾avn–Äc¸iŸÿ±1Ž›|s½,¸h¾avn“¸iŸÿ±2Ž˜½,¸h¾num“¸i½)²:‘^õ¸h¾avn“¸iŸÿ±1Ž‘¬%²bGe-Ž¡‘comes–UUvš¸ãector“¸h¾avn‘Äc¸iŸÿ±2Ž‘ÑȲscaled“b˜y“¸h¾num‘Äc¸i².Ž¦‘ ¸ŽŽŽ‘½mid_point(¸h¾avn–Äc¸iŸÿ±1Ž›|s½,¸h¾avn“¸iŸÿ±2Ž˜½,¸h¾avn“¸iŸÿ±3Ž˜½)²:‘ƒ0v¸ãector‘Þ (orŽ¡‘p•Goin¸ãt)›õ¸h¾avn‘Äc¸iŸÿ±1Ž‘ƒh²b“ecomes˜the˜mid-p“oin•¸ãt˜of˜v“ectorsŽ¡‘(or–ãof“the“line“joining“the“pGoin¸ãts)“¸h¾avn‘Äc¸iŸÿ±2Ž‘üV²andŽ¡‘¸h¾avn‘Äc¸iŸÿ±3Ž‘|s².Ž¦‘ ¸ŽŽŽ‘½vect_rotate(¸h¾avn–Äc¸iŸÿ±1Ž›|s½,¸h¾avn“¸iŸÿ±2Ž˜½,µa½)²:‘ü,v¸ãector‘j¸h¾avn“¸iŸÿ±1ŽŽ¡‘²is–4örotated“around“vš¸ãector“¸h¾avn‘Äc¸iŸÿ±2Ž‘±i²b˜y“the“angle“µa².ŽŸºOpQÇerations–Õ9on“ob‘£Žjects‘¡¥²Sev¸ãeral–öúopGerations“applyŽ¡globally–UUon“ob‘Ž8jects:ŽŸ‘ ¸ŽŽŽ‘½assign_obj(¸h¾obj–r]¸i½,¸h¾cl‘‰¸i½)²:‘ create›ó¸h¾obj“¸i˜²as˜anŽ¡‘instance–UUof“class“¸h¾cl‘‰¸i².Ž¦‘ ¸ŽŽŽ‘½reset_obj(¸h¾obj–r]¸i½)²:‘Ãput›¥M¸h¾obj“¸i˜²bac•¸ãk˜where˜it˜w“asŽ¡‘just–UUafter“it“w¸ãas“initialized.Ž¦‘ ¸ŽŽŽ‘½put_obj(¸h¾obj–r]¸i½,¸h¾avn‘Äc¸i½,µs½,µ [Ù½,µG½,µ½)²:‘ÜÐob‘Ž8ject‘ŠÚ¸h¾obj“¸iŽ¡‘²is–ßÉscaled“bš¸ãy“µs²,‘‚eshifted“b˜y“v˜ector“¸h¾avn‘Äc¸i“²andŽ¡‘orien¸ãted–@½true²,‘athe–vøfaces“areŽ¤ ’draš¸ãwn–_ lled;‘±…if‘&º½false²,‘Âonly“the“edges“are“dra˜wn,Ž¡’and–UUhidden“edges“are“dra¸ãwn“dashed;Ž© Ûz’ý¸ŽŽŽ’½draw_contours–¦ñ¸!“h¾b–ÿ}'o“ol‘‰¸i²:‘•if‘n½true²,‘ÉÒthe‘¦ñcon¸ãtoursŽ¡’of–$1the“faces“are“draš¸ãwn,‘×çand“the“lines“ha˜v˜eŽ¡’the–Ó‚thic¸ãkness“½contour_width²;‘˜if‘šŸ½false²,‘s theŽ¡’conš¸ãtours–UUare“not“dra˜wn;Ž¦’ý¸ŽŽŽ’½contour_width–Ø-¸!“h¾num‘Äc¸i²:‘wwdimension“used“forŽ¡’dra•¸ãwing›UUcon“tours˜of˜faces˜(default:‘qÇ1pt).ŽŸ’óºConstan®9ts‘Àî²These–Cv‘ÿqÇalues“represenš¸ãt“constan˜t“ob-Ž¡’ójects–o.sucš¸ãh“as“reference“v˜ectors,‘µ¥and“should“not“bGeŽ¡’óc¸ãhanged.Ž¤m½’ý¸ŽŽŽ’½vect_null–UU¸!“h¾avn‘Äc¸i²:‘qÇin¸ãternal“index“forŸýÜq‘rµ~ŽŸ#“²0ŽŽ‘UV.Ž¦’ý¸ŽŽŽ’½vect_I–UU¸!“h¾avn‘Äc¸i²:‘qÇin¸ãternal“index“for‘ôMµ~Ž“{ŽŽ‘ŽÒ².Ž¦’ý¸ŽŽŽ’½vect_J–UU¸!“h¾avn‘Äc¸i²:‘qÇin¸ãternal“index“for‘ÑXµ~Ž“|ŽŽ‘,s².ŽŸ$’ý¸ŽŽŽ’½vect_K–UU¸!“h¾avn‘Äc¸i²:‘qÇin¸ãternal“index“forŸý\q‘Óµ~ŽŸ£“kŽŽ‘Ú«².Ž¦’ý¸ŽŽŽ’½point_null–UU¸!“h¾apn‘Äc¸i²:‘qÇin¸ãternal“index“forŸýÜq‘rµ~ŽŸ#“²0ŽŽ‘UV.Ž¦’ý¸ŽŽŽ’½Obs–}¸!“h¾apn‘Äc¸i²:‘Ûobservš¸ãer's“in˜ternal“pGoin˜t“n˜um˜bGer.ŽŸ’óºDe ning–Õ9new“ob‘£Žject“pQÇoin®9ts“and“facesŽ¡’ý¸ŽŽŽ’½new_obj_points(¸h¾obj‘r]¸i½,¸h¾num‘Äc¸i½)²:‘2Žde nes‘ÖäpGoin¸ãtsŽ¤ ’1–Î1to“¸h¾num‘Äc¸i“²in“ob‘Ž8ject“¸h¾obj‘r]¸i²;‘û=m¸ãust“bšGe“used“b˜eforeŽ¡’setting–UUthe“pGoin¸ãts;Ž¦’ý¸ŽŽŽ’½new_obj_faces(¸h¾obj‘r]¸i½,¸h¾num–Äc¸i½)²:‘Ê€de nes‘²¸h¾num“¸iŽ¡’²faces–É‹in“ob‘Ž8ject“¸h¾obj‘r]¸i²;‘§m¸ãust“bšGe“used“b˜efore“set-Ž¡’ting–UUthe“faces;ŽŸ’óºO setsŽŸm½’ý¸ŽŽŽ’½pnt(¸h¾lpn›Äc¸i½)–Y,¸!“h¾apn˜¸i²:‘ó²returns“the“absolute“pGoin¸ãtŽ¡’n•¸ãum“bšGer–UUfor“a“giv¸ãen“lo˜cal“p˜oin¸ãt“index.Ž¦’ý¸ŽŽŽ’½face(¸h¾lfn›Äc¸i½)–2¥¸!“h¾afn˜¸i²:‘`oreturns“the“absolute“faceŽ¡’n•¸ãum“bšGer–UUfor“a“giv¸ãen“lo˜cal“face“index.ŽŸ’óºStandard‘Õ9classes‘YȲFiv¸ãe–¯standard“classes“are“de-Ž¡’ó ned–œqin“½poly.mp²:‘Uthey“de ne“the“ vš¸ãe“regular“con˜v˜exŽ¡’ópGolyhedra.‘ "F‘ÿ*ªor–:Åeacš¸ãh“class“¸h¾class‘Ò!¸i²,‘´ there“are“t˜w˜oŽ¡’ómacros:Ž¤m½’ý¸ŽŽŽ’½set_¸h¾class‘Ò!¸i½_points‘UU²(e.g.‘qǽset_cube_points²)Ž¦’ý¸ŽŽŽ’½def_¸h¾class‘Ò!¸i‘UU²(e.g.‘qǽdef_cube²)Ž¡’Eac¸ãh–oof“these“macros“is“de ned“with“a“parame-Ž¤ ’óter–UUwhic¸ãh“is“the“instance“name.ŽŸ’óºStandard‘Õ9animations‘The–Cù½3d“²pacš¸ãk‘ÿqÇage“pro˜videsŽ¡’óa–`~few“standard“animations“using“the“con•¸ãv“ex‘`~pGoly-Ž¡’óhedra.‘õ5In–Özeacš¸ãh“of“these“animations,‘6Ãthe“observ˜erŽ¡’ófolloš¸ãws–Ga“circular“path“pictured“in“ gure“7.‘ïžEac˜hŽ¡’óstandard–Řanimation“is“divided“inš¸ãto“t˜w˜o“macros.‘AÞTheŽ¡’ó rst,›}suc¸ãh–uas“½animate_object²,˜de nes“the“class(es)Ž¡’óthat–¬”are“used“and“sets“the“ob‘Ž8jects.‘9‡The“second,‘ÎUsuc¸ãhŽ¡’óas–­B½one_image²,›Îàsets“the“observ•¸ãer,˜dra“ws–­Bthe“ob‘Ž8ject(s)Ž¡’óand›xmo•¸ãv“es˜the˜ob‘Ž8ject(s)˜and˜the˜observ“er.‘ Ú TheŽ¡’ó le–v;½animpoly.mp“²giv¸ães“examples“of“the“use“of“theŽ¡’óstandard‘UUanimations.ŽŽŽŽŽŽŒ‹™— ¨ ýF ¬Ž²TUGbGoat,–UUV‘ÿ*ªolume“18“(1997),“No.“4’)§283ŽŽ œ þ?–äŸå9‘~Îï>PSfile="vect-fig.17" llx=-93 lly=-51 urx=122 ury=121 rwi=2150 ŽŽŸ’ŸˆºFigure‘ÕT7²:‘qÇMotion–UUof“the“observ¸ãerŽŽŽ Ài þ]–äºAppQÇendix‘Õ9BŽ¤ CoQÇding–Õ9an“ob‘£ŽjectŽŸ²In–ñorder“to“extend“the“½3d“²pac¸ãk‘ÿqÇage,‘it“is“necessary“toŽ¡understand–©¯hoš¸ãw“the“ob‘Ž8jects“are“coGded.‘8W‘ÿ*ªe“giv˜e“hereŽ¡an›ÔÖo•¸ãv“erview˜of˜this˜coGding,‘î‰but˜the˜reader˜is˜advisedŽ¡to–ÄApšGeek“in“the“co˜de“to“get“a“b˜etter“understanding“onŽ¡hoš¸ãw–UUall“the“functions“in˜teract.Ž¡‘First,›È›an–¥lob‘Ž8ject“has“a“name,˜for“instance“½"box"².Ž¡The–ýùmacro“½box_class“²(whic¸ãh“can“bGe“called“withŽ¡½obj_class_("box")²)–DKis“the“string“correspGonding“toŽ¡the–U$class“of“½"box"²,‘ˆafor“instance“½"cube"².‘bThe“v‘ÿqÇariableŽ¡½cube_point_offsetbox²,›2Ïof–„t¸ãypGe“½numeric²,˜and“ob-Ž¡tained–Ù“with“½obj_point_offset_("box")²,‘:¡is“equalŽ¡to–J¨the“absolute“index“of“the“last“pGoin¸ãt“of“the“pre-Ž¡vious– Ðob‘Ž8ject.‘›9A‘ ¡cubšGe“is“de ned“with“8–³Ü+“1‘ Ðp˜oin¸ãts.Ž¡Assuming– Pit“w¸ãas“de ned“after“an“icosahedron“(12–ÎÙ+“1Ž¡pGoin¸ãts)–ñnamed“½"ico"²,‘ê½cube_point_offsetbox“²willŽ¡bGe–¹³a“½numeric“²equal“to“13.‘žâ½cube_pointsbox“²(ob-Ž¡tained–,with“½obj_points_("box")²)“is“a“macro“equalŽ¡to–Ox9.‘`1The“v‘ÿqÇariable“½cube_face_offsetbox²,‘ŽsimilarŽ¡to–°b½cube_point_offsetbox²,‘Ç%obtained“with“a“call“toŽ¡½obj_face_offset_("box")²,‘ equals–Ýç20.‘ }The“macroŽ¡½cube_facesbox–Ëõ²(obtained“b¸ãy“½obj_faces_("box")²)Ž¡is–UUequal“to“6.Ž¡‘The–9é½obj_name“²macro“is“extended“eac¸ãh“time“aŽ¡new–|oob‘Ž8ject“is“de ned.‘çT‘ÿ*ªo“an“absolute“face“n•¸ãum“bGer,Ž¡it–AassošGciates“an“ob‘Ž8ject“name.‘Ÿ‹Hence,‘=¼it“is“p˜ossibleŽ¡to– “go“through“all“faces.‘”€½last_point_offset_“²andŽ¡½last_face_offset_–:²are“the“absolute“n•¸ãum“bGers–:of“theŽ¡last–UUpGoinš¸ãts“and“faces“de ned“up“to“no˜w.ŽŸi½def–?ýobj_name(expr“i)=Ž¡‘ úif–?ýi<1:“elseif“i<=20:"ico"Ž¡‘4âelseif‘?ýi<=26:"box"Ž¡‘ úfi;Ž¡enddef;ŽŽŽ þ]–ä’pnt(i)–킲givš¸ães“the“absolute“v˜ector“correspGondingŽ¤ ’óto–QlošGcal“p˜oin¸ãt“µi².‘ ±»½ipnt_(i)“²is“the“absolute“p˜oin¸ãtŽ¡’ón•¸ãum“bšGer,‘Tthat–S¯is“µi“²plus“the“n•¸ãum“b˜er–S¯of“p˜oin¸ãts“de nedŽ¡’óbGeforehand–ˆåin“other“ob‘Ž8jects.‘ w½points_[j]“²is“theŽ¡’óabsolute–Ö¼v¸ãector“correspGonding“to“absolute“ob‘Ž8jectŽ¡’ópGoin¸ãt–ZÓµj‘’‹².‘ ‚@Similarly‘ÿ*ª,‘Ü2½face(i)“²is“the“absolute“faceŽ¡’ócorrespšGonding–UUto“lo˜cal“face“µi².Ž¡’The–xÛlist“of“vš¸ãertices“of“absolute“face“n˜um˜bGer“µiŽ¡’ó²is–Xç½face_points_[i]².‘ |~The“color“of“absolute“faceŽ¡’ón•¸ãum“bGer–UUµi“²is“½face_color_[i]².Ž¡’When–ËÚthe“macros“½pnt“²or“½face“²are“to“bGe“used,Ž¡’óthe–5ˆcalls“½define_current_point_offset_("box")Ž¡’ó²and–y½define_current_face_offset_("box")“²m¸ãustŽ¡’óbGe‘UUissued.ŽŸv@Ÿ’:Àó ©±Ê cmsy9ËŽ’Dóo´‹Ç cmr9ÉDenis‘>RoAÇegelŽ¤ ’DCRIN–>(Cenš¾9tre“de“Rec˜herc˜he“enŽ¡’PInformatique–>de“Nancy)Ž¡’DB^‘û`atimen¾9t‘>LORIAŽ¡’DBP‘>239Ž¡’D54506‘>V‘ÿ:«anduvre-l¾ª‘û¡Xes-NancyŽ¡’DFRANCEŽ¡’Dó!ߤN cmtt9Ìroegel@loria.frŽ¡’D¿URLÉ:‘ŸþÌhttp://www.loria.fr/Ž¡’P~roegelŽŽŽŽŽŽŽŽŽŒø³"ƒ’À;è¨Ô ó!ߤN cmtt9ó ©±Ê cmsy9óo´‹Ç cmr9ót}\Êcmti7óŒ-ø cmcsc10óÓúö‚logo8óßCÊscmtt8ó¹Aa¨cmr6ó|{Ycmr8óý': cmti10óßê logo10ó{#ºõ logod10óò"V cmbx10óñkAHG® cmssbx10ó !",š cmsy10ó  b> cmmi10ó 0e—rcmmi7óKñ`y cmr10óÙ“ Rcmr7óú±u cmex10ùÀ˜ßßßßßß