C# ILNumerics:使用ILINEPLOT获取鼠标坐标

C# ILNumerics:使用ILINEPLOT获取鼠标坐标,c#,ilnumerics,C#,Ilnumerics,我在一个简单的WindowsFormsApplication上使用带C#的ilnumerics,并在ILPanel上的PlotCube中创建了一些线图。比如: 我试图在点击PlotCube时获得转换后的坐标,以创建类似于MATLAB数据提示的内容。 我用的不是ILINEPLOT曲面,我的x轴是对数标度。 因此,我将上述链接中提到的方法与我的设置相适应 我的问题是,我只有在精确单击线形图时才能获得正确的坐标! 当右键单击该行旁边或PlotCube上的任何其他位置时,上述鼠标单击方法会遇到Null

我在一个简单的WindowsFormsApplication上使用带C#的ilnumerics,并在ILPanel上的PlotCube中创建了一些线图。比如:

我试图在点击PlotCube时获得转换后的坐标,以创建类似于MATLAB数据提示的内容。 我用的不是ILINEPLOT曲面,我的x轴是对数标度。 因此,我将上述链接中提到的方法与我的设置相适应

我的问题是,我只有在精确单击线形图时才能获得正确的坐标! 当右键单击该行旁边或PlotCube上的任何其他位置时,上述鼠标单击方法会遇到NullReferenceException。
对于这个问题,我的想法不是在没有点击线条图的情况下使用MouseClick目标来获取变换,而是将组设置为线条图,就像我点击了它一样(参见我的示例)

但是,尽管我现在在while循环中得到了相同的组,并且没有异常,但调试表明PlotsData组和PlotCubeScale组的转换矩阵在这两种情况下都不同。 如果我不点击线条图,所有的变换矩阵都只是恒等式

下面是我的简短示例:

    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;
    }
private void ilPanel1\u加载(对象发送方,事件参数e)
{
ILArray A=新的双[,]{1,4,0},{10,12,0},{100,10,0},{1000,18,0},{10000,15,0};
var scene=new ILScene(){
新ILPlotCube(twoDMode:true){
新伊利内普洛特(ILMath.tosingle(A))
}
};
scene.First();
scene.First().MouseEnter+=(\u s,\u a)=>
{
如果(!\u a.方向向上)
{
//onplot是一个全局标志,如果鼠标位于LinePlot上,则为true
Text=“On Plot-Target:”+_a.Target.ToString();
onplot=true;
}
};
scene.First().MouseLeave+=(\u s,\u a)=>
{
如果(!\u a.方向向上)
{
Text=“Off Plot-Target:”+_a.Target.ToString();
onplot=false;
}
};
scene.First().MouseClick+=(s,arg)=>
{
如果(!arg.DirectionUp)
返回;
var group=arg.Target.Parent;
//*新零件:如果单击,组将保留我的线图
//否则它会保存PlotCube
如果(!onplot)
{
//因此,我在将组设置为它时搜索线条图
foreach(场景中的ILLineStrip strip.Find())
{
如果(strip.Tag==“LinePlotLine”)
{
组=strip.Parent;
}
}
}
如果(组!=null)
{
//向上走到下一个摄影机节点
Matrix4 trans=组转换;
而(!(组为ILCamera)&&group!=null)
{
组=组。父;
//收集向上路径上的所有节点
trans=组。Transform*trans;
}
如果(组!=null&&(组为ILCamera))
{
//将args.LocationF转换为世界坐标
//Z坐标不是由鼠标提供的!->选择任意值
变量位置=新向量3(参数位置F.X*2-1,参数位置F.Y*-2+1,0);
//反转矩阵。
trans=矩阵4。反转(trans);
//trans现在从世界坐标系(摄像机处)转换为
//“目标”组节点(表面)中的本地协调系统。
//为了变换鼠标(视口)位置,我们
//左乘变换矩阵。
pos=trans*pos;
//在这里,我处理xAxis的对数刻度
位置X=(浮动)ILMath.pow(10.0,位置X);
//在窗口标题中查看结果
Text=“型号位置:”+pos.ToString();
}
}
};
ilPanel1.场景=场景;
}
为什么group.Transform-matrix会因单击位置的不同而不同?在这两种情况下,while循环完全相同

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


非常感谢您的帮助。

一个解决方法是从鼠标处理程序的目标而不是直接从场景获取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
    }

希望能有帮助

部分答案可在此处找到:。它解释了单位矩阵。另外,尝试将处理程序附加到ILPLOTCUBEDATAGOUP而不是plotcube。这可能会使事情进一步简化。这有帮助吗?非常感谢您快速的回答!!我的PlotCube和LinePlot位于全局场景的不同同步上,因此我得到了不同的变换,这对吗?!当我将处理程序附加到ILPlotcubeDatagroup而不是plotcube时,它们似乎只有在我点击线图时才会触发。这是你想要的行为吗?所以这对我的鼠标点击事件没有意义,对吧?!或者我误解了什么?我必须在前两行周围放置if(!onplot),否则如果我点击LinePlot,plotcubeGroup将为null。但是,它的工作非常完美!谢谢!!但现在网格线是最后一个问题!当我击中一个时,我仍然得到错误的坐标,这可能又是一个现场管理的问题?!所有事件