2011-08-03 6 views

答えて

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

理由をヒットした場合見つけるために地域のためのisVisibleを呼びますか?彼らは同じになることができます。閉じた線または曲線がある場合...パスのすべての点が同じ点でないかどうかを確認する必要があります... – serhio

+0

@serhio私は、始点を持つ1行のパスを持つことはできないと思いますエンドポイントは同じです。 – 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

それは私が言ったことではありませんか? widenメソッドにはバグがあります。 – LarsTech

0

次のコードは、DrawPathのOutOfMemoryが.Net 4.0(およびそれ以上)の原因になります。 私はLineCap.NoAnchorの代わりにLineCap.Flatを使用して、それを回避するために管理されていた:私もこの例外に苦しんできた

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

  1. 保存ポイントをOutOfMemoryExceptionが原因となる正確なポイントを見るために拡大する前に:次のよう勧告は

    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; 
    } 
    

次に、あなたは、単にそれらのいずれかが