現在、システムは ILNumerics 3D プロット キューブ クラスと ILNumerics サーフェス コンポーネントを使用して、3D メッシュ サーフェスを表示します。私たちのシステムの目的は、プロットをマウスでクリックするだけで、表面上の個々の点を調べることができるようにすることです。プロットに MouseClick イベントを設定しました。問題は、クリックされたサーフェス上の特定のポイントの値を取得する方法がわからないことです。この問題を解決できる人はいますか?
1 に答える
2D マウス座標から 3D 'モデル' 座標への変換は可能ですが、いくつかの制限があります:
変換は明確ではありません。マウス イベントは、X と Y の画面座標の 2 つの次元のみを提供します。3D モデルでは、この 2D スクリーン ポイントの「背後」に複数のポイントがある場合があります。したがって、得られる最善の方法は、カメラから始まり無限の深さで終わる 3D の線を計算することです。
理論的には、少なくとも 3D オブジェクトとの線の交差を見つけようとすることは可能ですが、ILNumerics は現在のところそうではありません。単純なサーフェスの場合でも、複数の点で線を横切る 3D モデルを簡単に作成できます。
単純化された状況では、解決策があります。3D の Z 座標が問題にならない場合は、一般的な行列変換を使用して 3D の X 座標と Y 座標を取得し、これらのみを使用できます。プロットが 2D ライン プロットまたはサーフェス プロットであるとしましょう - ただし、'上' (つまり、回転していない XY 平面) からしか見られません。クリックされたポイントの Z 座標は重要でない場合があります。さらに、ILPanel を使用して一般的な Windows アプリケーションで ILScene シーンをセットアップしたとします。
private void ilPanel1_Load(オブジェクト送信者, EventArgs e) {
var scene = new ILScene() { new ILPlotCube(twoDMode: true) { new ILSurface(ILSpecialData.sincf(20,30)) } }; scene.First<ILSurface>().MouseClick += (s,arg) => { // we start at the mouse event target -> this will be the // surface group node (the parent of "Fill" and "Wireframe") var group = arg.Target.Parent; if (group != null) { // walk up to the next camera node Matrix4 trans = group.Transform; while (!(group is ILCamera) && group != null) { group = group.Parent; // collect all nodes on the path up trans = group.Transform * trans; } if (group != null && (group is ILCamera)) { // convert args.LocationF to world coords // The Z coord is not provided by the mouse! -> choose arbitrary value var pos = new Vector3(arg.LocationF.X * 2 - 1, arg.LocationF.Y * -2 + 1, 0); // invert the matrix. trans = Matrix4.Invert(trans); // trans now converts from the world coord system (at the camera) to // the local coord system in the 'target' group node (surface). // In order to transform the mouse (viewport) position, we // left multiply the transformation matrix. pos = trans * pos; // view result in the window title Text = "Model Position: " + pos.ToString(); } } }; ilPanel1.Scene = scene;
}
動作: サーフェス グループ ノードに MouseClick イベント ハンドラーを登録します。ハンドラーでは、クリックされたターゲット (サーフェス グループ ノード) から、サーフェスが子である次のカメラ ノードまでのパスに変換行列が蓄積されます。レンダリング中、頂点の (モデル) 座標は、すべてのグループ ノードでホストされているローカル座標変換マトリックスによって変換されます。すべての変換が蓄積されるため、頂点座標はすべてのカメラによって確立された「ワールド座標」システムになります。そのため、レンダリングは 3D モデルの頂点位置から 2D 画面の位置を見つけます。
2D スクリーン座標から 3D 位置を見つけるには、逆の方向に進む必要があります。この例では、すべてのグループ ノードの変換行列を取得し、それらをすべて乗算して、結果の変換行列を逆にします。このような変換は子ノードから親ノードへの変換を自然に記述するため、これが必要です。ここでは、反対の方法が必要です。したがって、反転が必要です。
このメソッドは、マウス位置の正しい 3D 座標を提供します。ただし、制限に注意してください。ここでは、プロット キューブの回転 (プロット キューブは回転させないでおく必要があります) と投影変換 (プロット キューブはデフォルトで正投影変換を使用しますが、これは基本的にノープです) を考慮していません。これらの変数も認識するために、それに応じて例を拡張できます。