Octave「surf」で表現力アップ!3Dグラフ作成のプロ技公開

2025-04-26

基本的な使い方

「surf」関数は、通常、3つの行列またはベクトルを引数として受け取ります。

  • Z
    z座標(高さ)の行列。これは、xとyの各点におけるzの値を表します。
  • Y
    y座標の行列またはベクトル
  • X
    x座標の行列またはベクトル

基本的な構文は次のとおりです。

surf(X, Y, Z);

詳細説明

    • まず、描画したい表面のx、y、z座標のデータを準備します。通常、xとyはメッシュグリッドとして生成され、zはxとyの関数として計算されます。
    • 例えば、次のコードは、xとyのメッシュグリッドを生成し、zを計算します。
    [X, Y] = meshgrid(-2:0.2:2, -2:0.2:2);
    Z = X .* exp(-X.^2 - Y.^2);
    
  1. 「surf」関数の実行

    • 次に、「surf」関数にX、Y、Zを引数として渡します。これにより、3次元の表面グラフが描画されます。
    surf(X, Y, Z);
    
  2. グラフのカスタマイズ

    • 「surf」関数には、さまざまなオプションがあり、グラフの外観をカスタマイズできます。
    • 例えば、カラーマップ、線のスタイル、照明などを変更できます。
    • colormap()関数を使用し色を変更できます。
    • shading interpを使用することで、色を滑らかに補完することも可能です。


[X, Y] = meshgrid(-2:0.2:2, -2:0.2:2);
Z = X .* exp(-X.^2 - Y.^2);

surf(X, Y, Z);
title("3次元表面グラフ");
xlabel("X軸");
ylabel("Y軸");
zlabel("Z軸");
colormap("jet");#color mapの変更
shading interp; #shading の変更

この例では、ガウス関数のような3次元表面グラフを描画し、タイトル、軸ラベル、カラーマップを追加しています。



  1. 行列の次元の不一致

    • エラー
      error: surf: X, Y, and Z must be matrices of the same size
    • 原因
      X, Y, Z の行列の次元が一致していない場合に発生します。
    • 解決策
      • meshgrid 関数を使用して XY を生成し、ZXY の関数として計算することで、次元を一致させます。
      • size(X), size(Y), size(Z) を使用して行列の次元を確認し、必要に応じて修正します。
  2. Z が行列でない場合

    • エラー
      error: surf: Z must be a matrix
    • 原因
      Z がベクトルまたはスカラーなど、行列でない場合に発生します。
    • 解決策
      Z が行列であることを確認し、必要に応じて reshape 関数などを使用して行列に変換します。
  3. データ範囲のエラー

    • 問題
      グラフが期待どおりに表示されない、またはデータが極端に大きすぎる/小さすぎる。
    • 原因
      X, Y, Z のデータ範囲が適切でない場合に発生します。
    • 解決策
      • データの範囲を確認し、必要に応じて調整します。
      • axis 関数を使用して軸の範囲を明示的に設定します。
      • log10 などを使用して、データのスケールを調整します。
  4. カラーマップの問題

    • 問題
      グラフの色が期待どおりに表示されない。
    • 原因
      カラーマップの設定が適切でない場合に発生します。
    • 解決策
      • colormap 関数を使用して、適切なカラーマップを選択します。
      • colorbar 関数を使用して、カラーバーを表示し、色の範囲を確認します。
      • caxis 関数を使用して、カラーマップの範囲を調整します。
  5. 照明とシェーディングの問題

    • 問題
      グラフの照明やシェーディングが期待どおりに表示されない。
    • 原因
      照明やシェーディングの設定が適切でない場合に発生します。
    • 解決策
      • shading 関数を使用して、適切なシェーディングモード(flat, interp など)を選択します。
      • light 関数を使用して、光源を追加または調整します。
      • material 関数を使用して、表面の材質特性を調整します。
  6. グラフの表示の問題

    • 問題
      グラフがウィンドウに表示されない、または表示が遅い。
    • 原因
      グラフィックドライバの問題、またはデータ量が大きすぎる場合に発生します。
    • 解決策
      • Octave を再起動します。
      • グラフィックドライバを更新します。
      • drawnow 関数を使用して、グラフを強制的に更新します。
      • データ量を減らすか、表示するデータの間隔を大きくします。
  7. meshgridの理解不足

    • 問題
      XとYのグリッドが期待したものではない。
    • 原因
      meshgridの理解が足りない。
    • 解決策
      meshgridの挙動を理解する。
      • meshgridは2つのベクトルから2次元のグリッドを作る関数である。
      • meshgrid(x,y)の場合、Xはxのベクトルを縦方向にコピーした行列、Yはyのベクトルを横方向にコピーした行列である。
      • meshgrid(x)とした場合meshgrid(x,x)と同じ結果になる。


% データの準備
[X, Y] = meshgrid(-2:0.2:2, -2:0.2:2); % xとyのメッシュグリッドを生成
Z = X .* exp(-X.^2 - Y.^2); % z座標を計算

% 表面グラフの描画
surf(X, Y, Z);

% グラフの装飾
title("基本的な3次元表面グラフ");
xlabel("X軸");
ylabel("Y軸");
zlabel("Z軸");

