The following SingleModel derived class computes the Solid or Mesh edge closest to the mouse position and draws it on screen with a different color to highlight it.
It iterates through the Edges of the Portions of each Solid and through the edges of each Mesh in the scene computing the one closest to the mouse.
If the distance is within 10 pixels, it draws it on top of the scene.
class MyDesign : Design
{
Segment2D nearestEdge;
protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
{
base.OnMouseMove(e);
if (ActionMode != actionType.None)
return;
Segment2D previousEdge = nearestEdge;
Point2D mousePos = new Point2D(e.X, Height - e.Y);
double minDist = double.MaxValue;
foreach (Entity ent in Entities)
{
if (ent is Solid)
{
Solid sol = (Solid)ent;
foreach (Solid.Portion solidPortion in sol.Portions)
{
FindClosestEdge(mousePos, solidPortion.Edges, solidPortion.Vertices, ref minDist, ref nearestEdge);
}
}
else if (ent is Mesh)
{
Mesh m = (Mesh)ent;
FindClosestEdge(mousePos, m.Edges, m.Vertices, ref minDist, ref nearestEdge);
}
}
if (minDist > 10 && nearestEdge != null)
{
nearestEdge = null;
Invalidate();
}
else if (minDist < 10 && Different(previousEdge, nearestEdge))
Invalidate();
}
private void FindClosestEdge(Point2D mousePos, IList edges, IList vertices, ref double minDist, ref Segment2D nearestEdge)
{
if (edges == null)
return;
foreach (IndexLine edge in edges)
{
Point3D pt1 =(Point3D) vertices[edge.V1];
Point3D pt2 =(Point3D) vertices[edge.V2];
Point2D p_2d_1 = WorldToScreen(pt1);
p_2d_1.Y = p_2d_1.Y;
Point2D p_2d_2 = WorldToScreen(pt2);
p_2d_2.Y = p_2d_2.Y;
Segment2D seg = new Segment2D(p_2d_1, p_2d_2);
double t = seg.ClosestPointTo(mousePos);
if (t >= 0 && t <= 1)
{
double dist = Point2D.Distance(mousePos, seg.PointAt(t));
if (dist < minDist)
{
minDist = dist;
nearestEdge = seg;
}
}
}
}
private bool Different(Segment2D seg1, Segment2D seg2)
{
return !(seg1 != null && seg2 != null && Math.Abs(seg1.P0.X - seg2.P0.X) < 1e-6 && Math.Abs(seg1.P0.Y - seg2.P0.Y) < 1e-6 && Math.Abs(seg1.P1.X - seg2.P1.X) < 1e-6 && Math.Abs(seg1.P1.Y - seg2.P1.Y) < 1e-6);
}
protected override void DrawOverlay(DrawSceneParams myParams)
{
base.DrawOverlay(myParams);
if (nearestEdge != null)
{
RenderContext.SetLineSize(4);
RenderContext.SetColorWireframe(Color.Red);
RenderContext.DrawLine(nearestEdge.P0, nearestEdge.P1);
}
}
}
Comments
Could you please add images to show what the code does exactly? It might be what I'm looking for, but I cannot easily determine this.
Hi Ewoud,
We added a short screen capture to highlight the expected behavior of the code within the article.
Thank you very much! This is greatly appreciated and helpful. It appears that I was looking for something else, so this saves some time :)
Thanks for the article, exactly what i was looking. Expanding further how can i avoid of highlighting non visible object?
There is some sort of occlusion culling/raycasting from camera point?
Please sign in to leave a comment.