投稿者:SECOND
投稿日:2011年10月18日(火)02時54分18秒
|
|
|
!4)自己相似写像で描く、立体と展開図のアニメ-ション。 2011.10 Updated
!---------------------------------------------------------
!改訂版 正多面体(4,6,8,12,20)、切頂20面体( 32面体・フラーレン・サッカーボール)
! <ドラッグ応答性の改善。 回る多面体を上下左右にドラッグしてみて下さい>
!1)どの方向へも、多面体の重心を中心に 回転し、
!2)又、その累積による応答変化も、無くした。
!3)左ボタンが離され、常時回転に戻るまでに、間を空けた。
!4)表示中の立体 → 右クリックで → その立体の平面展開図を表示する ようにした。
! 展開図のときに、右クリック すると、プログラム終了。
!5)アニメ速度が、パソコンの種類で変らないよう、周期偏差 積分の自動制御を付けた。
! ※構文の大幅な見直しと整理、6面体の追加。
OPTION ARITHMETIC NATIVE
SET TEXT JUSTIFY "center","half"
SET WINDOW -1.5, 1.5, -1.4, 1.6
DIM rotx(4,4), rotx2(4,4), Axys(4,4), shxyz(4,4), Abak(4,4)
DIM Vi(4), Vo(4), m(4,4), D3( 32+1, 0 TO 6+1, 3), msk(6, 0 TO 60), cg(6,3), D1(7,2)
DIM p3(0 TO 3, 2), p4(0 TO 4, 2), p5(0 TO 5, 2), p6(0 TO 6, 2)
!
CALL polygon(3, 1/2, ir3, p3) !正3角形, 中心(0,0)底辺(-1/2,-ir3)~(1/2,-ir3)
CALL polygon(4, 1/2, ir4, p4) !正4角形, 中心(0,0)底辺(-1/2,-ir4)~(1/2,-ir4)
CALL polygon(5, 1/6, ir5, p5) !正5角形, 中心(0,0)底辺(-1/6,-ir5)~(1/6,-ir5)
CALL polygon(6, 1/6, ir6, p6) !正6角形, 中心(0,0)底辺(-1/6,-ir6)~(1/6,-ir6)
SUB polygon(n, s, ir, p(,)) !n=角数, s=底辺/2, ir=内接円半径, p(,)=頂点座標
LET a=PI/n
LET r=s/SIN(a)
LET ir=r*COS(a)
FOR i=1 TO n
LET p(i,1)=r*COS((2*i-1)*a-PI/2)
LET p(i,2)=r*SIN((2*i-1)*a-PI/2)
NEXT i
END SUB
MAT rotx=IDN
MAT rotx2=IDN
LET Vi(4)=1
!
MAT Axys=IDN
LET Ax=-PI/3 !開始の常時回転軸( 画面垂直からのx軸回転)
LET opA=0.3 !回転体 開度の振幅
LET opS=0.95 !回転体 開度のバイアス
LET t0=TIME
DO
SET DRAW mode hidden
CLEAR
PLOT label,AT 0, 1.52:"左 click 一時停止、drag 手動回転。右 click 展開図。"
LET sq=0
LET sq0=0
SELECT CASE s
CASE 0 TO 1
LET item=1
CALL control_
CALL mat_rotx(rotx, op1*PI/4.305) !32面体 残部6角~残部6角 折り角
CALL mat_rotx(rotx2, op1*PI/4.815) ! 切頭部5角~残部6角 折り角
DRAW D32 WITH ROTATE(Az)*shxyz*Axys
IF s=0 THEN CALL priority(2) ELSE CALL priority(7)
CASE 2
LET item=2
CALL control_
CALL mat_rotx(rotx, op1*PI/4.305) !正20面体 3角~3角 折り角
DRAW D20 WITH ROTATE(Az)*shxyz*Axys
CALL priority(2)
CASE 3
LET item=3
CALL control_
CALL mat_rotx(rotx, op1*PI/2.8376) !正12面体 5角~5角 折り角
DRAW D12 WITH SCALE(1.9)*ROTATE(Az)*shxyz*Axys
CALL priority(2)
CASE 4
LET item=4
CALL control_
CALL mat_rotx(rotx, op1*PI/2.552) !正8面体 3角~3角 折り角
DRAW D20 WITH SCALE(1.4)*ROTATE(Az)*shxyz*Axys
CALL priority(2)
CASE 5
LET item=5
CALL control_
CALL mat_rotx(rotx, op1*PI/2) !正6面体 4角~4角 折り角
DRAW D06 WITH ROTATE(Az)*shxyz*Axys
CALL priority(2)
CASE 6
LET item=6
CALL control_
CALL mat_rotx(rotx, op1*PI/1.644) !正4面体 3角~3角 折り角
DRAW D20 WITH SCALE(1.5)*ROTATE(Az)*shxyz*Axys
CALL priority(2)
END SELECT
SET DRAW mode explicit
!----------------------
IF mlb=0 AND DEL=0 THEN
LET Az=Az-PI/64
LET sx=sx+PI/48
IF 2*PI<=sx THEN
LET sx=0
LET s=MOD(s+1, 7)
LET flt=0
END IF
LET op1=MIN(MAX( opA*COS(sx)+opS ,0),1)
ELSEIF mlb=1 THEN
LET DEL=7 !「左 click 一時停止」解除から再開までの 遅延回数
ELSE
LET DEL=DEL-1
END IF
!--------------------
IF msk(item,0)=0 THEN !各item は初回、標準 折り角 op1=1 で採取画 位置を → msk(item,1~sq0)
LET msk(item,0)=1 !← 完了マーク。以降 msk(,) を マスク にして画を取捨。
MAT Axys=Abak
END IF
!-----------
LET bmrb=mrb
mouse poll mx,my,mlb,mrb
!------------
WAIT DELAY t2 !t2:制御出力の、休止秒。
LET t1=TIME !t1:前の周期の終り。※TIME は 約.05秒毎の、更新。P3-500MHz 98SE
IF t1< t0 THEN LET t0=t0-86400
LET t2=t2+(.08-t1+t0)/20 !設定周期.08秒-検出周期(t1-t0)=偏差 →t2( 積分 Gain=1/20 )
! PRINT USING"#.### #.###":t2,t1-t0 !t2:制御_休止秒, t1-t0:検出周期。---debug
LET t0=t1 !t0:次の周期の始め= 前の周期の終り
!--------------debug---
IF sqb<>sq THEN
PRINT USING"## ### #.###":sq,sq0,t2 !sq:採取画数, sq0:写像_全画数, t2:制御_休止秒
LET sqb=sq
END IF
LOOP UNTIL opAbak>0 AND bmrb=0 AND mrb=1
SUB flatx(s0,za,x0,y0,hw)
IF s=s0 THEN
IF opAbak=0 THEN
SET WINDOW x0-hw,x0+hw,y0-hw,y0+hw
LET opAbak=opA
LET opSbak=opS
LET opA=.525 !平面図 開度の振幅
LET opS=.475 !平面図 開度のバイアス
MAT Abak=Axys
!LET sx=0
END IF
MAT Axys=IDN
LET Az=za
DRAW grid WITH ROTATE(Az)
PLOT label,AT x0-.48*hw, y0+.95*hw:"左 click 一時停止。右 click 終了。"
END IF
END SUB
SUB control_
IF flt=1 THEN
CALL flatx( 0,-PI/6, -.57,-1.5, 2.4) !(s0,za,x0,y0,hw) !32 平面展開図セットアップ
CALL flatx( 1,-PI/6, -.57,-1.5, 2.4) !(s0,za,x0,y0,hw) !32 〃
CALL flatx( 2, PI/12, -1.28,-1.98, 2.9) !(s0,za,x0,y0,hw) !20 〃
CALL flatx( 3, PI/.78, -2.06,-2.32, 2.95) !(s0,za,x0,y0,hw) !12 〃
CALL flatx( 4,-PI/1.71,-1.43,-1.42, 2.3) !(s0,za,x0,y0,hw) ! 8 〃
CALL flatx( 5,-PI/2, -1.5,-1.0, 2.1) !(s0,za,x0,y0,hw) ! 6 〃
CALL flatx( 6,-PI/1.17, -.91,-.688, 1.7) !(s0,za,x0,y0,hw) ! 4 〃
EXIT SUB
ELSEIF 0< opAbak THEN
SET WINDOW -1.5, 1.5, -1.4, 1.6
LET opA=opAbak
LET opS=opSbak
MAT Axys=Abak
LET opAbak=0
END IF
IF msk(item,0)=0 THEN
!-----initial setup
MAT Abak=Axys
MAT Axys=IDN
MAT shxyz=IDN
LET op1=1 !各item 初回を、op1=1 (標準 折り角)に強制。
ELSE
IF bmrb=0 AND mrb=1 THEN !平面図の開始 (右クリックの Leading Edge.)
LET flt=1
LET sx=0
EXIT SUB
END IF
!-----click_drag-----
CALL mat_shxyz( cg(item,1),cg(item,2),cg(item,3)) !重心を原点へ移動する行列 shxyz 作成
IF mlb=1 THEN
LET Ax= -(my-mybak)*PI/2 !ドラッグ方向から、軸方向と回転量
LET Ay= +(mx-mxbak)*PI/2
END IF
LET mxbak=mx
LET mybak=my
!-----
LET ar0=SQR(Ax^2+Ay^2) !回転の角度(∝マウス・ドラッグの長さ)
IF ar0<>0 THEN
LET DIRar0=ANGLE(Ax,Ay) !軸の角度
CALL mat_rotx(rotx, ar0)
MAT Axys=Axys*ROTATE(-DIRar0)*rotx*ROTATE(DIRar0) !ドラッグ累積 (方向,回転)
LET Ax=0
LET Ay=0
END IF !with ~~*shxyz*Axys の順序で使用。
END IF
END SUB
SUB priority( flg) !paint flg( 7= 5_6_mono, Others= color)
IF msk(item,0)=0 THEN
!-----initial setup
CALL centerG !初回は、多面体 重心計算のみ、描画なし。
ELSE
FOR j=1 TO sq !z 最小(奥) から描く。
LET z=1e9
FOR i=1 TO sq
IF D3(i,0,3)< z THEN
LET z=D3(i,0,3)
LET ib=i
END IF
NEXT i
LET D3(ib,0,3)=1e9
IF flg=7 THEN LET c=6-D3(ib,7,1) ELSE LET c=ib+1 !サッカーボール(flg=7)、5角(c=1),6角(c=0)
SET AREA COLOR c !各面の色
ASK COLOR MIX(c) r,g,b
IF .3*r+.59*g+.11*b< .5 THEN SET TEXT COLOR 0 ELSE SET TEXT COLOR 1 !明るさに 対比する文字色
FOR i=1 TO D3(ib,7,1)
LET D1(i,1)=D3(ib,i,1)
LET D1(i,2)=D3(ib,i,2)
NEXT i
LET D1(i,1)=D3(ib,1,1)
LET D1(i,2)=D3(ib,1,2)
MAT PLOT AREA ,LIMIT i:D1
MAT PLOT LINES ,LIMIT i:D1
PLOT label,AT D3(ib,0,1),D3(ib,0,2):STR$(ib)
NEXT j
SET TEXT COLOR 1
END IF
END SUB
SUB centerG !cg(item,1~3) …各多面体の重心座標(x,y,z)
LET cg(item,1)=0
LET cg(item,2)=0
LET cg(item,3)=0
FOR i=1 TO sq
LET cg(item,1)=cg(item,1)+D3(i,0,1) !D3(i,0,1~3) …各面の重心座標(x,y,z)
LET cg(item,2)=cg(item,2)+D3(i,0,2)
LET cg(item,3)=cg(item,3)+D3(i,0,3)
NEXT i
LET cg(item,1)=cg(item,1)/sq
LET cg(item,2)=cg(item,2)/sq
LET cg(item,3)=cg(item,3)/sq
END SUB
PICTURE getpos(n, p(,)) !return with ・・・ 採取画 msk(item,sq0)=1, 重複画 msk(item,sq0)=0
LET sq0=sq0+1 !呼出し 順番
IF msk(item,0)=1 AND msk(item,sq0)=0 THEN EXIT PICTURE
LET sq=sq+1 !採取画 順番
MAT m=TRANSFORM
FOR j=0 TO n !各面の、0=重心 1~n=頂点
LET Vi(1)=p(j,1)
LET Vi(2)=p(j,2)
MAT Vo=Vi*m
LET D3(sq,j,1)=Vo(1)
LET D3(sq,j,2)=Vo(2)
LET D3(sq,j,3)=Vo(3)
NEXT j
LET D3(sq,7,1)=n
IF msk(item,0)=1 THEN EXIT PICTURE
FOR i=1 TO sq-1
IF (D3(i,0,1)-D3(sq,0,1))^2+(D3(i,0,2)-D3(sq,0,2))^2+(D3(i,0,3)-D3(sq,0,3))^2< .05 THEN EXIT FOR
NEXT i
IF sq<=i THEN LET msk(item,sq0)=1 ELSE LET sq=sq-1 !採取画 位置の記憶と、重複画の除去
END PICTURE
PICTURE D32
DRAW getpos(6, p6) ! 基6角
IF msk(item,sq0)=0 THEN EXIT PICTURE
DRAW getpos(5, p5) WITH SHIFT(0,ir5)*rotx2*SHIFT(0,ir6) ! 上5角
IF msk(item,sq0)=0 THEN EXIT PICTURE
DRAW getpos(5, p5) WITH SHIFT(0,ir5)*rotx2*SHIFT(0,ir6)*ROTATE(-PI*2/3) !右下5角
DRAW D32 WITH SHIFT(0,ir6)*rotx*SHIFT(0,ir6)*ROTATE(-PI/3) !右上6角
DRAW D32 WITH SHIFT(0,ir6)*rotx*SHIFT(0,ir6)*ROTATE(PI/3) !左上6角
END PICTURE
PICTURE D20
DRAW getpos(3, p3) ! 基3角
IF msk(item,sq0)=0 THEN EXIT PICTURE
DRAW D20 WITH SHIFT(0,ir3)*rotx*SHIFT(0,ir3)*ROTATE(-PI/3) !右上3角
DRAW D20 WITH SHIFT(0,ir3)*rotx*SHIFT(0,ir3)*ROTATE(PI/3) !左上3角
END PICTURE
PICTURE D12
DRAW getpos(5, p5) ! 基5角
IF msk(item,sq0)=0 THEN EXIT PICTURE
DRAW D12 WITH SHIFT(0,ir5)*rotx*SHIFT(0,ir5)*ROTATE(-.2*PI) !右上5角
DRAW D12 WITH SHIFT(0,ir5)*rotx*SHIFT(0,ir5)*ROTATE(.2*PI) !左上5角
DRAW D12 WITH SHIFT(0,ir5)*rotx*SHIFT(0,ir5)*ROTATE(-.6*PI) !右下5角
END PICTURE
PICTURE D06
DRAW getpos(4, p4) ! 基4角
IF msk(item,sq0)=0 THEN EXIT PICTURE
DRAW D06 WITH SHIFT(0,ir4)*rotx*SHIFT(0,ir4)*ROTATE(-PI/2) ! 右4角
DRAW D06 WITH SHIFT(0,ir4)*rotx*SHIFT(0,ir4) ! 上4角
END PICTURE
!---------------------------------
! x軸で 回転する行列 → 配列引数
!(x,y,z,1)| 1, 0, 0, 0 |
! | 0, cos(a), sin(a), 0 |
! | 0,-sin(a), cos(a), 0 |
! | 0, 0, 0, 1 |
!---------------------------------
SUB mat_rotx(m(,), a)
LET m(2,2)=COS(a)
LET m(3,2)=-SIN(a)
LET m(2,3)=SIN(a)
LET m(3,3)=COS(a) !他の要素は、呼出し側で管理
END SUB
!-----------------------------
! 平行移動。(sx,sy,sz) → 原点
!(x,y,z,1)| 1, 0, 0, 0 |
! | 0, 1, 0, 0 |
! | 0, 0, 1, 0 |
! | -sx,-sy,-sz, 1 |
!-----------------------------
SUB mat_shxyz( sx,sy,sz)
LET shxyz(4,1)=-sx
LET shxyz(4,2)=-sy
LET shxyz(4,3)=-sz !他の要素は、呼出し側で管理
END SUB
END
|
|
|