- ベストアンサー
VB座標軸の回転で渦巻き状に広がる問題
- VB座標軸の回転で広がってしまう問題の解決方法を教えてください
- VB座標軸の回転による渦巻き状広がりの修正方法について教えてください
- VB座標軸の回転で広がる現象を解消する方法を教えてください
- みんなの回答 (13)
- 専門家の回答
質問者が選んだベストアンサー
そんなにおかしそうには思いませんが、気がつかないバグが潜んでいるのかなあ。 デバッガを使えば簡単なのですが、timerを使わずに、sleepなどの実行を遅らせる命令があれば、それ入れ、ループで回せばデバッガを使えるようになりませんかねえ。 それか、Timerやジョイスティックに依存しないサブルーチンを作ってユニットテストする方法もあります。 No.7に書いたプログラムは、ジョイスティック部分を除いて簡単なユニットテストをしております。複雑な動作はテストされていませんので思わぬ勘違いが潜んでいる可能性も無いとは言えませんので、後でもう少し複雑なテストをしてみます。 No.12に書いたDimの移動ですが、ブロックの中で宣言した場合には変数の寿命がブロックの寿命より長くなり、スコープと一致しないので、ブロックの外に出してスコープと変数の寿命が一致するほうが分かりやすいと思ったのですが、VBって変数の寿命はかなり複雑ですね。 プログラムの実行中に確実に一回しか初期化されないところに移動した方が間違いを防げるかもしれません。 VBのマニュアルざっと見ましたが、初期化はコンパイル時に行われるような記述が有ります。 Dim afLs(,) As Single = {{Cos_step, -Sin_step, 0.0}, {Sin_step, Cos_step, 0.0}, {0.0, 0.0, 1.0}} '左 は、コンパイル時にCos_step, Sin_stepは確定しているはずなので、値として大丈夫なはずですが、どうなのでしょうか。 デバッガを使えるようにプログラムを少し変更してテストするのが近道のような気がします。
その他の回答 (12)
- ki073
- ベストアンサー率77% (491/634)
あと一息のようですね。 さて、明らかなミスから Dim afLs(,) As Single = {{Cos_step, -Sin_step, 0.0}, {Sin_step, Cos_step, 0.0}, {0.0, 0.0, 0.0}} '左 Dim afRs(,) As Single = {{Cos_step, Sin_step, 0.0}, {-Sin_step, Cos_step, 0.0}, {0.0, 0.0, 0.0}} '右 で3行3列目が0.0になっています。1.0でないとおかしくなります。私自身もよくやります。 Dim afLs(,) As Single = {{Cos_step, -Sin_step, 0.0}, {Sin_step, Cos_step, 0.0}, {0.0, 0.0, 1.0}} '左 Dim afRs(,) As Single = {{Cos_step, Sin_step, 0.0}, {-Sin_step, Cos_step, 0.0}, {0.0, 0.0, 1.0}} '右 後は、変数のスコープと寿命の関係から、初期化のタイミングを考える必要が有ります。 VB, VBA, VB.NETで変数のスコープと寿命がどうも違うようで、ほとんど理解できていないのですが、、、 理解が間違っているかも知れませんが、一応書いていきます。 プログラム全体として、 Sub ABCD loop No.11のお礼欄のプログラム end loop end Sub のような感じでしょうか? 要するに、サブルイーチンはTimerで毎回呼び出されるのではなく、Timerによってその都度loopが実行されるように思っています。そうすると、変数の寿命は一旦動き出すとプログラムが終了するまであるように思うのですがどうでしょうか? (根拠として、Dim af(,) の寿命がプログラム終了まで続いてもらわないとおかしいくなる) そうすると、Dim afMs(,), Dim afLs(,), Dim afRs(,)も1回しか初期化されないように思われます。さいわい、afLs, afRsの角度は変わらないようですので、Dim宣言の場所をSub直後に移動して、loopの中で、変化するパラメータだけ変更するのはいかがでしょうか。 実質的には移動だけでは動作は変わらないと思います。 Sub ABCD Dim Sin_step, Cos_step As Single B = 1.0 / 24.0 * Math.PI Sin_step = Math.Sin(B) Cos_step = Math.Cos(B) Dim formation0(,) As Single = {{robot1_x0, robot2_x0, robot3_x0}, {robot1_y0, robot2_y0, robot3_y0}, {1, 1, 1}} '基本隊形 Dim formation(,) As Single = {{robot1_x, robot2_x, robot3_x}, {robot1_y, robot2_y, robot3_y}, {1.0, 1.0, 1.0}} '変換後隊形 Dim afMs(,) As Single = {{1.0, 0.0, X_step}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}} '直進 Dim afLs(,) As Single = {{Cos_step, -Sin_step, 0.0}, {Sin_step, Cos_step, 0.0}, {0.0, 0.0, 1.0}} '左 Dim afRs(,) As Single = {{Cos_step, Sin_step, 0.0}, {-Sin_step, Cos_step, 0.0}, {0.0, 0.0, 1.0}} '右 Dim af(,) As Single = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}} Dim aft(,) As Single = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}} loop No.11のお礼欄のプログラムの残り ただし、 '直進 Case in3 To in4 'joystick中央付近 の後に X_step= 2.0 * slottle_x afMs(2,2)=X_step を追加して、移動量を毎回変更。Bは使われていませんので B = 0.0は削除
お礼
少し変則的なプログラムをしています。 Sub ボタン1 クリック Timer1.Enable=True End Sub Sub Timer1.Enable = True Call afin(~変数~) '関数呼出し=Call End Sub Sub afin(~変数~) 行列宣言、計算式など (今回のプログラム) End Sub このような形式にしているのは、TimerのSubがメインであり、afinで計算された変数を使ってさらに計算するため、アフィン変換を関数化しているからです。 今回のご指摘を受けて、Sub afinを解体し、Sub Timer1に編入してみましたが、改善はされませんでした。 (Timer1自体がループなので変わらないのは当たり前なんですがね。。。) Timerを使わずにループを使えばいいんでしょうが、ほかの処理の関係で使わざるを得ない状態です。 値がバラけるのはどこかの行列式でインクリメントしてしまっているんでしょうか。。。 あとは半径が生まれるという問題が解決できれば完成にだいぶ近づく段階まできているので試行錯誤を繰り返してみます。
- ki073
- ベストアンサー率77% (491/634)
1) VBは特有の作法は分かりませんので、CやFortran, Rubyあたりでは問題になりそうな所から、 No.9のお礼欄に書かれているプログラム全体がloopで回っているように思いますので、その前提ですが 最初の方に B = -1 / 24 * Math.PI とありますが、多くの言語では整数どおしの割り算の結果は整数になり、 -1 / 24とすると0になる場合が多いです。 B = -1.0 / 24.0 * Math.PI とする方が無難かもしれません。 もうひとつ Dim formation0(,) As Single = {{robot1_x0, robot2_x0, robot3_x0}, {robot1_y0, robot2_y0, robot3_y0}, {1, 1, 1}} のようにDim ~ ={..のように宣言と初期値の設定がありますが、ループが2周目になった時に、 formation0などの配列が二重定義になってしまうように感じますが、VBでは宣言文の性格よりも代入文の性格が強いのでしたら問題が無いのかもしれません。エラーや警告が出ないのでしたら、問題ない可能性が高いですが。ちょっと気になる点です。 2) 言語の違いではなく、アルゴリズム上問題になりそうなところです。 最初の行に Select Case joyx 'ジョイスティック とあり、真ん中あたりに Select Case joyx 'ジョイスティックX軸 とあります。二回ジョイスティックの状態を見ているのですが、同じ状態である保証はありません。同じ状態だという前提に書かれているように思いますので、一度の判断で分岐した方が良いと思います。 3) 行列の積の計算が4カ所ありますが、残念ながら積にはなっていません。 簡単な方からみると、最後の方の formation(i, j) = af(i, k) * formation0(k, j) だと、formation(i, j) の各要素を事前に0にしておき,加算する必要があります。 For i = 0 To 2 For j = 0 To 2 formation(i, j) =0.0 Next Next For i = 0 To 2 For j = 0 To 2 For k = 0 To 2 formation(i, j) = formation(i, j)+af(i, k) * formation0(k, j) Next Next Next のような感じになります。 その上の af(i, j) = af(i, k) * afLs(k, j) af(i, j) = af(i, k) * afMs(k, j) af(i, j) = af(i, k) * afRs(k, j) の3つですが、直前のafの値に代入していますし、ループの最中にafの要素がどんどん書き変わっていますのでおかしくなります、一時的に変数aftを作り0で初期化します。 For i = 0 To 2 For j = 0 To 2 aft(i, j) =0.0 Next Next 次に aft(i, j) = aft(i, j)+af(i, k) * afLs(k, j) のようにafが変わらないように行列の計算し、後で For i = 0 To 2 For j = 0 To 2 af(i, j) =aft(i, j) Next Next のようにコピーする方法をとる必要があります。 他にもあるかも知れませんが、まず気がついたところです。
お礼
ありがとうございます! 先程まで制作していました。 ご指摘された部分を直しました。 行列の宣言についてはサブルーチンの外で宣言をするとエラーが消えないため、サブルーチンの中です。 そのほかはエラーなしです。 現状、直進については問題なし。 robot1_xそのほかも順調に値を変えます。 しかし、回転の部分に問題がありました。 回転をすると画面外に出るほど値が大きくなったりします。 時折画面に戻ってきます。 その時に表示されている隊形を見ると、前後の隊形で回転をしているので、隊形の回転自体には成功しているようです。 問題は隊形がその場で回転せずに、隊形を回転させながら最初の位置を原点に大きな半径を持って回転することです。 (わかりづらい表現で申し訳ありません) 観測している値を見ると、隊形の中心から他のロボットたちは±20の位置にいるので中心から±20で回転をしなけらばならないのに、±1000程度の移動をするので結果として画面から切れています。 これとは別なのですが、直進する際のラジアンはB=0.0なのかB=B なのかのどちらでしょうか? 現状はB=0.0にしています。 改善したプログラムです。 'X軸を基軸としてアフィン変換 Dim Sin_step, Cos_step As Single Sin_step = Math.Sin(B) Cos_step = Math.Cos(B) Dim X_step As Single '直進距離 X_step = 2.0 * slottle_x Dim i, j, k As Integer '行列計算用 Dim formation0(,) As Single = {{robot1_x0, robot2_x0, robot3_x0}, {robot1_y0, robot2_y0, robot3_y0}, {1, 1, 1}} '基本隊形 Dim formation(,) As Single = {{robot1_x, robot2_x, robot3_x}, {robot1_y, robot2_y, robot3_y}, {1.0, 1.0, 1.0}} '変換後隊形 Dim afMs(,) As Single = {{1.0, 0.0, X_step}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}} '直進 Dim afLs(,) As Single = {{Cos_step, -Sin_step, 0.0}, {Sin_step, Cos_step, 0.0}, {0.0, 0.0, 0.0}} '左 Dim afRs(,) As Single = {{Cos_step, Sin_step, 0.0}, {-Sin_step, Cos_step, 0.0}, {0.0, 0.0, 0.0}} '右 Dim af(,) As Single = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}} Dim aft(,) As Single = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}} 'アフィン変換 'aftを0で初期化 For i = 0 To 2 For j = 0 To 2 aft(i, j) = 0.0 Next Next Select Case joyx 'ジョイスティックX軸 '左 Case inmin To in3 'joystick左寄り B = -1.0 / 24.0 * Math.PI For i = 0 To 2 For j = 0 To 2 For k = 0 To 2 aft(i, j) = aft(i, j) + af(i, k) * afLs(k, j) Next Next Next '直進 Case in3 To in4 'joystick中央付近 B = 0.0 For i = 0 To 2 For j = 0 To 2 For k = 0 To 2 aft(i, j) = aft(i, j) + af(i, k) * afMs(k, j) Next Next Next '右 Case in4 To inmax 'joystick右寄り B = 1.0 / 24.0 * Math.PI For i = 0 To 2 For j = 0 To 2 For k = 0 To 2 aft(i, j) = aft(i, j) + af(i, k) * afRs(k, j) Next Next Next End Select 'afにaftを代入 For i = 0 To 2 For j = 0 To 2 af(i, j) = aft(i, j) Next Next 'アフィン変換合成 For i = 0 To 2 For j = 0 To 2 formation(i, j) = 0.0 Next Next For i = 0 To 2 For j = 0 To 2 For k = 0 To 2 formation(i, j) = formation(i, j) + af(i, k) * formation0(k, j) Next Next Next robot1_x = formation(0, 0) '一行一列成分 robot1_y = formation(1, 0) robot2_x = formation(0, 1) robot2_y = formation(1, 1) robot3_x = formation(0, 2) robot3_y = formation(1, 2)
- ki073
- ベストアンサー率77% (491/634)
ものすごく忙しかったので先ほど見たところです。 やっと時間ができたので、明日にでもきっちり見てみます。お待ちください。 ぱっと見た感じで理解できそうです。 他の方も気がつかれたらよろしく。
お礼
ありがとうございます! このプログラムはTimerで回しています(while~loopのようなもの) inmin,in1,in2,~,inmaxというのはjoystickの傾き値の具合です。 これで左、右、中央を判断しています。 この部分を使った他のプログラムでは大丈夫でした。 X_step = 2.0 * slottle_x slottle_xとはjoystickのy軸の傾きの度合いです。 傾きに比例して0~1で変化するようにしています。 Dim~As Single というのは変数の宣言です。 このプログラムでrobot1_x,robot1_yの値を検出すると、どちらも0になってしまいます。 robot1_x,robot1_yは書いてはいませんが上の方で定義、値の代入済みです。 お忙しい中ありがとうございます。 どうぞよろしくお願いします。
- ki073
- ベストアンサー率77% (491/634)
No.8のお礼欄の通りです。 行列の中の1.0をわすれて0.0にしてしまうことがありますので、注意してください。 結構美しいでしょう。
お礼
お久しぶりです。まだこのページを覚えてらしていれば良いのですが。。。 ここ一週間でプログラムを制作してみました。 行列の使い方などを図書館で専門書を借りて学んでみたりしたので時間が掛かり、すぐにお礼とお返事をできなくて申し訳ありません。 制作したプログラムを見て欲しいのです。 現状、すべての値が0になるのでどこがおかしいのかと。。。 VBをかじっていないようですが、VBはCがわかればわかる簡単な言語ですので、よろしければお願いします。 プログラムからコピペしたので、変な改行があって見づらいかもしれません。 inmin~inmaxはjoystickの傾きです。 ほかの関数はある程度、サンプルプログラムに合わせました。 Select Case joyx 'ジョイスティック Case inmin To in3 '左 B = -1 / 24 * Math.PI Case in3 To in4 '直進 B = B Case in4 To inmax '右 B = 1 / 24 * Math.PI End Select 'X軸を基軸としてアフィン変換 Dim Sin_step, Cos_step As Single Sin_step = Math.Sin(B) Cos_step = Math.Cos(B) Dim X_step As Single '直進距離 X_step = 2.0 * slottle_x Dim i, j, k As Integer '行列計算用 Dim formation0(,) As Single = {{robot1_x0, robot2_x0, robot3_x0}, {robot1_y0, robot2_y0, robot3_y0}, {1, 1, 1}} '基本隊形 Dim formation(,) As Single = {{robot1_x, robot2_x, robot3_x}, {robot1_y, robot2_y, robot3_y}, {1.0, 1.0, 1.0}} '変換後隊形 Dim afMs(,) As Single = {{1.0, 0.0, X_step}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}} '直進 Dim afLs(,) As Single = {{Cos_step, -Sin_step, 0.0}, {Sin_step, Cos_step, 0.0}, {0.0, 0.0, 0.0}} '左 Dim afRs(,) As Single = {{Cos_step, Sin_step, 0.0}, {-Sin_step, Cos_step, 0.0}, {0.0, 0.0, 0.0}} '右 Dim af(,) As Single = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}} 'アフィン変換 Select Case joyx 'ジョイスティックX軸 '左 Case inmin To in3 'joystick左寄り For i = 0 To 2 For j = 0 To 2 For k = 0 To 2 af(i, j) = af(i, k) * afLs(k, j) Next Next Next '直進 Case in3 To in4 'joystick中央付近 For i = 0 To 2 For j = 0 To 2 For k = 0 To 2 af(i, j) = af(i, k) * afMs(k, j) Next Next Next '右 Case in4 To inmax 'joystick右寄り For i = 0 To 2 For j = 0 To 2 For k = 0 To 2 af(i, j) = af(i, k) * afRs(k, j) Next Next Next End Select 'アフィン変換合成 For i = 0 To 2 For j = 0 To 2 For k = 0 To 2 formation(i, j) = af(i, k) * formation0(k, j) Next Next Next robot1_x = formation(0, 0) '一行一列成分 robot1_y = formation(1, 0) robot2_x = formation(0, 1) robot2_y = formation(1, 1) robot3_x = formation(0, 2) robot3_y = formation(1, 2)
- ki073
- ベストアンサー率77% (491/634)
formtion0はアフィン変換で一番右側の列ベクトルです。列ベクトルを3つ合わせて行列にしただけです。 1行1列 リーダーのx 1行2列 リーダーのy 2行1列 サブ1のx 2行2列 サブ1のy 3行1列 サブ2のx 3行2列 サブ2のy ではなく、行列が逆です。 1行1列 リーダーのx 2行1列 リーダーのy 1行2列 サブ1のx 2行2列 サブ1のy 1行3列 サブ2のx 2行3列 サブ2のy それと、Ystep=2にしたいのなら、X軸方向を向いている編隊を、formtion0修正してY軸方向に向けてください。 Xstepは0に変更してください。(Y軸方向を向く編隊にして、afMsをY軸方向の移動だけにする)
お礼
それぞれの座標をあらわすのは列ベクトルですから |x| |y| |1| でしたね。 これをリーダー、サブ1、サブ2の順において行列にしているわけですか。 それと、Xを進行方向にとっていて、Xstep,cosA,sinAで座標をとっているからYstepは考えなくてよかったのか!! 勘違いしてました。 夜通しちょっと作ってみます!!
- ki073
- ベストアンサー率77% (491/634)
アフィン変換はNo.1でリンクしているものと同じ書き方です。 Rubyで書いてありますが、多分やり方は理解できると思います。 afが順次変化していきますが、formation0, afMs, afLs, afRsは変化しません。 編隊の中心座標と、向いている方向はafの値を見るとわかります。 大きな勘違がないといいのですが、(多分大丈夫だと思います) require "matrix" Xf1=1.0 Xf2=-1.0 Yf2=1.0 Xstep=2.0 Cos_step=Math.cos(15.0/180.0*Math::PI) Sin_step=Math.sin(15.0/180.0*Math::PI) # formation0[0,0], formation0[1,0]がリーダーの初期位置 # formation0[0,1], formation0[1,1]がメンバーの初期位置 # formation0[0,2], formation0[1,2]がメンバーの初期位置 # 0,0が編隊の回転中心です formation0=Matrix[[Xf1, Xf2, Xf2], [0.0, Yf2, -Yf2], [1.0, 1.0, 1.0]] # 1ステップの前進移動 formation0の進行方向の成分(X方向)だけです afMs=Matrix[[1.0, 0.0, Xstep], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] # 1ステップの回転 afLs=Matrix[[Cos_step, -Sin_step, 0.0], [Sin_step, Cos_step, 0.0], [0.0, 0.0, 1.0]] afRs=Matrix[[Cos_step, Sin_step, 0.0], [-Sin_step, Cos_step, 0.0], [0.0, 0.0, 1.0]] # アフィン変換行列の初期値(何も移動しない) af=Matrix[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] loop{ case ジョイスティックの位置 when 前 then af=af*afMs when 左 then af=af*afLs when 右 then af=af*afRs end formation=af*formation0 # formation[0,0], formation[1,0]がリーダーの現在位置 # formation[0,1], formation[1,1]がメンバーの現在位置 # formation[0,2], formation[1,2]がメンバーの現在位置 }
お礼
わざわざソースコードを書いていただき、ありがとうございます! 概ねどうしたらいいか理解できました! afが変わっていくから進んでいくことが納得いきました! あと少しだけ分からないところ・確認したいところがあるので質問します。 > Xf1=1.0 Xf2=-1.0 Yf2=1.0 Xstep=2.0 XstepがX方向の移動量ってことはわかったのですが、他の変数が何なのかがちょっと・・・ (Ystepも2.0でいいんですよね?) 次の行列formation0が基本行列みたいなので座標なんだとは思いますが。 変数がなんなのかがわからないために > formation0=Matrix[[Xf1, Xf2, Xf2], [0.0, Yf2, -Yf2], [1.0, 1.0, 1.0]] のところが少し考えています・・・(符号など) 値を代入すると2行目が凸の三角形になることは分かりました。 > # 0,0が編隊の回転中心です これはリーダーのx座標のことなのでしょうか? あとは座標のことですが、formation0,formationは3行3列の行列で 1行1列 リーダーのx 1行2列 リーダーのy 2行1列 サブ1のx 2行2列 サブ1のy 3行1列 サブ2のx 3行2列 サブ2のy それぞれの3列目は無視していいと理解しています。
- ki073
- ベストアンサー率77% (491/634)
質問者さんから素早いレスポンスがあるので、回答する側も気分がのってきます。 お礼欄に書くと回答者にすぐメールが来ますので、こちらの確認する手間が省けますので、できればお礼欄でお願いします。 (補足欄はここに見にこないと分からないのです)、中には質問者さんのお礼率を見てとやかく言う人もおりますので、お礼欄の方がそう取られないので、書き込めるお礼欄を使い果たしてしまったら、やむなく補足欄にという質問者さんもいます。sabrina485さんが今やっているように補足欄に書くのが本来の使い方なのでしょうが、使う側としてはその方が使いやすいように思います。 さて、No.5の補足欄についてですが、 書いておられるように、現在位置が順次動いていくのですから、現在位置をデータとしてもっておき、ジョイステックの状態によって順次動かしていく発想が自然なのですが、考えたのは、編隊の最初の座標を覚えておき、現在位置に変換する式の係数を変えていくという方式です。(前者のやり方では、式の係数を変えず現在位置を変えていく方法) ジョイスティックの状態によって変換行列を変えていく方が多くのメリットがあるように思います。 少なくとも、進行方向をを知らなくても、編隊の先頭方向に動いてくれることや、前回の回答の拡大される問題も簡単に解決します。 変換行列を変えていくのもものすごく簡単なのです。 本日中にはソースコードを書き込んでおきます(VBではないですが、やっていることはVBより分かりやすと思います)
お礼
ありがとうございます。 二つのやり方で、使うデータの保持などが違っていたのですね。 変数を保持しておくなど私の中でごちゃごちゃになっていた部分があったみたいです。 ソースコードは大変助かります。お待ちしています。
- ki073
- ベストアンサー率77% (491/634)
3行3列と3行3列の積のサブルーチンはできましたでしょうか。これさえできれば、もう完成したようなものです。 VBは全く使ったことがないので、二次元配列を関数の値として返せたら便利なのですが、CやFortranのイメージからすると、関数ではなく、サブルーチンになるのではないかと思います。 まずは確認。それから進めましょう。 それとちょっと気になったところが、 >A=A±1/24π ではなく、 A=±1/24πになるはずなのですが、Aは回転の角速度なので。単なる書き間違いだと思いいますが。
補足
このリンク先のページの一番下の式がアフィン変換を表す敷みたいです。 http://msdn.microsoft.com/ja-jp/library/vstudio/8667dchf(v=vs.100).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1 Matrixの宣言がよくわからなかったので回転・平行移動の行列を分解しました。 (長々と書いてたのですが添削してたら消えてしまいました) x'= x*cosA - y*sinA + Tx y'= x*sinA + y*cosA + Ty 前回のご回答で気になった点があるので質問です。 >例えば、回転中心0,0, リーダーの初期座標1,0 メンバーの座標0, 1と0, -1とした三角形としたときに、これは最後まで変化させません。 列ベクトルのところにそれぞれこれらの変化しない値を入れて計算するだけです。 基本的には移動先の座標は直接計算時には考慮しませんが、列ベクトルのx=0, y=0として同じように計算したときに、中心の現在いる座標が計算できます。 三角形は移動するので座標は変わっていきますよね? 最後まで変化させないということは、最初の三角形の座標は別に取っておくということでしょうか? それを使って計算するということはどうやって前進するのでしょう? Txが平行移動の移動量とのことですが、これに計算結果を代入するのでしょうか?(Tx=x1) 一回目の計算をx1、二回目の計算をx2とすると x2 = x*cosA - y*sinA + x1 (x、yは初期位置?) でもこれじゃ最初の一歩が動かない・・・ それともTxは移動する量で x’を計算 前進するために X=X+x’ 毎日考えすぎておかしな発言をしてるかもしれません。。。
- ki073
- ベストアンサー率77% (491/634)
質問欄の式を確認しましたが、基本的には正しいです。 というのも、ちょっと気になる点を確認します。 1) cosθ, sinθの値は、それぞれθが10度固定で、一回の計算で10度回転して、36回やると元の位置に戻りますよね。 2) 何回も回転させると渦巻き状に拡がるのでしょうか?数回の回転で拡がるのであれば別の問題があるのかも知れません。 かなりの回転回数で拡がるのでしたら、計算誤差が蓄積している可能性が高いです。 sinθとcosθを別々に計算するのではなく、例えば cosθ=sqrt(1-sinθ*sinθ) にすると良くなるかもしれませんし、倍精度計算にするともう少し軽減されるかも知れません。 しかしながら、誤差の蓄積は避けられませんので、時々は隊形の位置関係から補正をかける必要があるように思います。 さて、アフィン変換に話を戻しますが、多くの利点があります。 質問欄のプログラムだと、現在の位置と、進行方向を正確に把握していないとおかしくなるのですが、 アフィン変換を使うと、現在の位置と進行方向は必要なく、簡単な計算でいつも進行方向に進んでくれます。 いきなり全部書いてしまうのは失礼かと思いますので、追加で質問があってからにしますが、非常に簡単にでします。また、上に書きました拡がる問題も簡単な方法で解決します。 (分からないことがあれば、どんどん書き込んでください)
補足
毎回ありがとうございますm(__)m 現状ではIF文で左右に傾いてる時A=A±1/24π、 dim A as single timerはinterval 200 でやっています。 >cosθ=sqrt(1-sinθ*sinθ) これは高校一年生で習ったsinとcosの置き換えの式ですね! 精度の問題もありそうですね。変えてやってみます。 広がる問題も、三角形の中心からdまで離れても良い、それ以上はdとする、という方法をとって解決しようとしたのですが、回転中にうまく機能しませんでした・・・ アフィン変換をここ数日で勉強してみて作ったプログラムなのですが、わかっている人から見ると問題があるようですね(汗) アフィン変換が便利そうで調べてみたところ、VBへの組み込み方に苦労しています。 しかし、現在位置と進行速度が必要ないというご説明から、なにか根本的なところで自分は勘違いをしていそうです・・・ 答えから自分で考えてアフィン変換の使い方について納得していきたいので、リーダーだけでも構いませんのでVBでのアフィン変換について組み込み方をご教授していただけると大変助かります。
- ki073
- ベストアンサー率77% (491/634)
No.1の補足欄について 行列の計算は習っていないとして書きます。 行列の積の計算をリンクしておきます。 http://naop.jp/text/c/gyouretu3.html 3行3列かける3行3列の場合の結果は3行3列になります。 最後のところは3行3列と3行1列との積になりますが、結果は3行1列になります。3行3列の場合の1列目だけと同じ結果です。 計算順序はひたすら左から計算していけば正しく計算できます。 そして最後の計算結果の1行1列目と、1行2列目がx'とy'となります。 例えば、回転中心0,0, リーダーの初期座標1,0 メンバーの座標0, 1と0, -1とした三角形としたときに、これは最後まで変化させません。 列ベクトルのところにそれぞれこれらの変化しない値を入れて計算するだけです。 基本的には移動先の座標は直接計算時には考慮しませんが、列ベクトルのx=0, y=0として同じように計算したときに、中心の現在いる座標が計算できます。 残りの質問については後で考えてみます。
- 1
- 2
お礼
行列式を解体して一つ一つの計算式にしたところ無事に動きました! 行列ではなくなったので、●の数を増やすことは困難になりましたが無事に完成のようです。 ありがとうございました!!