let strokeCol = "#fdfdfd";
let palette = ["#584594", "#e488b7", "#d74c41", "#f0d235", "#36ad63", "#69bcea"];
let randInt = (a, b) => (floor(random(a, b)));
maxSize = random([2, 2, 2, 3, 3, 3, 3, 4, 4, 5]);
DSatur("cubeType", [1, 2, 3, 4, 5, 6], true);
for (let recta of rectangles) {
function createComposition() {
if (random() < 1/100) nRects = 1;
for (let i = 0; i < nRects; i++) {
let newRecta = generateRectangle(rectangles);
if (newRecta.si > 1 || newRecta.sj > 1) {
rectangles.push(newRecta);
for (let i = margin; i < N-margin; i++) {
for (let j = margin; j < N-margin; j++) {
for (let recta of rectangles) {
if (rectanglesIntersect(newRecta, recta)) {
rectangles.push(newRecta);
function rectanglesIntersect(recta1, recta2) {
return ((recta1.i <= recta2.i && recta1.i+recta1.si > recta2.i) || (recta2.i <= recta1.i && recta2.i+recta2.si > recta1.i)) && ((recta1.j <= recta2.j && recta1.j+recta1.sj > recta2.j) || (recta2.j <= recta1.j && recta2.j+recta2.sj > recta1.j));
function generateRectangle(rectangles) {
let i = randInt(margin, N-margin);
let j = randInt(margin, N-margin);
if (rectangles.length == 0) {
s = min(maxSize, N-i-margin-1, N-j-margin-1);
for (let recta of rectangles) {
if (i+s > N-margin || j+s > N-margin || s > maxSize || rectanglesIntersect({i: i, j: j, si: s, sj: s}, recta)) {
if (i < N/2 && i+si > N/2) {
if (j < N/2 && j+sj > N/2) {
function createConnections() {
let l = rectangles.length;
for (let i = 0; i < l; i++) {
let recta1 = rectangles[i];
if (!recta1.neighbors) recta1.neighbors = [];
for (let j = 0; j < l; j++) {
let recta2 = rectangles[j];
if (!recta2.neighbors) recta2.neighbors = [];
if (i != j && rectanglesTouch(recta1, recta2)) {
recta1.neighbors.push(recta2);
function rectanglesTouch(recta1, recta2) {
if (((recta1.i <= recta2.i && recta1.i+recta1.si == recta2.i) || (recta2.i <= recta1.i && recta2.i+recta2.si == recta1.i)) && ((recta1.j <= recta2.j && recta1.j+recta1.sj > recta2.j) || (recta2.j <= recta1.j && recta2.j+recta2.sj > recta1.j)))
if (((recta1.i <= recta2.i && recta1.i+recta1.si > recta2.i) || (recta2.i <= recta1.i && recta2.i+recta2.si > recta1.i)) && ((recta1.j <= recta2.j && recta1.j+recta1.sj == recta2.j) || (recta2.j <= recta1.j && recta2.j+recta2.sj == recta1.j)))
function DSatur(el, elements, shuffleIt) {
for (let i = 0; i < rectangles.length; i++) {
let v, vSat = -1, vElementsUsed;
for (let recta of rectangles) {
let elementsUsed = elementsUsedByNeighbors(recta, el);
let sat = elementsUsed.length;
vElementsUsed = elementsUsed;
} else if (sat == vSat) {
if (largestDegreeInTheSubgraphInducedByTheUncoloredVertices(recta, el) > largestDegreeInTheSubgraphInducedByTheUncoloredVertices(v, el)) {
vElementsUsed = elementsUsed;
shuffle(elements, shuffleIt);
for (let element of elements) {
if (vElementsUsed.indexOf(element) == -1) {
function elementsUsedByNeighbors(v, el) {
for (let neigh of v.neighbors) {
if (neigh[el]) elementsUsed.push(neigh[el]);
return [...new Set(elementsUsed)];
function largestDegreeInTheSubgraphInducedByTheUncoloredVertices(v, el) {
for (let neigh of v.neighbors) {
let sat = elementsUsedByNeighbors(neigh, el);
if (sat > largestDegree) largestDegree = sat;
function drawRectangle(recta) {
let x = recta.i*u+gap/2, y = recta.j*u+gap/2;
let w = recta.si*u - gap, h = recta.sj*u - gap;
let tile = createGraphics(w, h);
tile.translate(w/2, h/2);
let iPos = recta.i+recta.si/2;
let iFirstHalf = (iPos < N/2);
let iMiddle = (iPos == N/2);
let iSecondHalf = (iPos > N/2);
let jPos = recta.j+recta.sj/2;
let jFirstHalf = (jPos < N/2);
let jMiddle = (jPos == N/2);
let jSecondHalf = (jPos > N/2);
if ((iFirstHalf || (iMiddle && random() < 1/2)) && (jFirstHalf || (jMiddle && random() < 1/2))) {
} else if ((iSecondHalf || (iMiddle && random() < 1/2)) && (jFirstHalf || (jMiddle && random() < 1/2))) {
} else if ((iSecondHalf || (iMiddle && random() < 1/2)) && (jSecondHalf || (jMiddle && random() < 1/2))) {
tile.translate(-w/2, -h/2);
if (recta.cubeType == 1) {
frontFacet(0, 0, w, h, dpth, tile);
rightFacet(0, 0, w, h, dpth, tile);
bottomFacet(0, 0, w, h, dpth, tile);
} else if (recta.cubeType == 2) {
backFacet(0, 0, w, h, dpth, tile);
tile.line(w-dpth, 0, w, dpth);
tile.line(0, h-dpth, dpth, h);
tile.line(w-dpth, h-dpth, w, h);
frontFacet(0, 0, w, h, dpth, tile);
} else if (recta.cubeType == 3) {
let invertCols = random() < 1/4;
tile.stroke(invertCols ? palette[0] : strokeCol);
topFacet(0, 0, w, h, dpth, tile);
bottomFacet(0, 0, w, h, dpth, tile);
leftFacet(0, 0, w, h, dpth, tile);
rightFacet(0, 0, w, h, dpth, tile);
tile.line(sw/2, sw/2, w-dpth, sw/2);
tile.line(sw/2, sw/2, sw/2, h-dpth);
tile.line(dpth, h-sw/2, w, h-sw/2);
tile.line(w-sw/2, dpth, w-sw/2, h);
} else if (recta.cubeType == 4) {
let invertCols = random() < 1/4;
tile.fill(invertCols ? strokeCol : palette[0]);
tile.stroke(invertCols ? palette[0] : strokeCol);
frontFacet(0, 0, w, h, dpth, tile);
rightFacet(0, 0, w, h, dpth, tile);
bottomFacet(0, 0, w, h, dpth, tile);
tile.line(sw/2, sw/2, w-dpth, sw/2);
tile.line(sw/2, sw/2, sw/2, h-dpth);
tile.line(dpth, h-sw/2, w, h-sw/2);
tile.line(w-sw/2, dpth, w-sw/2, h);
} else if (recta.cubeType == 5) {
topFacet(0, 0, w, h, dpth, tile);
leftFacet(0, 0, w, h, dpth, tile);
bottomFacet(0, 0, w, h, dpth, tile);
rightFacet(0, 0, w, h, dpth, tile);
tile.line(0, h-dpth, dpth, h);
tile.line(w-dpth, 0, w, dpth);
frontFacet(0, 0, w, h, dpth, tile);
tile.line(sw/2, sw/2, w-dpth, sw/2);
tile.line(sw/2, sw/2, sw/2, h-dpth);
rightFacet(0, 0, w, h, dpth, tile);
bottomFacet(0, 0, w, h, dpth, tile);
tile.line(w-dpth, h-dpth, w, h);
frontFacet(0, 0, w, h, dpth, tile);
function frontFacet(x, y, w, h, dpth, tile) {
tile.rect(x, y, w-dpth, h-dpth);
function backFacet(x, y, w, h, dpth, tile) {
tile.rect(x+dpth, y+dpth, w-dpth, h-dpth);
function topFacet(x, y, w, h, dpth, tile) {
tile.quad(x, y, x+dpth, y+dpth, x+w, y+dpth, x+w-dpth, y);
function bottomFacet(x, y, w, h, dpth, tile) {
tile.quad(x+w, y+h, x+w-dpth, y+h-dpth, x, y+h-dpth, x+dpth, y+h);
function leftFacet(x, y, w, h, dpth, tile) {
tile.quad(x, y, x, y+h-dpth, x+dpth, y+h, x+dpth, y+dpth);
function rightFacet(x, y, w, h, dpth, tile) {
tile.quad(x+w, y+w, x+w, y+dpth, x+w-dpth, y, x+w-dpth, y+h-dpth);