【问题标题】:How to select topmost element in a helix-toolkit sharpDX viewport?如何在 helix-toolkit sharpDX 视口中选择最上面的元素?
【发布时间】:2016-08-23 15:01:01
【问题描述】:

我正在为我大学的一个项目使用 helix-toolkit 库的 sharpDX 分支 (HelixToolKit Library)

目前我正在寻找一种在视口中正确选择元素的方法。

我在 helixtoolkit 库的源代码中找到了一个有用的例子:example code on GitHub

public class MyLineGeometryModel3D : LineGeometryModel3D
{
    private Color? initialColor = null;

    public override bool HitTest(Ray rayWS, ref List<HitTestResult> hits)
    {
        if (initialColor == null)
        {
            initialColor = this.Color;
        }

        var result = base.HitTest(rayWS, ref hits);
        var pressedMouseButtons = Viewport3DX.GetPressedMouseButtons();

        if (pressedMouseButtons == 0 || pressedMouseButtons.HasFlag(MouseButtons.Left))
        {
            this.Color = result ? Color.Red : this.initialColor.Value;
        }
        return result;
    }

}

我设法让它在我的应用程序中运行。但是,不是只选择最顶部的元素,而是选择与射线相交的所有元素。 可能需要某种处理函数来突出显示距离最短的元素?

我为此检查了一些标准的 WPF 解决方案,它们经常使用事件处理程序。 (例如3D Hit Testing in WPF

private void m_viewport3d_MouseDown(object sender, MouseButtonEventArgs e)
{
    Point mousePos = e.GetPosition(m_viewport3d);
    PointHitTestParameters hitParams = new PointHitTestParameters(mousePos);
    HitTestResult result = VisualTreeHelper.HitTest(m_viewport3d, mousePos);
    RayMeshGeometry3DHitTestResult rayMeshResult = result as RayMeshGeometry3DHitTestResult;
    if (rayMeshResult != null)
    {
        MeshGeometry3D mesh = new MeshGeometry3D();
        mesh.Positions.Add(rayMeshResult.MeshHit.Positions[rayMeshResult.VertexIndex1]);
        mesh.Positions.Add(rayMeshResult.MeshHit.Positions[rayMeshResult.VertexIndex2]);
        mesh.Positions.Add(rayMeshResult.MeshHit.Positions[rayMeshResult.VertexIndex3]);
        mesh.TriangleIndices.Add(0);
        mesh.TriangleIndices.Add(1);
        mesh.TriangleIndices.Add(2);
        GeometryModel3D marker = new GeometryModel3D(mesh, new DiffuseMaterial(Brushes.Blue));
        //...add marker to the scene...
    }
}

使用事件处理程序是一个明智的解决方案吗?如果是,如何在事件处理程序中获取用于调用 HitTest 函数的射线元素?

【问题讨论】:

    标签: c# wpf hittest sharpdx helix-3d-toolkit


    【解决方案1】:

    使用视口方法FindNearest:

    private void OnMouseDown(object sender, MouseButtonEventArgs e)
    {     
        Viewport3DX vp = e.Source as Viewport3DX;
    
        Point3D p;
        Vector3D v;
        Model3D m;
        if (vp.FindNearest(e.GetPosition(vp), out p, out v, out m))
        {
             //Do something with the found object
        }
     }
    

    【讨论】:

    • 感谢 egse 的帮助。我尝试了您的解决方案,但它对我不起作用,因为我需要更改模型的材料,该材料尚未包含在 Model3D 类中。也许有一个解决方法,我不知道:-)但我自己确实找到了一个解决方案(发布在下面)
    【解决方案2】:

    所以,我实际上自己找到了一个解决方案,这可能并不完美。但也许这对某人有用。

            private void ViewPort3D_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
    
                Ray ray = this.ViewPort3D.UnProject(new Vector2((float)e.GetPosition(ViewPort3D).X, (float)e.GetPosition(ViewPort3D).Y));
                var hits = new List<HitTestResult>();
    
                // dictionary for connecting the id of the specific element and its distance
                var hitElements = new Dictionary<int, double>();
    
                // loop over all MeshGeometryModel3D elements
                foreach (var geometry in Geometrys)
                {
                    var isHit = geometry.Model3D.HitTest(ray, ref hits);
                    if (isHit)
                    {
                        hitElements.Add(geometry.Id, hits[hits.Count - 1].Distance);
                    }
                }
    
                if (hits.Count > 0)
                {
    
                    double minDistance = hitElements.First().Value;
                    int id_of_hit_element = hitElements.First().Key;
    
                    foreach (var hit in hitElements)
                    {
                        if (hit.Value < minDistance)
                        {
                            minDistance = hit.Value;
                            id_of_hit_element = hit.Key;
                        }
                    }
    
                    var topElement = Geometrys.Find(geometry => geometry.Id == id_of_hit_element);
    
                    // do something with top element
                }
            }
    

    附:顺便说一句,不是计算机科学家,只是一个正在尽力而为的土木工程专业学生 xD

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多