同次座標で、平行投影から投影図法まで

このページは[url=https://www.geogebra.org/m/ddm5798j]マス旅[/url]の一部です。[br][br]前回は、アフィン変換をまるごと1つの行列で表現できましたね。[br][br]今回はアフィン変換から射影変換へと進みましょう。
1.ベクトルで、投影を数式で表そう
射影変換の行列を作る前のウォーミングアップです。[br]ベクトルと方程式の知識を使って平行投影を数式化し、[br]それを利用して点からの射影を数式化してみよう。[br][br][b][size=150]<ベクトルの表記のお約束>[br][/size][/b][br][size=150][color=#0000ff][b]ベクトルはふつうの小文字を扱い、内積だけなので、積マークは省略します[/b]。[br][/color][/size]2つのベクトルa、bの内積は、成分の積の和です。[br]「平面の方程式」は、点P(p)を通り法線ベクトルn=(a,b,c)に対して、[b][color=#0000ff][size=150]np=d(dはスカラー)[/size][/color][/b][br]「直線の方程式」は、点P(p)を通り方向ベクトルv=(i,j,k)に対して、[b][color=#0000ff][size=150]p+tv(tはスカラー)[/size][/color][/b][br][br][b][size=150]<点Pから平面πへの平行投影>[/size][/b][br][br]点P(p=(q,r,s))から法線ベクトルn=(a,b,c)の平面π:np=dに対して、v=(i,j,k)方向の影の点Qの位置をベクトルで表そう。[br]点Q(q)は直線PQ上にあるので、[b]q=p+tv[/b]とかける。[br]点Q(q)は平面πにあるので、[b]nq=d[/b][br]このqは同じだから、n(p+tv)=np+tnv=dとなり、[br][b]t=(d-np)/nv[/b][br]これから、点Qは[br][b][color=#0000ff][size=150]q=p+{(d-np)/nv} v[br][/size][/color][/b][br]この[b]平行投影[/b]をvによるπへの[b]直交射影(正射影)[/b]ともいうね。[br][br][b][size=150]<点Vを視点にして、点Pから平面πへの透視点>[br][/size][/b][br]直線PVとπの交点を点Qとする。[br]直線の方向ベクトルがv-pだから、点Q(q)は[b]q=p+t(v-p)[/b]とかける。[br]円Q(q)は平面πにあるので、[b]nq=d[/b]。[br]このpは同じだから、n(p+t(v-p))=np+tn(v-p)=dとなり、[br][b]t=(d-np)/n(v-p)[/b][br]これから、点Qは[br][size=150][b][color=#0000ff]q=p+{(d-np)/n(v-p)} (v-p)[br][/color][/b][/size][br]平行投影の数式でベクトル[b]v[/b]を[b]v-p[/b]に置き換えただけの式になったね。
2.Geogebraで確認しよう
ここまでベクトルでやったことの確認をしよう。[br][br][b][size=150][color=#9900ff][u]課題:3点の平行投影をgeogebraで視覚化しよう。[br][/u][/color][/size][/b][br]#q=p+{(d-np)/nv} vの確認[br]タイトルは「3点の平行投影」[br]空間図形を選択してアプレットの作成[br]s=slider(0.1, 0.9, 0.1)[br]p1=(1,2,3)   #投影前の位置ベクトル非表示[br]p2=(5,6,7)   #投影前の位置ベクトル非表示[br]p3=p1+s(p1-p2) #投影前の位置ベクトル非表示[br]n=(1,2,3)    #法線ベクトルは非表示[br]d=slider(-10,10,1)[br]v=(0,0,1) #投影の方向ベクトル[br]q1=p1+(d-n p1)/(n v) v #投影後の位置ベクトル非表示[br]q2=p2+(d-n p2)/(n v) v #投影後の位置ベクトル非表示[br]q3=p3+(d-n p3)/(n v) v #投影後の位置ベクトル非表示[br]#点として見るために原点にベクトルをたした点を生成します。[br]A=Point((0,0,0),p1)[br]B=Point((0,0,0),p2)[br]C=Point((0,0,0),p3)[br]D=Point((0,0,0),q1)[br]E=Point((0,0,0),q2)[br]F=Point((0,0,0),q3)[br]Segment(A,B) #青[br]Segment(A,C) #赤[br]segment(D,E) #青[br]segment(D,F) #赤[br]Vector(A,D) ♯点線で細線太さ2[br]Vector(B,E) ♯点線で細線太さ2[br]Vector(C,F) ♯点線で細線太さ2[br]#法線ベクトルnの平面nx=dと3軸との交点を決める[br]H=(0,0,d/z(n)) ♯非表示[br]G=(0,d/y(n),0) ♯非表示[br]I=(d/x(n),0,0) ♯非表示[br]#3点D,E,Fが平面に乗っかっていることを確認するため[br]Plane(H,G,I)[br][br]#dをアニメーションにすると平面が動いても、3点A,B,Cの平行投影である3点D,E,Fが予想どうり連動して動くことがわかるね。[br]
3点の平行投影
[color=#9900ff][b][u][size=150][br]課題:視点Vからの透視図をgeogebraでかこう。[br][/size][/u][/b][/color][br]#q=p+((d-np)/n(v-p)) (v-p)[br]タイトルは「三角形の透視図」[br]空間図形を選択してアプレットの作成[br][br]p1=(1,4,2)   #投影前の位置ベクトル非表示[br]p2=(2,2,4)   #投影前の位置ベクトル非表示[br]p3=(3,1,3)  #投影前の位置ベクトル非表示[br]n=(1,2,3)    #法線ベクトルは非表示[br]d=slider(5,10,1)[br]V=(-2,-2,-2)  #視点V[br]v=Vector(V)  #視点の位置ベクトル非表示[br]q1=p1+(d-n p1)/(n (v-p1)) (v-p1) #投影後の位置ベクトル非表示[br]q2=p2+(d-n p2)/(n (v-p2)) (v-p2) #投影後の位置ベクトル非表示[br]q3=p3+(d-n p3)/(n (v-p3)) (v-p3) #投影後の位置ベクトル非表示[br]#点として見るために原点にベクトルをたした点を生成します。[br]A=Point((0,0,0),p1)[br]B=Point((0,0,0),p2)[br]C=Point((0,0,0),p3)[br]D=Point((0,0,0),q1)[br]E=Point((0,0,0),q2)[br]F=Point((0,0,0),q3)[br]Polygon(A,B,C) #青[br]Polygon(D,E,F) #青[br]♯polygonを描くと、頂点を結ぶセグメントも自動生成されますのでご注意ください。[br]うっとうしかったら、自動生成されて自動表示されたセグメント6本を非表示にしよう。[br]Vector(V,A) #点線の細線(太さを標準の5から2に減らす)[br]Vector(V,B) #点線の細線[br]Vector(V,C) #点線の細線[br]#法線ベクトルnの平面nx=dと3軸との交点を決める[br]H=(0,0,d/z(n)) ♯非表示[br]G=(0,d/y(n),0) ♯非表示[br]I=(d/x(n),0,0) ♯非表示[br]#3点D,E,Fが平面に乗っかっていることを確認するため[br]Plane(H,G,I)[br][br]#dをアニメーションにすると平面が動いても、[br]3点A,B,Cの透視である3点D,E,Fが予想どうり連動して動くことがわかるね。[br]また、点Vをつかんで動かしても、連動して透視三角形ができます。
三角形の透視図
3.同次座標で透視変換
一般の平面への透視を考える前に[br]準備として、yz平面(x=0)への透視を考えよう。[br][br][b][size=150]<yz平面に透視する>[br][/size][/b][br]法線ベクトル[b]n=(1,0,0)[/b]のyz平面:[b]np=0[/b]の上に、[br]点P(p=(p1,p2,p3))の視点V(v=(v1,v2,v3))から見た透視点Qを作る。[br][br]直線PVとyzの交点を点Qとする。[br]直線の方向ベクトルがv-pだから、点Q(q)は[b]q=p+t(v-p)[/b]とかける。[br]円Q(q)はyz平面にあるので、[b]nq=0[/b]。[br]このpは同じだから、n(p+t(v-p))=np+tn(v-p)=0となり、[br][b]t=(0-np)/n(v-p)[/b][br]これから、点Qは[br]q=p-np/n(v-p) (v-p)[br][br][b]ベクトルがn=(1,0,0)だから、nとの内積はx成分どうしの積(スカラーになる)となる[/b]から、[br][b]q=p-p1/(v1-p1) (v-p) [/b]となる。[br][br]列ベクトルqの成分を詳細化してみよう。[br]q=[p1,p2,p3] - p1/(v1-p1) [v1-p1,v2-p2,v3-p3][br]=[p1-p1(v1-p1)/(v1-p1) ,p2-p1(v2-p2)/(v1-p1) ,p3-p1(v3-p3)/(v1-p1) ] [br]=[0, p2-p1(v2-p2)/(v1-p1) ,p3-p1(v3-p3)/(v1-p1)][br][br]だから、qの同次座標は、[br]q=[0, p2-p1(v2-p2)/(v1-p1) , p3-p1(v3-p3)/(v1-p1),1 ][br]=[0, p2(v1-p1)-p1(v2-p2), p3(v1-p1)-p1(v3-p3), (v1-p1)][br]=[0, p2v1-p1v2, p3v1-p1v3, v1-p1][br][br]ここで、[br]p,vの同次座標をpd=[p1,p2,p3,1]=[a1,a2,a3,a0] , vd=[v1,v2,v3,1]=[b1,b2,b3,b0]とおくと、[br]p1=a1/a0,p2=a2/a0,p3=a3/a0, v1=b1/b0,v2=b2/b0, v3=b3/b0となるので、[br]qd=[0,(a2b1-a1b2)/a0b0,(a3b1-a1b3)/a0b0, b1/b0-a1/a0][br]=[0, (a2b1-a1b2) , (a3b1-a1b3), (a0b1-a1b0)][br]=[b][color=#0000ff][size=150]{{0,0,0,0},{-b2,b1,0,0},{-b3,0,b1,0},{-b0,0,0,b1}}[/size][/color][/b] [a1,a2,a3,a0][br]=M pd[br]透視変換行列Mを求めることができました。[br][br][color=#9900ff][b][u][size=150]課題:同次座標で点Pのyz平面への点Vからの透視点Qを求めよう。[br][/size][/u][/b][/color][br]タイトルは「視点Vから点Pをyz平面に透視した点Qを同次座標で求める」[br]P=(1,4,2)   [br]p=Vector(P) #投影前の位置ベクトル非表示[br]n=(1,0,0)    #法線ベクトルは非表示[br]d=0[br]t=10 #4次元の座標[br]V=(-2,-2,-2)  #視点V[br]v=Vector(V)  #視点の位置ベクトル非表示[br]a1=x(p) t[br]a2=y(p) t[br]a3=z(p) t[br]a0= t[br]b1=x(v) t[br]b2=y(v) t[br]b3=z(v) t[br]b0= t[br]pd={{a1},{a2} ,{a3} ,{a0}} #pの同次座標[a1,a2,a3,a0][br]vd={{b1},{b2} ,{b3} ,{b0}} #vの同次座標[b1,b2,b3,b0][br]M={{0,0,0,0},{-b2,b1,0,0},{-b3,0,b1,0},{-b0,0,0,b1}} [br]qd = M pd[br]q1=Element(qd,1,1)/Element(qd,4,1)[br]q2=Element(qd,2,1)/Element(qd,4,1)[br]q3=Element(qd,3,1)/Element(qd,4,1)[br]q=(q1,q2,q3)[br]P=Point((0,0,0),p)[br]Q=Point((0,0,0),q)[br]Vector(V,P) #点線の細線(太さを標準の5から2に減らす)[br][br]点Pや点Vをつかんで動かすと、点Qも連動して変化することがわかりますね。[br]
視点Vから点Pをyz平面に透視した点Qを同次座標で求める
[b][size=150][br]<一般平面に透視する>[br][/size][/b][br]法線ベクトル[b]n=(a,b,c)[/b]のyz平面:[b]np=0[/b]の上に、[br]点P(p=(p1,p2,p3))の視点V(v=(v1,v2,v3))から見た透視点Qを作る。[br][br]直線PVとyzの交点を点Qとする。[br]直線の方向ベクトルがv-pだから、点Q(q)は[b]q=p+t(v-p)[/b]とかける。[br]円Q(q)はyz平面にあるので、[b]nq=d[/b]。[br]このpは同じだから、n(p+t(v-p))=np+tn(v-p)=0となり、[br][b]t=(d-np)/n(v-p)[/b][br]これから、点Qは[br]q=p+((d-np)/n(v-p)) (v-p)[br]=p+(d-np)(v-p)/n(v-p)[br]=p+(dv-dp-npv+npp)/(nv-np)[br]=(nvp -npp+ dv-dp-npv-npp)/(nv-np)[br]=(nvp +dv-dp-npv)/(nv-np)[br]={(nv-d)p+(d-np)v}/(nv-np)[br]=[b]{kp+(d-np)v}/(nv-np)[/b]( nv-d=kとおく。)[br]k=nv-d=av1+bv2+cv3-dだから、点pを動かしても変わらない定数扱いができる。[br]d-np=d-(ap1+bp2+cp3)=lは、成分によらない。[br]分母はnv-np=nv-d+d-np=k+(d-np)=k+l[br]分子はkp+(d-np)v=kp+lv[br]列ベクトルqの成分を詳細化してみよう。[br]q=(kp+lv)/(k+l)=[(kp1+lv1)/(k+l),(kp2+lv2)/(k+l),(kp3+lv3)/(k+l)][br]だから、qの同次座標は、[br]qd=[kp1+lv1,kp2+lv2,kp3+lv3,k+l][br]ここで、[br]p,vの同次座標をpd=[p1,p2,p3,1]=[a1,a2,a3,a0] , vd=[v1,v2,v3,1]=[b1,b2,b3,b0]とおくと、[br]p1=a1/a0,p2=a2/a0,p3=a3/a0, v1=b1/b0,v2=b2/b0, v3=b3/b0となるので、[br]k=av1+bv2+cv3-d=(ab1+bb2+cb3-db0)/b0[br]l=d-(ap1+bp2+cp3)=(da0-aa1-ba2-ca3)/a0となるので、[br]qdの第1成分=kp1+lv1[br]=(ab1+bb2+cb3-db0)/b0 *(a1/a0 )+ (da0-aa1-ba2-ca3)/a0*(b1/b0)[br]={a1(ab1+bb2+cb3-db0)+b1(da0-aa1-ba2-ca3)}/a0b0[br]={b (a1b2-a2b1)+c(a1b3-a3b1)+d(a0b1-a1b0)}/a0b0[br]qdの第2成分=kp2+lv2[br]={a2(ab1+bb2+cb3-db0)+b2(da0-aa1-ba2-ca3)}/a0b0[br]={a(a2b1-a1b2)+c(a2b3-a3b2)+d(-a2b0+a0b2)}/a0b0[br]qdの第3成分=kp3+lv3=d(a0b3-a3b0)/a0b0[br]={a3(ab1+bb2+cb3-db0)+b3(da0-aa1-ba2-ca3)}/a0b0[br]={a(a3b1-a1b3)+b(a3b2-a2b3)+d(-a3b0+a0b3)}/a0b0[br]qdの第4成分=k+l[br]=(ab1+bb2+cb3-db0)/b0 + (da0-aa1-ba2-ca3)/a0[br]={a0(ab1+bb2+cb3-db0)+b0(da0-aa1-ba2-ca3)}/a0b0[br]={a(a0b1-a1b0)+b(a0b2-a2b0)+c(a0b3-a3b0)}/a0b0[br]これらから、[br]qd=[{b (a1b2-a2b1)+c(a1b3-a3b1)+d(a0b1-a1b0)} , {a(a2b1-a1b2)+c(a2b3-a3b2)+d(-a2b0+a0b2)}[br] , {a(a3b1-a1b3)+b(a3b2-a2b3)+d(-a3b0+a0b3)},{a(a0b1-a1b0)+b(a0b2-a2b0)+c(a0b3-a3b0)}][br]=[a1(bb2+cb3-db0) +a2(-bb1) +a3(-cb1) +a0(db1),[br] a1(-ab2) + a2( ab1+cb3-db0) +a3(cb2) +a0(db2),[br] a1(-ab3) + a2(-bb3) + a3(ab1+bb2-db0) +a0(db3),[br] a1(-ab0) + a2(-bb0) + a3(-cb0) + a0(ab1+bb2+cb3)][br]=[color=#0000ff][size=150]{{bb2+cb3-db0 ,-bb1 , -cb1 , db1 },[br] {-ab2 , ab1+cb3-db0 , -cb2 , db2 },[br] {-ab3 ,-bb3 , ab1+bb2-db0 , db3 },[br] {-ab0 ,-bb0 , -cb0 , ab1+bb2+cb3 }}[/size][/color] [a1,a2,a3,a0][br]=M pd[br]透視変換行列Mを求めることができました。[br][br]形をそろえるために、[br][br]k=av1+bv2+cv3-d=(ab1+bb2+cb3-db0)/b0を利用して、[br]kb0=ab1+bb2+cb3-db0となるから、[br]M=[br]=[color=#0000ff][size=150]{{kb0-ab1, -bb1 , -cb1 , db1},[br] { -ab2, kb0-bb2 , -cb2 , db2},[br] { -ab3, -bb3 ,kb0-cb3 , db3},[br] { -ab0, -bb0 . -cb0 ,kb0+db0 }}[/size][/color][br][b]=(ab1+bb2+cb3-db0) [/b][color=#0000ff][size=150][b] E4+[b1,b2,b3,b0]{-a,-b,-c,d}[br][/b][size=200][b]=nd vd E4 - vd nd[br][br][/b][/size][b]vdは列ベクトルで、[br]nd={a,b,c,-d}は行ベクトルです。[br][/b][/size][/color]4行1列ベクトルに1行4列ベクトルをかけると4行4列の行列になり、[br]1行4列ベクトルに4行1列ベクトルをかけるとスカラーになることを利用しました。[br][br]yz平面の場合をあてはめて検証しましょう。[br](a,b,c,d)=(1,0,0,0)から、kb0=ab1+bb2+cb3-db0=b1,[-a,-b,-c,d]=[-1,0,0,0][br]Myz=diag(b1,b1,b1,b1)+{b1{-1,0,0,0},b2{-1,0,0,0},b3{-1,0,0,0},b0{-1,0,0,0}}[br]={{0,0,0,0},{-b2,b1,0,0},{-b3,0,b1,0},{-b0,0,0,b1}}[br]同じになったね。
[color=#9900ff][u][b][size=150]課題:同次座標で、点Pの一般平面への点Vからの透視点Qを求めよう。[br][/size][/b][/u][/color][br]タイトルは「視点Vから点Pを一般平面に透視した点Qを同次座標で求める」[br]#演算部[br]p1=(1,4,2)   #投影前の位置ベクトル非表示[br]p2=(2,2,4)   #投影前の位置ベクトル非表示[br]p3=(3,1,3)    #投影前の位置ベクトル非表示[br]n=(1,2,3)    #法線ベクトルは非表示[br]d=slider(5,10,1)[br]t=10 #4次元の座標[br]V=(-2,-2,-2) #視点V[br]v=Vector(V)  #視点の位置ベクトル非表示[br]#点として見るために原点にベクトルをたした点を生成します。[br]vd={{x(v) t},{y(v) t} ,{z(v) t} ,{t}} #vの同次座標[b1,b2,b3,b0]列ベクトル[br]nd={{x(n),y(n) ,z(n) ,-d}} #[a,b,c,-d]行ベクトルにするにはカッコを2重にする。[br]p1d={{x(p1) t},{y(p1) t} ,{z(p1) t} ,{t}}[br]p2d={{x(p2) t},{y(p2) t} ,{z(p2) t} ,{t}}[br]p3d={{x(p3) t},{y(p3) t} ,{z(p3) t} ,{t}}[br]E4 = Identity(4)[br]# geogebraが行ベクトル×列ベクトルが1行1列の行列とみなすため[br]m1=nd vd[br]a=Element(m1,1,1)[br]M = a E4 - vd nd[br]q1d= M p1d[br]q2d= M p2d[br]q3d= M p3d[br]#geogebraのバグ?列ベクトルか行ベクトルに設定したとしても、表示は行列なのにリスト扱いになるので、最初っからリストを作ることにした。[br]q1={Element(q1d,1,1)/Element(q1d,4,1),Element(q1d,2,1)/Element(q1d,4,1),Element(q1d,3,1)/Element(q1d,4,1)}[br]q2={Element(q2d,1,1)/Element(q2d,4,1),Element(q2d,2,1)/Element(q2d,4,1),Element(q2d,3,1)/Element(q2d,4,1)}[br]q3={Element(q3d,1,1)/Element(q3d,4,1),Element(q3d,2,1)/Element(q3d,4,1),Element(q3d,3,1)/Element(q3d,4,1)}[br]#ここから表示部[br]A=Point((0,0,0),p1)[br]B=Point((0,0,0),p2)[br]C=Point((0,0,0),p3)[br]D=(q1(1),q1(2),q1(3))[br]E=(q2(1),q2(2),q2(3))[br]F=(q3(1),q3(2),q3(3))[br]Polygon(A,B,C) #緑[br]Polygon(D,E,F) #緑[br]♯polygonを描くと、頂点を結ぶセグメントも自動生成されますのでご注意ください。[br]うっとうしかったら、自動生成されて自動表示されたセグメント6本を非表示にしよう。[br]Vector(V,A) #点線の細線(太さを標準の5から2に減らす)[br]Vector(V,B) #点線の細線[br]Vector(V,C) #点線の細線[br]#法線ベクトルnの平面nx=dと3軸との交点を決める[br]H=(0,0,d/z(n)) ♯非表示[br]G=(0,d/y(n),0) ♯非表示[br]I=(d/x(n),0,0) ♯非表示[br]#3点D,E,Fが平面に乗っかっていることを確認するため[br]Plane(H,G,I)[br][br]dをアニメーションにすると、透視図変換が正しく動いているのがわかりますね。
視点Vから点Pを一般平面に透視した点Qを同次座標で求める

Information: 同次座標で、平行投影から投影図法まで