Highlighting the edge closest to the mouse

The following SingleViewportLayout 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 MySingleViewportLayout : SingleViewportLayout 
{ 
        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<IndexLine> edges, IList<Point3D> vertices, ref double minDist, ref Segment2D nearestEdge) 
        { 
            if (edges == null) 
                return; 

            foreach (IndexLine edge in edges) 
            { 
                Point3D pt1 = vertices[edge.V1]; 
                Point3D pt2 = 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) 
            { 
                gl.Color3ub(255, 0, 0); 
                gl.LineWidth(4); 

                gl.Begin(gl.LINES); 
                gl.Vertex2d(nearestEdge.P0.X, nearestEdge.P0.Y); 

                gl.Vertex2d(nearestEdge.P1.X, nearestEdge.P1.Y); 

                gl.End(); 
            } 
        } 
}
Have more questions? Submit a request

2 Comments

  • 0
    Avatar
    Mustafa KAPLAN

    thanks

  • 1
    Avatar
    Mustafa KAPLAN

    please for face

Please sign in to leave a comment.