Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net GraphicsPath和OutOfMemoryException_.net_Gdi+ - Fatal编程技术网

.net GraphicsPath和OutOfMemoryException

.net GraphicsPath和OutOfMemoryException,.net,gdi+,.net,Gdi+,我有以下几点 private bool IsPathVisible(Rectangle detectorRectangle, GraphicsPath path, Pen pen) { path.Widen(pen); return IsPathVisible(detectorRectangle, path); } 当路径点是同一点时,我收到一个OutOfMemoryException(使用加宽函数) 我如何管理它?这是笔和加宽方法的一个缺陷。确保路径的起点和终点不相同 这是一

我有以下几点

private bool IsPathVisible(Rectangle detectorRectangle, GraphicsPath path, Pen pen)
{
    path.Widen(pen);
    return IsPathVisible(detectorRectangle, path);
}
路径
点是同一点时,我收到一个OutOfMemoryException(使用
加宽
函数)


我如何管理它?

这是笔和加宽方法的一个缺陷。确保路径的起点和终点不相同

这是一个演示:

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

这里是向Microsoft报告的地方:

如果路径
是点
,请不要加宽

_
公共函数IsPoint(ByVal路径作为System.Drawing.Drawing2D.GraphicsPath)作为布尔值
如果路径为Nothing,则抛出新的ArgumentNullException(“路径”)
如果path.PathPoints.Count<2,则返回True
如果path.PathPoints(0)path.PathPoints(path.PathPoints.Count-1),则返回False
对于i=1到path.PathPoints.Count-1
如果path.PathPoints(i-1)path.PathPoints(i),则返回False
接下来我
“如果所有的点都相同
返回真值
端函数

以下代码导致.Net 4.0(可能更高版本)中DrawPath中的OutOfMemory。
我使用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);
        }
    }
}

我也经历了这个例外。建议如下:

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;
}
  • 加宽前保存点,以查看导致OutOfMemoryException的确切点:

    private bool IsPathVisible(Rectangle detectorRectangle, GraphicsPath path, Pen pen)
    {
        var points = path.PathPoints.Clone() as PointF[];
        path.Widen(pen);
        return IsPathVisible(detectorRectangle, path);
    }
    
  • 您可能会看到,可能会有具有相同坐标的后续点。他们实际上是问题的根源

  • 此外,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;
    }
    
    公共区域[]CreateRegionFromGraphicsPath(GraphicsPath,画笔加宽画笔)
    {
    var regions=新列表();
    var itPath=新图形转换器(路径);
    itPath.Rewind();
    var curSubPath=new GraphicsPath();
    对于(int i=0;i

  • 然后,您只需调用IsVisible for regions来查找是否有任何区域被击中

    为什么?它们可以是相同的。如果我有一条闭合的直线或曲线。。。我需要检查路径的所有点是否都不是同一点…@serhio我想你不可能有一条起点和终点相同的直线。路径-单行就是路径的一个例子。它可以是圆、曲线、闭合线或任何其他几何图形。这不是我说的吗?加宽方法中有一个错误。