Я пытаюсь создать инструмент заливки для моего приложения для рисования, созданный с помощью Electron.js и P5.js для холста. каждый раз, когда пользователь нажимает на холст, а его переменная mode
равна «fill», он вызывает функцию floodFill. я попытался реализовать алгоритм отсюда: https://en.wikipedia.org/wiki/Flood_fill#Pseudocode (рекурсивная реализация на основе стека (четырехсторонняя)), но у меня есть проблема - я достигаю максимального стека вызовов.
То, как я отображаю все на экране, это то, что у меня есть массив с именем drawing
, и есть функции конструктора для типов объектов, которые вы можете рисовать (Круг, Квадрат), поэтому я создал функцию конструктора Pixel, чтобы я мог отображать ее каждый раз, я не могу вызвать updatePixels()
, потому что я рендерил все каждый кадр с помощью функции draw()
.
это моя функция заливки:
function floodFill(x, y, target_col, replace_col) {
if (x >= 0 && y >= 0 && x <= width && y <= height) {
let index = (x + y * width) * 4;
if (target_col === replace_col) {
return;
} else if (
pixels[index] !== target_col.levels[0] &&
pixels[index + 1] !== target_col.levels[1] &&
pixels[index + 2] !== target_col.levels[2] &&
pixels[index + 3] !== target_col.levels[3]
) {
return;
} else {
drawing.push(new Pixel(x, y, replace_col));
floodFill(x, y - 1, target_col, replace_col);
floodFill(x, y + 1, target_col, replace_col);
floodFill(x - 1, y, target_col, replace_col);
floodFill(x + 1, y, target_col, replace_col);
}
}
}
вот как я вызываю функцию:
if (mode === "fill") {
loadPixels();
let index = (mouseX + mouseY * width) * 4;
// target_color = what the user wants to replace
let target_color = color(
pixels[index],
pixels[index + 1],
pixels[index + 2],
pixels[index + 3]
);
// replacement_color = the color that will be instead of the target_color
let replacement_color = color(current_color);
floodFill(mouseX, mouseY, target_color, replacement_color);
}
Кстати, в функции floodFill
в else if
я использовал эту технику, потому что простое выполнение color(pixels[index], pixels[index + 1], pixels[index + 2], pixels[index + 3]) !== target_col
не сработало
EDIT:
Я понял, что у меня есть ошибка с функцией floodFill, мой else if
почти никогда не верен, потому что он также пытается проверить, не равны ли альфы, и почти всегда они равны 255. поэтому я добавил к остальному, если это:
else if (
(pixels[index] !== target_col.levels[0] &&
pixels[index + 1] !== target_col.levels[1] &&
pixels[index + 2] !== target_col.levels[2]) ||
pixels[index + 3] !== target_col.levels[3]
) {
теперь, что происходит, если я пытаюсь заполнить что-то, оно рисует прямую линию, пока не достигнет другого цвета, но затем достигнет максимального размера стека,
пример:
возможно, это связано с тем, что в функции floodFill
первый рекурсивный вызов, который я выполняю, - y - 1
(вверх).
Я хотел бы услышать больше предложений
ДРУГОЕ РЕДАКТИРОВАНИЕ:
я понял, что в floodFill
в рекурсивном разделе я называю его y - 1
, затем y + 1
, что не имеет смысла, потому что оно идет вверх, а затем вниз означает, что оно остается в том же пикселе, поэтому я отредактировал его так, чтобы как это:
floodFill(x, y - 1, target_col, replace_col);
floodFill(x - 1, y, target_col, replace_col);
floodFill(x, y + 1, target_col, replace_col);
floodFill(x + 1, y, target_col, replace_col);
теперь это выглядит так:
![paint](https://i.stack.imgur.com/qvcnZ.png)