3D曲線 を、マウスで、ひっくり返す

 投稿者:SECOND  投稿日:2009年 6月27日(土)18時52分20秒
  ! 3D曲線 を、マウスで、ひっくり返す。
! サンプルに、見づらい Hodgkin-Huxley 方程式 のグラフを、使用。
!-------------------------------
OPTION ARITHMETIC NATIVE
OPTION ANGLE DEGREES
DIM pV(4), P3D(4,4), LH(6), copy(0 TO 100000, 3)
DIM rotx(4,4), shxyzM(4,4), shxyzP(4,4)
MAT rotx=IDN
MAT shxyzM=IDN
MAT shxyzP=IDN
!
!-----
LET t$="ヤリイカの巨大神経(カオス)"
LET t2$="Hodgkin-Huxley ホジキン-ハクスレイ方程式 のストレンジ アトラクタ"

DEF I(t)= I0+A*SIN( 360*f*t ) ! 膜電流 +外部入力

LET t3$="膜電位 V →( X)"
! (d V/dt)= I(t)-120*m^3*h*(V-115) -40*n^4*(V+12) -.24*(V-10.613)
LET t4$="ナトリウム 活性化変数( 0< m< 1) →( Y)"
! (d m/dt)= .1*(25-V)/(EXP((25-V)/10)-1)*(1-m) -4*EXP(-V/18)*m
LET t5$="ナトリウム不活性化変数( 0< h< 1) →( Z)"
! (d h/dt)= .07*EXP(-V/20)*(1-h) -1/(EXP((30-V)/10)+1)*h
!            カリウム活性化変数( 0< n< 1) →描画しない。
! (d n/dt)= .01*(10-V)/(EXP((10-V)/10)-1)*(1-n) -.125*EXP(-V/80)*n

SUB Dxyzn( kx,ky,kz,kn, x,y,z,n)
   LET kx= I(t)-120*y^3*z*(x-115) -40*n^4*(x+12) -.24*(x-10.613) ! (d V/dt)
   LET ky= .1*(25-x)/(EXP((25-x)/10)-1)*(1-y) -4*EXP(-x/18)*y    ! (d m/dt)
   LET kz= .07*EXP(-x/20)*(1-z) -1/(EXP((30-x)/10)+1)*z          ! (d h/dt)
   LET kn= .01*(10-x)/(EXP((10-x)/10)-1)*(1-n) -.125*EXP(-x/80)*n! (d n/dt)
END SUB

LET I0=20   !膜電流 パラメーター
LET A=40
LET f=.3000001
!
LET x=6.24  !初期値 x,y,z,n
LET y=.0761
LET z=.301
LET n=.519
LET dt=.05  !RungeKutta pitch time
LET t99=500 !RungeKutta close time
DATA -15,100, -.3,1, -.04,.45 !座標軸の両端座標 xL,xH, yL,yH, zL,zH
MAT READ LH
LET zox=35  !回転 旋回中心点 center へのオフセットxyz
LET zoy=.6
LET zoz=.2
!
LET Sx=1    !スケール倍率 Sx,Sy,Sz
LET Sy=50
LET Sz=200
LET xm=35   !画面中心 xm,ym
LET ym=35
LET hw=80   !画面幅/2 ±hw
!
LET ax=-75  !z軸をx軸で倒す開始角度
LET ay=0    !z軸をy軸で倒す開始角度
LET SS=0    !z軸 回転開始角度
LET ST= +5  !z軸 回転ステップ +:左回転 -:右回転
!
SET WINDOW xm-hw,xm+hw,ym-hw,ym+hw
CALL graph3D


!-----
SUB RungeKutta
   CALL Dxyzn( kx1,ky1,kz1,kn1, x,y,z,n)
   CALL Dxyzn( kx2,ky2,kz2,kn2, x+kx1*dt/2,y+ky1*dt/2,z+kz1*dt/2,n+kn1*dt/2)
   CALL Dxyzn( kx3,ky3,kz3,kn3, x+kx2*dt/2,y+ky2*dt/2,z+kz2*dt/2,n+kn2*dt/2)
   CALL Dxyzn( kx4,ky4,kz4,kn4, x+kx3*dt  ,y+ky3*dt  ,z+kz3*dt  ,n+kn3*dt  )
   LET x=x+(kx1+2*kx2+2*kx3+kx4)*dt/6
   LET y=y+(ky1+2*ky2+2*ky3+ky4)*dt/6
   LET z=z+(kz1+2*kz2+2*kz3+kz4)*dt/6
   LET n=n+(kn1+2*kn2+2*kn3+kn4)*dt/6
END SUB

