forked from hughsk/flood-fill
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmod.ts
112 lines (87 loc) · 2.22 KB
/
mod.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
export type Grid = {
width: number;
height: number;
cells: Uint32Array;
floodFill: (x: number, y: number) => FloodFillResult;
fill: (value: number) => void;
set: (x: number, y: number, value: number) => void;
get: (x: number, y: number) => number;
};
export type FloodFillResult = {
filledGrid: Grid;
cellCount: number;
startValue: number;
startX: number;
startY: number;
};
export const createGrid = (width: number, height: number): Grid => {
const cells = new Uint32Array(width * height);
const fill = (value: number): void => {
cells.fill(value);
};
const set = (x: number, y: number, value: number): void => {
x = x | 0;
y = y | 0;
cells[y * width + x] = value;
};
const get = (x: number, y: number): number => {
x = x | 0;
y = y | 0;
return cells[y * width + x];
};
const floodFill = (x: number, y: number): FloodFillResult => {
x = x | 0;
y = y | 0;
const filledGrid = createGrid(width, height);
const enqueued = createGrid(width, height);
const startValue = get(x, y);
let cellCount = 0;
const queue = [];
const enqueue = (x: number, y: number) => {
// Outside the grid
if (x < 0 || x >= width || y < 0 || y >= height) return;
// Already in queue
if (enqueued.get(x, y) !== 0) return;
// Already visited
if (filledGrid.get(x, y) !== 0) return;
enqueued.set(x, y, 1);
queue.push({ x, y });
};
enqueue(x, y);
while (queue.length > 0) {
const { x, y } = queue.shift();
// Outside the grid
if (x < 0 || x >= width || y < 0 || y >= height) continue;
// Current value to check
const value = get(x, y);
// Not of the same kind
if (value !== startValue) continue;
// Already visited
if (filledGrid.get(x, y) !== 0) continue;
// Mark as visited
filledGrid.set(x, y, 1);
cellCount++;
// Visit neighbors
enqueue(x - 1, y);
enqueue(x + 1, y);
enqueue(x, y - 1);
enqueue(x, y + 1);
}
return {
filledGrid,
cellCount,
startValue,
startX: x,
startY: y,
};
};
return {
width,
height,
cells,
fill,
floodFill,
set,
get,
};
};