洪水填充算法无法按预期工作-在像素之间会产生间隙

时间:2018-11-14 19:14:22

标签: c# algorithm unity3d optimization flood-fill

好吧,我的标题表达得不太好,所以我将在这里解释一下。

基本上,我的洪水填充算法是这样做的:

...

不同的颜色表示以下含义:

  • 蓝色像素是来自多边形的点
  • 红色像素是洪水填充已经填充的颜色
  • 洋红色是两种颜色的组合
  • 永远不要出现黄色像素(这意味着已经对迭代形状的算法进行了迭代)
  • 其他都是源纹理

这是我当前的方法:

    /// <summary>
    /// Floods the fill.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="source">The source.</param>
    /// <param name="x">The x.</param>
    /// <param name="y">The y.</param>
    /// <param name="width">The width.</param>
    /// <param name="height">The height.</param>
    /// <param name="target">The target.</param>
    /// <param name="replacement">The replacement.</param>
    public static void FloodFill<T>(this T[] source, int x, int y, int width, int height, T target, T replacement)
        where T : IEquatable<T>
    {
        int i;

        source.FloodFill(x, y, width, height, target, replacement, out i);
    }

    /// <summary>
    /// Floods the array following Flood Fill algorithm
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="source">The source.</param>
    /// <param name="x">The x.</param>
    /// <param name="y">The y.</param>
    /// <param name="width">The width.</param>
    /// <param name="height">The height.</param>
    /// <param name="target">The target to replace.</param>
    /// <param name="replacement">The replacement.</param>
    /// <param name="i">The i.</param>
    // This was generic
    public static void FloodFill<T>(this T[] source, int x, int y, int width, int height, T target, T replacement, out int i)
        where T : IEquatable<T>
    {
        i = 0;
        HashSet<int> queue = new HashSet<int>();

        queue.Add(P(x, y, width, height));

        while (queue.Count > 0)
        {
            int _i = queue.First(),
                _x = _i % width,
                _y = _i / width;

            queue.Remove(_i);

            if (source[_i].Equals(target))
                source[_i] = replacement;

            for (int offsetX = -1; offsetX < 2; offsetX++)
                for (int offsetY = -1; offsetY < 2; offsetY++)
                {
                    // do not check origin or diagonal neighbours
                    if (offsetX == 0 && offsetY == 0 || offsetX == offsetY || offsetX == -offsetY || -offsetX == offsetY)
                        continue;

                    int targetIndex = Pn(_x + offsetX, _y + offsetY, width); // This is already inverted that's why we don't use F.P(...)
                    int _tx = targetIndex % width,
                        _ty = targetIndex / width;

                    // skip out of bounds point
                    if (_tx < 0 || _ty < 0 || _tx >= width || _ty >= height)
                        continue;

                    if (!queue.Contains(targetIndex) && source[targetIndex].Equals(target))
                    {
                        queue.Add(targetIndex);

                        if (Monitor.IsEntered(i))
                            ++i;
                        else
                            Interlocked.Increment(ref i);
                    }
                }

            if (i > 100000)
                break;
        }
    }

我无法显示其他代码,但是我可以尝试解释一下。

基本上,我们具有这种纹理(https://themindheist.files.wordpress.com/2015/03/gta_usa_map3.png)(太大了,无法出现在这里)。

  • 我们逐像素进行迭代。
  • 如果发现任何允许的像素(草,岩石,冰,雪或其他),则...
  • 我们开始寻找当前生物群落的形状
  • 然后在继续进行迭代之前,我们将其称为Flood Fill算法。
  • 通过此调用,我们确保我们永远不会越过构成地图任何多边形一部分的任何像素。

但是如您所见,我有问题。

看着我的实现,我想当排队的像素寻找邻居时,它们被困住了,并且不返回任何邻居像素。

或者,也许这就是我的洪水填充算法的执行方式(在我不知道的特殊条件下)。

您可以建议/推荐我做什么?

注意:当我手动退出该方法时,纹理已获得。因此,我的填充算法是按“图层”填充纹理,这就是为什么有这么多黄色像素的原因。

0 个答案:

没有答案