• ベストアンサー

行列を利用した座標変換をVBAでコードに

今 P1(x1、y1)   P2(x2、y2)   P3(x3、y3)      略   Pn(xn,yn) の点群があったとします。この点群が座標原点に対して 角度k度反時計方向に回転する場合の新座標値の解法に ついて(行列を用いる前提で)エクセルVBAでコード 作成のサンプルをご教示お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • inara
  • ベストアンサー率72% (293/404)
回答No.4

状況を整理します ・実験設備でデータが次々と10秒おきに入ってくる ・データは200列あたりまで連続する ・A列はx値、B列はy値、D列に新x値、E列に新y値 C列を飛ばすようなので、回転の計算は5列おきにやるわけですね。複数のデータ組を計算するプログラムを作ってみました(動作確認済み)。プログラム中の変数 M はデータ組の数です(新x値は 列5*(M-1)+4に、新y値はその次の列に書き込まれる)。MとNdataの値は適当に変えてください。 Dim i As Long, j As Long, i0 As Long, j0 As Long, i1 As Long, j1 As Long, jj As Long, Ndata As Long Dim x0 As Double, y0 As Double, c As Double, sn As Double, cs As Double Dim xy() As Double ' 回転後の xn,yn Dim Ndada As Long ' データ数 Dim M As Long ' データ組の数 Dim k As Double ' 回転角度(度) ' i0 = 1 ' x1があるセルの行 j0 = 1 ' 最初のx1があるセルの列(A列 i1 = 1 ' 回転後のx1を書き込むセルの行 j1 = 4 ' 最初の回転後x1を書き込むセルの列(D列) Ndata = 10000 ' データ数 M = 100 ' データ組の数 k = 90 ' 角度(度) ' ReDim xy(Ndata, 2) As Double c = 3.14159265358979 / 180 sn = Sin(c * k) cs = Cos(c * k) ' Application.ScreenUpdating = False ' Excelグラフの再描画を禁止する For j = 0 To M - 1 jj = j0 + 5 * j For i = 0 To Ndata - 1 x0 = Val(Cells(i0 + i, jj)) y0 = Val(Cells(i0 + i, jj + 1)) xy(i, 0) = x0 * cs - y0 * sn xy(i, 1) = x0 * sn + y0 * cs Next i Range(Cells(i1, jj + 3), Cells(i1 + Ndata - 1, jj + 4)) = xy() Next j Application.ScreenUpdating = True ' Excelグラフの再描画を許可する

catshoes01
質問者

お礼

動作速度まで試していただき完璧です。 これで極めて複雑なデータの振舞いを グラフ表示で視認できます。 ありがとうございました。

その他の回答 (3)

  • inara
  • ベストアンサー率72% (293/404)
回答No.3

一括計算するプログラムを作ってみました(動作確認済み)。マクロの作成方法と実行方法は以下のとおりです。プログラム中に変数の意味うを書いておきましたので、数値は適当に直してください。 【マクロ作成】 「ツール」→「マクロ」→「マクロ」→マクロ名に名前(kaiten)を入力→「作成」→ sub kaiten() と End Sub の間の行に以下のコードを貼り付ける 【実行方法】  ワークシートに戻り、「表示」→「ツールバー」→「Visual Basic」→出てきたツールバーの「マクロの実行(▲)」をクリック→「実行」をクリックすると計算される ↓----ここからコピー Dim i As Long, i0 As Long, j0 As Long, i1 As Long, j1 As Long, Ndata As Long Dim x0 As Double, y0 As Double, c As Double, sn As Double, cs As Double Dim xy() As Double ' 回転後の xn,yn Dim Ndada As Long ' ' データ数 Dim k As Double ' 回転角度(度) ' i0 = 1 ' x1があるセルの行 j0 = 1 ' x1があるセルの列 i1 = 1 ' 回転後のx1を書き込むセルの行 j1 = 3 ' 回転後のx1を書き込むセルの列 Ndata = 10000 ' データ数 k = 90 ' 角度(度) ' ReDim xy(Ndata, 2) As Double c = 3.14159265358979 / 180 sn = Sin(c * k) cs = Cos(c * k) ' Application.ScreenUpdating = False ' Excelグラフの再描画を禁止する Range(Cells(i1, j1), Cells(i1 + Ndata - 1, j1 + 1)).ClearContents ' 結果セルの消去 ' ' ------- xn,yn の読み込み&回転計算 ' For i = 0 To Ndata - 1 x0 = Val(Cells(i0 + i, j0)) y0 = Val(Cells(i0 + i, j0 + 1)) xy(i, 0) = x0 * cs - y0 * sn xy(i, 1) = x0 * sn + y0 * cs Next i ' ' ------- 計算結果の書き出し ' Range(Cells(i1, j1), Cells(i1 + Ndata - 1, j1 + 1)) = xy() ' Application.ScreenUpdating = True ' Excelグラフの再描画を許可する ' ↑----ここまでコピー ちなみに、このプルグラムでの計算時間はデータ数が10000で1秒くらいです。 ANo.2の方法(user関数)だと1分くらいかかります。

  • inara
  • ベストアンサー率72% (293/404)
回答No.2

どうしてもVBAで書きたいのなら、 (1) Excelワークシートで「ツール」→「マクロ」→「Visual Basic Editor」 (2) Visual Basic Editor で 「挿入」→「標準モジュール」で出てきた画面に以下をコピー Const c As Double = 3.14159265358979 / 180 Function new_x( k As Double, x As Double, y As Double) As Double new_x = x * Cos(c * k) - y * Sin(c * k) End Function Function new_y( k As Double, x As Double, y As Double) As Double new_y = x * Sin(c * k) + y * Cos(c * k) End Function (3) Excelワークシートに戻って、C1 に =new_x(90,A1,B1)、D1 に =new_y(90,A1,B1) と記入(k = 90度 の場合)し、C1とD1のセルをn 行までコピーする。 ANo.1 で書いたのと同様、 A列 に xn、B 列に yn が書かれていて、A1にx1、B1にy1があるとします。

catshoes01
質問者

お礼

すみません。何とかしてURLを探しました。 http://www.sis.otsuma.ac.jp/~tsutsumi/lecture/graphics/s6.htm このような例です。ここのURLからの引用になりますが、 Excel VBAでもできないのか?という相談です。 当方は下記のそれぞれの式の意味が全く理解できていないので P(xn,yn)としたときどう表示するかを聞きたいのですが・・・ 下記は多分エクセルではなくてVBだと思いますが・・・ Private Sub Multi_Mat_Vec_Click() Const pi = 3.1415927 Dim mat_a(1 To 2, 1 To 2) Dim vec_b(1 To 2), vec_c(1 To 2) rot_ang = Val(InputBox("回転角度は")) rot_ang = rot_ang * pi / 180 mat_a(1, 1) = Cos(rot_ang): mat_a(1, 2) = -Sin(rot_ang) mat_a(2, 1) = Sin(rot_ang): mat_a(2, 2) = Cos(rot_ang) vec_b(1) = Val(InputBox("xの値は ")) vec_b(2) = Val(InputBox("yの値は ")) '行列の掛け算の定番プログラム----------------------------------------  For i = 1 To 2 vec_c(i) = 0# For j = 1 To 2 vec_c(i) = vec_c(i) + mat_a(i, j) * vec_b(j) Next j Next i Print "変換結果は ("; Format(vec_c(1), "0.000"); ","; Format(vec_c(2), "0.000"); ")" End Sub 上記のどこにnが相当するかさえ理解できていません。

catshoes01
質問者

補足

すみません。データ量(n個)が多いのと速度を優先させるために matrixを利用したいのです。データ量は約10000行あります。 (一度に処理するデータ) これを一定の座標変換処理で A列はx値 B列はy値 として 一定の角度変換処理でD列に新x値 E列に新y値この操作が 200列あたりまで連続します。シートが数字だらけになるのです。 この操作を極力早く処理するためにMatrixを利用する必要が あるのです。

  • inara
  • ベストアンサー率72% (293/404)
回答No.1

VBAで書くほどでもないと思います。 Excelのワークシートの A列 に xn、B 列に yn が書かれているとき(A1にx1、B1にy1があるとにます) C1 に =A1*cos(k/180*PI())-B1*sin(k/180*PI()) D1 に =A1*sin(k/180*PI())+B1*cos(k/180*PI()) という式を書けば、C1 がx1'、D1 がy1'となります。あとはC1とD1をn行までコピーすれば xn, yn まで計算されます。

catshoes01
質問者

お礼

すみません。VBAコードでないと処理しきれないのです。 実験設備でデータが次々と10秒おきに入ってくる状況を 想定してください。似たような状況が存在しています。

関連するQ&A