Dot-Net
.NET 確定滑鼠在兩個任意點之間繪製的線上
我在 Winform 上的兩個對象之間繪製了一個箭頭。
確定我的滑鼠目前懸停在這條線上或附近的最簡單方法是什麼。
我考慮過測試滑鼠點是否與由兩個點定義和外推的正方形相交,但是這只有在兩個點具有非常相似的 x 或 y 值時才可行。
我也在想,這個問題可能更多地屬於線性代數而不是簡單的三角學,雖然我確實記得矩陣的簡單方面,但這個問題超出了我對線性代數的了解。
另一方面,如果 .NET 庫能夠處理該功能,那就更好了。
編輯 感謝您的回答,有一些非常好的都值得被標記為已回答。
我選擇了 Coincoin 的答案作為接受,因為我喜歡它可以應用於繪製的任何形狀,但最終實現了 Tim Robinson 的方程,因為使用簡單的方程而不是更新圖形路徑和筆似乎更有效,如我的情況我需要為 1-n 個不同的關係做 onMouseMove (顯然會有一些記憶體和優化,但重點仍然存在)
該方程的主要問題是它似乎將這條線視為無限,所以我也添加了一個邊界測試。
對於那些感興趣的人,程式碼(最初的剪輯,我可能會稍微整理一下)如下
if (Math.Sqrt( Math.Pow(_end.X - _start.X, 2) + Math.Pow(_end.Y - _start.Y, 2) ) == 0) { _isHovering = new RectangleF(e.X, e.Y, 1, 1).IntersectsWith(_bounds); } else { float threshold = 10.0f; float distance = (float)Math.Abs( ( ( (_end.X - _start.X) * (_start.Y - e.Y) ) - ( (_start.X - e.X) * (_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(e.X, e.Y, 1, 1).IntersectsWith(_bounds) ); }並且 _bounds 定義為:
_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));
如果您想輕鬆地對任意繪製的形狀進行命中測試,您可以創建一個包含您的繪圖的路徑,然後加寬路徑並僅使用框架函式進行可見性測試。
例如,在這裡我們創建一條帶有一行的路徑:
GraphicsPath path = new GraphicsPath(); path.AddLine(x1, y1, x2, y2); path.CloseFigure();然後,加寬路徑並為命中測試創建一個區域:
path.Widen(new Pen(Color.Black, 3)); region = new Region(path);最後,命中測試:
region.IsVisible(point);該方法的優點是它可以輕鬆擴展到樣條線、箭頭、弧線、餅圖或幾乎任何可使用 GDI+ 繪製的東西。通過提取相同的路徑可以在
HitTest和邏輯中使用。Draw這是結合所有這些的程式碼:
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); }