簡體   English   中英

如何在helix-toolkit sharpDX視口中選擇最頂層的元素?

[英]How to select topmost element in a helix-toolkit sharpDX viewport?

我正在使用helix-toolkit庫的sharpDX分支來處理我大學的一個項目( HelixToolKit庫

目前,我正在尋找一種正確選擇視口中元素的方法。

我在helixtoolkit庫的源代碼中找到了一個有用的示例: 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解決方案,並且它們經常使用事件處理程序。 (例如,WPF中的3D命中測試

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函數?

使用視口方法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
    }
 }

因此,我實際上自己找到了一個解決方案,這可能並不完美。 但這也許對某人有用。

        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
            }
        }

PS不是一名計算機科學家,而是一名土木工程專業的學生,​​他正在嘗試最好的xD

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM