3

写真のような3D曲面グラフを作りたいです。私はILNumerics、ウェブサイトからの最近のRCを使用しています。これまでのところ、次のコードを使用してサーフェスを作成できました (データはテスト用のみです)。

using System;
using System.Drawing;
using System.Windows.Forms;
using ILNumerics; 
using ILNumerics.Drawing; 
using ILNumerics.Drawing.Plotting; 

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

    private void ilPanel1_Load(object sender, EventArgs e) {
        using (ILScope.Enter()) {
            ILArray<float> R = ILMath.linspace<float>(-4, 4, 100);
            ILArray<float> y = 1;
            ILArray<float> x = ILMath.meshgrid(R, R, y);

            ILArray<float> Z = ILMath.zeros<float>(x.S[0], x.S[1], 3); 
            Z[":;:;1"] = x; Z[":;:;2"] = y; 
            Z[":;:;0"] = 0.4f * x * x - 0.2f * y * y * y; 

            ilPanel1.Scene.Add(new ILPlotCube(twoDMode: false) {
                new ILSurface(Z, colormap: Colormaps.Cool) {
                    Colors = 1.4f * x * x * x + 0.13f * y * y,
                    Childs = { new ILColorbar() }
                }
            }); 
        }
    }
    }
}

マークされた値のない曲面グラフ

データ (色) 値が 0 のすべてのファセットを別の色でマークする最良の方法は何ですか? おそらく、カラーバーを使用する方法でしょうか?しかし、これはどのように正確に行われますか?

4

1 に答える 1

3

これは、カスタム カラーマップを使用して実現できます。しかし、確実に行うには注意が必要です。カラーマップの真ん中に新しい赤いキーポイントを配置するだけでは、非常に不正確な結果になります... :|

あなたの例を少し修正して文書化しました。基本的に、カラーマップには位置と色を持つキーポイントが含まれています。位置は一般的に (必ずしもそうとは限りません) [0..1] の範囲です。色の範囲は常に [0..1] です。ここでの課題は、カラーマップ範囲内で「0」cdata 値の正しい位置を見つけることです。

まず、デフォルトの Cool カラーマップを作成します。次の 2 つのキーポイントがあります (行内)。

colorkeys
<Single> [2,5]
    [0]: 0,00000 0,00000 1,00000 1,00000 1,00000 <- position: 0, color: RGBA
    [1]: 1,00000 1,00000 0,00000 1,00000 1,00000 <- position: 1

少なくとも 3 つの新しいキーポイントを追加する必要があります。最初の 2 つは、マークされた領域の端で元の色をサンプリングします。3 番目は、マークされた領域を赤色にします。赤のキーポイントを追加するだけでは機能しません。これは、0 付近のデータ値だけでなく、マップ内の すべての値に影響を与えるためです。

最後に、キーポイントは次のようになります。

colorkeys
<Single> [5,5]
     [0]: 0,00000 0,00000 1,00000 1,00000 1,00000 
     [1]: 1,00000 1,00000 0,00000 1,00000 1,00000 
     [2]: 0,49150 0,49150 0,50850 1,00000 1,00000 
     [3]: 0,49702 0,49702 0,50298 1,00000 1,00000 
     [4]: 0,49426 1,00000 0,00000 0,00000 1,00000 

キーポイントの順序は重要ではないことに注意してください。新しいカラーマップを作成するとき、それらはとにかくソートされます。新しいマップは単純に ILSurface に提供されます。

private void ilPanel1_Load(object sender, EventArgs e) {

    // create some X/Y meshgrid data 
    ILArray<float> y = 1, R = ILMath.linspace<float>(-4, 4, 100);
    ILArray<float> x = ILMath.meshgrid(R, ILMath.linspace<float>(-4, 4, 100), y);

    // precreate the surface data array
    ILArray<float> Z = ILMath.zeros<float>(x.S[0], x.S[1], 3);
    // surface expects Z, X and Y coords (in that order)
    Z[":;:;2"] = y; Z[":;:;1"] = x;
    Z[":;:;0"] = 0.4f * x * x - 0.2f * y * y * y;

    // our color data are based on another function 
    ILArray<float> cdata = 1.4f * x * x * x + 0.13f * y * y;

    // we need cdatas limits for creating a new colormap
    float min, max; cdata.GetLimits(out min, out max);

    // get default 'Cool' colormap
    var colormap = new ILColormap(Colormaps.Cool);
    // get colormap keys as array: [position,R,G,B,A]
    ILArray<float> colorkeys = colormap.Data;
    // helper function to map true values to 0..1 range 
    Func<float, float> map = a => { return (a - min) / (max - min); };

    // the value to mark and +/- tolerance width (to make it a visible strip at least)
    float markValue = 0, tolerance = 0.5f;
    // sample the colormap at the marked edges
    Vector4 key1 = colormap.Map(markValue - tolerance, new Tuple<float, float>(min, max));
    Vector4 key2 = colormap.Map(markValue + tolerance, new Tuple<float, float>(min, max));
    // create new keypoints at the edges of marked area
    colorkeys[ILMath.end + 1, ":"] = ILMath.array(map(markValue - tolerance), key1.X, key1.Y, key1.Z, 1f); 
    colorkeys[ILMath.end + 1, ":"] = ILMath.array(map(markValue + tolerance), key2.X, key2.Y, key2.Z, 1f); 
    // create new keypoint for the marked area itself; color red
    colorkeys[ILMath.end + 1, ":"] = ILMath.array(map(markValue), 1f, 0f, 0f, 1f); // red
    // make a new colormap out of it 
    colormap = new ILColormap(colorkeys);
    // create & add a plot cube 
    ilPanel1.Scene.Add(new ILPlotCube(twoDMode: false) {
        // add surface plot, give custom colormap & colormap data ...
        new ILSurface(Z, colormap: colormap, C: cdata) {
            // add colorbar
            Childs = { new ILColorbar() }
        }
    }); 
}

これにより、次の出力が生成されます。 ここに画像の説明を入力

于 2013-06-01T20:13:03.533 に答える