xxxxxxxxxx
// Pxl is 8 x 4 with 8 brightness
// 1: 1000000, 2: 110000, 3: 11100000, 4: 1111000, 5: 1111100, ...
// 1000000, 110000, 11100000, 1111000, 1111100, ...
// 1000000, 110000, 11100000, 1111000, 1111100, ...
// 1000000, 110000, 11100000, 1111000, 1111100, ...
// Block are placed in a grid of pxls by inceasing brightness each time
// can have width of one pxl (eq 8 pxls) and height of 1, 2, or 4 (2, 4, 8 pixels)
// starting x: random(pxl | 8 pixels), y: x: random(4*pxl | 8 pixels)
// y-offset <0.2%: h=1->{1,2,3}, h=2->{2}, h=4->{0}
let grid, SZE = {x: 8, y: 4}, NUM, histo;
const SCL = 1;
function setup() {
createCanvas(SCL*210, SCL*297); //createCanvas(210, 297); // createCanvas(windowWidth, windowHeight);
NUM = {
x: Math.ceil(width / SZE.x),
y: Math.ceil(height / SZE.y)
}; // round up
grid = arrCreate2D(NUM.x, NUM.y);
histo = []; for (let i = 0; i <= SZE.x; i++) histo[i] = (i === 0) ? NUM.x*NUM.y : 0;
// console.log(NUM, grid, histo)
background(212);
stroke(32);
strokeCap(SQUARE);
}
function draw() {
for (let i = 0; i < 100; i++) {
addBlock(true); // true = show block
// pixel will be drawn while adding
// drawPxl(~~random(NUM.x), ~~random(NUM.y)); // draw random Pixel
// finished state
if (histo[SZE.x] > histo[0]) {
console.log(histo);
noLoop();
break;
// console.log(grid);
// saveSvg(); // key S
} // finished
} // for-loop
// drawGrid(); // takes time
// drawPxl(frameCount % NUM.x, ~~(frameCount / NUM.y));
}
function addBlock(show = false) {
const x = ~~random(width / SZE.x); // random(width);
const y = ~~random(height / SZE.y);
const w = random([1, 1, 2]);
const h = random([1, 2, 2, 4, 4, 4]); // * SZE.y;
let o = 0;
if (h < 4 && random() < 0.2) {
o = h === 1 ? random([1, 2, 3]) : /* (h==2) */ 2;
}
for (let j = 0; j < w; j++) {
for (let i = 0; i < h; i++) {
const xi = x + i;
const yi = y + o + j;
addPxl(xi, yi, show);
/*
if (yi < NUM.y && xi < NUM.x)
grid[yi][xi] = constrain(grid[yi][xi]+1, 0, SZE.x);
if (show) drawPxl(xi, yi);
}
*/
}
}
}
function addPxl(x, y, show = false) {
if (x<0 || x>=NUM.x || y<0 || y>=NUM.y) return;
if (grid[y][x] >= SZE.x) return;
histo[grid[y][x]]--;
grid[y][x]++;
histo[grid[y][x]]++;
// grid[y][x] = constrain(grid[y][x]+1, 0, SZE.x);
if (show) drawPxl(x, y);
}
function drawGrid() {
for (let y = 0; y < NUM.y; y++) {
for (let x = 0; x < NUM.x; x++) {
drawPxl(x, y);
}
}
}
function drawPxl(x, y) {
const br = constrain(grid[y][x], 0, SZE.x)
// console.log(`drawPxl(${x}, ${y}, ${br})`);
for (let i = 0; i < br; i++) {
const xx = x * SZE.x + i;
const yy = y * SZE.y;
line(xx, yy, xx, yy + SZE.y);
}
}
function arrCreate2D(x, y, val = 0) {
let arr = [];
for (let j = 0; j < y; j++) {
arr[j] = [];
for (let i = 0; i < x; i++) {
arr[j][i] = val;
}
}
return arr;
}
function arrDeepCopy(obj) {
if (typeof obj == 'object') {
if (isArray(obj)) {
const l = obj.length;
let r = new Array(l);
for (let i = 0; i < l; i++) {
r[i] = arrDeepCopy(obj[i]);
}
return r;
} else {
let r = {};
r.prototype = obj.prototype;
for (let k in obj) {
r[k] = arrDeepCopy(obj[k]);
}
return r;
}
}
return obj;
}
function mousePressed() {
if (mouseButton !== RIGHT && dist(mouseX, mouseY, width/2, height/2) < min(width, height)/2) {
loop();
setup();
}
}
function keyPressed() {
if (key === "s" || key === "S") {
saveSvg();
}
}
function ownGridArr(VAL) {
const arr = arrCreate2D(NUM.x, NUM.y);
for (let j = 0; j < NUM.y; j++) {
let moveCell = false;
for (let i = 0; i < NUM.x; i++) {
const br = constrain(grid[j][i], 0, SZE.x);
if (br === VAL) {
moveCell = true;
}
if (moveCell) {
arr[j][i] = grid[j][i];
grid[j][i] = 0;
moveCell = br === SZE.x; // special case to get also next cell
}
}
}
return arr;
}
function getLineArr(grid) {
const lineArr = arrCreate2D(NUM.x*SZE.x, NUM.y);
for (let i = 0; i < NUM.x; i++) {
for (let j = 0; j < NUM.y; j++) {
const br = constrain(grid[j][i], 0, SZE.x);
for (let k = 0; k < br; k++) {
lineArr[j][i*SZE.x+k] = 1;
}
}
}
return lineArr;
}
function getSvgLines(lineArr, doSort = false, doShuffle = false) {
let lnArr = [];
let svgStr = `<g fill="none" stroke="black" stroke-width="1">\n`;
for (let x = 0; x < NUM.x*SZE.x; x++) {
let yStart, lineStarted = false;
for (let y = 0; y < NUM.y; y++) {
const v = lineArr[y][x];
if (!lineStarted && v) {
lineStarted = true;
yStart = y;
} else if (lineStarted && !v) {
lineStarted = false;
// svgStr += getSvgLine(x, yStart*SZE.y, x, (y-0)*SZE.y);
const ln = {x1: x, y1: yStart*SZE.y, x2: x, y2: (y-0)*SZE.y};
ln.len = dist(ln.x1, ln.y1, ln.x2, ln.y2);
lnArr.push(ln);
}
} // y
if (lineStarted) {
// svgStr += getSvgLine(x, yStart*SZE.y, x, (NUM.y-1)*SZE.y);
const ln = {x1: x, y1: yStart*SZE.y, x2: x, y2: (NUM.y-0)*SZE.y};
ln.len = dist(ln.x1, ln.y1, ln.x2, ln.y2);
lnArr.push(ln);
}
} // x
// shuffle'n'sort
if (doShuffle) shuffle(lnArr, true);
if (doSort) lnArr = lnArr.sort((a, b) => b.len - a.len);
// gen svg str
for (const ln of lnArr) {
svgStr += getSvgLine(ln.x1, ln.y1, ln.x2, ln.y2);
}
svgStr += `</g>\n`;
return svgStr;
}
function saveSvg() {
let svgStr = `<svg width="${NUM.x*SZE.x}" height="${NUM.y*SZE.y}" xmlns="http://www.w3.org/2000/svg">\n`;
// ToDo: make copy of grid for a) len 8 + succ b) len 7
const gridLvl8 = ownGridArr(SZE.x);
const gridLvl7 = ownGridArr(SZE.x-1);
const lineArr = getLineArr(grid)
const lineArr8 = getLineArr(gridLvl8)
const lineArr7 = getLineArr(gridLvl7)
// console.log(lineArr);
svgStr += getSvgLines(lineArr, true, true);
svgStr += getSvgLines(lineArr7, true, true);
svgStr += getSvgLines(lineArr8, true, true);
svgStr += `</svg>`;
save(svgStr.split("\n"), "epi_blocks.svg.txt");
// console.log(svgStr);
}
function getSvgLine(x1, y1, x2, y2, prec = 0) {
return ` <line x1="${nf(x1,0,prec)}" y1="${nf(y1,0,prec)}" x2="${nf(x2,0,prec)}" y2="${nf(y2,0,prec)}" />\n`;
}