■n次元楕円をm次元空間に投影する(その5)

 (その4)では,任意の超平面
  α1X1+α2X2=0
と超楕円体
  x’Hx=1
の交わりをm次元空間へ投影すると,m次元楕円体
  X1’[A−Bα2~α1−(α2~α1)’C+(α2~α1)’Dα2~α1]X1=1
が得られることがわかりましたが,m次元空間に投影するとはいっても,最終的に表示するのはモニタ画面上ですから平面です.したがって,(i,j)平面上にm次元楕円体を描く手順が必要とされます.
 
 その際,
  (1)行列:M=[A−Bα2~α1−(α2~α1)’C+(α2~α1)’Dα2~α1]
を求める
  (2)Mの小行列Mijの固有値・固有ベクトルを求める
  (3)軸の長さを1/√λとする
とすると,m次元楕円体の(i,j)平面での切り口が描かれてしまいます.
 
 問題点は何かを意識していないと肝心なところがわからないので,くどくど説明しますが,いま求められているのは,m次元楕円の2次元平面での切り口ではなく,m次元楕円体を2次元平面に正射影することです.
 
 その計算手順は,以下のようになります.
  (1)行列:M=[A−Bα2~α1−(α2~α1)’C+(α2~α1)’Dα2~α1]を求める
  (2)Mの逆行列Wを求める
  (3)逆行列の小行列Wijの固有値・固有ベクトルを求める
  (4)軸の長さを√λとする
 
 なお,3次元空間に投影する際は,
  (3)逆行列の小行列Wijkの固有値・固有ベクトルを求める
ことになります.
 
 ここで,(1)の前に
  (a)超平面のパラメータmとα=[α1,α2]を定める
  (b)ムーア・ペンローズ逆行列
  α2~=α2’α2(α2’α2α2’α2)^(-1)α2’
あるいは
  α2~=α2’(α2α2’)^(-1)α2(α2’α2)^(-1)α2’
を求める
  (c)α2~α1を求める
という手順のサブルーチンを組めば,実用的なプログラムを作成することが可能になるはずです.早速作成してみましょう.
 
===================================
 
【2】プログラム
 
1000 '
1010 ' **** robot-arm control ****
1020 '            2002/01/18 (C) サトウ イクロウ
1030 SCREEN 3,0:CONSOLE ,,0,1
1040 CLS 3:WIDTH 80,25:COLOR 6
1050 GOSUB *INITIALIZE
1060 '
1070 GOSUB *HYPERPLANE
1080 'GOSUB *HYPER.CONTOUR
1090 'GOSUB *HYPER.SECTION
1100 GOSUB *ELLIPSOID:GOTO 1230
1110 '
1120 STAGE$="1":' [contour]
1130 'GOSUB *HYPERPLANE
1140 GOSUB *HYPER.CONTOUR
1150 'GOSUB *ELLIPSOID.WF
1160 GOSUB *ELLIPSOID3
1170 '
1180 STAGE$="2":' [section]
1190 'GOSUB *HYPERPLANE
1200 GOSUB *HYPER.SECTION
1210 'GOSUB *ELLIPSOID.WF
1220 GOSUB *ELLIPSOID3
1230 '
1240 CLS 3
1250 END
1260 '
1270 ' *** 初期設定 ***
1280 '
1290 *INITIALIZE:
1300 RX=.7:RY=.8:BOX=1:KIND=1:POWER=0
1310 IX=.7:IY=.8:MARK=1:CLR=2:DRAW.COLOR=4
1320 TXT.COLOR=6:GRP.COLOR=5:REF.COLOR=6
1330 SCALE.KIND=1:PLOT=1
1340 PI=3.14159
1350 JX=.709:JY=1
1360 RX=IX*JX:RY=IY*JY
1370 '
1380 M=6:M0=M
1390 N1=7
1400 '
1410 MMAX=10:NMAX=10
1420 DIM V(MMAX)
1430 DIM JACOBI(MMAX,NMAX)
1440 DIM AZ(MMAX,MMAX),BZ(MMAX,MMAX)
1450 DIM HESSE(MMAX,MMAX)
1460 DIM COV(MMAX,MMAX)
1470 DIM VO(MMAX),VL(MMAX)
1480 DIM VD(MMAX),VS(MMAX)
1490 DIM UNIT$(MMAX)
1500 '
1510 DIM EDGE(MMAX)
1520 DIM S(MMAX),S0(MMAX)
1530 DIM S1(MMAX),S2(MMAX)
1540 DIM SS(MMAX*2,MMAX)
1550 DIM GXS(MMAX*2),GYS(MMAX*2)
1560 DIM GXE(MMAX*2),GYE(MMAX*2)
1570 DIM GZ(MMAX*2)
1580 '
1590 DIM XX1(MMAX,MMAX),YY1(MMAX,MMAX)
1600 DIM H1(MMAX,MMAX),H2(MMAX,MMAX)
1610 DIM H3(MMAX,MMAX)
1620 DIM C1(MMAX,MMAX),C2(MMAX,MMAX)
1630 DIM C3(MMAX,MMAX),C4(MMAX,MMAX)
1640 DIM C5(MMAX,MMAX),C6(MMAX,MMAX)
1650 DIM C7(MMAX,MMAX),C8(MMAX,MMAX)
1660 DIM ALPHA(MMAX),ALPHA1(MMAX),ALPHA2(MMAX)
1670 DIM ALPHA3(MMAX,MMAX),ALPHA4(MMAX,MMAX)
1680 '
1690 FOR I=1 TO 3
1700  VO(I)=0:VL(I)=.5
1710 'VO(I)=0:VL(I)=1
1720  VD(I)=5:VS(I)=1
1730  UNIT$(I)="m/s"
1740 NEXT I
1750 FOR I=4 TO 6
1760  VO(I)=0:VL(I)=2
1770 'VO(I)=0:VL(I)=4
1780  VD(I)=4:VS(I)=1
1790  UNIT$(I)="rad/s"
1800 NEXT I
1810 RETURN
1820 '
1830 ' *** 任意の超平面による切断面 ***
1840 '
1850 *HYPERPLANE:' [arbitary section]
1860 ALPHA(1)=1
1870 ALPHA(2)=1
1880 ALPHA(3)=1
1890 ALPHA(4)=1
1900 ALPHA(5)=1
1910 ALPHA(6)=1
1920 '
1930 S=0
1940 FOR I=1 TO M
1950  S=S+ALPHA(I)*ALPHA(I)
1960 NEXT I
1970 FOR I=1 TO M
1980  ALPHA(I)=ALPHA(I)/SQR(S)
1990 NEXT I
2000 '
2010 GOSUB *HYPERPLANE.DEF
2020 GOSUB *HYPERPLANE.1
2030 GOSUB *HYPERPLANE.2
2040 GOSUB *HYPERPLANE.3
2050 RETURN
2060 '
2070 *HYPERPLANE.DEF:
2080 M=M0
2090 KEY1$="123"
2100 KEY2$="456"
2110 MI=LEN(KEY1$)
2120 MJ=M0-MI
2130 RETURN
2140 '
2150 *HYPERPLANE.1:
2160 GOSUB *JACOBIAN
2170 GOSUB *HESSIAN
2180 '
2190 FOR I=1 TO M
2200  FOR J=1 TO M
2210   X=HESSE(I,J)
2220   X1=INSTR(KEY1$,MID$(STR$(I),2))
2230   X2=INSTR(KEY2$,MID$(STR$(I),2))
2240   Y1=INSTR(KEY1$,MID$(STR$(J),2))
2250   Y2=INSTR(KEY2$,MID$(STR$(J),2))
2260   IF X1<>0 AND Y1<>0 THEN C1(X1,Y1)=X
2270   IF X1<>0 AND Y1=0 THEN C2(X1,Y2)=X
2280   IF X1=0  AND Y1<>0 THEN C3(X2,Y1)=X
2290   IF X1=0  AND Y1=0 THEN C4(X2,Y2)=X
2300  NEXT J
2310 NEXT I
2320 RETURN
2330 '
2340 *HYPERPLANE.2:
2350 FOR I=1 TO M
2360  X=ALPHA(I)
2370  X1=INSTR(KEY1$,MID$(STR$(I),2))
2380  X2=INSTR(KEY2$,MID$(STR$(I),2))
2390  IF X1<>0 THEN ALPHA1(X1)=X
2400  IF X2<>0 THEN ALPHA2(X2)=X
2410 NEXT I
2420 '
2430 ' [contour]
2440 FOR I=1 TO MJ
2450  FOR J=1 TO MJ:AZ(I,J)=C4(I,J):NEXT J
2460 NEXT I
2470 NZ=MJ:GOSUB *INVERSE
2480 '
2490 FOR I=1 TO MJ
2500  FOR J=1 TO MI
2510   S=0
2520   FOR K=1 TO MJ
2530    S=S+BZ(I,K)*C3(K,J)
2540   NEXT K
2550   ALPHA4(I,J)=S
2560  NEXT J
2570 NEXT I
2580 RETURN
2590 '
2600 *HYPERPLANE.3:
2610 RN=1:CN=MJ
2620 FOR J=1 TO CN:XX1(1,J)=ALPHA2(J):NEXT J
2630 GOSUB *PENROSE
2640 '
2650 FOR I=1 TO MJ
2660  FOR J=1 TO MI
2670  'ALPHA3(I,J)=YY1(I,1)*ALPHA1(J):' [arbitary]
2680  'ALPHA3(I,J)=0         :' [section]
2690   ALPHA3(I,J)=ALPHA4(I,J)    :' [contour]
2700  NEXT J
2710 NEXT I
2720 '
2730 FOR I=1 TO MI
2740  FOR J=1 TO MI
2750   S=0
2760   FOR K=1 TO MJ
2770    S=S+C2(I,K)*ALPHA3(K,J)
2780   NEXT K
2790   C5(I,J)=S
2800  NEXT J
2810 NEXT I
2820 '
2830 FOR I=1 TO MI
2840  FOR J=1 TO MI
2850   S=0
2860   FOR K=1 TO MJ
2870    S=S+ALPHA3(K,I)*C3(K,J)
2880   NEXT K
2890   C6(I,J)=S
2900  NEXT J
2910 NEXT I
2920 '
2930 FOR I=1 TO MI
2940  FOR J=1 TO MJ
2950   S=0
2960   FOR K=1 TO MJ
2970    S=S+ALPHA3(K,I)*C4(K,J)
2980   NEXT K
2990   C7(I,J)=S
3000  NEXT J
3010 NEXT I
3020 '
3030 FOR I=1 TO MI
3040  FOR J=1 TO MI
3050   S=0
3060   FOR K=1 TO MJ
3070    S=S+C7(I,K)*ALPHA3(K,J)
3080   NEXT K
3090   C8(I,J)=S
3100  NEXT J
3110 NEXT I
3120 '
3130 FOR I=1 TO MI
3140  FOR J=1 TO MI
3150  'AZ(I,J)=C1(I,J)-C5(I,J)-C6(I,J)+C8(I,J)
3160   AZ(I,J)=C1(I,J)-C5(I,J)-C5(J,I)+C8(I,J)
3170   HESSE(I,J)=AZ(I,J)
3180  NEXT J
3190 NEXT I
3200 NZ=MI:GOSUB *INVERSE
3210 '
3220 FOR I=1 TO MI
3230  FOR J=1 TO MI:COV(I,J)=BZ(I,J):NEXT J
3240 NEXT I
3250 M0=M:M=MI
3260 RETURN
3270 '
3280 ' *** Moore-Penrose 逆行列 ( XX1==>YY1 ) ***
3290 '
3300 *PENROSE:
3310 GOSUB *EXACT2
3320 RETURN
3330 '
3340 ' ** XT*X **
3350 '
3360 *EXACT2:
3370 FOR I=1 TO CN
3380  FOR J=I TO CN
3390   S=0
3400   FOR K=1 TO RN
3410    S=S+XX1(K,I)*XX1(K,J)
3420   NEXT K
3430   AZ(I,J)=S:AZ(J,I)=S
3440  NEXT J
3450 NEXT I
3460 '
3470 ' ** (XT*X)^(-1) **
3480 '
3490 NZ=CN:GOSUB *INVERSE
3500 '
3510 ' ** X*(XT*X)^(-1) **
3520 '
3530 FOR I=1 TO RN
3540  FOR J=1 TO CN
3550   S=0
3560   FOR K=1 TO CN
3570    S=S+XX1(I,K)*BZ(K,J)
3580   NEXT K
3590   H1(I,J)=S
3600  NEXT J
3610 NEXT I
3620 '
3630 ' ** X*XT **
3640 '
3650 FOR I=1 TO RN
3660  FOR J=I TO RN
3670   S=0
3680   FOR K=1 TO CN
3690    S=S+XX1(I,K)*XX1(J,K)
3700   NEXT K
3710   AZ(I,J)=S:AZ(J,I)=S
3720  NEXT J
3730 NEXT I
3740 '
3750 ' ** (X*XT)^(-1) **
3760 '
3770 NZ=RN:GOSUB *INVERSE
3780 '
3790 ' ** XT*(X*XT)^(-1) **
3800 '
3810 FOR I=1 TO CN
3820  FOR J=1 TO RN
3830   S=0
3840   FOR K=1 TO RN
3850    S=S+XX1(K,I)*BZ(K,J)
3860   NEXT K
3870   H2(I,J)=S
3880  NEXT J
3890 NEXT I
3900 '
3910 ' ** XT*(X*XT)^(-1)*X*(XT*X)^(-1) **
3920 '
3930 FOR I=1 TO CN
3940  FOR J=1 TO CN
3950   S=0
3960   FOR K=1 TO RN
3970    S=S+H2(I,K)*H1(K,J)
3980   NEXT K
3990   H3(I,J)=S
4000  NEXT J
4010 NEXT I
4020 '
4030 ' ** XT*(X*XT)^(-1)*X*(XT*X)^(-1)*XT **
4040 '
4050 FOR I=1 TO CN
4060  FOR J=1 TO RN
4070   S=0
4080   FOR K=1 TO CN
4090    S=S+H3(I,K)*XX1(J,K)
4100   NEXT K
4110   YY1(I,J)=S
4120  NEXT J
4130 NEXT I
4140 RETURN
4150 '
4160 ' *** 超平面への正射影 ***
4170 '
4180 *HYPER.CONTOUR:
4190 GOSUB *HYPERPLANE.DEF
4200 GOSUB *HYPERPLANE.1
4210 '
4220 FOR I=1 TO MJ
4230  FOR J=1 TO MJ:AZ(I,J)=C4(I,J):NEXT J
4240 NEXT I
4250 NZ=MJ:GOSUB *INVERSE
4260 '
4270 FOR I=1 TO MI
4280  FOR J=1 TO MJ
4290   S=0
4300   FOR K=1 TO MJ
4310    S=S+C2(I,K)*BZ(K,J)
4320   NEXT K
4330   C5(I,J)=S
4340  NEXT J
4350 NEXT I
4360 '
4370 FOR I=1 TO MI
4380  FOR J=1 TO MI
4390   S=0
4400   FOR K=1 TO MJ
4410    S=S+C5(I,K)*C3(K,J)
4420   NEXT K
4430   C6(I,J)=S
4440  NEXT J
4450 NEXT I
4460 '
4470 FOR I=1 TO MI
4480  FOR J=1 TO MI
4490   AZ(I,J)=C1(I,J)-C6(I,J)
4500   HESSE(I,J)=AZ(I,J)
4510  NEXT J
4520 NEXT I
4530 NZ=MI:GOSUB *INVERSE
4540 '
4550 FOR I=1 TO MI
4560  FOR J=1 TO MI:COV(I,J)=BZ(I,J):NEXT J
4570 NEXT I
4580 M0=M:M=MI
4590 RETURN
4600 '
4610 ' *** 超平面による切断面 ***
4620 '
4630 *HYPER.SECTION:
4640 GOSUB *HYPERPLANE.DEF
4650 GOSUB *HYPERPLANE.1
4660 '
4670 FOR I=1 TO MI
4680  FOR J=1 TO MI
4690   AZ(I,J)=C1(I,J)
4700   HESSE(I,J)=AZ(I,J)
4710  NEXT J
4720 NEXT I
4730 NZ=MI:GOSUB *INVERSE
4740 '
4750 FOR I=1 TO MI
4760  FOR J=1 TO MI:COV(I,J)=BZ(I,J):NEXT J
4770 NEXT I
4780 M0=M:M=MI
4790 RETURN
4800 '
4810 ' *** ヤコビアンの読み込み ***
4820 '
4830 *JACOBIAN:
4840 RESTORE *J
4850 FOR J=1 TO M
4860  FOR I=1 TO N1
4870   READ JACOBI(J,I)
4880  NEXT I
4890 NEXT J
4900 '
4910 RESTORE *V
4920 FOR J=1 TO M
4930  READ V(J)
4940 NEXT J
4950 RETURN
4960 '
4970 *J:'[1]
4980 DATA .2084, .0320, .0409,-.0413,-.0032,-.0086, .0033
4990 DATA   0,-.3443, .1829,-.1264,-.0153,-.0227,-.0493
5000 DATA -.3425, .0606,-.1273,-.1929, .0157, .0446,-.0244
5010 DATA   0, .8841, .4161, .1965, .9440,-.3250, .1699
5020 DATA   1,   0, .4550, .8003,-.3106,-.8159, .4470
5030 DATA   0,-.4673, .7873,-.5664,-.1115,-.4782,-.8782
5040 '
5050 *V:'[1]
5060 DATA -.0013
5070 DATA -.0020
5080 DATA -.0005
5090 DATA .0007
5100 DATA -.0506
5110 DATA -.0119
5120 '
5130 '*J:'[20]
5140 DATA .3063,-.1201, .1035, .1037,-.0128,-.0019, .0373
5150 DATA   0,-.1692, .2014,-.2040,-.0076,-.0405,-.0248
5160 DATA -.1289, .1619,-.1761,-.1737, .0217, .0301,-.0311
5170 DATA   0, .8031,-.4195, .3965, .8705, .3581, .0393
5180 DATA   1,   0, .7101, .7037,-.0844,-.5671, .8029
5190 DATA   0, .5958, .5655,-.5896, .4848,-.7418,-.5948
5200 '
5210 '*V:'[20]
5220 DATA -.6581
5230 DATA  .0862
5240 DATA  .1687
5250 DATA  .5254
5260 DATA -1.1528
5270 DATA  .7858
5280 '
5290 ' *** ヘシアンと共分散行列 ***
5300 '
5310 *HESSIAN:
5320 FOR M1=1 TO M
5330  FOR M2=M1 TO M
5340   S=0
5350   FOR I=1 TO N1
5360    S=S+JACOBI(M1,I)*JACOBI(M2,I)
5370   NEXT I
5380   AZ(M1,M2)=S:AZ(M2,M1)=S
5390   COV(M1,M2)=S:COV(M2,M1)=S
5400  NEXT M2
5410 NEXT M1
5420 NZ=M
5430 '
5440 GOSUB *INVERSE
5450 '
5460 FOR I=1 TO M
5470  FOR J=1 TO M:HESSE(I,J)=BZ(I,J):NEXT J
5480 NEXT I
5490 RETURN
5500 '
5510 ' ** 逆行列 ( AZ==>BZ ) **
5520 '
5530 *INVERSE:' [GAUSS-JORDAN]
5540 FOR I=1 TO NZ
5550  FOR J=1 TO NZ:BZ(I,J)=0:NEXT J
5560  BZ(I,I)=1
5570 NEXT I
5580 FOR I=1 TO NZ
5590  IZ=I
5600  IF AZ(I,I)=0 THEN 5610 ELSE 5670
5610  IZ=IZ+1:IF IZ>NZ THEN RZ=1:RETURN
5620  IF AZ(IZ,I)=0 THEN 5610
5630  FOR J=1 TO NZ
5640   SWAP AZ(I,J),AZ(IZ,J)
5650   SWAP BZ(I,J),BZ(IZ,J)
5660  NEXT J
5670  AII=AZ(I,I)
5680  FOR J=1 TO NZ
5690   AZ(I,J)=AZ(I,J)/AII
5700   BZ(I,J)=BZ(I,J)/AII
5710  NEXT J
5720  FOR K=1 TO NZ
5730   AKI=AZ(K,I):IF K=I THEN 5780
5740   FOR J=1 TO NZ
5750    AZ(K,J)=AZ(K,J)-AKI*AZ(I,J)
5760    BZ(K,J)=BZ(K,J)-AKI*BZ(I,J)
5770   NEXT J
5780  NEXT K
5790 NEXT I
5800 RZ=0
5810 RETURN
5820 '
5830 ' *** 楕円体 ***
5840 '
5850 *ELLIPSOID:
5860 IF M<2 THEN RETURN
5870 '
5880 FOR I=1 TO M
5890  FOR J=1 TO M:AZ(I,J)=COV(I,J):NEXT J
5900 NEXT I
5910 NZ=M:GOSUB *JACOBI
5920 '
5930 FOR I=1 TO M-1
5940  FOR J=I+1 TO M
5950   IB=VAL(MID$(KEY1$,I,1))
5960   JB=VAL(MID$(KEY1$,J,1))
5970   UO=VO(IB):UL=VL(IB)
5980   VO=VO(JB):VL=VL(JB)
5990   DU=VD(IB):SU=VS(IB)
6000   DV=VD(JB):SV=VS(JB)
6010 '
6020   GOSUB *DRAW.AXIS
6030   GOSUB *DRAW.ELLIPSE:'IF I=1 AND J=2 THEN FL$="b:e1":GOSUB *GSAVE
6040   GOSUB *TEMP
6050  NEXT J
6060 NEXT I
6070 RETURN
6080 '
6090 ' ** 固有値 ( AZ==>BZ ) **
6100 '
6110 *JACOBI:' [ EIGEN-VECTOR: BZ(J,I) ]
6120 EPSL=.00001
6130 FOR I=1 TO NZ
6140  FOR J=1 TO NZ:BZ(I,J)=0:NEXT J
6150  BZ(I,I)=1
6160 NEXT I
6170 '
6180 CMAX=0
6190 FOR I=1 TO NZ
6200  FOR J=1 TO NZ
6210   IF CMAX<ABS(AZ(I,J)) THEN CMAX=ABS(AZ(I,J))
6220  NEXT J
6230 NEXT I
6240 EPS=CMAX*EPSL
6250 '
6260 LMAX=100
6270 LOOP=0
6280 SW=0
6290 WHILE LOOP<LMAX AND SW=0
6300 '
6310 FOR L=1 TO NZ-1
6320 FOR I=1 TO NZ-1
6330  J=I+L:IF J>NZ THEN 6520
6340  IF ABS(AZ(I,J))<EPS THEN 6510
6350  DIF=AZ(I,I)-AZ(J,J)
6360  IF DIF=0 THEN T=PI/4 ELSE T=1/2*ATN(2*AZ(I,J)/DIF)
6370  C=COS(T):S=SIN(T)
6380  FOR K=1 TO NZ
6390   A1=AZ(I,K):A2=AZ(J,K)
6400   AZ(I,K)= C*A1+S*A2
6410   AZ(J,K)=-S*A1+C*A2
6420  NEXT K
6430  FOR K=1 TO NZ
6440   A1=AZ(K,I):A2=AZ(K,J)
6450   AZ(K,I)= C*A1+S*A2
6460   AZ(K,J)=-S*A1+C*A2
6470   B1=BZ(K,I):B2=BZ(K,J)
6480   BZ(K,I)= C*B1+S*B2
6490   BZ(K,J)=-S*B1+C*B2
6500  NEXT K
6510 NEXT I
6520 NEXT L
6530 '
6540 SW=1
6550 FOR I=1 TO NZ-1
6560  FOR J=I+1 TO NZ
6570   IF ABS(AZ(I,J))>EPS THEN SW=0
6580  NEXT J
6590 NEXT I
6600 LOOP=LOOP+1
6610 '
6620 WEND
6630 RZ=0
6640 RETURN
6650 '
6660 ' *** 正射影 ***
6670 '
6680 *DRAW.ELLIPSE:
6690 'DRAW.COLOR=4
6700 WUO=UO-UL:WUL=UO+UL
6710 WVO=VO-VL:WVL=VO+VL
6720 WINDOW(WUO,-WVL)-(WUL,-WVO)
6730 VIEW(SX1,SY1)-(SX2,SY2)
6740 '
6750 'GOSUB *POLAR
6760 'GOSUB *EQUATOR
6770 'GOSUB *SECTION
6780 GOSUB *CONTOUR
6790 'GOSUB *HYPERCUBE
6800 'GOSUB *DUALCUBE
6810 'GOSUB *SIMPLEX
6820 '
6830 WINDOW(0,0)-(639,399)
6840 VIEW(0,0)-(639,399)
6850 RETURN
6860 '
6870 ' *** 輪郭 ***
6880 '
6890 *CONTOUR:
6900 GOTO 7120
6910 '
6920 S1=COV(I,I)
6930 S2=COV(J,J)
6940 S3=COV(I,J)
6950 LAMBDA1=(S1+S2+SQR((S1-S2)*(S1-S2)+4*S3*S3))/2
6960 LAMBDA2=(S1+S2-SQR((S1-S2)*(S1-S2)+4*S3*S3))/2
6970 'LAMBDA2=(S1*S2-S3*S3)/LAMBDA1
6980 T=1:' [non-stochastic]
6990 AAA=SQR(T*LAMBDA1)
7000 BBB=SQR(T*LAMBDA2)
7010 IF S3=0 THEN CCC=PI/2                                  ELSE B3=(S2-S1+SQR((S1-S2)*(S1-S2)+4*S3*S3))/2/S3:CCC=ATN(B3)
7020 'IF S3=0 THEN CCC=PI/2 ELSE B3=(LAMBDA1-S2)/S3:CCC=ATN(B3)
7030 '
7040 G=0
7050 FOR ANGLE=0 TO 2*PI+.01 STEP PI/180
7060  GX=AAA*COS(ANGLE)*COS(CCC)-BBB*SIN(ANGLE)*SIN(CCC)+VO(IB)
7070  GY=AAA*COS(ANGLE)*SIN(CCC)+BBB*SIN(ANGLE)*COS(CCC)+VO(JB)
7080  IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
7090  LINE-(GX,-GY),DRAW.COLOR
7100 NEXT ANGLE
7110 RETURN
7120 '
7130 DIF=COV(I,I)-COV(J,J)
7140 IF DIF=0 THEN TH=PI/4 ELSE TH=1/2*ATN(2*COV(I,J)/DIF)
7150 C=COS(TH):S=SIN(TH)
7160 '
7170 LAMBDA1=COV(I,I)*C*C+2*COV(I,J)*C*S+COV(J,J)*S*S
7180 LAMBDA2=COV(I,I)*S*S-2*COV(I,J)*C*S+COV(J,J)*C*C
7190 T=1:' [non-stochastic]
7200 AAA=SQR(T*LAMBDA1)
7210 BBB=SQR(T*LAMBDA2)
7220 '
7230 G=0
7240 FOR ANGLE=0 TO 2*PI+.01 STEP PI/180
7250  GX=AAA*COS(ANGLE)*C-BBB*SIN(ANGLE)*S+VO(IB)
7260  GY=AAA*COS(ANGLE)*S+BBB*SIN(ANGLE)*C+VO(JB)
7270  IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
7280  LINE-(GX,-GY),DRAW.COLOR
7290 NEXT ANGLE
7300 RETURN
7310 '
7320 ' *** 極線 ***
7330 '
7340 *POLAR:
7350 FOR K=1 TO M
7360  T=1:' [non-stochastic]
7370  RRR=SQR(T*AZ(K,K))
7380  GX=BZ(I,K)*RRR
7390  GY=BZ(J,K)*RRR
7400  GX1= GX+VO(IB):GY1= GY+VO(JB)
7410  GX2=-GX+VO(IB):GY2=-GY+VO(JB)
7420  LINE(GX1,-GY1)-(GX2,-GY2),7
7430  IF K=I OR K=J THEN LINE(GX1,-GY1)-(GX2,-GY2),CLR
7440 NEXT K
7450 RETURN
7460 '
7470 ' *** 赤道 ***
7480 '
7490 *EQUATOR:
7500 T=1:' [non-stochastic]
7510 AAA=SQR(T*AZ(I,I))
7520 BBB=SQR(T*AZ(J,J))
7530 '
7540 G=0
7550 FOR ANGLE=0 TO 2*PI+.01 STEP PI/180
7560  GX=AAA*COS(ANGLE)*BZ(I,I)+BBB*SIN(ANGLE)*BZ(I,J)+VO(IB)
7570  GY=AAA*COS(ANGLE)*BZ(J,I)+BBB*SIN(ANGLE)*BZ(J,J)+VO(JB)
7580  IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
7590  LINE-(GX,-GY),DRAW.COLOR
7600 NEXT ANGLE
7610 RETURN
7620 '
7630 ' *** 断面 ***
7640 '
7650 *SECTION:
7660 DIF=HESSE(I,I)-HESSE(J,J)
7670 IF DIF=0 THEN TH=PI/4 ELSE TH=1/2*ATN(2*HESSE(I,J)/DIF)
7680 C=COS(TH):S=SIN(TH)
7690 '
7700 LAMBDA1=HESSE(I,I)*C*C+2*HESSE(I,J)*C*S+HESSE(J,J)*S*S
7710 LAMBDA2=HESSE(I,I)*S*S-2*HESSE(I,J)*C*S+HESSE(J,J)*C*C
7720 T=1:' [non-stochastic]
7730 AAA=SQR(T/LAMBDA1)
7740 BBB=SQR(T/LAMBDA2)
7750 '
7760 G=0
7770 FOR ANGLE=0 TO 2*PI+.01 STEP PI/180
7780  GX=AAA*COS(ANGLE)*C-BBB*SIN(ANGLE)*S+VO(IB)
7790  GY=AAA*COS(ANGLE)*S+BBB*SIN(ANGLE)*C+VO(JB)
7800  IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
7810  LINE-(GX,-GY),DRAW.COLOR
7820 NEXT ANGLE
7830 RETURN
7840 '
7850 ' *** 超立方体 ***
7860 '
7870 *HYPERCUBE:
7880 T=1:' [non-stochastic]
7890 FOR IS=1 TO M:EDGE(IS)=SQR(T*AZ(IS,IS)):NEXT IS
7900 '
7910 FOR IS=0 TO 2^M-1
7920  FOR JS=1 TO M:S(JS)=-1:NEXT JS
7930  FOR JS=1 TO M
7940   IF (IS AND 2^(JS-1))=0 THEN S(JS)=1
7950  NEXT JS
7960  FOR JS=1 TO M:S0(JS)=S(JS):NEXT JS
7970 'GOSUB *VERTEX:GXS=GX:GYS=GY
7980  '
7990  COUNT=0
8000  FOR JS=1 TO M
8010   COUNT=COUNT+1
8020   FOR KS=1 TO M:S(KS)=S0(KS):NEXT KS
8030   S(JS)=-S(JS)
8040   FOR KS=1 TO M:SS(COUNT,KS)=S(KS):NEXT KS
8050  'GOSUB *VERTEX:GXE=GX:GYE=GY
8060  'LINE(GXS,-GYS)-(GXE,-GYE),7
8070  NEXT JS
8080  GOSUB *POLYGON
8090 NEXT IS
8100 RETURN
8110 '
8120 ' *** 頂点 ***
8130 '
8140 *VERTEX:
8150 'GOSUB *INTERNAL
8160 GX=0:GY=0
8170 FOR GS=1 TO M
8180  GX=GX+BZ(I,GS)*EDGE(GS)*S(GS)
8190  GY=GY+BZ(J,GS)*EDGE(GS)*S(GS)
8200 NEXT GS
8210 GX=GX+VO(IB):GY=GY+VO(JB)
8220 RETURN
8230 '
8240 ' *** 内接化 ***
8250 '
8260 *INTERNAL:
8270 X=(1-SQR(1+M))/M
8280 G=SQR(1+1/M)
8290 FOR GS=1 TO M
8300  S(GS)=(S(GS)-(X+1)/(M+1))*G
8310 NEXT GS
8320 RETURN
8330 '
8340 ' *** 輪郭抽出 ***
8350 '
8360 '*POLYGON:
8370 EPS=.05
8380 FOR KS=1 TO M
8390  FOR LS=1 TO M:S(LS)=S0(LS):NEXT LS
8400  IF KS=JS THEN 8420
8410  S(KS)=S(KS)*(1-EPS)
8420  GOSUB *VERTEX:GXS(KS)=GX:GYS(KS)=GY
8430  '
8440  FOR LS=1 TO M:S(LS)=S0(LS):NEXT LS
8450  S(JS)=-S(JS)
8460  IF KS=JS THEN 8480
8470  S(KS)=S(KS)*(1-EPS)
8480  GOSUB *VERTEX:GXE(KS)=GX:GYE(KS)=GY
8490 NEXT KS
8500 '
8510 X=GXS(JS):Y=GYS(JS)
8520 FOR KS=1 TO M
8530  GZ(KS)=(GYE(KS)-GYS(KS))*(X-GXS(KS))-(GXE(KS)-GXS(KS))*(Y-GYS(KS))
8540 NEXT KS
8550 '
8560 ZMAX=GZ(JS):ZMIN=GZ(JS)
8570 FOR KS=1 TO M
8580  IF KS=JS THEN 8610
8590  IF ZMAX<GZ(KS) THEN ZMAX=GZ(KS)
8600  IF ZMIN>GZ(KS) THEN ZMIN=GZ(KS)
8610 NEXT KS
8620 '
8630 SW=0
8640 IF (ZMAX-GZ(JS))*(ZMIN-GZ(JS))=0 THEN SW=1
8650 GXS=GXS(JS):GYS=GYS(JS)
8660 GXE=GXE(JS):GYE=GYE(JS)
8670 IF SW=1 THEN LINE(GXS,-GYS)-(GXE,-GYE),7
8680 RETURN
8690 '
8700 ' *** 輪郭抽出 ***
8710 '
8720 *POLYGON:
8730 EPS=.05
8740 FOR JS=1 TO COUNT
8750  FOR LS=1 TO M:S1(LS)=SS(JS,LS):NEXT LS
8760  FOR KS=1 TO COUNT
8770   FOR LS=1 TO M:S2(LS)=SS(KS,LS):NEXT LS
8780   '
8790   FOR LS=1 TO M:S(LS)=S0(LS):NEXT LS
8800   IF KS=JS THEN 8820
8810   FOR LS=1 TO M:S(LS)=S0(LS)+EPS*(S2(LS)-S0(LS)):NEXT LS
8820   GOSUB *VERTEX:GXS(KS)=GX:GYS(KS)=GY
8830   '
8840   FOR LS=1 TO M:S(LS)=S1(LS):NEXT LS
8850   IF KS=JS THEN 8870
8860   FOR LS=1 TO M:S(LS)=S1(LS)+EPS*(S2(LS)-S0(LS)):NEXT LS
8870   GOSUB *VERTEX:GXE(KS)=GX:GYE(KS)=GY
8880  NEXT KS
8890  GOSUB *POLYGON.LINE
8900 NEXT JS
8910 RETURN
8920 '
8930 *POLYGON.LINE:
8940 X=GXS(JS):Y=GYS(JS)
8950 FOR KS=1 TO COUNT
8960  GZ(KS)=(GYE(KS)-GYS(KS))*(X-GXS(KS))-(GXE(KS)-GXS(KS))*(Y-GYS(KS))
8970 NEXT KS
8980 '
8990 ZMAX=GZ(JS):ZMIN=GZ(JS)
9000 FOR KS=1 TO COUNT
9010  IF KS=JS THEN 9040
9020  IF ZMAX<GZ(KS) THEN ZMAX=GZ(KS)
9030  IF ZMIN>GZ(KS) THEN ZMIN=GZ(KS)
9040 NEXT KS
9050 '
9060 SW=0
9070 IF (ZMAX-GZ(JS))*(ZMIN-GZ(JS))=0 THEN SW=1
9080 GXS=GXS(JS):GYS=GYS(JS)
9090 GXE=GXE(JS):GYE=GYE(JS)
9100 IF SW=1 THEN LINE(GXS,-GYS)-(GXE,-GYE),7
9110 RETURN
9120 '
9130 ' *** 双対立方体 ***
9140 '
9150 *DUALCUBE:
9160 T=1:' [non-stochastic]
9170 FOR IS=1 TO M:EDGE(IS)=SQR(T*AZ(IS,IS)):NEXT IS
9180 '
9190 FOR IS=1 TO M
9200  FOR JS=1 TO M:S(JS)=0:NEXT JS
9210  S(IS)=1
9220  FOR JS=1 TO M:S0(JS)=S(JS):NEXT JS
9230 'GOSUB *VERTEX:GXS=GX:GYS=GY
9240  '
9250  COUNT=0
9260  FOR JS=1 TO M
9270   IF JS=IS THEN 9410
9280   COUNT=COUNT+1
9290   FOR KS=1 TO M:S(KS)=0:NEXT KS
9300   S(JS)=1
9310   FOR KS=1 TO M:SS(COUNT,KS)=S(KS):NEXT KS
9320  'GOSUB *VERTEX:GXE=GX:GYE=GY
9330  'LINE(GXS,-GYS)-(GXE,-GYE),7
9340   '
9350   COUNT=COUNT+1
9360   FOR KS=1 TO M:S(KS)=0:NEXT KS
9370   S(JS)=-1
9380   FOR KS=1 TO M:SS(COUNT,KS)=S(KS):NEXT KS
9390  'GOSUB *VERTEX:GXE=GX:GYE=GY
9400  'LINE(GXS,-GYS)-(GXE,-GYE),7
9410  NEXT JS
9420  GOSUB *POLYGON
9430 NEXT IS
9440 '
9450 FOR IS=1 TO M
9460  FOR JS=1 TO M:S(JS)=0:NEXT JS
9470  S(IS)=-1
9480  FOR JS=1 TO M:S0(JS)=S(JS):NEXT JS
9490 'GOSUB *VERTEX:GXS=GX:GYS=GY
9500  '
9510  COUNT=0
9520  FOR JS=1 TO M
9530   IF JS=IS THEN 9670
9540   COUNT=COUNT+1
9550   FOR KS=1 TO M:S(KS)=0:NEXT KS
9560   S(JS)=1
9570   FOR KS=1 TO M:SS(COUNT,KS)=S(KS):NEXT KS
9580  'GOSUB *VERTEX:GXE=GX:GYE=GY
9590  'LINE(GXS,-GYS)-(GXE,-GYE),7
9600   '
9610   COUNT=COUNT+1
9620   FOR KS=1 TO M:S(KS)=0:NEXT KS
9630   S(JS)=-1
9640   FOR KS=1 TO M:SS(COUNT,KS)=S(KS):NEXT KS
9650  'GOSUB *VERTEX:GXE=GX:GYE=GY
9660  'LINE(GXS,-GYS)-(GXE,-GYE),7
9670  NEXT JS
9680  GOSUB *POLYGON
9690 NEXT IS
9700 RETURN
9710 '
9720 ' *** 正単体 ***
9730 '
9740 *SIMPLEX:
9750 T=1:' [non-stochastic]
9760 FOR IS=1 TO M:EDGE(IS)=SQR(T*AZ(IS,IS)):NEXT IS
9770 '
9780 FOR IS=1 TO M
9790  FOR JS=1 TO M:S(JS)=0:NEXT JS
9800  S(IS)=1
9810  FOR JS=1 TO M:S0(JS)=S(JS):NEXT JS
9820 'GOSUB *VERTEX:GXS=GX:GYS=GY
9830  '
9840  COUNT=0
9850  FOR JS=1 TO M
9860   IF JS=IS THEN 9930
9870   COUNT=COUNT+1
9880   FOR KS=1 TO M:S(KS)=0:NEXT KS
9890   S(JS)=1
9900   FOR KS=1 TO M:SS(COUNT,KS)=S(KS):NEXT KS
9910  'GOSUB *VERTEX:GXE=GX:GYE=GY
9920  'LINE(GXS,-GYS)-(GXE,-GYE),7
9930  NEXT JS
9940  '
9950   COUNT=COUNT+1
9960   FOR KS=1 TO M:S(KS)=(1-SQR(1+M))/M:NEXT KS
9970   FOR KS=1 TO M:SS(COUNT,KS)=S(KS):NEXT KS
9980  'GOSUB *VERTEX:GXE=GX:GYE=GY
9990  'LINE(GXS,-GYS)-(GXE,-GYE),7
10000  GOSUB *POLYGON
10010 NEXT IS
10020 RETURN
10030 '
10040 ' *** 座標軸 ***
10050 '
10060 *DRAW.AXIS:
10070 CLS 3
10080 SX1=59:SY1=360*(1-RY):SX2=580*RX+59:SY2=360
10090 LINE(SX1,SY1)-(SX2,SY2),GRP.COLOR,B
10100 RR=3:GOSUB *X.SCALE2:GOSUB *X.REF2
10110 RR=3:GOSUB *Y.SCALE2:GOSUB *Y.REF2
10120 RR=3:GOSUB *DOT.PLOT
10130 GOSUB *TITLE.BACK2
10140 RETURN
10150 '
10160 ' *** 等分目盛り (X) ***
10170 '
10180 *X.SCALE2:
10190 CU=(SX2-SX1)/DU/2
10200 IF KIND=0 THEN KARA=-RR:MADE=0
10210 IF KIND=1 THEN KARA=0 :MADE=RR
10220 IF KIND=2 THEN KARA=-RR:MADE=RR
10230 FOR K=0 TO DU*2
10240  LINE(CU*K+SX1,SY2+KARA)-(CU*K+SX1,SY2+MADE),GRP.COLOR
10250  LINE(CU*K+SX1,SY1-KARA)-(CU*K+SX1,SY1-MADE),GRP.COLOR
10260 NEXT K
10270 'GOSUB *X.REF2
10280 RETURN
10290 '
10300 ' *** 参照値の記入 (X) ***
10310 '
10320 *X.REF2:
10330 REF.COLOR=6
10340 UW=UL-UO
10350 FOR K=0 TO DU*2 STEP SU
10360  F=UW*(K/DU-1):F$=STR$(F)
10370  IF F>=0 THEN F$=MID$(F$,2)
10380  FL=LEN(F$)
10390  FOR L=1 TO FL
10400   GX=CU*K+59-FL*8/2+(L-1)*8:GY=23*16
10410   PUT(GX,GY),KANJI(ASC(MID$(F$,L,1))),PSET,REF.COLOR,0
10420  NEXT L
10430 NEXT K
10440 RETURN
10450 '
10460 ' *** 等分目盛り (Y) ***
10470 '
10480 *Y.SCALE2:
10490 CV=(SY2-SY1)/DV/2
10500 IF KIND=0 THEN KARA=0 :MADE=RR
10510 IF KIND=1 THEN KARA=-RR:MADE=0
10520 IF KIND=2 THEN KARA=-RR:MADE=RR
10530 FOR K=0 TO DV*2
10540  LINE(SX1+KARA,SY2-CV*K)-(SX1+MADE,SY2-CV*K),GRP.COLOR
10550  LINE(SX2-KARA,SY2-CV*K)-(SX2-MADE,SY2-CV*K),GRP.COLOR
10560 NEXT K
10570 'GOSUB *Y.REF2
10580 RETURN
10590 '
10600 ' *** 参照値の記入 (Y) ***
10610 '
10620 *Y.REF2:
10630 REF.COLOR=6
10640 VW=VL-VO
10650 FOR K=0 TO DV*2 STEP SV
10660  F=VW*(K/DV-1):F$=STR$(F)
10670  IF F>=0 THEN F$=MID$(F$,2)
10680  FL=LEN(F$)
10690  FOR L=1 TO FL
10700   GX=48-FL*8+(L-1)*8:GY=360-CV*K-8
10710   PUT(GX,GY),KANJI(ASC(MID$(F$,L,1))),PSET,REF.COLOR,0
10720  NEXT L
10730 NEXT K
10740 RETURN
10750 '
10760 ' *** プロット ***
10770 '
10780 *DOT.PLOT:
10790 WUO=UO-UL:WUL=UO+UL
10800 WVO=VO-VL:WVL=VO+VL
10810 WX=WUL-WUO
10820 BX=(WUL*SX1-WUO*SX2)/WX
10830 AX=(SX2-SX1)/WX
10840 WY=WVL-WVO
10850 BY=(WVL*SY2-WVO*SY1)/WY
10860 AY=(SY1-SY2)/WY
10870 '
10880 XX=AX*V(IB)+BX
10890 YY=AY*V(JB)+BY
10900 CIRCLE(XX,YY),RR,1
10910 PAINT(XX,YY),CLR,1
10920 CIRCLE(XX,YY),RR,CLR
10930 RETURN
10940 '
10950 ' *** タイトル ***
10960 '
10970 *TITLE.BACK2:
10980 LX=INT((580*RX+59)/8)
10990 LY=INT(360*(1-RY)/16)
11000 LZ=INT((290*RX+59)/8)
11010 L1$="ellipsoid projection of "
11020 L2$="v"+MID$(STR$(IB),2)+"-"
11030 L3$="v"+MID$(STR$(JB),2)+" plane"
11040 L$=L1$+L2$+L3$
11050 LOCATE LZ-LEN(L$)\2,LY-3:PRINT L$
11060 L$=UNIT$(JB)
11070 IF LEN(L$)=0 THEN 11090
11080 LOCATE 7,LY-1:PRINT "("+L$+")"
11090 L$=UNIT$(IB)
11100 IF LEN(L$)=0 THEN 11120
11110 LOCATE LX+3,21:PRINT "("+L$+")"
11120 '
11130 LOCATE LX+3,LY:PRINT "v components: "
11140 FOR K=1 TO M0
11150  V$="v"+MID$(STR$(K),2)+"="
11160  LOCATE LX+3,LY+K+1:PRINT V$;:PRINT V(K)
11170 NEXT K
11180 RETURN
11190 '
11200 *TEMP:
11210 LOCATE 0,24:PRINT "何かキーを押してください";:WHILE INKEY$="":WEND
11220 RETURN
11230 '
11240 ' *** ワイヤーフレーム楕円体 ***
11250 '
11260 *ELLIPSOID.WF:
11270 IF M<3 THEN RETURN
11280 '
11290 IB=VAL(MID$(KEY1$,1,1))
11300 JB=VAL(MID$(KEY1$,2,1))
11310 KB=VAL(MID$(KEY1$,3,1))
11320 IJK=3:GOSUB *ELLIPSOID.WF.SUB
11330 '
11340 IB=VAL(MID$(KEY1$,1,1))
11350 JB=VAL(MID$(KEY1$,3,1))
11360 KB=VAL(MID$(KEY1$,2,1))
11370 IJK=3:GOSUB *ELLIPSOID.WF.SUB
11380 '
11390 IB=VAL(MID$(KEY1$,2,1))
11400 JB=VAL(MID$(KEY1$,3,1))
11410 KB=VAL(MID$(KEY1$,1,1))
11420 IJK=3:GOSUB *ELLIPSOID.WF.SUB
11430 RETURN
11440 '
11450 *ELLIPSOID.WF.SUB:
11460 UO=VO(IB):UL=VL(IB)
11470 VO=VO(JB):VL=VL(JB)
11480 DU=VD(IB):SU=VS(IB)
11490 DV=VD(JB):SV=VS(JB)
11500 '
11510 GOSUB *DRAW.AXIS.WF
11520 GOSUB *DRAW.ELLIPSE.WF:'IF IB=1 AND JB=2 THEN FL$="b:e2":GOSUB *GSAVE
11530 GOSUB *TEMP
11540 RETURN
11550 '
11560 ' *** 正射影 ***
11570 '
11580 *DRAW.ELLIPSE.WF:
11590 'DRAW.COLOR=4
11600 WUO=UO-UL:WUL=UO+UL
11610 WVO=VO-VL:WVL=VO+VL
11620 WINDOW(WUO,-WVL)-(WUL,-WVO)
11630 VIEW(SX1,SY1)-(SX2,SY2)
11640 '
11650 IF IJK<>0 THEN GOSUB *EIGEN.WF:GOSUB *COMMON.WF
11660 IF IJK=0 AND STAGE$="1" THEN I=IB:J=JB:GOSUB *CONTOUR
11670 IF IJK=0 AND STAGE$="2" THEN I=IB:J=JB:GOSUB *SECTION
11680 'GOSUB *COMMON.WF
11690 'I=IB:J=JB:GOSUB *CONTOUR
11700 'I=IB:J=JB:GOSUB *SECTION
11710 '
11720 WINDOW(0,0)-(639,399)
11730 VIEW(0,0)-(639,399)
11740 RETURN
11750 '
11760 *EIGEN.WF:
11770 IF STAGE$="2" THEN 11960
11780 '
11790 AZ(1,1)=COV(IB,IB)
11800 AZ(1,2)=COV(IB,JB)
11810 AZ(1,3)=COV(IB,KB)
11820 AZ(2,1)=AZ(1,2)
11830 AZ(2,2)=COV(JB,JB)
11840 AZ(2,3)=COV(JB,KB)
11850 AZ(3,1)=AZ(1,3)
11860 AZ(3,2)=AZ(2,3)
11870 AZ(3,3)=COV(KB,KB)
11880 NZ=3:GOSUB *JACOBI
11890 '
11900 T=1:' [non-stochastic]
11910 AAA=SQR(T*AZ(1,1))
11920 BBB=SQR(T*AZ(2,2))
11930 CCC=SQR(T*AZ(3,3))
11940 KS=PI/12
11950 GOTO 12130
11960 '
11970 AZ(1,1)=HESSE(IB,IB)
11980 AZ(1,2)=HESSE(IB,JB)
11990 AZ(1,3)=HESSE(IB,KB)
12000 AZ(2,1)=AZ(1,2)
12010 AZ(2,2)=HESSE(JB,JB)
12020 AZ(2,3)=HESSE(JB,KB)
12030 AZ(3,1)=AZ(1,3)
12040 AZ(3,2)=AZ(2,3)
12050 AZ(3,3)=HESSE(KB,KB)
12060 NZ=3:GOSUB *JACOBI
12070 '
12080 T=1:' [non-stochastic]
12090 AAA=SQR(T/AZ(1,1))
12100 BBB=SQR(T/AZ(2,2))
12110 CCC=SQR(T/AZ(3,3))
12120 KS=PI/12
12130 RETURN
12140 '
12150 ' *** 経線・緯線 ***
12160 '
12170 *COMMON.WF:
12180 FOR V=PI/2-KS TO -PI/2+KS-.01 STEP -KS
12190  G=0
12200  FOR U=0 TO 2*PI+.01 STEP KS
12210   GOSUB *WIRE.FRAME
12220  NEXT U
12230 NEXT V
12240 '
12250 FOR U=0 TO 2*PI+.01 STEP KS
12260  G=0
12270 'FOR V=PI/2-KS TO -PI/2+KS-.01 STEP -KS
12280  FOR V=PI/2 TO -PI/2-.01 STEP -KS
12290   GOSUB *WIRE.FRAME
12300  NEXT V
12310 NEXT U
12320 RETURN
12330 '
12340 *WIRE.FRAME:
12350 ON IJK GOTO 12480,12420,12360
12360 '
12370 '[k-pole]
12380 GX=AAA*COS(U)*COS(V)*BZ(1,1)+BBB*SIN(U)*COS(V)*BZ(1,2)+CCC*SIN(V)*BZ(1,3)
12390 GY=AAA*COS(U)*COS(V)*BZ(2,1)+BBB*SIN(U)*COS(V)*BZ(2,2)+CCC*SIN(V)*BZ(2,3)
12400 GZ=AAA*COS(U)*COS(V)*BZ(3,1)+BBB*SIN(U)*COS(V)*BZ(3,2)+CCC*SIN(V)*BZ(3,3)
12410 GOTO 12530
12420 '
12430 '[j-pole]
12440 GX=AAA*SIN(U)*COS(V)*BZ(1,1)+BBB*SIN(V)*BZ(1,2)+CCC*COS(U)*COS(V)*BZ(1,3)
12450 GY=AAA*SIN(U)*COS(V)*BZ(2,1)+BBB*SIN(V)*BZ(2,2)+CCC*COS(U)*COS(V)*BZ(2,3)
12460 GZ=AAA*SIN(U)*COS(V)*BZ(3,1)+BBB*SIN(V)*BZ(3,2)+CCC*COS(U)*COS(V)*BZ(3,3)
12470 GOTO 12530
12480 '
12490 '[i-pole]
12500 GX=AAA*SIN(V)*BZ(1,1)+BBB*COS(U)*COS(V)*BZ(1,2)+CCC*SIN(U)*COS(V)*BZ(1,3)
12510 GY=AAA*SIN(V)*BZ(2,1)+BBB*COS(U)*COS(V)*BZ(2,2)+CCC*SIN(U)*COS(V)*BZ(2,3)
12520 GZ=AAA*SIN(V)*BZ(3,1)+BBB*COS(U)*COS(V)*BZ(3,2)+CCC*SIN(U)*COS(V)*BZ(3,3)
12530 '
12540 GX=GX+VO(IB)
12550 GY=GY+VO(JB)
12560 GZ=GZ+VO(KB)
12570 '
12580 ON VHP+1 GOSUB *VERTICAL,*VERTICAL,*HORIZONTAL,*PROFILE
12590 RETURN
12600 '
12610 *VERTICAL:
12620 IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
12630 GOSUB *NORMAL.VECTOR
12640 IF DZ<=0 THEN LINE-(GX,-GY),DRAW.COLOR
12650 IF DZ> 0 THEN LINE-(GX,-GY),DRAW.COLOR,,&H1111
12660 RETURN
12670 '
12680 *HORIZONTAL:
12690 IF G=0 THEN PSET(GX,-GZ),DRAW.COLOR:G=1
12700 GOSUB *NORMAL.VECTOR:DY=-DY
12710 IF DY<=0 THEN LINE-(GX,-GZ),DRAW.COLOR
12720 IF DY> 0 THEN LINE-(GX,-GZ),DRAW.COLOR,,&H1111
12730 RETURN
12740 '
12750 *PROFILE:
12760 IF G=0 THEN PSET(GZ,-GY),DRAW.COLOR:G=1
12770 GOSUB *NORMAL.VECTOR:DX=-DX
12780 IF DX<=0 THEN LINE-(GZ,-GY),DRAW.COLOR
12790 IF DX> 0 THEN LINE-(GZ,-GY),DRAW.COLOR,,&H1111
12800 RETURN
12810 '
12820 ' *** 法線ベクトル ***
12830 '
12840 *NORMAL.VECTOR:
12850 ON IJK GOTO 13040,12950,12860
12860 '
12870 '[k-pole]
12880 DXDU=-AAA*SIN(U)*COS(V)*BZ(1,1)+BBB*COS(U)*COS(V)*BZ(1,2)
12890 DYDU=-AAA*SIN(U)*COS(V)*BZ(2,1)+BBB*COS(U)*COS(V)*BZ(2,2)
12900 DZDU=-AAA*SIN(U)*COS(V)*BZ(3,1)+BBB*COS(U)*COS(V)*BZ(3,2)
12910 DXDV=-AAA*COS(U)*SIN(V)*BZ(1,1)-BBB*SIN(U)*SIN(V)*BZ(1,2)+CCC*COS(V)*BZ(1,3)
12920 DYDV=-AAA*COS(U)*SIN(V)*BZ(2,1)-BBB*SIN(U)*SIN(V)*BZ(2,2)+CCC*COS(V)*BZ(2,3)
12930 DZDV=-AAA*COS(U)*SIN(V)*BZ(3,1)-BBB*SIN(U)*SIN(V)*BZ(3,2)+CCC*COS(V)*BZ(3,3)
12940 GOTO 13120
12950 '
12960 '[j-pole]
12970 DXDU=AAA*COS(U)*COS(V)*BZ(1,1)-CCC*SIN(U)*COS(V)*BZ(1,3)
12980 DYDU=AAA*COS(U)*COS(V)*BZ(2,1)-CCC*SIN(U)*COS(V)*BZ(2,3)
12990 DZDU=AAA*COS(U)*COS(V)*BZ(3,1)-CCC*SIN(U)*COS(V)*BZ(3,3)
13000 DXDV=-AAA*SIN(U)*SIN(V)*BZ(1,1)+BBB*COS(V)*BZ(1,2)-CCC*COS(U)*SIN(V)*BZ(1,3)
13010 DYDV=-AAA*SIN(U)*SIN(V)*BZ(2,1)+BBB*COS(V)*BZ(2,2)-CCC*COS(U)*SIN(V)*BZ(2,3)
13020 DZDV=-AAA*SIN(U)*SIN(V)*BZ(3,1)+BBB*COS(V)*BZ(3,2)-CCC*COS(U)*SIN(V)*BZ(3,3)
13030 GOTO 13120
13040 '
13050 '[i-pole]
13060 DXDU=-BBB*SIN(U)*COS(V)*BZ(1,2)+CCC*COS(U)*COS(V)*BZ(1,3)
13070 DYDU=-BBB*SIN(U)*COS(V)*BZ(2,2)+CCC*COS(U)*COS(V)*BZ(2,3)
13080 DZDU=-BBB*SIN(U)*COS(V)*BZ(3,2)+CCC*COS(U)*COS(V)*BZ(3,3)
13090 DXDV=AAA*COS(V)*BZ(1,1)-BBB*COS(U)*SIN(V)*BZ(1,2)-CCC*SIN(U)*SIN(V)*BZ(1,3)
13100 DYDV=AAA*COS(V)*BZ(2,1)-BBB*COS(U)*SIN(V)*BZ(2,2)-CCC*SIN(U)*SIN(V)*BZ(2,3)
13110 DZDV=AAA*COS(V)*BZ(3,1)-BBB*COS(U)*SIN(V)*BZ(3,2)-CCC*SIN(U)*SIN(V)*BZ(3,3)
13120 '
13130 DX=DYDU*DZDV-DYDV*DZDU
13140 DY=DZDU*DXDV-DZDV*DXDU
13150 DZ=DXDU*DYDV-DXDV*DYDU
13160 RETURN
13170 '
13180 ' *** 座標軸 ***
13190 '
13200 *DRAW.AXIS.WF:
13210 CLS 3
13220 SX1=59:SY1=360*(1-RY):SX2=580*RX+59:SY2=360
13230 LINE(SX1,SY1)-(SX2,SY2),GRP.COLOR,B
13240 RR=3:GOSUB *X.SCALE2:GOSUB *X.REF2
13250 RR=3:GOSUB *Y.SCALE2:GOSUB *Y.REF2
13260 I=IB:J=JB:RR=3:GOSUB *DOT.PLOT
13270 GOSUB *TITLE.BACK2.WF
13280 RETURN
13290 '
13300 ' *** タイトル ***
13310 '
13320 *TITLE.BACK2.WF:
13330 LX=INT((580*RX+59)/8)
13340 LY=INT(360*(1-RY)/16)
13350 LZ=INT((290*RX+59)/8)
13360 L1$="ellipsoid projection of "
13370 L2$="v"+MID$(STR$(IB),2)+"-"
13380 L3$="v"+MID$(STR$(JB),2)+"-"
13390 L4$="v"+MID$(STR$(KB),2)+" space"
13400 L$=L1$+L2$+L3$+L4$
13410 LOCATE LZ-LEN(L$)\2,LY-3:PRINT L$
13420 L$=UNIT$(JB)
13430 IF LEN(L$)=0 THEN 11090
13440 LOCATE 7,LY-1:PRINT "("+L$+")"
13450 L$=UNIT$(IB)
13460 IF LEN(L$)=0 THEN 11120
13470 LOCATE LX+3,21:PRINT "("+L$+")"
13480 '
13490 LOCATE LX+3,LY:PRINT "v components: "
13500 FOR K=1 TO M0
13510  V$="v"+MID$(STR$(K),2)+"="
13520  LOCATE LX+3,LY+K+1:PRINT V$;:PRINT V(K)
13530 NEXT K
13540 RETURN
13550 '
13560 ' *** 楕円体三面図 ***
13570 '
13580 *ELLIPSOID3:
13590 IF M<3 THEN RETURN
13600 '
13610 CLS 3
13620 IJK=2
13630 IB=VAL(MID$(KEY1$,1,1))
13640 JB=VAL(MID$(KEY1$,2,1))
13650 KB=VAL(MID$(KEY1$,3,1))
13660 BIAS=0
13670 IF IJK<>0 THEN GOSUB *EIGEN.WF
13680 IF IJK=0 AND STAGE$="2" THEN GOSUB *SECTION3
13690 IF IJK=0 THEN GOSUB *COMMON3:GOTO 13800
13700 '
13710 SX1=59:SY1=360*(1-RY/2):SX2=580*RX/2+59:SY2=360
13720 VHP=1:I=IB:J=JB:GOSUB *ELLIPSOID3.SUB
13730 '
13740 SX1=59:SY1=360*(1-RY):SX2=580*RX/2+59:SY2=360*(1-RY/2)
13750 VHP=2:I=IB:J=KB:GOSUB *ELLIPSOID3.SUB
13760 '
13770 SX1=580*RX/2+59:SY1=360*(1-RY/2):SX2=580*RX+59:SY2=360
13780 VHP=3:I=KB:J=JB:GOSUB *ELLIPSOID3.SUB
13790 'DRAW.COLOR=1:VHP=0:IJK=0:GOSUB *COMMON3:DRAW.COLOR=4
13800 '
13810 GOSUB *TITLE.BACK3:'FL$="b:e3":GOSUB *GSAVE
13820 GOSUB *TEMP
13830 RETURN
13840 '
13850 *COMMON3:
13860 SX1=59:SY1=360*(1-RY/2):SX2=580*RX/2+59:SY2=360
13870 I=IB:J=JB:GOSUB *ELLIPSOID3.SUB
13880 '
13890 SX1=59:SY1=360*(1-RY):SX2=580*RX/2+59:SY2=360*(1-RY/2)
13900 I=IB:J=KB:GOSUB *ELLIPSOID3.SUB
13910 '
13920 SX1=580*RX/2+59:SY1=360*(1-RY/2):SX2=580*RX+59:SY2=360
13930 I=KB:J=JB:GOSUB *ELLIPSOID3.SUB
13940 'SX1=580*RX/2+59:SY1=360*(1-RY):SX2=580*RX+59:SY2=360*(1-RY/2)
13950 RETURN
13960 '
13970 *ELLIPSOID3.SUB:
13980 UO=VO(IB):UL=VL(IB)
13990 VO=VO(JB):VL=VL(JB)
14000 DU=VD(IB):SU=VS(IB)
14010 DV=VD(JB):SV=VS(JB)
14020 '
14030 LINE(SX1,SY1)-(SX2,SY2),GRP.COLOR,B
14040 RR=2:GOSUB *X.SCALE2
14050 RR=2:GOSUB *Y.SCALE2
14060 'RR=2:GOSUB *DOT.PLOT
14070 GOSUB *DRAW.ELLIPSE3
14080 RETURN
14090 '
14100 ' *** 三面鏡 ***
14110 '
14120 *DRAW.ELLIPSE3:
14130 'DRAW.COLOR=4
14140 WUO=UO-UL:WUL=UO+UL
14150 WVO=VO-VL:WVL=VO+VL
14160 WINDOW(WUO,-WVL)-(WUL,-WVO)
14170 VIEW(SX1,SY1)-(SX2,SY2)
14180 '
14190 IF IJK<>0 THEN GOSUB *COMMON.WF
14200 IF IJK=0 AND STAGE$="1" THEN GOSUB *CONTOUR
14210 IF IJK=0 AND STAGE$="2" THEN GOSUB *CONTOUR
14220 'IF IJK=0 AND STAGE$="2" THEN GOSUB *SECTION
14230 'GOSUB *COMMON.WF
14240 'GOSUB *CONTOUR
14250 'GOSUB *SECTION
14260 '
14270 WINDOW(0,0)-(639,399)
14280 VIEW(0,0)-(639,399)
14290 RETURN
14300 '
14310 ' *** 3次元切断面の輪郭 ***
14320 '
14330 *SECTION3:
14340 AZ(1,1)=HESSE(IB,IB)
14350 AZ(1,2)=HESSE(IB,JB)
14360 AZ(1,3)=HESSE(IB,KB)
14370 AZ(2,1)=AZ(1,2)
14380 AZ(2,2)=HESSE(JB,JB)
14390 AZ(2,3)=HESSE(JB,KB)
14400 AZ(3,1)=AZ(1,3)
14410 AZ(3,2)=AZ(2,3)
14420 AZ(3,3)=HESSE(KB,KB)
14430 NZ=3:GOSUB *INVERSE
14440 '
14450 BIAS=0:' [*]
14460 FOR I=1 TO 3
14470  FOR J=1 TO 3:COV(I+BIAS,J+BIAS)=BZ(I,J):NEXT J
14480 NEXT I
14490 RETURN
14500 '
14510 ' *** タイトル ***
14520 '
14530 *TITLE.BACK3:
14540 LX=INT((580*RX+59)/8)
14550 LY=INT(360*(1-RY)/16)
14560 LZ=INT((290*RX+59)/8)
14570 L1$="ellipsoid projection of "
14580 L2$="v"+MID$(STR$(IB),2)+"-"
14590 L3$="v"+MID$(STR$(JB),2)+"-"
14600 L4$="v"+MID$(STR$(KB),2)+" space"
14610 L$=L1$+L2$+L3$+L4$
14620 LOCATE LZ-LEN(L$)\2,LY-3:PRINT L$
14630 '
14640 LOCATE LX+3,LY:PRINT "v components: "
14650 FOR K=1 TO M0
14660  V$="v"+MID$(STR$(K),2)+"="
14670  LOCATE LX+3,LY+K+1:PRINT V$;:PRINT V(K)
14680 NEXT K
14690 '
14700 LOCATE LX+3,19:PRINT "horizontal|"
14710 LOCATE LX+3,20:PRINT "-------------------"
14720 LOCATE LX+3,21:PRINT " vertical | profile"
14730 RETURN
14740 '
14750 ' ** VRAM SAVE **
14760 '
14770 *GSAVE:
14780 DEF SEG=&HA000
14790 BSAVE FL$+".CHR",&H0,&HFA0
14800 DEF SEG=&HA200
14810 BSAVE FL$+".ATR",&H0,&HFA0
14820 DEF SEG=&HA800
14830 BSAVE FL$+".BLU",&H0,&H7D00
14840 DEF SEG=&HB000
14850 BSAVE FL$+".RED",&H0,&H7D00
14860 DEF SEG=&HB800
14870 BSAVE FL$+".GRN",&H0,&H7D00
14880 RETURN
 
 
===================================
 
【3】プログラムの概説
 
 コラム「高次元の正多胞体」が「ロボットアームと6次元直方体」の続編だったように,このシリーズは「ロボットアームと6次元楕円体」の続編です.
 
 前編「ロボットアームと6次元楕円体」で紹介したプログラムは,
  (1)6次元楕円を直接指定した2次元平面(3次元空間)へ投影する
ものだったのですが,続編ではそれを
  (a)6次元楕円の任意の超平面での切り口をm次元空間に投影する(あるいは,m次元空間での切り口か正射影を求める)
  (b)それを指定した2次元平面(3次元空間)へ投影する
といった2ステップ方式の投影方法に変更しています.
 
 (a)を行う際,行列Mを,m次元空間での切り口か正射影かに応じて
  α2~α1=0   → M=[A]
  α2~α1=D~C → M=[A−BD~C]
とすれば,切り口の正射影を求めたり,正射影の切り口を求めたりすることもできるようになります.
 
 6次元楕円の2次元平面および3次元空間への正射影を考えると,3次元空間への正射影(3次元楕円)を2次元平面に投影した楕円と,最初から2次元平面に正射影した楕円は一致します.
 
 それに対して,6次元楕円の2次元平面での切り口と3次元空間での切り口(3次元楕円)を2次元平面に投影したものでは,楕円の大きさが一致しません.2次元切り口は3次元切り口の2次元平面での切り口であって,3次元切り口の2次元平面への正射影ではないからです.
 
 歯切れの悪い説明で申し訳ありませんが,正射影の正射影は正射影ですが,切り口の切り口は切り口であって正射影ではないために,楕円の大きさが一致しないのです.
 
 プログラム(*hyperplane)では,m次元空間の定義を
  gosub *hyperplane.def
で行っています.それに従って,
  gosub *hyperplane.1
で,分割型正方行列
  H=[A,B]
    [C,D]
を取り込んで,
  gosub *hyperplane.2,
  gosub *hyperplane.3
で,任意の超平面による切り口のm次元空間への投影:
  M=[A−Bα2~α1−(α2~α1)’C+(α2~α1)’Dα2~α1]
を計算しています.
 
 また,gosub *hyperplaneの代わりに
  gosub *hyper.contour
とすればm次元空間への正射影:M=[A−BD~C],
  gosub *hyper.section
ではm次元空間での切り口:M=[A]となります.
 
 これらの考え方については(その4)で既に説明してありますが,実際のプログラム作りに際しては,(b)についての書き直しが最小になるように配慮しました.
 
 実際に動かしてみると,*hyperplaneは思ったほどには機能せず,アイディア倒れの感なきにしもあらずでしたが,*hyper.contourや*hyper.sectionは以前作成したプログラムとの比較を行う上で,有益な情報をもたらしてくれました.
 
 また,「ロボットアームと6次元楕円体」に掲げたプログラムでは,6次元楕円を直接2次元平面に投影するため,3次元楕円の極と元の6次元楕円の極は無関係でしたが,いったん3次元空間に投影することによって,2次元楕円上に3次元楕円の極を描くことができるようになりました.
 
 なお,このプログラムは9次元以下であれば修正なしに使えますが,10次元を超えると文字列処理の部分を書き直す必要が生じます.
 
===================================