Ну, я не могу быть настолько выразительным в названии, поэтому я попытаюсь объяснить это здесь.
В основном мой алгоритм заполнения флудом делает это:
![...](https://i.stack.imgur.com/Jb42E.png)
Различные цвета означают следующее:
- Синие пиксели - это точки из многоугольника
- Красные пиксели - это то, что 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.
- С помощью этого вызова мы гарантируем, что мы никогда не пропустим ни один пиксель, являющийся частью какого-либо из полигонов карты.
Но, как вы видите, у меня проблемы.
Наблюдая за моей реализацией, я полагаю, что когда пиксели в очереди ищут соседей, они попадают в ловушку и не возвращают соседний пиксель.
Или, может быть, так работает мой алгоритм заливки (в особых условиях, я не знаю).
Что вы могли бы предложить / посоветовать мне сделать?
Примечание: Текстура была получена, когда я вручную вышел из метода.Итак, мой алгоритм заполнения - это заполнение текстуры «слоями», поэтому так много желтых пикселей.