【发布时间】:2018-06-30 13:25:18
【问题描述】:
我正在尝试为我用电子.js 和 P5.js 制作的画布应用程序创建一个桶工具。每当用户点击画布并且他的mode 变量等于“fill”时,它就会调用floodFill 函数。我试图从这里实现算法:https://en.wikipedia.org/wiki/Flood_fill#Pseudocode(基于堆栈的递归实现(四向)),但我有一个问题 - 我正在达到最大调用堆栈。
我将所有内容渲染到屏幕上的方式是我有一个名为drawing 的数组,并且您可以绘制的事物类型(圆形,方形)有构造函数,所以我创建了一个像素构造函数,以便我可以每次都渲染它,我无法调用updatePixels(),因为我使用draw() 函数渲染每一帧的所有内容。
这是我的 floodFill 函数:
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);
}
顺便说一句,在else if 中的floodFill 函数中,我使用了这种技术,因为简单地执行color(pixels[index], pixels[index + 1], pixels[index + 2], pixels[index + 3]) !== target_col 不起作用
编辑:
我意识到我的 floodFill 函数有一个错误,我的 else if 几乎永远不会是真的,因为它还会尝试检查 alpha 是否不相等并且它们几乎总是 255。所以我添加到 else if 这个:
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);
现在它显示如下:
【问题讨论】:
标签: javascript p5.js flood-fill