説明

  • title, xlabel, ylabel, zlabel: グラフのタイトルと軸ラベルを設定します。
  • surf(X, Y, Z): X, Y, Z のデータを使用して3次元表面グラフを描画します。
  • Z = X .* exp(-X.^2 - Y.^2): xy の関数として z 座標を計算します。
  • meshgrid(-2:0.2:2, -2:0.2:2): -2 から 2 まで 0.2 刻みの xy のメッシュグリッドを生成します。
% データの準備
[X, Y] = meshgrid(-pi:0.1:pi, -pi:0.1:pi);
Z = sin(X) .* cos(Y);

% 表面グラフの描画とカスタマイズ
surf(X, Y, Z);
title("カラーマップとシェーディングの変更");
xlabel("X軸");
ylabel("Y軸");
zlabel("Z軸");
colormap("jet"); % カラーマップを"jet"に変更
shading interp; % シェーディングを補間モードに変更
colorbar; % カラーバーを表示

説明

  • colorbar: カラーバーを表示し、色の範囲を示します。
  • shading interp: シェーディングを補間モードに変更し、表面を滑らかに表示します。
  • colormap("jet"): カラーマップを「jet」に変更します。他のカラーマップ(hot, cool, gray など)も使用できます。
% データの準備
[X, Y] = meshgrid(-2:0.2:2, -2:0.2:2);
Z = X.^2 + Y.^2;

% 表面グラフの描画と照明の追加
surf(X, Y, Z);
title("照明の追加");
xlabel("X軸");
ylabel("Y軸");
zlabel("Z軸");
light; % デフォルトの光源を追加
lighting gouraud; % 照明モデルを"gouraud"に変更

説明

  • lighting gouraud: 照明モデルを「gouraud」に変更し、滑らかな照明効果を実現します。他の照明モデル(flat, phong など)も使用できます。
  • light: デフォルトの光源を追加します。光源の位置や色をカスタマイズすることもできます。
% データの準備
[X, Y] = meshgrid(-2:0.2:2, -2:0.2:2);
Z = X.^2 - Y.^2;

% 表面グラフの描画と軸の範囲設定
surf(X, Y, Z);
title("軸の範囲の修正");
xlabel("X軸");
ylabel("Y軸");
zlabel("Z軸");
axis([-3 3 -3 3 -5 5]); % 軸の範囲を[-3 3 -3 3 -5 5]に設定
  • axis([-3 3 -3 3 -5 5]): 軸の範囲を [xmin xmax ymin ymax zmin zmax] に設定します。これにより、グラフの表示範囲を調整できます。


「mesh」関数

  • 構文は「surf」とほぼ同じです。
  • データの形状を把握するのに役立ちます。
  • 「mesh」関数は、「surf」関数と似ていますが、表面を塗りつぶさずに、ワイヤーフレームとして描画します。
[X, Y] = meshgrid(-2:0.2:2, -2:0.2:2);
Z = X .* exp(-X.^2 - Y.^2);
mesh(X, Y, Z);
title("mesh関数によるワイヤーフレーム");

「plot3」関数

  • しかし、複雑な表面を描画するには、多くの処理が必要になります。
  • 表面を描画する場合、複数の「plot3」を組み合わせて、表面のワイヤーフレームのようなものを生成できます。
  • 表面ではなく、3次元空間内の点の軌跡を表示するのに適しています。
  • 「plot3」関数は、3次元の線グラフを描画します。
t = 0:0.1:10*pi;
x = sin(t);
y = cos(t);
z = t;
plot3(x, y, z);
title("plot3関数による3次元線グラフ");

「contour3」関数

  • 表面の形状と高さの変化を視覚化するのに役立ちます。
  • 表面の等高線を3次元空間に表示します。
  • 「contour3」関数は、3次元の等高線グラフを描画します。
[X, Y] = meshgrid(-2:0.2:2, -2:0.2:2);
Z = X .* exp(-X.^2 - Y.^2);
contour3(X, Y, Z);
title("contour3関数による3次元等高線グラフ");

「imagesc」と「view」関数

  • 完全な3次元表面グラフではありませんが、特定の視点からの表面の様子を表現できます。
  • 「imagesc」で高さデータをカラーマップとして表示し、「view」で視点を調整します。
  • 「imagesc」関数は、2次元のイメージデータを表示しますが、「view」関数と組み合わせることで、擬似的な3次元表面グラフを作成できます。
[X, Y] = meshgrid(-2:0.2:2, -2:0.2:2);
Z = X .* exp(-X.^2 - Y.^2);
imagesc(Z);
view(30, 45); % 視点を調整
title("imagescとview関数による擬似3次元グラフ");
  • 点の密度や色で表面の形状を表現できますが、表面自体を描画するわけではありません。
  • 表面ではなく、3次元空間内の点の分布を表示するのに適しています。
  • 「scatter3」関数は、3次元の散布図を描画します。
x = randn(100, 1);
y = randn(100, 1);
z = randn(100, 1);
scatter3(x, y, z);
title("scatter3関数による3次元散布図");
  • 「scatter3」は3次元散布図。
  • 「imagesc」と「view」は擬似的な3次元表示。
  • 「contour3」は3次元等高線グラフ。
  • 「plot3」は3次元線グラフ。
  • 「mesh」はワイヤーフレーム表示。