ILNumerics:使用ILLinePlot获取鼠标坐标

本文关键字:鼠标 坐标 获取 ILLinePlot 使用 ILNumerics | 更新日期: 2023-09-27 18:19:41

我在一个简单的WindowsFormsApplication上使用带有C#的ilnumerics,并在ILPanel上的PlotCube中创建了一些LinePlots。类似于:
如何从鼠标在ILNumerics曲面图上的单击位置找到曲面的三维坐标
我试图在点击PlotCube的同时获得转换后的坐标,以创建类似于MATLAB中的数据提示的东西。我使用的不是ILSurface,而是ILLinePlot,我的x轴是对数刻度的。因此,我将上述链接中提到的方法应用于我的设置。

我的问题是,只有当我准确地点击LinePlot时,我才能得到正确的坐标!当右键单击该行旁边或PlotCube的其他任何位置时,上述MouseClick方法将运行NullReferenceException
我对这个问题的想法是,如果我没有点击LinePlot,就不要使用MouseClick目标来获得转换,而是像点击它一样将组设置为LinePlot(参见我的示例)。

但是,尽管我现在在while循环中得到了相同的组,并且没有异常调试显示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;
    }

为什么要分组。转换矩阵根据我的单击位置而不同?while循环在这两种情况下完全相同。

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

事先非常感谢您的帮助。

ILNumerics:使用ILLinePlot获取鼠标坐标

一个解决方案是从鼠标处理程序的目标获取lineplot节点,而不是直接从场景获取。这样我们总能得到正确的转变。用以下替换识别线形图的逻辑

 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
    }

希望能有所帮助。