【入門】Matlab quiverの使い方とサンプルコード集


【入門】Matlab quiverの使い方とサンプルコード集

1. まえがき:なぜベクトル場の可視化が重要なのか?

科学技術計算、特に物理学、工学、数学といった分野では、「ベクトル場」という概念が頻繁に登場します。ベクトル場とは、空間の各点にベクトルが割り当てられたものです。例えば、以下のようなものがベクトル場の具体例として挙げられます。

  • 物理学:
    • 流体の速度場(各点での流体の速度と方向)
    • 電場、磁場(各点での電場/磁場の強さと方向)
    • 力の場(重力場、ばねの力の場など)
    • 熱流束(熱が流れる方向と量)
  • 工学:
    • 構造物にかかる応力やひずみの分布
    • 熱伝導解析における温度勾配
    • 電磁界解析における電磁波の進行方向
  • 数学:
    • 関数の勾配ベクトル場(最も急峻に値が増加する方向)
    • 微分方程式の方向場(各点での解曲線の接線の方向)

これらのベクトル場を理解するためには、数式を追うだけでなく、視覚的にその構造を捉えることが非常に効果的です。ベクトル場の可視化は、パターン、特異点(ソース、シンク、渦など)、全体の振る舞いを直感的に把握する手助けとなります。

Matlabには、このベクトル場を効率的に可視化するための強力な関数がいくつか用意されています。その中でも最も基本的な関数が quiver およびその3次元版である quiver3 です。これらの関数は、各点のベクトルを「矢印」(quiver)として描画します。矢印の根元がベクトルの始点、矢印の長さがベクトルの大きさ、矢印の向きがベクトルの方向を表します。

本記事では、Matlabのquiver関数に焦点を当て、その基本的な使い方から応用、そして様々なオプション設定について、豊富なサンプルコードと共に詳細に解説します。これを読めば、あなたもMatlabでベクトル場を自在に可視化できるようになるでしょう。

2. quiver関数の基本:2次元ベクトル場を描く

quiver関数は、2次元平面上のベクトル場を矢印で描画します。最も基本的な使い方は以下の2つの形式です。

  1. quiver(U, V)
  2. quiver(X, Y, U, V)

それぞれの引数の意味と、これらの形式がどのように使われるのかを見ていきましょう。

2.1. quiver(U, V): グリッド点上に描画する最もシンプルな方法

この形式では、ベクトルの始点座標を省略します。Matlabは自動的に、UVのサイズに基づいて、等間隔のグリッド点をベクトルの始点とみなします。

  • U: 各グリッド点におけるベクトルのX方向成分(x成分)を格納した行列。
  • V: 各グリッド点におけるベクトルのY方向成分(y成分)を格納した行列。

UVは同じサイズの2次元行列である必要があります。例えば、Umn列の行列であれば、Vmn列の行列でなければなりません。この場合、quiver(U, V)は、y座標が1からmまで、x座標が1からnまでの範囲で、(y, x)というグリッド点(行列の添え字の考え方)にベクトル (U(y, x), V(y, x)) を描画します。

例1:単純な定数ベクトル場

すべての場所で同じ方向、同じ大きさを持つベクトル場を描いてみましょう。

“`matlab
% グリッド点の数を定義
rows = 10;
cols = 15;

% 各グリッド点でのX方向成分とY方向成分を定義
% すべての点で右斜め上向き (1, 1) のベクトルとする
U = ones(rows, cols); % 10×15の行列、すべての要素が1
V = ones(rows, cols); % 10×15の行列、すべての要素が1

% ベクトル場を描画
figure; % 新しい図ウィンドウを開く
quiver(U, V);

% グラフのタイトルと軸ラベルを設定
title(‘単純な定数ベクトル場 (quiver(U, V))’);
xlabel(‘X方向 (列)’);
ylabel(‘Y方向 (行)’);
grid on; % グリッド線を表示
axis tight; % 軸の範囲をデータに合わせて調整
axis ij; % Y軸の向きを反転 (行列の行方向を下向きにする場合)
% 注: デフォルトではY軸は上向きなので、axis ij は通常不要ですが、
% 行列の添え字と対応させたい場合に便利です。
% 通常の数学的なY軸の向きにしたい場合は axis ij をコメントアウトしてください。
“`

このコードを実行すると、10×15のグリッド点上に、すべて同じ長さと向き(右斜め上)の矢印が描画されます。矢印の始点は、グリッドの交点に配置されます。デフォルトでは、Matlabは矢印が重なりすぎないように自動的に長さを調整します。

quiver(U, V)形式は、UVが行列の添え字に対応するようなデータ(例えば、画像処理における勾配など)を扱う場合に直感的です。しかし、多くの物理的な問題では、ベクトルは特定のデカルト座標系上の点に関連付けられます。その場合は次の形式がより適しています。

2.2. quiver(X, Y, U, V): 始点座標を明示的に指定する

この形式では、ベクトルの始点のX座標とY座標を明示的に指定します。

  • X: 各ベクトルの始点のX座標を格納した行列。
  • Y: 各ベクトルの始点のY座標を格納した行列。
  • U: 各ベクトルに対応するX方向成分を格納した行列。
  • V: 各ベクトルに対応するY方向成分を格納した行列。

この形式を使う場合、X, Y, U, Vの4つの行列はすべて同じサイズである必要があります。例えば、すべてmn列の行列であれば、quiver(X, Y, U, V)は、各(i, j)番目の要素 (X(i, j), Y(i, j)) を始点として、ベクトル (U(i, j), V(i, j)) を描画します。

ベクトルの始点座標を指定するために、通常はmeshgrid関数を使用します。meshgridは、指定したX座標とY座標の範囲でグリッドを生成し、そのグリッド点のX座標とY座標をそれぞれ行列として返します。

例2:座標に依存するベクトル場(渦巻きのような場)

各点(x, y)におけるベクトルが (-y, x) で与えられるようなベクトル場を描画してみましょう。これは原点中心の渦巻きのような場になります。

“`matlab
% 描画する座標の範囲を定義
x_range = -2:0.2:2; % X座標を-2から2まで0.2刻みで
y_range = -2:0.2:2; % Y座標を-2から2まで0.2刻みで

% meshgridを使ってグリッド点を生成
[X, Y] = meshgrid(x_range, y_range);
% Xはy_rangeの長さの行ベクトルがx_rangeの長さだけ繰り返される行列
% Yはx_rangeの長さの列ベクトルがy_rangeの長さだけ繰り返される行列
% サイズはどちらも [length(y_range), length(x_range)]

% 各グリッド点におけるベクトルの成分を計算
% ベクトル (U, V) は (-y, x) となる場
U = -Y; % Y座標の行列をU成分とする
V = X; % X座標の行列をV成分とする
% UとVはXとYと同じサイズになります

% ベクトル場を描画
figure;
quiver(X, Y, U, V);

% グラフの設定
title(‘渦巻きベクトル場 (quiver(X, Y, U, V))’);
xlabel(‘X座標’);
ylabel(‘Y座標’);
grid on;
axis equal; % X軸とY軸のスケールを同じにする(重要!)
axis tight; % 軸の範囲をデータに合わせて調整
“`

このコードを実行すると、原点((0, 0))を中心に反時計回りの渦巻き状のベクトル場が描画されます。axis equalは、X軸とY軸の単位長さを同じにすることで、矢印の向きや長さが正しく比例して表示されるようにするために重要です。meshgridquiver(X, Y, U, V)の組み合わせは、座標系に紐づいたベクトル場を描画する際の標準的な方法です。

3. quiver関数の引数の詳細と使い分け

quiver関数の引数について、もう少し詳しく見ていきましょう。特に、X, Y, U, Vのサイズの関係性や、省略した場合の挙動について理解を深めます。

3.1. 引数のサイズと形状

quiver関数に渡すU, V、そしてもし指定するならX, Yは、すべて同じサイズの行列である必要があります。

  • UVは、描画したいグリッド点の数と同じ数の要素を持つ行列(またはベクトル)です。これらの要素が、各グリッド点におけるベクトルのX成分とY成分に対応します。
  • XYは、それぞれ対応するベクトルの始点のX座標とY座標を格納した行列(またはベクトル)です。

もしquiver(U, V)のようにXYを省略した場合、Matlabは以下のように仮定します。

  • ベクトルの始点のY座標は、行列U (またはV) の行インデックス(1から行数まで)に対応します。
  • ベクトルの始点のX座標は、行列U (またはV) の列インデックス(1から列数まで)に対応します。

つまり、行列の(i, j)番目の要素U(i, j)V(i, j)に対応するベクトルは、点(j, i)に始点を持つと解釈されます。これが、例1でxlabel('X方向 (列)'); ylabel('Y方向 (行)');と記述した理由です。行列の添え字(行, 列)が、描画上の点(X座標, Y座標)に対して(列, 行)と逆になる点に注意が必要です。axis ijはこの対応をより直感的にするための一つの方法です。

quiver(X, Y, U, V)のようにXYを明示的に指定する場合、通常はmeshgridを使って生成されたグリッド座標を行列として渡します。meshgrid(x_vec, y_vec)は、x_vecの長さnxy_vecの長さnyに対して、nynx列のX行列とY行列を生成します。このXYを使ってベクトル成分UVを計算する場合、UVも自然にnynx列の行列になります。

例3:meshgridのサイズとU, Vのサイズの確認

簡単な例でmeshgridの出力を確認し、それを使ってU, Vを計算する流れを見てみましょう。

“`matlab
x_vec = 1:3; % [1, 2, 3]
y_vec = 10:2:14; % [10, 12, 14]

[X_grid, Y_grid] = meshgrid(x_vec, y_vec);

disp(‘X_grid:’);
disp(X_grid);
% 期待される出力:
% 1 2 3
% 1 2 3
% 1 2 3

disp(‘Y_grid:’);
disp(Y_grid);
% 期待される出力:
% 10 10 10
% 12 12 12
% 14 14 14

% X_grid と Y_grid は 3×3 の行列
% これに対応する U, V も 3×3 の行列である必要がある

% 例として、U = X^2, V = Y となる場を考える
U_comp = X_grid.^2; % 各要素を二乗
V_comp = Y_grid;

disp(‘U_comp:’);
disp(U_comp);
% 期待される出力:
% 1 4 9
% 1 4 9
% 1 4 9

disp(‘V_comp:’);
disp(V_comp);
% 期待される出力:
% 10 10 10
% 12 12 12
% 14 14 14

% quiver(X_grid, Y_grid, U_comp, V_comp) で描画可能
figure;
quiver(X_grid, Y_grid, U_comp, V_comp);
title(‘meshgridとquiverの連携’);
xlabel(‘X’);
ylabel(‘Y’);
grid on;
axis equal;
“`

このように、meshgrid(x_vec, y_vec)は、y_vecの長さを「行数」、x_vecの長さを「列数」とする行列XYを生成します。ベクトル成分UVも、この[length(y_vec), length(x_vec)]というサイズになるように計算する必要があります。

3.2. スカラー場と勾配ベクトル場

quiver関数は、スカラー場の勾配を可視化するのにも非常によく使われます。勾配ベクトルは、スカラー場が最も急峻に増加する方向とその変化率の大きさを表します。Matlabのgradient関数を使うと、離散的なグリッド点上のスカラー場の勾配を簡単に計算できます。

gradient(F): 行列Fのスカラー場に対する勾配を計算します。行方向の勾配成分と列方向の勾配成分を別々の行列として返します。
gradient(F, h): グリッド間隔hを指定して勾配を計算します。
gradient(..., hx, hy): X方向とY方向で異なるグリッド間隔を指定して勾配を計算します。
gradient(Fx, Fy, F): Fx, Fyで指定されるグリッド点でのスカラー場Fの勾配を計算します。

gradient関数の出力は、quiver関数のUおよびV引数として直接使用できます。

例4:2次元ガウス関数の勾配ベクトル場

2次元ガウス関数 $f(x, y) = e^{-(x^2 + y^2)}$ の勾配ベクトル場を描画してみましょう。勾配は中心から外側に向かう場になり、中心から離れるほど勾配の大きさは小さくなります。

“`matlab
% 座標の範囲を定義
x_range = -3:0.3:3;
y_range = -3:0.3:3;

% グリッド点を生成
[X, Y] = meshgrid(x_range, y_range);

% 2次元ガウス関数を計算 (スカラー場)
F = exp(-(X.^2 + Y.^2));

% スカラー場の勾配を計算
% [Vy, Vx] = gradient(F); % デフォルトのグリッド間隔 (1) を使う場合
% または、実際の座標間隔を指定する場合:
hx = x_range(2) – x_range(1); % X方向のグリッド間隔
hy = y_range(2) – y_range(1); % Y方向のグリッド間隔
[Vy, Vx] = gradient(F, hx, hy); % gradient(F, hx, hy) の出力順は [Y方向勾配, X方向勾配] です!

% quiverに渡すための成分名をU, Vとする (U:X成分, V:Y成分)
U = Vx; % gradientの2番目の出力がX方向勾配
V = Vy; % gradientの1番目の出力がY方向勾配

% ベクトル場を描画
figure;
quiver(X, Y, U, V);

% グラフ設定
title(‘2次元ガウス関数の勾配ベクトル場’);
xlabel(‘X’);
ylabel(‘Y’);
grid on;
axis equal;
axis tight;

% 背景にスカラー場を表示してみる(オプション)
hold on; % 既存のプロットに重ねて描画
contour(X, Y, F, 15); % スカラー場の等高線を描画 (15は等高線の数)
colorbar; % カラーバーを表示
hold off; % 重ね描きモードを終了
“`

この例では、まずmeshgridでグリッド点を作り、そこでスカラー場Fを計算します。次にgradient(F, hx, hy)で勾配を計算します。ここで注意が必要なのは、gradient(F, hx, hy)の出力順が [Fy, Fx]、つまりY方向の勾配(行方向の変化率)が最初で、X方向の勾配(列方向の変化率)が次に来るということです。quiver(X, Y, U, V)ではUがX方向成分、VがY方向成分なので、U = FxV = Fyとなるように代入します。
実行すると、中心から放射状に外側に向かう矢印が描画されるはずです。contourで元のスカラー場を重ねて描画すると、矢印が等高線を直交して横切る様子(勾配の性質)がよく分かります。

4. オプション引数 (PropertyName, PropertyValue ペア)

quiver関数は、矢印の見た目や描画の挙動を制御するための多くのオプション引数を受け付けます。これらは 'PropertyName', PropertyValue のペアとして、必須引数の後に追加します。

matlab
quiver(..., 'PropertyName', PropertyValue, ...);

主なオプションを見ていきましょう。

4.1. 矢印の長さと縮尺 ('AutoScale', 'AutoScaleFactor')

デフォルトでは、quiverは矢印が密集しすぎて見づらくならないように、矢印の長さを自動的に調整(縮小)します。この自動調整の挙動は 'AutoScale' プロパティで制御できます。

  • 'AutoScale', 'on' (デフォルト): 自動調整を有効にします。
  • 'AutoScale', 'off': 自動調整を無効にします。この場合、矢印の長さはベクトルの実際の大きさ sqrt(U.^2 + V.^2) に比例します。

自動調整が 'on' の場合、矢印の長さは 'AutoScaleFactor' プロパティで調整できます。

  • 'AutoScaleFactor', factor: デフォルトの矢印の長さにfactorを掛けます。factor > 1 で長く、0 < factor < 1 で短くなります。デフォルト値は通常 0.9 です。

例5:AutoScaleのOnOffとAutoScaleFactorの調整

例2の渦巻きベクトル場を使い、AutoScaleの効果を見てみましょう。

“`matlab
x_range = -2:0.3:2; % グリッドを少し粗くする
y_range = -2:0.3:2;
[X, Y] = meshgrid(x_range, y_range);
U = -Y;
V = X;

figure;

% AutoScale ON (デフォルト)
subplot(1, 3, 1); % 1行3列のサブプロットの1つ目
quiver(X, Y, U, V);
title(‘AutoScale: on (Default)’);
axis equal tight;

% AutoScale OFF
subplot(1, 3, 2); % 2つ目
quiver(X, Y, U, V, ‘AutoScale’, ‘off’);
title(‘AutoScale: off’);
axis equal tight;
% 注意: AutoScale off では、ベクトルが大きい場所で矢印が非常に長くなることがあります。

% AutoScale ON で AutoScaleFactor を変更
subplot(1, 3, 3); % 3つ目
quiver(X, Y, U, V, ‘AutoScaleFactor’, 0.5); % デフォルトより短く
title(‘AutoScale: on, Factor: 0.5’);
axis equal tight;

% 全体の図にタイトル
sgtitle(‘quiver AutoScaleの比較’); % 図全体のタイトル
“`

'AutoScale', 'off'にすると、原点から離れるほどベクトルの大きさが大きくなるため、矢印も長くなることが分かります。'AutoScaleFactor'は、自動調整が有効な場合に、描かれる矢印の相対的な長さを調整するためのものです。

4.2. 矢印の色 ('Color')

矢印の色全体を uniform に設定するには 'Color' プロパティを使用します。

  • 'Color', colorSpec: 色指定。例えば 'r' (赤), 'b' (青), 'k' (黒), [R G B] のRGBトリプレットなど。

例6:矢印の色指定

“`matlab
x_range = -1:0.5:1;
y_range = -1:0.5:1;
[X, Y] = meshgrid(x_range, y_range);
U = ones(size(X));
V = zeros(size(Y)); % すべて右向きのベクトル場

figure;
quiver(X, Y, U, V, ‘Color’, ‘r’); % 矢印を赤色で描画
title(‘矢印の色指定’);
xlabel(‘X’);
ylabel(‘Y’);
grid on;
axis equal tight;
“`

4.3. 矢印のスタイル ('LineStyle', 'LineWidth', 'Marker')

矢印の線や先端のスタイルをカスタマイズできます。

  • 'LineStyle', lineSpec: 線のスタイル ('-' 実線, '--' 破線, ':' 点線, '-.' 一点鎖線)。
  • 'LineWidth', width: 線の太さ(ポイント単位)。
  • 'Marker', markerSpec: ベクトルの始点にマーカーを描画します ('.', 'o', 'x', etc.)。マーカーの色は 'MarkerEdgeColor''MarkerFaceColor' で指定できます。

例7:矢印のスタイルとマーカー

“`matlab
x_range = -1.5:0.5:1.5;
y_range = -1.5:0.5:1.5;
[X, Y] = meshgrid(x_range, y_range);
U = Y; % 時計回りの渦巻き場
V = -X;

figure;
quiver(X, Y, U, V, …
‘LineStyle’, ‘–‘, … % 破線
‘LineWidth’, 1.5, … % 少し太く
‘Color’, [0 0.5 0], … % 深い緑色
‘Marker’, ‘o’, … % 始点に丸マーカー
‘MarkerEdgeColor’, ‘b’, … % マーカーの縁を青色に
‘MarkerFaceColor’, ‘c’); % マーカーの内側をシアンに
title(‘矢印のスタイルとマーカー’);
xlabel(‘X’);
ylabel(‘Y’);
grid on;
axis equal tight;
“`

4.4. 矢印の先端スタイル ('ShowArrowHead', 'MaxHeadSize')

矢印の先端の形状を細かく制御できます。

  • 'ShowArrowHead', 'on' (デフォルト) または 'off': 矢印の先端を描画するかどうか。
  • 'MaxHeadSize', size: 矢印の先端の相対的なサイズを制御します。この値が大きいほど、先端が大きく描かれます。デフォルトは通常 0.3 です。これは、矢印全体の長さに対する先端の相対的な大きさとして解釈されることが多いです。

例8:矢印先端の調整

“`matlab
x_range = -1:1:1;
y_range = -1:1:1;
[X, Y] = meshgrid(x_range, y_range);
U = [1 1 1; 1 0 1; 1 1 1]; % 外側向きの場
V = [1 0 -1; 1 0 -1; 1 0 -1]; % Y成分

figure;
subplot(1, 2, 1);
quiver(X, Y, U, V, ‘MaxHeadSize’, 0.1); % 小さい先端
title(‘MaxHeadSize: 0.1’);
axis equal tight;

subplot(1, 2, 2);
quiver(X, Y, U, V, ‘MaxHeadSize’, 1); % 大きい先端
title(‘MaxHeadSize: 1’);
axis equal tight;

sgtitle(‘quiver MaxHeadSizeの比較’);
``MaxHeadSize`の値は絶対的なサイズではなく、矢印の長さや軸のスケールによって相対的に解釈されることに注意してください。試しながら調整するのが良いでしょう。

4.5. ベクトルの密度(間引き)

ベクトル場データが非常に密なグリッドで与えられている場合、すべての点を描画すると矢印が重なりすぎて見づらくなります。このような場合は、データ自体を間引いてからquiverに渡すか、quiverに間引きを指示する引数を使います。

quiver(..., s) または quiver(..., 'Scale', s): 矢印の長さをs倍します。s=0'AutoScale', 'off'と同じ効果を持ち、矢印の長さはベクトルの実際の大きさになります。s > 0 の場合、矢印の長さはベクトルの大きさのs倍になります。この引数は非推奨とされていますが、古いコードで見かけることがあります。代わりに'AutoScale', 'off'としたい場合はs=0、長さをスケーリングしたい場合は'AutoScale', 'off'quiverが出力するオブジェクトのDataLengthプロパティを後から変更するなどの方法が推奨されますが、シンプルに長さを調整するだけなら'AutoScaleFactor'を使うのが最も簡単です。

より一般的な間引きの方法は、X, Y, U, V行列自体をインデックスで間引いてからquiverに渡すことです。

例9:グリッドの間引きによるベクトル密度の調整

例2の渦巻きベクトル場を密なグリッドで生成し、間引いて描画してみましょう。

“`matlab
% 元の密なグリッド
x_range_dense = -2:0.1:2;
y_range_dense = -2:0.1:2;
[X_dense, Y_dense] = meshgrid(x_range_dense, y_range_dense);
U_dense = -Y_dense;
V_dense = X_dense;

figure;

% 間引きなしで描画 (おそらく密集しすぎる)
subplot(1, 2, 1);
quiver(X_dense, Y_dense, U_dense, V_dense);
title(‘間引きなし’);
xlabel(‘X’); ylabel(‘Y’); grid on; axis equal tight;

% 2点おきに間引いて描画
skip = 2; % 1点描画し、2点スキップする -> 3点ごとに描画
% インデックスを使って間引く:
% X(start:skip:end, start:skip:end) の形式
% 例えば、行は1行目から、列は1列目から skip+1 ごとに取得
X_sparse = X_dense(1:skip+1:end, 1:skip+1:end);
Y_sparse = Y_dense(1:skip+1:end, 1:skip+1:end);
U_sparse = U_dense(1:skip+1:end, 1:skip+1:end);
V_sparse = V_dense(1:skip+1:end, 1:skip+1:end);

subplot(1, 2, 2);
quiver(X_sparse, Y_sparse, U_sparse, V_sparse);
title([‘間引き (skip = ‘, num2str(skip), ‘)’]);
xlabel(‘X’); ylabel(‘Y’); grid on; axis equal tight;

sgtitle(‘quiverのベクトル密度調整’);
“`

このように、行列のインデックスを指定してデータを間引くことで、描画されるベクトルの密度を簡単に調整できます。X(1:skip:end, 1:skip:end)のような形式で指定すると、指定した範囲でskipおきに要素を選択できます。上記のコードではskip=2なので、1:3:endとなり、1, 4, 7, …番目の要素が選択され、3点おきに描画されます。

5. quiver3関数の基本:3次元ベクトル場を描く

quiver3関数は、3次元空間上のベクトル場を矢印で描画します。基本的な使い方はquiverの3次元版です。

最も基本的な使い方は以下の2つの形式です。

  1. quiver3(U, V, W)
  2. quiver3(X, Y, Z, U, V, W)

  3. X, Y, Z: 各ベクトルの始点のX, Y, Z座標を格納した配列。

  4. U, V, W: 各ベクトルに対応するX, Y, Z方向成分を格納した配列。

これらの配列はすべて同じサイズである必要があります。通常はmeshgridの3次元版であるmeshgrid(x_vec, y_vec, z_vec)を使ってグリッド点を生成し、X, Y, Z、そしてそれに対応するU, V, Wを計算します。

quiver3(U, V, W)のように始点座標を省略した場合、Matlabは配列の添え字を始点座標とみなします。quiverと同様、X座標が行列の列インデックス、Y座標が行インデックス、Z座標がページインデックスに対応します。通常はquiver3(X, Y, Z, U, V, W)の形式を使用します。

例10:3次元の放射状ベクトル場

原点から外側に向かう放射状のベクトル場を描画してみましょう。ベクトル (x, y, z) は、点 (x, y, z) において原点からその点へ向かう方向を指します。

“`matlab
% 座標の範囲を定義
x_range = -1:0.5:1;
y_range = -1:0.5:1;
z_range = -1:0.5:1;

% 3Dグリッド点を生成
[X, Y, Z] = meshgrid(x_range, y_range, z_range);
% X, Y, Z は size(y_range) x size(x_range) x size(z_range) の3次元配列になります

% 各グリッド点におけるベクトルの成分を計算
% 放射状ベクトル (x, y, z)
U = X;
V = Y;
W = Z;
% U, V, W は X, Y, Z と同じサイズの3次元配列になります

% ベクトル場を描画
figure;
quiver3(X, Y, Z, U, V, W);

% グラフ設定
title(‘3次元放射状ベクトル場’);
xlabel(‘X’);
ylabel(‘Y’);
zlabel(‘Z’);
grid on;
axis equal; % 軸のスケールを等しくする (重要!)
view(3); % 3次元ビューにする (デフォルト)
“`

このコードを実行すると、原点付近に集まり、外側に向かって広がる矢印の集まりが描画されます。axis equalは、3次元空間でのベクトル場の形状を歪めずに表示するために非常に重要です。

5.1. quiver3のオプション引数

quiver3関数も、quiverと同様に多くのオプション引数を受け付けます。プロパティ名と値のペアで指定します。

  • 矢印の長さと縮尺: 'AutoScale', 'AutoScaleFactor' (quiverと同じ)
  • 矢印の色: 'Color' (quiverと同じ)
  • 矢印のスタイル: 'LineStyle', 'LineWidth', 'Marker' (quiverと同じ)
  • 矢印の先端スタイル: 'ShowArrowHead', 'MaxHeadSize' (quiverと同じ)

使い方は2次元の場合と全く同じです。3Dで密集しがちなベクトル場では、特に'AutoScaleFactor'や間引き処理が重要になります。

例11:3次元ベクトル場の間引きとオプション設定

例10の放射状ベクトル場を、少し密なグリッドで生成し、間引きと色指定をして描画してみましょう。

“`matlab
% 元の密なグリッド
x_range_dense = -1:0.3:1;
y_range_dense = -1:0.3:1;
z_range_dense = -1:0.3:1;

[X_dense, Y_dense, Z_dense] = meshgrid(x_range_dense, y_range_dense, z_range_dense);

U_dense = X_dense;
V_dense = Y_dense;
W_dense = Z_dense;

% 2点おきに間引いて描画 (skip+1 = 3点ごとに描画)
skip = 2;
X_sparse = X_dense(1:skip+1:end, 1:skip+1:end, 1:skip+1:end);
Y_sparse = Y_dense(1:skip+1:end, 1:skip+1:end, 1:skip+1:end);
Z_sparse = Z_dense(1:skip+1:end, 1:skip+1:end, 1:skip+1:end);
U_sparse = U_dense(1:skip+1:end, 1:skip+1:end, 1:skip+1:end);
V_sparse = V_dense(1:skip+1:end, 1:skip+1:end, 1:skip+1:end);
W_sparse = W_dense(1:skip+1:end, 1:skip+1:end, 1:skip+1:end);

figure;
quiver3(X_sparse, Y_sparse, Z_sparse, U_sparse, V_sparse, W_sparse, …
‘Color’, [0.8 0.2 0.2], … % 赤っぽい色
‘LineWidth’, 0.8, … % 少し細め
‘AutoScaleFactor’, 0.7); % 矢印を短く

title(‘3次元ベクトル場 (間引き & オプション)’);
xlabel(‘X’);
ylabel(‘Y’);
zlabel(‘Z’);
grid on;
axis equal;
view(3);
box on; % 枠を表示
“`

3次元のデータの間引きも、2次元と同様に行列インデックスを使って行います。3次元配列なので、インデックス指定が3つになります。

6. 応用例

ここでは、quiver関数を使った具体的な応用例をいくつか紹介します。

6.1. 2次元ポテンシャル流れの速度場

流体力学におけるポテンシャル流れは、速度ベクトルがスカラー関数(速度ポテンシャル)の勾配で与えられる流れです。例えば、原点にあるソース(湧き出し)とシンク(吸い込み)による速度場を考えてみましょう。

ソースによる速度ポテンシャルは $\phi_{source}(r) = \frac{Q}{2\pi} \ln r$、シンクによる速度ポテンシャルは $\phi_{sink}(r) = -\frac{Q}{2\pi} \ln r$ となります。ここで、$r = \sqrt{x^2 + y^2}$ は原点からの距離、$Q$ は流量です。速度ベクトル $\mathbf{v} = (u, v)$ は速度ポテンシャルの勾配、つまり $\mathbf{v} = \nabla \phi = (\frac{\partial \phi}{\partial x}, \frac{\partial \phi}{\partial y})$ で与えられます。

原点にソース、点 (x0, y0) にシンクがある場合の合成速度ポテンシャルは、重ね合わせの原理により $\phi(x, y) = \phi_{source}(x, y) + \phi_{sink}(x-x0, y-y0)$ となります。ただし、シンクの距離は点 (x0, y0) からの距離 $\sqrt{(x-x0)^2 + (y-y0)^2}$ を使う必要があります。

計算を簡単にするため、ここではより基本的な例として、一様流(速度ベクトルが一定)と原点にあるソースの重ね合わせによる流れを描画してみましょう。

一様流の速度ベクトルは $(U_\infty, 0)$、速度ポテンシャルは $\phi_{uniform}(x, y) = U_\infty x$ です。
原点にあるソースの速度ポテンシャルは $\phi_{source}(x, y) = \frac{Q}{2\pi} \ln \sqrt{x^2 + y^2}$ です。
合成速度ポテンシャルは $\phi(x, y) = U_\infty x + \frac{Q}{2\pi} \ln \sqrt{x^2 + y^2}$。

速度ベクトル $(u, v)$ は $\nabla \phi = (\frac{\partial \phi}{\partial x}, \frac{\partial \phi}{\partial y})$ です。
$\frac{\partial \phi}{\partial x} = U_\infty + \frac{Q}{2\pi} \frac{x}{x^2 + y^2}$
$\frac{\partial \phi}{\partial y} = \frac{Q}{2\pi} \frac{y}{x^2 + y^2}$

したがって、速度ベクトルは $(u, v) = (U_\infty + \frac{Q}{2\pi} \frac{x}{x^2 + y^2}, \frac{Q}{2\pi} \frac{y}{x^2 + y^2})$ となります。

これをquiverで描画します。原点 $(0,0)$ 付近では $x^2+y^2$ がゼロに近づくため、速度成分が無限大に発散します。原点その点では勾配は定義されないため、原点を含むグリッド点で計算を行う際には注意が必要です。計算を避けるために、原点をグリッドから外すか、原点を含むセルをスキップする必要があります。ここでは簡単な方法として、グリッド点の範囲を原点を含まないように設定します。

“`matlab
% パラメータ
U_inf = 1; % 一様流の速度
Q = 5; % ソースの強さ

% 描画範囲 (原点を避ける)
x_range = -5:0.5:5;
y_range = -5:0.5:5;

% グリッド点の生成
[X, Y] = meshgrid(x_range, y_range);

% 原点からの距離の二乗 (分母用)
R2 = X.^2 + Y.^2;

% 原点付近での発散を避けるため、R2が非常に小さい点を特定し、その点のベクトル成分をNaNにするか、
% あるいは計算から除外する(ここでは描画範囲で原点を避けているので不要ですが、一般的な注意点)
% 例: R2(R2 < 1e-6) = NaN; % 発散する点をNaNにする方法

% 速度成分の計算
u = U_inf + (Q / (2pi)) * (X ./ R2);
v = (Q / (2
pi)) * (Y ./ R2);

% ベクトル場の描画
figure;
quiver(X, Y, u, v);

% グラフ設定
title(‘一様流とソースの重ね合わせによる速度場’);
xlabel(‘X’);
ylabel(‘Y’);
grid on;
axis equal tight;

% ストリームラインを重ねて描画すると流れの様子がより分かりやすい
% hold on;
% startx = -5 * ones(size(y_range));
% starty = y_range;
% streamline(X, Y, u, v, startx, starty);
% hold off;
“`

この例を実行すると、左から右への一様流に、原点からの放射状の流れが加わったような速度場が描画されます。特に原点の右側では、一様流とソースの流れが合わさって速度が速くなり、左側では一様流に逆らう形で流れが遅くなる様子が見て取れます。

6.2. 電磁場の可視化(例:点電荷による電場)

点電荷が作る電場もベクトル場です。原点にある点電荷 $q$ が点 (x, y) に作る電場 $\mathbf{E} = (E_x, E_y)$ は、クーロンの法則から $\mathbf{E} = k_e \frac{q}{r^2} \hat{\mathbf{r}}$ で与えられます。ここで $k_e$ はクーロン定数、$r = \sqrt{x^2 + y^2}$ は距離、$\hat{\mathbf{r}} = (\frac{x}{r}, \frac{y}{r})$ は原点から点 (x, y) へ向かう単位ベクトルです。

したがって、電場成分は
$E_x = k_e q \frac{x}{r^3}$
$E_y = k_e q \frac{y}{r^3}$
となります。ここでも原点では発散するため、計算から除外するか描画範囲を調整します。

“`matlab
% パラメータ
k_e_q = 1; % k_e * q をまとめて定数とする (電荷の強さ)

% 描画範囲 (原点を避ける)
x_range = -2:0.3:2;
y_range = -2:0.3:2;

% グリッド点の生成
[X, Y] = meshgrid(x_range, y_range);

% 原点からの距離
R = sqrt(X.^2 + Y.^2);

% 原点その点での処理 (R=0 となる点を避ける、またはNaNに設定)
R(R < 1e-6) = NaN; % 非常に小さい距離の点をNaNにする

% 電場成分の計算
Ex = k_e_q * X ./ (R.^3);
Ey = k_e_q * Y ./ (R.^3);

% ベクトル場の描画
figure;
quiver(X, Y, Ex, Ey);

% グラフ設定
title(‘原点にある点電荷による電場’);
xlabel(‘X’);
ylabel(‘Y’);
grid on;
axis equal tight;
“`

この例を実行すると、原点から放射状に外側に向かう矢印(正電荷の場合)または内側に向かう矢印(負電荷の場合、$k_e q < 0$)が描画されます。原点に近いほど矢印が長くなり(電場が強く)、離れるほど短くなる(電場が弱くなる)様子が分かります。

7. quiverを使う上でのヒントと注意点

quiver関数は強力ですが、効果的に使うためにはいくつかの注意点があります。

  • 矢印の密集と重なり: データ点の密度が高いと、矢印が密集して重なり、図が見づらくなります。
    • 対処法1: データの選択/間引き: X, Y, U, V行列を作成する際に、グリッドの間隔を粗くするか、計算した行列をインデックスを使って間引いてからquiverに渡します(例9参照)。これが最も推奨される方法です。
    • 対処法2: 'AutoScaleFactor'の調整: 'AutoScale''on' (デフォルト) の場合、'AutoScaleFactor' を小さくすると矢印が短くなり、密集が緩和されることがあります。
    • 対処法3: 'AutoScale', 'off' + 手動スケーリング: 'AutoScale', 'off'にして、矢印の長さがベクトルの大きさに比例するようにし、必要に応じて矢印の長さを全体的に手動でスケーリングします。これは、quiverが出力するLineオブジェクトのDataLengthプロパティを後から設定する方法などがありますが、少し手間がかかります。シンプルに長さの相対的な比較をしたい場合は、自動スケーリングを使いつつ'AutoScaleFactor'を調整するのが楽です。
  • 適切なスケールの選択: axis equalは、X軸とY軸(quiver3ではZ軸も)の単位長さを同じにすることで、ベクトル場の形状を正しく表示するために非常に重要です。特に、異なる方向に速度成分を持つ場や、渦巻きのような場を描画する際には必ず使用しましょう。
  • 背景のスカラー場や等高線との組み合わせ: ベクトル場は、そのベクトルが定義されている基となるスカラー場(例えばポテンシャルや圧力)と合わせて描画すると、より多くの情報を伝えられます。
    • 背景にスカラー場を色で表示するには imagescpcolor を使用します。
    • スカラー場の等高線を描画するには contour を使用します。
    • これらの関数で背景を描画した後、hold on を実行してから quiver を呼び出すことで、同じ軸上に重ねて描画できます。描画が終わったら hold off を忘れずに実行しましょう。
  • インタラクティブな操作: figureウィンドウで作成されたグラフは、ツールバーのパン、ズーム、回転(3Dの場合)などのツールを使ってインタラクティブに操作できます。ベクトル場のような複雑な構造を持つグラフでは、様々な視点から観察することが理解を深める上で役立ちます。
  • 矢印の根本の正確性: quiver(X, Y, U, V) の場合、矢印の根本は厳密に (X, Y) に描画されます。quiver(U, V) の場合、矢印の根本はグリッド点 (j, i) に描画されます(行列の添え字と座標の対応に注意)。計算で求めたベクトルがどの座標点に対応するのかを明確にして、適切な形式でquiverを呼び出すことが重要です。特に物理現象を扱う場合は、通常は座標系に紐づいたデータなので quiver(X, Y, U, V) 形式を使用することになります。

8. 関連関数

quiverquiver3と合わせて使うと便利な関連関数がいくつかあります。

  • meshgrid: 2次元または3次元のグリッド点を生成する関数。quiver(X, Y, U, V)quiver3(X, Y, Z, U, V, W)形式で必須引数X, Y, Zを生成するのに使います。
  • gradient: スカラー場の勾配ベクトル場を計算する関数。計算結果をquiverquiver3U, V, (W) 引数として渡すことで、勾配ベクトル場を可視化できます。
  • contour, contourf: 2次元スカラー場の等高線を描画します。contourfは等高線の間を塗りつぶします。背景に重ねて描画することで、ベクトル場とスカラー場の関係(例:勾配は等高線に直交する)を視覚的に確認できます。
  • imagesc, pcolor: 2次元スカラー場を色の濃淡で表示します。これも背景に重ねて描画するのに便利です。
  • surf, mesh: 3次元スカラー場(または関数$z=f(x,y)$)を曲面として描画します。3次元ベクトル場と合わせて表示することは少ないですが、関連するスカラー場を理解するのに役立つことがあります。
  • streamline: ベクトル場に沿った流線を描画する関数。quiverがベクトル場の「スナップショット」であるのに対し、streamlineは「流れの軌跡」を示します。quiverstreamlineを組み合わせて描画することで、ベクトル場の全体的な構造や流れのパターンをより深く理解できます。
  • streamslice: 3次元ベクトル場をスライス面で切断し、その面上の流線を描画する関数。

これらの関数を組み合わせることで、ベクトル場とそれに付随する情報を多角的に解析し、可視化することができます。

9. まとめ

本記事では、Matlabのquiverおよびquiver3関数について、その基本的な使い方から、引数の詳細、様々なオプション、そして物理学や工学における応用例までを詳しく解説しました。

quiver関数は、2次元平面上のベクトル場を矢印として直感的に描画するための基本的なツールです。quiver(U, V)形式で手軽に描画することも、quiver(X, Y, U, V)形式で座標系を指定して正確に描画することも可能です。特に後者の形式は、meshgrid関数と組み合わせて物理的な座標系に基づいたベクトル場を描画する際に広く利用されます。

3次元ベクトル場にはquiver3関数を使用します。基本的な考え方やオプション設定はquiverと共通しており、meshgridの3次元版と組み合わせて使用するのが一般的です。

矢印の色、太さ、スタイル、先端の形状といった見た目のカスタマイズは、プロパティ名と値のペアによって柔軟に行えます。また、ベクトル場の密度が高すぎる場合には、データのインデックスによる間引き処理が有効です。

ベクトル場の可視化は、物理現象、数学的な概念、工学的な問題などを理解する上で非常に強力な手法です。quiver関数は、勾配ベクトル場、流体の速度場、電場などを視覚的に表現する上で欠かせないツールと言えるでしょう。

本記事で紹介したサンプルコードを実際にMatlabで実行し、結果を観察することで、quiver関数の理解を深めることができます。さらに、streamlinecontourといった関連関数と組み合わせることで、より豊かで情報量の多いベクトル場表現が可能になります。

Matlabを使ったデータ解析やシミュレーションにおいて、ベクトル場の可視化が必要になった際には、ぜひ本記事を参考にquiver関数を活用してください。これを足がかりに、さらに複雑なベクトル場の解析や可視化に進んでいくことができるでしょう。


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール