Generalize surface painting algorithm to get a zone detector
This commit is contained in:
parent
7a6e815b61
commit
88483c72bf
3 changed files with 54 additions and 40 deletions
|
@ -1,35 +1,59 @@
|
||||||
function CellSet(definition) {
|
function CellSet(definition) {
|
||||||
definition = definition || {};
|
definition = definition || {};
|
||||||
this.cells = {};
|
this.cells = {};
|
||||||
if(definition.shape == 'rectangle') {
|
if(definition.type == 'rectangle') {
|
||||||
var xMax = definition.x + definition.width;
|
this.fromRectangle(definition);
|
||||||
var yMax = definition.y + definition.height;
|
} else if(definition.type == 'isochrome') {
|
||||||
for(var i = definition.x; i < xMax; i++) {
|
this.fromIsochrome(definition);
|
||||||
for(var j = definition.y; j < yMax; j++) {
|
|
||||||
this.add(i, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(definition.shape == 'points') {
|
|
||||||
for(var i = 0; i < definition.points.length; i++) {
|
|
||||||
this.cells[id(definition.points[i].i, definition.points[i].j)];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CellSet.prototype.fromRectangle = function(definition) {
|
||||||
|
var xMax = definition.x + definition.width;
|
||||||
|
var yMax = definition.y + definition.height;
|
||||||
|
for(var i = definition.x; i < xMax; i++) {
|
||||||
|
for(var j = definition.y; j < yMax; j++) {
|
||||||
|
this.add(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CellSet.prototype.fromIsochrome = function(definition) {
|
||||||
|
var originColor = definition.data[definition.x][definition.y];
|
||||||
|
var queue = [{i: definition.x, j: definition.y}];
|
||||||
|
while(queue.length > 0) {
|
||||||
|
var p = queue[0];
|
||||||
|
this.add(p.i, p.j);
|
||||||
|
for(var d = -1; d < 2; d += 2) {
|
||||||
|
[{i: p.i + d, j: p.j}, {i: p.i, j: p.j + d}].forEach(
|
||||||
|
gateKeeper(this, definition.data, queue, originColor)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
queue.shift();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
CellSet.prototype.add = function(i, j) {
|
CellSet.prototype.add = function(i, j) {
|
||||||
this.cells[id(i, j)] = true;
|
this.cells[id(i, j)] = true;
|
||||||
}
|
};
|
||||||
|
|
||||||
CellSet.prototype.remove = function(i, j) {
|
CellSet.prototype.remove = function(i, j) {
|
||||||
delete this.cells[id(i, j)];
|
delete this.cells[id(i, j)];
|
||||||
}
|
};
|
||||||
|
|
||||||
CellSet.prototype.contains = function(i, j) {
|
CellSet.prototype.contains = function(i, j) {
|
||||||
return !!this.cells[id(i, j)];
|
return !!this.cells[id(i, j)];
|
||||||
}
|
};
|
||||||
|
|
||||||
CellSet.prototype.isEmpty = function() {
|
CellSet.prototype.isEmpty = function() {
|
||||||
return Object.keys(this.cells).length < 1;
|
return Object.keys(this.cells).length < 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
CellSet.prototype.iter = function(f) {
|
||||||
|
for(var key in this.cells) {
|
||||||
|
var coordinates = key.split(':');
|
||||||
|
f(coordinates[0], coordinates[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -39,3 +63,13 @@ return {
|
||||||
function id(i, j) {
|
function id(i, j) {
|
||||||
return i + ':' + j;
|
return i + ':' + j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function gateKeeper(cellSet, data, queue, originColor) {
|
||||||
|
return function(p1) {
|
||||||
|
if(p1.i >= 0 && p1.i < data.length && p1.j >= 0 && p1.j < data.length
|
||||||
|
&& !cellSet.contains(p1.i, p1.j)
|
||||||
|
&& data[p1.i][p1.j] == originColor) {
|
||||||
|
queue.push(p1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ function makeRow(config) {
|
||||||
function clear() {
|
function clear() {
|
||||||
grid.data = generate(function() {return; });
|
grid.data = generate(function() {return; });
|
||||||
grid.missing = CellSet.make(
|
grid.missing = CellSet.make(
|
||||||
{shape: 'rectangle', x: 0, y: 0, width: 8, height: 8}
|
{type: 'rectangle', x: 0, y: 0, width: 8, height: 8}
|
||||||
);
|
);
|
||||||
iter(function(row, column) {
|
iter(function(row, column) {
|
||||||
cell(row, column).className = '';
|
cell(row, column).className = '';
|
||||||
|
|
|
@ -15,28 +15,8 @@ function colorize(row, column, color) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function paint(i0, j0) {
|
function paint(i0, j0) {
|
||||||
var originColor = Grid.get().data[i0][j0];
|
var cellSet = CellSet.make(
|
||||||
var done = CellSet.make();
|
{type: 'isochrome', x: i0, y: j0, data: Grid.get().data}
|
||||||
var queue = [{i: i0, j: j0}];
|
);
|
||||||
while(queue.length > 0) {
|
cellSet.iter(colorize);
|
||||||
var p0 = queue[0];
|
|
||||||
colorize(p0.i, p0.j);
|
|
||||||
done.add(p0.i, p0.j);
|
|
||||||
extend(p0, queue, done, originColor);
|
|
||||||
queue.shift();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function extend(p0, queue, done, originColor) {
|
|
||||||
var size = Grid.get().size;
|
|
||||||
for(var d = -1; d < 2; d += 2) {
|
|
||||||
[{i: p0.i + d, j: p0.j}, {i: p0.i, j: p0.j + d}].forEach(function(p1) {
|
|
||||||
if(p1.i >= 0 && p1.i < size && p1.j >= 0 && p1.j < size
|
|
||||||
&& !done.contains(p1.i, p1.j)
|
|
||||||
&& Grid.get().data[p1.i][p1.j] == originColor) {
|
|
||||||
queue.push(p1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue