.NET The dedicated mouse is on a line drawn between two arbitrary points.

I have an arrow drawn between two objects on Winform.

What would be the easiest way to determine if my mouse is currently freezing or approaching this line.

I examined the question of whether a mouse point intersects a square defined and extrapolated by two points, however this would be possible only if the two points had very similar x or y values.

I also think that this problem is probably more in the fields of linear algebra, rather than simple trigonometry, and although I remember simpler aspects of matrices, this problem does not depend on linear algebra.

On the other hand, if the .NET library can handle this function, even better.

EDIT Thanks for the answers, there were a few very good ones that deserve to be marked as an answer.

I chose Coincoin's answer as accepted, because I like that it can be applied to any figure, but ultimately embodied Tim Robinson's decision, since it turned out to be much more effective with a simple equation, and not with the appearance of graphic tracks and pens, since in my case I need to do this onMouseMove for 1 different relationship (obviously, there will be caching and optimization, but the point still remains)

The main problem with this equation was that he considered the line to be infinite, so I also added a border test.

Code (initial cut, I’m probably a little ahead), for those who are interested, below

if (Math.Sqrt( Math.Pow(_end.X - _start.X, 2) + Math.Pow(_end.Y - _start.Y, 2) ) == 0) { _isHovering = new RectangleF(eX, eY, 1, 1).IntersectsWith(_bounds); } else { float threshold = 10.0f; float distance = (float)Math.Abs( ( ( (_end.X - _start.X) * (_start.Y - eY) ) - ( (_start.X - eX) * (_end.Y - _start.Y) ) ) / Math.Sqrt( Math.Pow(_end.X - _start.X, 2) + Math.Pow(_end.Y - _start.Y, 2) )); _isHovering = ( distance <= threshold && new RectangleF(eX, eY, 1, 1).IntersectsWith(_bounds) ); } 

and _bounds is defined as:

  _bounds = new Rectangle( Math.Min(_start.X, _end.X), Math.Min(_start.Y, _end.Y), Math.Abs(_start.X - _end.X), Math.Abs(_start.Y - _end.Y)); 
+7
geometry intersection
source share
5 answers

If you want to easily run tests for arbitrary drawn shapes, you can create a path containing your drawing, then skip the path and perform a visibility test using only the framework functions.

For example, here we create a path with a line:

 GraphicsPath path = new GraphicsPath(); path.AddLine(x1, y1, x2, y2); path.CloseFigure(); 

Then expand the path and create an area for impact testing:

 path.Widen(new Pen(Color.Black, 3)); region = new Region(path); 

Finally, a shock test:

 region.IsVisible(point); 

The advantage of this method is that it can easily spread to splines, arrows, arcs, pies, or just about anything that can be used with GDI +. The same path can be used both in HitTest logic and Draw , extracting it.

Here is the code that combines all of this:

 public GraphicsPath Path { get { GraphicsPath path = new GraphicsPath(); path.AddLine(x1, y1, x2, y2); path.CloseFigure(); return path; } } bool HitTest(Point point) { using(Pen new pen = Pen(Color.Black, 3)) using(GraphicsPaht path = Path) { path.Widen(pen); using(Region region = new Region(path)) return region.IsVisible(point); } } void Draw(Graphics graphics) { using(Pen pen = new Pen(Color.Blue, 0)) using(GraphicsPaht path = Path) graphics.DrawPath(pen, path); } 
+7
source share

To answer β€œIs the mouse above this line?” You need to check the intersection of the point with the line. However, since you ask, β€œIs the mouse near the line?”, It sounds like you want to calculate the distance between the mouse point and the line.

Here is a fairly detailed explanation of the distance between the points: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html

I would say that you need to implement this formula in your code: (stolen from wolfram.com)

Where:

  • (x0, x0) - location of the mouse pointer
  • (x1, y1) - one end of the line
  • (x2, y2) - the other end of the line
  • |n| is Math.Abs(n)
  • Bottom half is Math.Sqrt
  • You can ignore |vr| if you want to
+4
source share

I would calculate the Slope-Intercept equation (y = mx + b) for my line, and then use it to check the coordinates of the mouse. You can easily set the range around y to see if you are close.

Edit for sample.

I think this works:

 PointF currentPoint; PointF p1, p2; float threshold = 2.0f; float m = (p1.Y - p2.Y) / (p1.X - p2.X); float b = p1.Y - (m * p1.X); if (Math.Abs(((m * currentPoint.X) + b) - currentPoint.Y) <= threshold) { //On it. } 
+2
source share

You need to build two (conditional) boundary lines parallel to the ideal path. Then you only need to calculate for each mouse position whether the mouse is outside or inside the channel formed by these lines.

You do not need to calculate the distance from the mouse to the main line.

+1
source share

Check MouseEnter (object sender, EventArgs e). Trap when it "enters" into the control area.

0
source share

All Articles