class Piece {
constructor(cells = []) {
this.cells = [];
for (let cell of cells) {
this.cells.push(cell.copy());
}
}
translate(v) {
let {x: dx, y: dy} = v;
for (let i = 0; i < this.cells.length; i++) {
this.cells[i].x += dx;
this.cells[i].y += dy;
}
return this;
}
normalize() {
let minSize = this.getLowerBound();
this.translate({x: -minSize.x, y: -minSize.y});
return this;
}
getSize() {
let upper = this.getUpperBound();
let lower = this.getLowerBound();
return {x: upper.x - lower.x, y: upper.y - lower.y};
}
getLowerBound() {
let minSize = {x: Infinity, y: Infinity};
for (let cell of this.cells) {
if (cell.x < minSize.x) { minSize.x = cell.x }
if (cell.y < minSize.y) { minSize.y = cell.y }
}
return minSize;
}
getUpperBound() {
let maxSize = {x: 0, y: 0};
for (let cell of this.cells) {
if (cell.x > maxSize.x) { maxSize.x = cell.x }
if (cell.y > maxSize.y) { maxSize.y = cell.y }
}
return {x: maxSize.x + 1, y: maxSize.y + 1};
}
static fromMask(mask) {
const piece = new Piece();
for (let i = 0; i < mask.length; i++) {
let row = mask[i];
for (let j = 0; j < row.length; j++) {
if (row[j] === 1) {
piece.cells.push(new Cell(j, i));
}
}
}
return piece;
}
static fromArray(pairs) {
const piece = new Piece();
for (let pair of pairs) {
let [x, y] = pair;
piece.cells.push(new Cell(x, y));
}
return piece;
}
static fromString(s) {
let [x, y] = [0, 0];
let p = new Piece();
for (let ch of s) {
if ('\n\t\r '.includes(ch)) { continue; }
if (ch === '|') { y++; x=0; continue; }
if (ch === '*') { p.cells.push(new Cell(x, y)); }
x++;
}
return p;
}
toSVG() {
const pieceSize = this.getUpperBound();
let svgSize = {x: rectSize * pieceSize.x + margin.left, y: rectSize * pieceSize.y + margin.top};
const svg = d3.create('svg').attr('width', svgSize.x).attr('height', svgSize.y);
showPiece(svg, {x: 0, y: 0}, this);
graphics.line(svg, [margin.left, margin.top], [svgSize.x, margin.top]);
graphics.line(svg, [margin.left, margin.top], [margin.left, svgSize.y]);
return svg.node();
}
}