Constellations/js/Geometry/CellSet.js

100 lines
2.2 KiB
JavaScript
Raw Permalink Normal View History

2022-08-10 21:12:39 +02:00
import {diagonal, isSmaller, key, plus, ofKey, zero} from Geometry.Vector;
import {at, generate} from Grid.Util;
function CellSet(definition) {
definition = definition || {};
this.cells = {};
if(definition.type == 'rectangle') {
this.fromRectangle(definition.origin, definition.offset);
} else if(definition.type == 'isochrome') {
this.fromIsochrome(definition.grid, definition.origin);
} else if(definition.type == 'union') {
this.fromUnion(definition.sets);
}
}
CellSet.prototype.fromRectangle = function(origin, maxOffset) {
generate(
maxOffset.row,
maxOffset.column,
function(offset) {
this.add(plus(origin, offset));
}.bind(this)
);
};
CellSet.prototype.fromIsochrome = function(grid, origin) {
var originColor = at(grid, origin);
var queue = [origin];
while(queue.length > 0) {
var cell = queue.shift();
this.add(cell);
for(var d = -1; d < 2; d += 2) {
[plus(cell, vertical(d)), plus(cell, horizontal(d))].forEach(
gateKeeper(this, grid, queue, originColor)
);
}
}
};
CellSet.prototype.fromUnion = function(sets) {
for(var i = 0; i < sets.length; i++) {
for(var k in sets[i].cells) {
this.cells[k] = true;
}
}
}
CellSet.prototype.add = function(v) {
this.cells[key(v)] = true;
};
CellSet.prototype.remove = function(v) {
delete this.cells[key(v)];
};
CellSet.prototype.contains = function(v) {
return !!this.cells[key(v)];
};
CellSet.prototype.isEmpty = function() {
return Object.keys(this.cells).length < 1;
};
CellSet.prototype.map = function(f) {
var result = [];
for(var k in this.cells) {
result.push(f(ofKey(k)));
}
return result;
}
CellSet.prototype.iter = function(f) {
this.map(f);
}
CellSet.prototype.difference = function(cellSet) {
var newCellSet = new CellSet();
this.iter(function(v) {
if(!cellSet.contains(v)) {
newCellSet.add(v);
}
});
return newCellSet;
}
return {
make: function(definition) {return new CellSet(definition);},
union: function(sets) {return new CellSet({type: 'union', sets: sets});}
};
function gateKeeper(cellSet, grid, queue, originColor) {
return function(cell) {
if(isSmaller(zero(), cell) && isSmaller(cell, diagonal(grid.length-1))
&& !cellSet.contains(cell)
&& at(grid, cell) == originColor) {
queue.push(cell);
}
}
}