2013-10-09 4 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 줄 정도 잘 수행됩니다. 내가 1,000에 도달하면 프로그램이 멈추는 속도가 느려집니다 (프로파일 링은 IsOutlineVisible로 인해 발생 함을 보여줍니다). 그래서, 내 히트 테스트 알고리즘의 성능을 향상시킬 수있는 방법이 있습니까? IsOutlineVisible이 얼마나 효율적인지 모르겠으므로이 메서드가 이미 사용하고있는 최적화를 구현하고 싶지 않습니다. 어떤 아이디어?

편집 :
내 데이터로 파고 후 나는 라인 중 일부는 매우 큰했다났습니다. 예를 들면 :
endpoint1 = (16000, -16000)
endpoint2 = (5041448, -32868734)

(예, 좌표 중 하나가 수백만의 부정적인 수만에 ...)

I 그러한 라인 세그먼트 하나에 대한 히트 테스트만으로도 프로그램을 정지시킬 수 있다는 것을 확인했습니다 (IsOutlineVisible은 테스트를 수행하는 데 2 ​​~ 3 초가 소요되며 커서가 움직일 때마다 테스트가 실행됩니다 ...).

내가 게시하기 전에 이것을 철저히 테스트 했어야합니다. 응답 한 모든 분들께 감사드립니다. (수천 줄을 처리하면 2 차원 공간 인덱스가 좋은 제안입니다).

p.s. IsOutlineVisible에 커다란 라인 세그먼트가 큰 문제가되는 이유를 아는 분이라면 좋을 것입니다.

+0

[My Example] (http://stackoverflow.com/a/15469477/643085)에서 현재의 관련성을 사용하여 매우 비슷한 것을보고 싶을 수 있습니다.Net 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를 사용하는 방법에 따라, 우리는 네 그 경우, drawing이며, drawing하지 detecting the hovered line의 성능을주의해야 너의 문제. 여기에 Thread을 사용할 수있을 것 같습니다. 어쨌든, 나는 1000 라인으로 테스트했고 어떤 스레드도 사용하지 않고 OK (모든 라인을 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); 
} 

, 이들은 사용되는 모든 그래픽 요소의 2D 인덱스를 구축 같은 최적화를 사용하지 않는 테스트를했다. 성능을 향상시키기 위해 내가

  1. 하려고 할 구현 < 1000 개 요소에 대해 내가 거의이 필요하다 생각하지 않지만, 자신을 테스트하고 어쩌면 2D 인덱스를 사용하는 모든 요소
  2. 에 걸쳐 반복했다.