立体図形と立体図

 投稿者:山中和義  投稿日:2011年 6月 4日(土)10時19分24秒
  FullBASICでは、3D仕様の文・関数がありません。
2Dの絵定義を、副プログラムなどを使って、擬似的に拡張することを考えてみました。


●稜線モデル

!立体図の表現

PUBLIC NUMERIC T(4,4) !変換行列 ※TRANSFORM関数の値に相当
MAT T=IDN
PUBLIC NUMERIC D(4,4) !投影法の変換行列
MAT D=IDN
PUBLIC NUMERIC XX(20),YY(20) !描画する点列

DIM W(4,4),WW(4,4) !DRAW pict WITH ~ 算出用
DIM TT(4,4) !スタック領域
!---


!家の頂点の定義(ワイヤーフレーム)

DATA 8
DATA 80,50,100 !0
DATA  0,50,100 !1
DATA  0, 0,100 !2
DATA 80, 0,100 !3
DATA 80, 0,  0 !4
DATA 80,50,  0 !5
DATA 80,50,100 !6
DATA 80, 0,100 !7

DATA 4
DATA  0,50,100 !8
DATA  0,50,  0 !9
DATA  0, 0,  0 !10
DATA  0, 0,100 !11

DATA 2
DATA  0,50,  0 !12
DATA 80,50,  0 !13

DATA 2
DATA  0, 0,  0 !14
DATA 80, 0,  0 !15

DATA 3
DATA  0,50,100 !16
DATA 40,80,100 !17
DATA 80,50,100 !18

DATA 3
DATA  0,50,  0 !19
DATA 40,80,  0 !20
DATA 80,50,  0 !21

DATA 2
DATA 40,80,100 !22
DATA 40,80,  0 !23

DATA 8
DATA 50,72,100 !24
DATA 50,90,100 !25
DATA 65,90,100 !26
DATA 65,61,100 !27
DATA 65,61, 80 !28
DATA 65,90, 80 !29
DATA 50,90, 80 !30
DATA 50,90,100 !31

DATA 2
DATA 65,90,100 !32
DATA 65,90, 80 !33

DATA 3
DATA 50,90, 80 !34
DATA 50,72, 80 !35
DATA 65,61, 80 !36

DATA 2
DATA 50,72,100 !37
DATA 50,72, 80 !38

DATA -1 !EOF


!--- SET PROJECTION WINDOW x1,x2,y1,y2
SET WINDOW -120,120,-120,120 !投影面の表示領域 ※
!---

!--- SET PROJECTION MODE isometric
!!CALL orthographic(1, 40,50,50, D)
!!CALL axonometric(RAD(20),RAD(-45),RAD(0), D)
CALL isometric(D)
!!CALL cabinet(D)
!!CALL perspective2p(RAD(-25),0,50,0,-300, D)
!---


!--- DRAW house
CALL house
!---


!--- PICTURE house
SUB house
   local TT(4,4) !スタック領域
   !---

   !--- DRAW D3GRID(150,100,150) !ローカル座標
   CALL D3GRID(150,100,150)
   !---

   READ N !データ列を読み込む
   DO WHILE N>0 !最後なら、終了
      FOR i=1 TO N
         READ x,y,z

         !--- PLOT LINES: x,y,z; !折れ線
         CALL L2WV(1, x,y,z)
         PLOT LINES: XX(1),YY(1);
         !---
      NEXT i
      !--- PLOT LINES
      PLOT LINES
      !---

      READ N !次へ
   LOOP

   !--- END PICTURE
END SUB
!---


END


