如何 select helix-toolkit sharpDX viewport 中的最顶层元素?
How to select topmost element in a helix-toolkit sharpDX viewport?
我正在为我大学的一个项目使用 helix-toolkit 库的 sharpDX 分支 (HelixToolKit Library)
目前我正在寻找一种在视口中正确 select 元素的方法。
我在 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;
}
}
我设法在我的应用程序中得到这个 运行。然而,不是 select 只对最上面的元素进行编辑,而是对与射线相交的所有元素进行 select 编辑。
可能需要某种处理函数来突出显示距离最短的元素?
我为此检查了一些标准的 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 函数?
使用视口方法 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
}
}
P.S。顺便说一句,不是计算机科学家,只是一个尽力而为的土木工程专业学生 xD
我正在为我大学的一个项目使用 helix-toolkit 库的 sharpDX 分支 (HelixToolKit Library)
目前我正在寻找一种在视口中正确 select 元素的方法。
我在 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;
}
}
我设法在我的应用程序中得到这个 运行。然而,不是 select 只对最上面的元素进行编辑,而是对与射线相交的所有元素进行 select 编辑。 可能需要某种处理函数来突出显示距离最短的元素?
我为此检查了一些标准的 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 函数?
使用视口方法 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
}
}
P.S。顺便说一句,不是计算机科学家,只是一个尽力而为的土木工程专业学生 xD