2011-08-03 89 views
3

我有以下的GraphicsPath和OutOfMemoryException異常

private bool IsPathVisible(Rectangle detectorRectangle, GraphicsPath path, Pen pen) 
{ 
    path.Widen(pen); 
    return IsPathVisible(detectorRectangle, path); 
} 

path點是相同的點,我接收OutOfMemoryException異常(使用Widen功能)。

我該如何管理它?

回答

6

這是筆和擴大方法的錯誤。確保路徑的起點和路徑的終點不相同。

這是一個演示:

private void panel1_Paint(object sender, PaintEventArgs e) 
{ 
    //This works: 
    using (GraphicsPath path = new GraphicsPath()) 
    { 
    path.AddLine(new Point(16, 16), new Point(20, 20)); 
    path.Widen(Pens.Black); 
    e.Graphics.DrawPath(Pens.Black, path); 
    } 

    //This does not: 
    using (GraphicsPath path = new GraphicsPath()) 
    { 
    path.AddLine(new Point(20, 20), new Point(20, 20)); 
    path.Widen(Pens.Black); 
    e.Graphics.DrawPath(Pens.Black, path); 
    } 
} 

這裏是有人向微軟:GraphicsPath.Widen throw OutOfMemoryException if the path has a single point

+0

爲什麼呢?他們可以是相同的。如果我有一條封閉的線條或曲線...我需要檢查路徑上的所有點是否不是相同的點... – serhio

+0

@serhio我認爲你不能擁有一條具有起點的單一行的路徑和一個相同的端點。 – LarsTech

+0

一條路徑 - 單條線就是一條路徑。它可以是圓形,曲線,封閉線或任何其他幾何圖形。 – serhio

-1

如果路徑IsPoint,不做拓寬

<System.Runtime.CompilerServices.Extension()> _ 
Public Function IsPoint(ByVal path As System.Drawing.Drawing2D.GraphicsPath) As Boolean 
    If path Is Nothing Then Throw New ArgumentNullException("path") 

    If path.PathPoints.Count < 2 Then Return True 

    If path.PathPoints(0) <> path.PathPoints(path.PathPoints.Count - 1) Then Return False 

    For i = 1 To path.PathPoints.Count - 1 
    If path.PathPoints(i - 1) <> path.PathPoints(i) Then Return False 
    Next i 

    ' if all the points are the same 
    Return True 
End Function 
+0

這不就是我說的嗎?在擴展方法中有一個錯誤。 – LarsTech

0

下面的代碼使在內存不足在DrawPath .NET 4.0(以及可能更高)。 我使用管理,而不是LineCap.Flat的LineCap.NoAnchor繞過它:

public void TestDrawPath() 
{ 
    PointF[] points = new PointF[13] 
    { 
     new PointF(0.491141558f, 1.53909028f), 
     new PointF(0.491141558f, 1.55148673f), 
     new PointF(0.4808829f, 1.56153619f), 
     new PointF(0.468228281f, 1.56153619f), 
     new PointF(0.4555736f, 1.56153619f), 
     new PointF(0.445314974f, 1.55148673f), 
     new PointF(0.445314974f, 1.53909028f), 
     new PointF(0.445314974f, 1.52669382f), 
     new PointF(0.4555736f, 1.51664436f), 
     new PointF(0.468228281f, 1.51664436f), 
     new PointF(0.4808829f, 1.51664436f), 
     new PointF(0.491141558f, 1.52669382f), 
     new PointF(0.491141558f, 1.53909028f) 
    }; 
    byte[] types = new byte[13] { 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 131 }; 

    using (Bitmap bitmap = new Bitmap(2, 2)) 
    using (Graphics g = Graphics.FromImage(bitmap)) 
    { 
     using (Pen pen = new Pen(Color.Black)) 
     using (GraphicsPath path = new GraphicsPath(points, types)) 
     { 
      pen.StartCap = LineCap.NoAnchor; 
      pen.EndCap = LineCap.NoAnchor; 
      g.DrawPath(pen, path); 
     } 
    } 
} 
1

我也一直從這個異常痛苦。建議如下:拓寬看到,導致OutOfMemoryException異常確切點之前

  1. 保存點:

    private bool IsPathVisible(Rectangle detectorRectangle, GraphicsPath path, Pen pen) 
    { 
        var points = path.PathPoints.Clone() as PointF[]; 
        path.Widen(pen); 
        return IsPathVisible(detectorRectangle, path); 
    } 
    

什麼,你可能會看到的是,有一些具有相同的可能因之點座標。他們實際上是造成這個問題。

  1. 此外,GraphicsPath可以由多個子路徑組成。爲了讓一個可靠的命中測試,我想提出以下建議:

    public Region[] CreateRegionFromGraphicsPath(GraphicsPath path, Pen wideningPen) 
    { 
        var regions = new List<Region>(); 
    
        var itPath = new GraphicsPathIterator(path); 
        itPath.Rewind(); 
        var curSubPath = new GraphicsPath(); 
    
        for (int i = 0; i < itPath.SubpathCount; i++) 
        { 
         bool isClosed; 
         itPath.NextSubpath(curSubPath, out isClosed); 
    
         if (!isClosed && CanWiden(curSubPath)) curSubPath.Widen(wideningPen); // widen not closed paths 
    
         int regionIndex = i/100; // max region scan rectangles count 
    
         if (regions.Count < regionIndex + 1) 
         { 
          regions.Add(new Region(curSubPath)); 
         } 
         else 
         { 
          regions[regionIndex].Union(curSubPath); 
         } 
        } 
    
        curSubPath.Dispose(); 
        itPath.Dispose(); 
    
        return regions.ToArray(); 
    } 
    
    /// <summary> 
    /// Determines whether widening this graphics path will not lead to an exception 
    /// </summary> 
    public static bool CanWiden(GraphicsPath gp) 
    { 
        const float regionPointsTolerance = 1e-8f; 
        var pts = gp.PathPoints; 
        if (pts.Length < 2) return false; 
        for (int i = 1; i < pts.Length; i++) 
        { 
         if (Math.Abs(pts[i-1].X - pts[i].X) < regionPointsTolerance && Math.Abs(pts[i-1].Y - pts[i].Y) < regionPointsTolerance) return false; 
        } 
        return true; 
    } 
    

然後你只需撥打ISVISIBLE的地區發現如果其中任何被擊中

相關問題