!立体図の表現
!
!投影法と投影図
! 透視投影法(Perspective projection、中心投影法)
!  1点投影法
!  2点投影法
!  3点投影法
! 平行投影法(Parallel projection)
!  垂直(直角)投影法
!   正投影法(Orthographic projection) → 正投影図(三面図)
!    第一角法
!    第三角法
!   軸測投影法(アクソノメトリック投影法、Axonometric projection)
!    等角投影法(アイソメトリック投影法、Isometric projection、等軸測投影法)→ 等角図(アイソメトリック図)
!    二等角投影法(ダイメトリック投影法、Dimetric projection)
!    不等角投影法(トリメトリック投影法、Trimetric projection)
!  斜投影法(Oblique projection)
!   → キャビネット図、カバリエ図


EXTERNAL SUB L2WV(k, x,y,z) !座標変換 (x' y' z' w')=(x y z 1)*T[n]* … *T[3]*T[2]*T[1]*T[0]
DIM P(4) !同次座標系

LET P(1)=x
LET P(2)=y
LET P(3)=z
LET P(4)=1 !w

MAT P=P*T !変換
MAT P=P*D

LET XX(k)=P(1)/P(4) !(x'[k]/w', y'[k]/w')
LET YY(k)=P(2)/P(4)
END SUB


EXTERNAL SUB D3ROTATE(a,Vx,Vy,Vz, M(,)) !任意軸(位置ベクトル(Vx,Vy,Vz) )まわりの回転
LET l=SQR(Vx*Vx+Vy*Vy+Vz*Vz) !単位ベクトルへ
LET x=Vx/l
LET y=Vy/l
LET z=Vz/l

MAT M=ZER
LET c=COS(a)
LET s=SIN(a)
LET M(1,1)=x*x*(1-c)+c
LET M(1,2)=x*y*(1-c)+z*s
LET M(1,3)=z*x*(1-c)-y*s
LET M(2,1)=x*y*(1-c)-z*s
LET M(2,2)=y*y*(1-c)+c
LET M(2,3)=y*z*(1-c)+x*s
LET M(3,1)=z*x*(1-c)+y*s
LET M(3,2)=y*z*(1-c)-x*s
LET M(3,3)=z*z*(1-c)+c
LET M(4,4)=1
END SUB


EXTERNAL SUB D3SCALE(a,b,c, M(,)) !拡大・縮小
MAT M=IDN
LET M(1,1)=a
LET M(2,2)=b
LET M(3,3)=c
END SUB


EXTERNAL SUB D3SHEAR(a,b,c, M(,)) !傾ける(せん断)
MAT M=IDN
LET M(1,2)=TAN(a)
LET M(1,3)=TAN(a)
LET M(2,1)=TAN(b)
LET M(2,3)=TAN(b)
LET M(3,1)=TAN(c)
LET M(3,2)=TAN(c)
END SUB


EXTERNAL SUB D3SHIFT(l,m,n, A(,)) !平行移動
MAT A=IDN
LET A(4,1)=l
LET A(4,2)=m
LET A(4,3)=n
END SUB


!共通ルーチン

EXTERNAL SUB D3GRID(x,y,z) !XYZ座標軸を表示する
ASK LINE COLOR c1 !save it
ASK TEXT COLOR c2

SET LINE COLOR 4 !X軸
!--- PLOT LINES: 0,0,0; x,0,0
CALL L2WV(1, 0,0,0)
CALL L2WV(2, x,0,0)
PLOT LINES: XX(1),YY(1); XX(2),YY(2) !線分
!---

!--- PLOT TEXT ,AT x,0,0: "X"
SET TEXT COLOR 4
PLOT TEXT ,AT XX(2),YY(2): "X"
!---

SET LINE COLOR 3 !Y軸
!--- PLOT LINES: 0,0,0; 0,y,0
CALL L2WV(1, 0,0,0)
CALL L2WV(2, 0,y,0)
PLOT LINES: XX(1),YY(1); XX(2),YY(2) !線分
!---

!--- PLOT TEXT ,AT 0,y,0: "Y"
SET TEXT COLOR 3
PLOT TEXT ,AT XX(2),YY(2): "Y"
!---

SET LINE COLOR 2 !Z軸
!--- PLOT LINES: 0,0,0; 0,0,z
CALL L2WV(1, 0,0,0)
CALL L2WV(2, 0,0,z)
PLOT LINES: XX(1),YY(1); XX(2),YY(2) !線分
!---

!--- PLOT TEXT ,AT 0,0,z: "Z"
SET TEXT COLOR 2
PLOT TEXT ,AT XX(2),YY(2): "Z"
!---

SET LINE COLOR c1 !restore it
SET TEXT COLOR c2
END SUB



!投影図

!右手座標系
! X軸…親指、Y軸…人差し指、Z軸…中指、指のさす方向が正(プラス)。
!  右手系  Y
!       │
!       ・─X
!      /
!     Z    X軸…右方向、Y軸…高さ、Z軸…奥行き。(XZ平面は床)

EXTERNAL SUB orthographic(i, l,m,n, W(,)) !正投影図(三面図) ※第三角法
DIM WW(4,4)
CALL D3SHIFT(-l,-m,-n, W) !図面の中心 ※(l,m,n)→(0,0)

SELECT CASE i
CASE 0 !正面図
!nop
CASE 1 !平面図
   CALL D3ROTATE(RAD(90),1,0,0, WW) !X軸
   MAT W=W*WW
CASE 2 !右側面図
   CALL D3ROTATE(RAD(-90),0,1,0, WW) !Y軸
   MAT W=W*WW
CASE ELSE
   PRINT "引数が不正です。"
   STOP
END SELECT
END SUB


EXTERNAL SUB axonometric(ax,ay,az, W(,)) !軸測投影図
DIM WW(4,4)
MAT W=IDN
CALL D3ROTATE(ay,0,1,0, WW) !Y軸
MAT W=W*WW
CALL D3ROTATE(ax,1,0,0, WW) !X軸
MAT W=W*WW
CALL D3ROTATE(az,0,0,1, WW) !Z軸
MAT W=W*WW
END SUB


EXTERNAL SUB isometric(W(,)) !等角投影(アイソメトリック)図
DIM WW(4,4)
MAT W=IDN
CALL D3ROTATE(RAD(-45),0,1,0, WW) !Y軸 ※方位角45度
MAT W=W*WW
CALL D3ROTATE(ATN(SQR(2)/2),1,0,0, WW) !X軸 ※天頂角54.7356度
MAT W=W*WW
END SUB


EXTERNAL SUB cabinet(W(,)) !キャビネット図
DIM WW(4,4)
MAT W=IDN
CALL D3SCALE(1,1,SQR(2)/4, WW) !Z軸を1/2
MAT W=W*WW
CALL D3SHEAR(RAD(0),RAD(0),RAD(-45), WW) !Z軸で傾ける
MAT W=W*WW
END SUB


EXTERNAL SUB perspective2p(ay, l,m,n, vp, W(,)) !2点透視投影図
DIM WW(4,4)
MAT W=IDN

CALL D3SHIFT(-l,-m,-n, WW) !平行移動 ※図面の中心 (l,m,n)→(0,0)
MAT W=W*WW

CALL D3ROTATE(ay,0,1,0, WW) !Y軸
MAT W=W*WW

!投影の中心(消失点)を(0,0,-VP)、投影面z=0(XY平面)とする。

MAT WW=IDN !ビュー変換
LET WW(4,3)=vp !視点を原点にする(平行移動)
MAT W=W*WW

MAT WW=ZER !透視投影
LET WW(1,1)=vp
LET WW(2,2)=vp
LET WW(3,4)=1
MAT W=W*WW
END SUB



●回転体モデル

!立体図の表現

PUBLIC NUMERIC T(4,4) !変換行列 ※TRANSFORM関数の値に相当
MAT T=IDN
PUBLIC NUMERIC D(4,4) !投影法の変換行列
MAT D=IDN
PUBLIC NUMERIC XX(20),YY(20) !描画する点列

