2022-07-28 17:39:51 +02:00
|
|
|
function CellSet(definition) {
|
|
|
|
definition = definition || {};
|
|
|
|
this.cells = {};
|
2022-07-31 16:11:22 +02:00
|
|
|
if(definition.type == 'rectangle') {
|
|
|
|
this.fromRectangle(definition);
|
|
|
|
} else if(definition.type == 'isochrome') {
|
|
|
|
this.fromIsochrome(definition);
|
2022-07-31 16:32:24 +02:00
|
|
|
} else if(definition.type == 'union') {
|
|
|
|
this.fromUnion(definition.sets);
|
2022-07-31 16:11:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CellSet.prototype.fromRectangle = function(definition) {
|
2022-07-31 16:32:24 +02:00
|
|
|
var iMax = definition.row + definition.height;
|
|
|
|
var jMax = definition.column + definition.width;
|
|
|
|
for(var i = definition.row; i < iMax; i++) {
|
|
|
|
for(var j = definition.column; j < jMax; j++) {
|
2022-07-31 16:11:22 +02:00
|
|
|
this.add(i, j);
|
2022-07-28 17:39:51 +02:00
|
|
|
}
|
2022-07-31 16:11:22 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
CellSet.prototype.fromIsochrome = function(definition) {
|
2022-07-31 16:32:24 +02:00
|
|
|
var originColor = definition.data[definition.row][definition.column];
|
|
|
|
var queue = [{i: definition.row, j: definition.column}];
|
2022-07-31 16:11:22 +02:00
|
|
|
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)
|
|
|
|
);
|
2022-07-28 17:39:51 +02:00
|
|
|
}
|
2022-07-31 16:11:22 +02:00
|
|
|
queue.shift();
|
2022-07-28 17:39:51 +02:00
|
|
|
}
|
2022-07-31 16:11:22 +02:00
|
|
|
};
|
2022-07-28 17:39:51 +02:00
|
|
|
|
2022-07-31 16:32:24 +02:00
|
|
|
CellSet.prototype.fromUnion = function(sets) {
|
|
|
|
for(var i = 0; i < sets.length; i++) {
|
|
|
|
for(var key in sets[i].cells) {
|
|
|
|
this.cells[key] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-28 17:39:51 +02:00
|
|
|
CellSet.prototype.add = function(i, j) {
|
|
|
|
this.cells[id(i, j)] = true;
|
2022-07-31 16:11:22 +02:00
|
|
|
};
|
2022-07-28 17:39:51 +02:00
|
|
|
|
|
|
|
CellSet.prototype.remove = function(i, j) {
|
|
|
|
delete this.cells[id(i, j)];
|
2022-07-31 16:11:22 +02:00
|
|
|
};
|
2022-07-28 17:39:51 +02:00
|
|
|
|
|
|
|
CellSet.prototype.contains = function(i, j) {
|
|
|
|
return !!this.cells[id(i, j)];
|
2022-07-31 16:11:22 +02:00
|
|
|
};
|
2022-07-28 17:39:51 +02:00
|
|
|
|
|
|
|
CellSet.prototype.isEmpty = function() {
|
|
|
|
return Object.keys(this.cells).length < 1;
|
2022-07-31 16:11:22 +02:00
|
|
|
};
|
|
|
|
|
2022-07-31 16:32:24 +02:00
|
|
|
CellSet.prototype.map = function(f) {
|
|
|
|
var result = [];
|
2022-07-31 16:11:22 +02:00
|
|
|
for(var key in this.cells) {
|
2022-07-31 16:32:24 +02:00
|
|
|
result.push(f.apply(null, key.split(':')));
|
2022-07-31 16:11:22 +02:00
|
|
|
}
|
2022-07-31 16:32:24 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
CellSet.prototype.iter = function(f) {
|
|
|
|
this.map(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
CellSet.prototype.difference = function(cellSet) {
|
|
|
|
var newCellSet = new CellSet();
|
|
|
|
this.iter(function(i, j) {
|
|
|
|
if(!cellSet.contains(i, j)) {
|
|
|
|
newCellSet.add(i, j);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return newCellSet;
|
2022-07-28 17:39:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
make: function(definition) {return new CellSet(definition);},
|
2022-07-31 16:32:24 +02:00
|
|
|
union: function(sets) {return new CellSet({type: 'union', sets: sets});}
|
2022-07-28 17:39:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
function id(i, j) {
|
|
|
|
return i + ':' + j;
|
|
|
|
}
|
2022-07-31 16:11:22 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|