ILNumerics:使用ILLinePlot获取鼠标坐标

时间:2014-08-26 23:02:45

标签: c# ilnumerics

我在一个简单的WindowsFormsApplication上使用带有C#的ilnumerics,并在ILPanel上的PlotCube中创建了一些LinePlots。喜欢:
How to find the 3D coordinates of a surface from the click location of the mouse on the ILNumerics surface plots?
我试图在点击PlotCube时获得翻译的坐标,以创建类似于MATLAB的数据提示。 而不是ILSurface我使用ILLinePlot和我的x轴是对数刻度。 所以我将上面链接中提到的方法改编为我的设置。

我的问题是,当我在LinePlot上完全点击时,我只能得到正确的坐标! 当点击该行旁边或PlotCube上的任何其他位置时,上面的MouseClick方法会遇到NullReferenceException。
我对这个问题的想法是不使用MouseClick目标来获得转换,如果我没有点击LinePlot但是将组设置为LinePlot就像我点击它一样(参见我的例子)。 / p>

但是我现在在while循环中得到相同的组,并且没有Exception调试显示PlotsData组和PlotCubeScale组的转换矩阵在两种情况下都不同。 如果我没有点击LinePlot,那么所有转换矩阵都只是身份。

这是我的简短例子:

    private void ilPanel1_Load(object sender, EventArgs e)
    {
        ILArray<double> A = new Double[,] {{1,4,0},{10,12,0},{100,10,0},{1000,18,0},{10000,15,0}};
        var scene = new ILScene() {
            new ILPlotCube(twoDMode: true){
                new ILLinePlot(ILMath.tosingle(A))
            }
        };
        scene.First<ILPlotCube>().ScaleModes.XAxisScale = AxisScale.Logarithmic;

        scene.First<ILPlotCube>().MouseEnter += (_s, _a) =>
        {
            if (!_a.DirectionUp)
            {
                //onplot is a global flag which is true if the mouse is over the LinePlot
                Text = "On Plot - Target: " + _a.Target.ToString();
                onplot = true;
            }
        };

        scene.First<ILPlotCube>().MouseLeave += (_s, _a) =>
        {
            if (!_a.DirectionUp)
            {
                Text = "Off Plot - Target: " + _a.Target.ToString();
                onplot = false;
            }
        };
        scene.First<ILPlotCube>().MouseClick += (s, arg) =>
        {
            if (!arg.DirectionUp)
                return;
            var group = arg.Target.Parent;
            // *new part: group holds my LinePlot if I clicked on it
            // else it holds the PlotCube 
            if (!onplot)
            {
                // so I search the LinePlot at set group to it
                foreach (ILLineStrip strip in scene.Find<ILLineStrip>())
                {
                    if (strip.Tag == "LinePlotLine")
                    {
                        group = strip.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;
                    // here I take care of the logarithmic scale of the xAxis
                    pos.X = (float)ILMath.pow(10.0, pos.X);
                    // view result in the window title
                    Text = "Model Position: " + pos.ToString();
                }
            }
        };

        ilPanel1.Scene = scene;
    }

为什么group.Transform-matrices根据我的点击位置而有所不同?在这两种情况下,while循环完全相同。

我希望任何人都能理解我的问题。虽然搜索了几个星期我没有找到任何答案或不同的方法来达到我的目标,这只是向用户显示他点击的线上点的坐标。

非常感谢您提前寻求帮助。

1 个答案:

答案 0 :(得分:1)

一种解决方法是从鼠标处理程序的目标而不是直接从场景中获取线图节点。这样我们总能得到正确的变换。用以下

替换识别线图的逻辑
 ILGroup plotcubeGroup = e.Target as ILGroup;
 ILGroup group = plotcubeGroup.Children.Where(item => item.Tag == "LinePlot").First() as ILGroup;
 if(group != null)
    {
    // continue with same logic as above
    }

希望它有所帮助。