DIM W(4,4),WW(4,4) !DRAW pict WITH ~ 算出用
DIM TT(4,4) !スタック領域
!---


!回転体モデル

!ワイングラスの頂点の定義(ワイヤーフレーム)

DATA 8
DATA 180,100 !高さ(0,y,0)、半径(r*cosθ,0,r*sinθ)
DATA 140, 55
DATA 100, 10
DATA  60, 10
DATA  20, 10
DATA  10, 50
DATA   4, 80
DATA   0, 80


!--- SET PROJECTION WINDOW x1,x2,y1,y2
SET WINDOW -150,150,-150,150 !投影面の表示領域 ※
!---

!--- SET PROJECTION MODE isometric
CALL isometric(D)
!!CALL perspective2p(RAD(-35),10,-30,0,-500, D)
!---



!--- DRAW model WITH D3ROTATEX(RAD(10))*D3SHIFT(0,-80,-20)
MAT TT=T !save it
MAT W=IDN
CALL D3ROTATE(RAD(10),1,0,0, WW)
MAT W=W*WW
CALL D3SHIFT(0,-80,-20, WW)
MAT W=W*WW
MAT T=W *T !変換行列を算出する
CALL model
MAT T=TT !restore it
!---


!--- PICTURE model
SUB model
   local TT(4,4) !スタック領域
   !---

   !--- DRAW D3GRID(150,260,150) !ローカル座標
   CALL D3GRID(150,260,150)
   !---

   READ N !データ列を読み込む
   FOR i=1 TO N
      READ y,r

      FOR a=0 TO 360 STEP 5 !Y軸まわりに回転させる
         LET th=RAD(a)

         !--- PLOT LINES: r*COS(th),y,r*SIN(th); !折れ線による近似で円を描く
         CALL L2WV(1, r*COS(th),y,r*SIN(th))
         PLOT LINES: XX(1),YY(1);
         !---
      NEXT a
      !--- PLOT LINES
      PLOT LINES
      !---

      IF i>1 THEN
         FOR a=0 TO 360 STEP 60 !稜線
            LET th=RAD(a)

            !--- PLOT LINES: r0*COS(th),y0,r0*SIN(th); r*COS(th),y,r*SIN(th)
            CALL L2WV(1, r0*COS(th),y0,r0*SIN(th))
            CALL L2WV(2, r*COS(th),y,r*SIN(th))
            PLOT LINES: XX(1),YY(1); XX(2),YY(2)
            !---
         NEXT a
      END IF

      LET y0=y !次へ
      LET r0=r
   NEXT i

   !--- END PICTURE
END SUB
!---


END


※サブルーチン部分は省略しています。
 

Re: 立体図形と立体図

 投稿者:山中和義  投稿日:2011年 6月 5日(日)10時52分53秒
  > No.1574[元記事へ]

つづき

●展開図から立体へのアニメーション

!展開図から立体へ

PUBLIC NUMERIC T(4,4) !変換行列 ※TRANSFORM関数の値に相当
MAT T=IDN
PUBLIC NUMERIC D(4,4) !投影法の変換行列
MAT D=IDN
PUBLIC NUMERIC XX(20),YY(20) !描画する点列

DIM W(4,4),WW(4,4) !DRAW pict WITH ~ 算出用
DIM TT(4,4) !スタック領域
!---



!--- SET PROJECTION WINDOW x1,x2,y1,y2
SET WINDOW -150,150,-150,150 !投影面の表示領域 ※
!---

!--- SET PROJECTION MODE isometric
CALL isometric(D)
!!CALL perspective2p(RAD(-25),10,50,0,-400, D)
!---



!立方体の展開図
!  □     1
! □□□□  2345
!  □     6

FOR a=0 TO 90 !折り曲げる
   CLEAR

   !--- DRAW model(a) WITH D3SCALE(100) !立方体
   MAT TT=T !save it
   MAT W=IDN
   CALL D3SCALE(100,100,100, WW)
   MAT W=W*WW
   MAT T=W *T !変換行列を算出する
   CALL model(a)
   MAT T=TT !restore it
   !---

   WAIT DELAY 0.2 !5fps
NEXT a


!--- PICTURE model(a) !立方体を描く
SUB model(a)
   local TT(4,4) !スタック領域
   !---

   !--- DRAW face
   CALL face !面3を描く
   !---


   !面3に接合された面を描く

   !--- DRAW face WITH D3SHIFT(0,0,-1)*D3ROTATEX(RAD(a)) !面1
   MAT TT=T !save it
   MAT W=IDN
   CALL D3SHIFT(0,0,-1, WW)
   MAT W=W*WW
   CALL D3ROTATE(RAD(a),1,0,0, WW)
   MAT W=W*WW
   MAT T=W *T !変換行列を算出する
   CALL face
   MAT T=TT !restore it
   !---

   !--- DRAW face WITH D2SHIFT(-1,0,0)*D3ROTATEZ(RAD(-a)) !面2
   MAT TT=T !save it
   MAT W=IDN
   CALL D3SHIFT(-1,0,0, WW)
   MAT W=W*WW
   CALL D3ROTATE(RAD(-a),0,0,1, WW)
   MAT W=W*WW
   MAT T=W *T !変換行列を算出する
   CALL face
   MAT T=TT !restore it
   !---

   !--- DRAW face4(a) WITH D3ROTATEZ(RAD(a))*D3SHIFT(1,0,0) !面4
   MAT TT=T !save it
   MAT W=IDN
   CALL D3ROTATE(RAD(a),0,0,1, WW)
   MAT W=W*WW
   CALL D3SHIFT(1,0,0, WW)
   MAT W=W*WW
   MAT T=W *T !変換行列を算出する
   CALL face4(a)
   MAT T=TT !restore it
   !---

   !--- DRAW face WITH D3ROTATEX(RAD(-a))*D3SHIFT(0,0,1) !面6
   MAT TT=T !save it
   MAT W=IDN
   CALL D3ROTATE(RAD(-a),1,0,0, WW)
   MAT W=W*WW
   CALL D3SHIFT(0,0,1, WW)
   MAT W=W*WW
   MAT T=W *T !変換行列を算出する
   CALL face
   MAT T=TT !restore it
   !---

   !--- END PICTURE
END SUB
!---


!--- PICTURE face4(a) !面4を描く
SUB face4(a)
   local TT(4,4) !スタック領域
   !---

   !--- DRAW face
   CALL face !面4を描く
   !---

   !面4に接合された面を描く
   !--- DRAW face WITH D3ROTATEZ(RAD(a))*D3SHIFT(1,0,0) !面5
   MAT TT=T !save it
   MAT W=IDN
   CALL D3ROTATE(RAD(a),0,0,1, WW)
   MAT W=W*WW
   CALL D3SHIFT(1,0,0, WW)
   MAT W=W*WW
   MAT T=W *T !変換行列を算出する
   CALL face
   MAT T=TT !restore it
   !---

   !--- END PICTURE
END SUB
!---


!  右手系  Y
!       │  1
!       ・───X
!      /   /
!    1 /──
!    /
!   Z

!--- PICTURE face !xz平面上に正方形の面を描く
SUB face
   local TT(4,4) !スタック領域
   !---

   !--- PLOT LINES: 0,0,0; 0,0,1; 1,0,1; 1,0,0; 0,0,0 !正方形
   CALL L2WV(1, 0,0,0)
   CALL L2WV(2, 0,0,1)
   CALL L2WV(3, 1,0,1)
   CALL L2WV(4, 1,0,0)
   CALL L2WV(5, 0,0,0)
   MAT PLOT LINES, LIMIT 5: XX,YY !折れ線
   !---

   !--- END PICTURE
END SUB
!---


END

※以降のサブルーチン部分は省略します。
 

戻る