SUB graph3D
! 回転 旋回中心点 center を 原点へ移動し、又、元へ戻す行列。
!(x,y,z,1)|      1,      0,      0, 0 |
!         |      0,      1,      0, 0 |
!         |      0,      0,      1, 0 |
!         |-zox*Sx,-zoy*Sy,-zoz*Sz, 1 |
   LET shxyzM(4,1)=-zox*Sx
   LET shxyzM(4,2)=-zoy*Sy
   LET shxyzM(4,3)=-zoz*Sz
   !
   !(x,y,z,1)|      1,      0,      0, 0 |
   !         |      0,      1,      0, 0 |
   !         |      0,      0,      1, 0 |
   !         | zox*Sx, zoy*Sy, zoz*Sz, 1 |
   LET shxyzP(4,1)=zox*Sx
   LET shxyzP(4,2)=zoy*Sy
   LET shxyzP(4,3)=zoz*Sz
   !
   LET az=SS
   CALL rot_panel
   !---3D 曲線、1回目で、3D原画 記録を撮る。
   LET ci=0
   FOR t=0 TO t99 STEP dt
      LET copy(ci,1)=x
      LET copy(ci,2)=y
      LET copy(ci,3)=z
      ! PRINT x;y;z;n ! データーを保存したい時。
      CALL line3D(x,y,z)
      CALL RungeKutta
      LET ci=ci+1
   NEXT t
   !----
   MOUSE POLL m_x,m_y,mlb,mrb
   LET mxbak=m_x
   LET mybak=m_y
   DO
      IF mlb=0 THEN LET az=MOD(az+ST,360) ! z軸で、1ステップ回す。
      SET DRAW mode hidden
      CALL rot_panel
      !---3D 曲線、2回目以降は、記録の再生で、高速描画。
      FOR ci=0 TO ci-1
         CALL line3D( copy(ci,1),copy(ci,2),copy(ci,3) )
      NEXT ci
      SET DRAW mode explicit
      !----
      MOUSE POLL m_x,m_y,mlb,mrb
      IF mlb=1 THEN
         LET ax=ax -(m_y-mybak)!/2 ! 変移方向は、+90度 回す。
         LET ay=ay +(m_x-mxbak)!/2
      END IF
      LET mxbak=m_x
      LET mybak=m_y
      ! WAIT DELAY 0.05
   LOOP UNTIL mrb=1
END SUB

SUB rot_panel
   LET ar0=SQR(ax^2+ay^2) ! 旋回角度
   IF ar0<>0 THEN LET DIRar0=ANGLE(ax,ay) ! 旋回軸の方向
   IF 180< ar0 THEN
      LET ax=(ar0-360)*COS(DIRar0)
      LET ay=(ar0-360)*SIN(DIRar0)
   END IF
   ! xy平面上、0度方向(x軸)を、軸として旋回する行列 rotx
   !(x,y,z,1)| 1,        0,        0, 0 |
   !         | 0, cos(ar0), sin(ar0), 0 |
   !         | 0,-sin(ar0), cos(ar0), 0 |
   !         | 0,        0,        0, 1 |
   LET rotx(2,2)=COS(ar0)
   LET rotx(3,2)=-SIN(ar0)
   LET rotx(2,3)=SIN(ar0)
   LET rotx(3,3)=COS(ar0)
   !
   MAT P3D= shxyzM*ROTATE(az-DIRar0)*rotx*ROTATE(DIRar0)*shxyzP !変形指示MAT
   !----
   CLEAR
   PLOT TEXT,AT xm-hw*.9,ym+hw*.90 :t2$
   PLOT TEXT,AT xm-hw*.9,ym+hw*.83 :t$
   PLOT TEXT,AT xm+hw*.1,ym+hw*.83,USING"Ax=####  Ay=####  Az=####":ax,ay,az
   PLOT TEXT,AT xm-hw*.9,ym-hw*.92 :t5$
   PLOT TEXT,AT xm-hw*.9,ym-hw*.99 :t4$& "  "& t3$ ! PEN-off
   !---
   IF ar0< 90 THEN SET AREA COLOR "cyan" ELSE SET AREA COLOR "black"
   DRAW disk WITH SCALE(15)*P3D ! 原点近傍、裏表 のマーカー1
   DRAW disk WITH SCALE(5)*SHIFT(zox*Sx,zoy*Sy)*P3D ! マーカー2
   CALL axes3D( zox,zoy,0, zox,zoy,zoz, "center" ) ! マーカー3
   !---座標軸
   CALL axes3D( LH(1),0,0, LH(2),0,0, STR$(LH(2))& "( X)" )
   CALL axes3D( 0,LH(3),0, 0,LH(4),0, STR$(LH(4))& "( Y)" )
   CALL axes3D( 0,0,LH(5), 0,0,LH(6), STR$(LH(6))& "( Z)" )
END SUB

SUB axes3D(x1,y1,z1, x2,y2,z2, a$ )
   CALL line3D(x1,y1,z1)
   CALL line3D(x2,y2,z2)
   PLOT TEXT,AT pV(1),pV(2) :a$ ! PEN-off
END SUB

SUB line3D(x,y,z)
   LET pV(1)=x*Sx  !描画目盛は、全方向等しくないと、回転で、形が保てない。
   LET pV(2)=y*Sy  !スケール Sx,Sy,Sz の違いは、入力の倍率として、行なう。
   LET pV(3)=z*Sz  !入力 z 座標は 出力 x,y に反映。出力zは 描画不可。
   LET pV(4)=1 ! shxyzM …shxyzP で必要。
   MAT pV=pV*P3D
   PLOT LINES: pV(1),pV(2); ! PEN-on
END SUB

END

!-----
!1)画面に写るxyz軸の、z軸に平行で、
!  center を通る軸で、常時回転。
!
!2)マウス 左ボタン押下で 一時停止、離すと再開。
!      右ボタン押下で 終了。
!
!3)左ボタン押下のまま、引きずると、
!  xy平面に平行で、center を通る
!  任意な方向の軸で、全体が旋回する。
!
! (z軸 先端を、ドラッグする感じ。)
!
!※ここまで 貼り付けて、実行時のヘルプにする。
 

戻る