2013-10-09 58 views
1

1)我有一個線段列表(由它們的兩個端點和一個寬度定義)
2)這些線段在面板中繪製。
3)當我的鼠標移動(Panel.MouseMove事件)時,我遍歷線段列表。
4)的foreach:命中測試線段

gPath.Reset(); 
    Pen Pen = new Pen(Color.White, 20); 
    gPath.AddLine(P1, P2); 
    return gPath.IsOutlineVisible(cursorPos, Pen); 

5)如果我真的,那麼我知道我的光標懸停在當前線段。

這適用於約300行左右。當我達到1000時,我的程序放慢速度(分析表明它是由IsOutlineVisible引起的)。那麼,有什麼辦法可以提高我的命中測試算法的性能嗎?我不知道IsOutlineVisible的效率如何,因此我不想實現該方法已經使用的任何優化。有任何想法嗎?

編輯:
在挖掘我的數據後,我注意到一些線條非常大。例如:
端點1 =(16000 -16000)
端點2 =(5041448,-32868734)

(是的,座標之一是否定的數以千萬計的......)

我證明只針對一個這樣的線段進行命中測試就足以讓我的程序停下來(IsOutlineVisible需要2-3秒才能完成測試,並且只要光標移動就運行測試...)。

我應該在發佈之前對此進行更徹底的測試。感謝所有的迴應(如果我最終處理了數千行代碼,那麼2D空間索引是一個很好的建議)。

p.s.如果有人知道爲什麼一個大的線段是IsOutlineVisible的一個大問題,那就太好了。

+0

您可能想看看[我的示例](http://stackoverflow.com/a/15469477/643085)使用當前相關的類似事物。淨Windows UI技術。它包含一些有趣的功能,如線條選擇和突出顯示。 –

+0

謝謝,但我目前使用winforms。 –

+0

只是一個評論。我認爲它然後成矩形敵人命中測試。數學運算會提高性能,例如邊界框和距離矢量應該很快。儘管1000行太多了 – GorillaApe

回答

0

試試這個:

public Line GetHotSpottedLine(Point mousePos){ 
     var line = lines.Where(line => 
     { 
      Point p1 = new Point(Math.Min(line.P1.X, line.P2.X), Math.Min(line.P1.Y, line.P2.Y)); 
      Point p2 = new Point(Math.Max(line.P1.X, line.P2.X), Math.Max(line.P1.Y, line.P2.Y)); 
      return mousePos.X >= p1.X && mousePos.X <= p2.X && mousePos.Y >= p1.Y && mousePos.Y <= p2.Y; 
     }).FirstOrDefault(line => { 
      using (GraphicsPath gp = new GraphicsPath()) 
      { 
       gp.AddLine(line.P1, line.P2); 
       //You can declare your pen outside and this pen should be used to draw your lines. 
       using (Pen p = new Pen(Color.Red, 20)) 
       { 
        return gp.IsOutlineVisible(mousePos, p); 
       } 
      } 
     }); 
     return line; 
} 
public class Line{ 
     public Point P1 { get; set; } 
     public Point P2 { get; set; } 
} 
List<Line> lines = new List<Line>(); 

這取決於你想如何使用你的lines,如果你想吸引他們,我們要注意的drawingdetecting the hovered line的表現,是在這種情況下,drawing是你的問題。我想我們可以在這裏使用一些Thread。無論如何,我用1000行進行了測試,並且它工作正常(在Form Paint中繪製所有行),而無需使用任何線程。

0

IsOutlineVisible調用Gdi +,也許這會降低一點。

public bool GraphicsPath.IsOutlineVisible(PointF pt, Pen pen, Graphics graphics) 
{ 
    int num; 
    if (pen == null) 
    { 
     throw new ArgumentNullException("pen"); 
    } 
    int status = SafeNativeMethods.Gdip.GdipIsOutlineVisiblePathPoint(new HandleRef(this, this.nativePath), pt.X, pt.Y, new HandleRef(pen, pen.NativePen), new HandleRef(graphics, (graphics != null) ? graphics.NativeGraphics : IntPtr.Zero), out num); 
    if (status != 0) 
    { 
     throw SafeNativeMethods.Gdip.StatusException(status); 
    } 
    return (num != 0); 
} 

除此之外,在這些命中測試不使用優化等建築用的所有圖形元素的二維索引。爲了提高性能我想嘗試

  1. 執行命中測試自己並遍歷所有元素
  2. 也許使用2D指數,雖然< 1000元我不敢相信這是必要的。