【问题标题】:ILNumerics: Get mouse coordinates with ILLinePlotILNumerics:使用 ILLinePlot 获取鼠标坐标
【发布时间】:2014-08-27 20:20:59
【问题描述】:

我在一个简单的 WindowsFormsApplication 上使用带有 C# 的 ilnumerics,并在 ILPanel 上的 PlotCube 中创建了一些 LinePlot。喜欢在:
How to find the 3D coordinates of a surface from the click location of the mouse on the ILNumerics surface plots?
我试图在单击 PlotCube 时获取翻译后的坐标,以创建类似于 MATLAB 上的数据提示的内容。 我使用的是 ILLinePlot 而不是 ILSurface,我的 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;
    }

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

我希望任何人都能理解我的问题。尽管搜索了数周,但我没有找到任何答案或不同的方法来实现我的目标,即向用户显示他点击的线上的点坐标。

非常感谢您的任何帮助。

【问题讨论】:

  • 部分答案可以在这里找到:ilnumerics.net/scene-management.html。它解释了恒等矩阵。此外,尝试将处理程序附加到 ILPlotcubeDatagroup 而不是 plotcube。它可能会进一步简化事情。有帮助吗?
  • 非常感谢您的快速答复!我的 PlotCube 和 LinePlot 生活在我的全局场景的不同同步上,因此我得到不同的转换,我是否理解正确?!当我将处理程序附加到 ILPlotcubeDatagroup 而不是 plotcube 时,它​​们似乎只在我点击 LinePlot 时触发。这是期望的行为吗?所以这对我的 MouseClick 事件没有意义,对吧?!还是我误会了什么?

标签: c# ilnumerics


【解决方案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
    }

希望对您有所帮助。

【讨论】:

  • 我必须把我的 if(!onplot) 放在你的前两行周围,否则如果我点击 LinePlot,plotcubeGroup 将为空。但有了它,它就可以完美地工作了!非常感谢!!但现在 GridLines 是最后一个问题!当我击中一个时,我仍然得到错误的坐标,这可能又是场景管理的问题?!​​
  • 所有事件都在剧情场景的同步副本上引发。上述问题也可以通过从同步副本中访问ILLinePlot来解决。这也会给出正确的转换。例如: var group = ilPanel1.SceneSyncRoot.First(谓词:Item => Item.Tag == "LinePlotLine").Parent;使用 sceneSyncRoot,我认为您不会遇到 gridLines 问题。
  • 是的!这很好用!现在我只需要 sceneSyncRoot 行,它适用于所有情况!非常感谢!
猜你喜欢
  • 2011-04-11
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多