填充矩形

时间:2011-04-25 20:42:29

标签: c# graphics grid draw

我创建了一个winform程序,它使用Graphics对象和2个for循环来生成方形网格,具体取决于用户输入。

我还创建了一个方法,通过使用与网格相同的坐标,用随机颜色填充网格中的每个方块。

现在我想使用光标位置单独绘制每个方块。我该怎么做?

2 个答案:

答案 0 :(得分:2)

为什么不跟踪网格线,从而知道你点击的方格?根据这些知识,你可以画一个属于它的正方形。

答案 1 :(得分:1)

洪水填充最简单。与其他方法相比它很慢并占用堆栈空间,但在不到15年的计算机上它不应该是一个问题。

<强>更新

正如@Ron所提到的,一个典型的递归填充很容易打击堆栈。所以,我修改了代码以使用Stack<>实例(我相信是从堆中分配的)和所谓的“数据递归”。对于大型(2000x2000 +像素)区域来说,它仍然很慢,但对于小型区域应该没问题。

bool[] canDraw;
/// <summary>
/// make sure that the given point is within our image boundaries.
/// BufferSize(Point) contains the dimensions of the image buffer.
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
bool InBounds(Point p)
{
    return p.X >= 0 && p.X < BufferSize.X && p.Y >= 0 && p.Y < BufferSize.Y;
}

/// <summary>
/// make sure that we haven't already drawn this pixel and that it has
/// valid coordinates
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
bool CanDraw(Point p)
{
    return InBounds(p) && canDraw[p.Y * BufferSize.X + p.X];
}

/// <summary>
/// Heap "stack" to track which pixels we need to visit
/// </summary>
Stack<Point> fillStack = new Stack<Point>();

/// <summary>
/// initialize recursion.
/// </summary>
/// <param name="startPosition"></param>
/// <param name="fillColor"></param>
void Fill(Point startPosition, Color fillColor)
{
    canDraw = Enumerable.Repeat(true, BufferSize.X * BufferSize.Y).ToArray();
    var backgroundColor = GetPixel(startPosition);

    if (backgroundColor != fillColor)
    {
        fillStack.Push(startPosition);
        RecurseFloodFill(fillColor, backgroundColor);
    }

}

/// <summary>
/// data-recurse through the image.
/// </summary>
/// <param name="fillColor">Color we want to fill with</param>
/// <param name="backgroundColor">Initial background color to overwrite</param>
void RecurseFloodFill(Color fillColor, Color backgroundColor)
{
    while (fillStack.Count > 0 && !IsExiting)
    {
        /*if (fillStack.Count != depth)
            Debug.WriteLine("Depth: {0}", depth = fillStack.Count);
        */
        var position = fillStack.Pop();
        if(!CanDraw(position))
            continue;

        var color = GetPixel(position);
        if (color != backgroundColor)
            continue;

        SetPixel(position, fillColor);

        for(var i=position.X-1;i<=position.X+1;i++)
            for (var j = position.Y - 1; j <= position.Y + 1; j++)
            {
                var p = new Point(i, j);
                fillStack.Push(p);
            }

    }

}

注意我甚至都没有尝试编译它。

基本上:

  1. 点击:阅读用户点击的颜色(背景颜色)。
  2. 递归开始:
  3. 读取用户点击的颜色(背景颜色)。
  4. 确保它与步骤1中的背景颜色相同。否则返回。
  5. 将像素设置为填充颜色。
  6. 针对8个周围像素递归步骤3。当您读取的背景像素与最初读取的背景颜色不同时,递归会停止。