Алгоритм заливки не работает должным образом - он создает промежутки между пикселями - PullRequest
0 голосов
/ 14 ноября 2018

Ну, я не могу быть настолько выразительным в названии, поэтому я попытаюсь объяснить это здесь.

В основном мой алгоритм заполнения флудом делает это:

...

Различные цвета означают следующее:

  • Синие пиксели - это точки из многоугольника
  • Красные пиксели - это то, что 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) (она слишком велика, чтобы быть здесь).

  • Мы повторяем ее попиксельно.
  • Если мы нашли какой-либо разрешенный пиксель (Grass, Скала, Лед, Снег или что-то еще) затем ...
  • Мы начинаем искать форму текущего биома
  • Затем перед продолжением итерации мы вызываем алгоритм Flood Fill.
  • С помощью этого вызова мы гарантируем, что мы никогда не пропустим ни один пиксель, являющийся частью какого-либо из полигонов карты.

Но, как вы видите, у меня проблемы.

Наблюдая за моей реализацией, я полагаю, что когда пиксели в очереди ищут соседей, они попадают в ловушку и не возвращают соседний пиксель.

Или, может быть, так работает мой алгоритм заливки (в особых условиях, я не знаю).

Что вы могли бы предложить / посоветовать мне сделать?

Примечание: Текстура была получена, когда я вручную вышел из метода.Итак, мой алгоритм заполнения - это заполнение текстуры «слоями», поэтому так много желтых пикселей.

...