/* * CELL CLASS * desc: saves geometry for rendering the grid * */ class Grid { float grid00X, grid00Y, grid00Z; // origin of grid int cellsX, cellsY, cellsZ; // number of cells in grid float gSizeX, gSizeY, gSizeZ; // with cellSize calculated size of grid float cellSize, // size of one module in m gTSize; // thickness of the structure in m int gT; // thickness of the structure to be created Cell cells[][][]; // all cells, topological access ArrayList structureCells = new ArrayList(); // cells in Structure ArrayList NeighboursList = new ArrayList(); // saves directions of active neighbours //::: CONSTRUCTOR Grid(int cellsX, int cellsY, int cellsZ, float gSizeX, float gSizeY, float gSizeZ, float cellSize, int gT) { this.cellsX = cellsX; this.cellsY = cellsY; this.cellsZ = cellsZ; this.gSizeX = gSizeX; this.gSizeY = gSizeY; this.gSizeZ = gSizeZ; this.cellSize = cellSize; this.gTSize = gTSize; this.gT = gT; gTSize = gT * cellSize; boolean cellStructure = false; // true if cell is part of structure boolean cellActive = false; // true if cell is active/shown boolean unique = false; // true if cell has not been set cells = new Cell[cellsX][cellsY][cellsZ]; // make array with cells the right size float gridX, gridY, gridZ; // X/Y/Z positions boolean argX, argY, argZtop, argZbottom; // arguments describing shell structure int randomCellIndex; // stores randomly generated cell index Cell currCell; // temporary storageplace for cell props. for (int g=0; g <= this.cellsZ-1; g++) { gridZ = grid00Z + cellSize/2 + cellSize*g; for (int h=0; h <= this.cellsY-1; h++) { gridY = grid00Y + cellSize/2 + cellSize*h; for (int i=0; i <= this.cellsX-1; i++) { gridX = grid00X + cellSize/2 + cellSize*i; //check if cell is inside the shell structure argX = (cellsX - gT <= i) || (i <= gT - 1); argY = (cellsY - gT <= h) || (h <= gT - 1); argZbottom = ((g <= gT - 1) && (argX == true)) || ((g <= gT - 1) && (argY == true)); argZtop = (cellsZ - gT <= g); cellStructure = (argX || argY || argZtop || argZbottom); cells[i][h][g] = new Cell(int(gridX), int(gridY), int(gridZ), i, h, g, cellSize, cellStructure, false); // includes all cells, topological data if (cellStructure) { structureCells.add(cells[i][h][g]); } } } } //::: BREEDER INIT /* for (int s=0; s <= numBreederCells-1; s++) // USE THIS FOR COMPLETE RANDOM DISTRIBUTION OF BREEDER CELLS { while (unique == false) { randomCellIndex = int(random(0, structureCells.size())); currCell = (Cell)structureCells.get(randomCellIndex); if (currCell.isActive() == false) // is this cell already active { currCell.setActive(true); unique = true; println("BREEDER " + s + ": " + randomCellIndex); } } unique = false; } // END OF BLOCK */ // USE THIS FOR CELLS THAT START GROWING FROM THE BOTTOM int randomX, randomY; // temp. stores random x-/y-position of breeding cell for (int s=0; s <= numBreederCells-1; s++) { while (unique == false) { randomX = int(random(0, cellsX)); randomY = int(random(0, cellsY)); if ((cells[randomX][randomY][0].isStructure() == true) && (cells[randomX][randomY][0].isActive() == false)) // is this cell already active { cells[randomX][randomY][0].setActive(true); unique = true; } } unique = false; } // END OF BLOCK //::: VOID INIT for (int s=0; s <= numVoidCells-1; s++) // get & set void cells { while (unique == false) { randomCellIndex = int(random(0, structureCells.size())); currCell = (Cell)structureCells.get(randomCellIndex); if ((currCell.isActive() == false) || (currCell.isBreeding() == false)) // don't kill active cells { currCell.setVoid(true); unique = true; } } unique = false; } } /* DRAW ME * draws all cells */ void drawMe(boolean boxOutline) { Cell currCell; for (int g=0; g <= structureCells.size()-1; g++) { currCell = (Cell)structureCells.get(g); if (currCell.isActive() || currCell.isVoid()) { currCell.drawMe(boxOutline); } } } /* GROW CELL * add new active cells */ void growCell() { Cell currCell; int currXpos, currYpos, currZpos; boolean growing = true; int randomDirIndex; // random direction index for (int g=0; g <= structureCells.size()-1; g++) { currCell = (Cell)structureCells.get(g); currXpos = currCell.getXind(); currYpos = currCell.getYind(); currZpos = currCell.getZind(); if (currCell.isBreeding()) currCell.setActive(true); // cells set to breeding in last grow cycle come alive now if (currCell.isActive() && !currCell.isVoid()) { NeighboursList = getInactiveNeighbours(currXpos, currYpos, currZpos); // get inactive neighbours if (NeighboursList.size() > 0) { randomDirIndex = int(random(0, NeighboursList.size()-1)); if (NeighboursList.get(randomDirIndex) == "0") cells[currXpos-1][currYpos][currZpos].setBreeding(); if (NeighboursList.get(randomDirIndex) == "1") cells[currXpos+1][currYpos][currZpos].setBreeding(); if (NeighboursList.get(randomDirIndex) == "2") cells[currXpos][currYpos-1][currZpos].setBreeding(); if (NeighboursList.get(randomDirIndex) == "3") cells[currXpos][currYpos+1][currZpos].setBreeding(); if (NeighboursList.get(randomDirIndex) == "4") cells[currXpos][currYpos][currZpos-1].setBreeding(); if (NeighboursList.get(randomDirIndex) == "5") cells[currXpos][currYpos][currZpos+1].setBreeding(); } } } } /* GROW VOID * grow void perpendicular to structure */ void growVoid() { Cell currCell; int currXpos, currYpos, currZpos; boolean growing = true; boolean argX, argY, argZtop; // arguments for distribution of cells int randomDirIndex; // random direction index for (int g=0; g <= structureCells.size()-1; g++) { currCell = (Cell)structureCells.get(g); currXpos = currCell.getXind(); currYpos = currCell.getYind(); currZpos = currCell.getZind(); if (currCell.isVoid()) { NeighboursList = getNeighbours(currXpos, currYpos, currZpos); // get all neighbours if (NeighboursList.size() > 0) { argX = (currXpos >= cellsX - gT) || (currXpos <= gT - 1); // x-value is in vertical part of structure argY = (currYpos >= cellsY - gT) || (currYpos <= gT - 1); // y-value is in vertical part of structure argZtop = (currZpos >= cellsZ - gT); // z-value in horizontal part and x/y-values not in vertical structure if ((argY) && (NeighboursList.contains("2") || NeighboursList.contains("3"))) // grow perdendicular i.e. y-direction here { randomDirIndex = int(random(0, 1)); if ((randomDirIndex == 1) && NeighboursList.contains("3")) { cells[currXpos][currYpos+1][currZpos].setVoid(true); cells[currXpos][currYpos+1][currZpos].setActive(false); } else if (NeighboursList.contains("2")) { cells[currXpos][currYpos-1][currZpos].setVoid(true); cells[currXpos][currYpos-1][currZpos].setActive(false); } else { cells[currXpos][currYpos+1][currZpos].setVoid(true); cells[currXpos][currYpos+1][currZpos].setActive(false); } } else if ((argX) && (NeighboursList.contains("0") || NeighboursList.contains("1"))) // grow perdendicular i.e. x-direction here, prevent out of bounds { randomDirIndex = int(random(0, 1)); if ((randomDirIndex == 1) && NeighboursList.contains("1")) { cells[currXpos+1][currYpos][currZpos].setVoid(true); cells[currXpos+1][currYpos][currZpos].setActive(false); } else if (NeighboursList.contains("0")) { cells[currXpos-1][currYpos][currZpos].setVoid(true); cells[currXpos-1][currYpos][currZpos].setActive(false); } else { cells[currXpos+1][currYpos][currZpos].setVoid(true); cells[currXpos+1][currYpos][currZpos].setActive(false); } } else if ((argZtop) && (NeighboursList.contains("4") || NeighboursList.contains("5"))) // grow perdendicular i.e. z-direction here, prevent out of bounds { randomDirIndex = int(random(0, 1)); if ((randomDirIndex == 1) && NeighboursList.contains("5")) { cells[currXpos][currYpos][currZpos+1].setVoid(true); cells[currXpos][currYpos][currZpos+1].setActive(false); } else if (NeighboursList.contains("4")) { cells[currXpos][currYpos][currZpos-1].setVoid(true); cells[currXpos][currYpos][currZpos-1].setActive(false); } } else { if (random(0, 1) <= voidAggresiveness) { randomDirIndex = int(random(0, NeighboursList.size()-1)); if (NeighboursList.get(randomDirIndex) == "0") cells[currXpos-1][currYpos][currZpos].setVoid(true); if (NeighboursList.get(randomDirIndex) == "1") cells[currXpos+1][currYpos][currZpos].setVoid(true); if (NeighboursList.get(randomDirIndex) == "2") cells[currXpos][currYpos-1][currZpos].setVoid(true); if (NeighboursList.get(randomDirIndex) == "3") cells[currXpos][currYpos+1][currZpos].setVoid(true); } else { randomDirIndex = int(random(0, NeighboursList.size()-1)); if (NeighboursList.get(randomDirIndex) == "0") { cells[currXpos-1][currYpos][currZpos].setVoid(true); cells[currXpos-1][currYpos][currZpos].setActive(false); } if (NeighboursList.get(randomDirIndex) == "1") { cells[currXpos+1][currYpos][currZpos].setVoid(true); cells[currXpos+1][currYpos][currZpos].setActive(false); } if (NeighboursList.get(randomDirIndex) == "2") { cells[currXpos][currYpos-1][currZpos].setVoid(true); cells[currXpos][currYpos-1][currZpos].setActive(false); } if (NeighboursList.get(randomDirIndex) == "3") { cells[currXpos][currYpos+1][currZpos].setVoid(true); cells[currXpos][currYpos+1][currZpos].setActive(false); } if (NeighboursList.get(randomDirIndex) == "4") { cells[currXpos][currYpos][currZpos-1].setVoid(true); cells[currXpos][currYpos][currZpos-1].setActive(false); } if (NeighboursList.get(randomDirIndex) == "5") { cells[currXpos][currYpos][currZpos+1].setVoid(true); cells[currXpos][currYpos][currZpos+1].setActive(false); } } } } } } } /* GET NEIGHBOURS * expects that the cell provided is in the structure * returns List with directions of the neighbouring cells * checks that they are in the structure */ ArrayList getNeighbours(int cellX, int cellY, int cellZ) { ArrayList NeighboursList = new ArrayList(); // saves directions of active neighbours if (cellX != 0) // prevent out of bounds for X-1 { if (cells[cellX-1][cellY][cellZ].isStructure() && !cells[cellX-1][cellY][cellZ].isVoid()) // cells need to be in structure { NeighboursList.add("0"); } } if (cellX != cellsX-1) // prevent out of bounds for X+1 { if (cells[cellX+1][cellY][cellZ].isStructure() && !cells[cellX+1][cellY][cellZ].isVoid()) // cells need to be in structure and inactive { NeighboursList.add("1"); } } if (cellY != 0) // prevent out of bounds for Y-1 { if (cells[cellX][cellY-1][cellZ].isStructure() && !cells[cellX][cellY-1][cellZ].isVoid()) // cells need to be in structure and inactive { NeighboursList.add("2"); } } if (cellY != cellsY-1) // prevent out of bounds for Y+1 { if (cells[cellX][cellY+1][cellZ].isStructure() && !cells[cellX][cellY+1][cellZ].isVoid()) // cells need to be in structure and inactive { NeighboursList.add("3"); } } if (cellZ != 0) // prevent out of bounds for Z-1 { if (cells[cellX][cellY][cellZ-1].isStructure() && !cells[cellX][cellY][cellZ-1].isVoid()) // cells need to be in structure and inactive { NeighboursList.add("4"); } } if (cellZ != cellsZ-1) // prevent out of bounds for Z+1 { if (cells[cellX][cellY][cellZ+1].isStructure() && !cells[cellX][cellY][cellZ+1].isVoid()) // cells need to be in structure and inactive { NeighboursList.add("5"); } } return NeighboursList; } /* GET INACTIVE NEIGHBOURS * expects that the cell provided is in the structure (and active) * returns List with directions of the inactive neighbouring cells * checks that they are in the structure */ ArrayList getInactiveNeighbours(int cellX, int cellY, int cellZ) { ArrayList InactiveNeighboursList = new ArrayList(); // saves directions of active neighbours if (cellX != 0) // prevent out of bounds for X-1 { if (cells[cellX-1][cellY][cellZ].isStructure() && !cells[cellX-1][cellY][cellZ].isActive() && !cells[cellX-1][cellY][cellZ].isVoid()) // cells need to be in structure and inactive { InactiveNeighboursList.add("0"); } } if (cellX != cellsX-1) // prevent out of bounds for X+1 { if (cells[cellX+1][cellY][cellZ].isStructure() && !cells[cellX+1][cellY][cellZ].isActive() && !cells[cellX+1][cellY][cellZ].isVoid()) // cells need to be in structure and inactive { InactiveNeighboursList.add("1"); } } if (cellY != 0) // prevent out of bounds for Y-1 { if (cells[cellX][cellY-1][cellZ].isStructure() && !cells[cellX][cellY-1][cellZ].isActive() && !cells[cellX][cellY-1][cellZ].isVoid()) // cells need to be in structure and inactive { InactiveNeighboursList.add("2"); } } if (cellY != cellsY-1) // prevent out of bounds for Y+1 { if (cells[cellX][cellY+1][cellZ].isStructure() && !cells[cellX][cellY+1][cellZ].isActive() && !cells[cellX][cellY+1][cellZ].isVoid()) // cells need to be in structure and inactive { InactiveNeighboursList.add("3"); } } if (cellZ != 0) // prevent out of bounds for Z-1 { if (cells[cellX][cellY][cellZ-1].isStructure() && !cells[cellX][cellY][cellZ-1].isActive() && !cells[cellX][cellY][cellZ-1].isVoid()) // cells need to be in structure and inactive { InactiveNeighboursList.add("4"); } } if (cellZ != cellsZ-1) // prevent out of bounds for Z+1 { if (cells[cellX][cellY][cellZ+1].isStructure() && !cells[cellX][cellY][cellZ+1].isActive() && !cells[cellX][cellY][cellZ+1].isVoid()) // cells need to be in structure and inactive { InactiveNeighboursList.add("5"); } } return InactiveNeighboursList; } /* SHOW GRID * */ void showGrid() { //::: OUTLINES rectMode(CORNER); fill(cGrey2); stroke(cGrey1); rect(0, 0, gSizeX, gSizeY); stroke(cGrey1); line(0, 0, 0, 0, 0, gSizeZ); // outer verticals line(0, gSizeY, 0, 0, gSizeY, gSizeZ); line(gSizeX, 0, 0, gSizeX, 0, gSizeZ); line(gSizeX, gSizeY, 0, gSizeX, gSizeY, gSizeZ); line(0, 0, gSizeZ, gSizeX, 0, gSizeZ); // outer horizontals line(0, 0, gSizeZ, 0, gSizeY, gSizeZ); line(gSizeX, gSizeY, gSizeZ, gSizeX, 0, gSizeZ); line(gSizeX, gSizeY, gSizeZ, 0, gSizeY, gSizeZ); line(gTSize, gTSize, 0, gTSize, gTSize, gSizeZ-gTSize); // inner verticals line(gSizeX-gTSize, gTSize, 0, gSizeX-gTSize, gTSize, gSizeZ-gTSize); line(gTSize, gSizeY-gTSize, 0, gTSize, gSizeY-gTSize, gSizeZ-gTSize); line(gSizeX-gTSize, gSizeY-gTSize, 0, gSizeX-gTSize, gSizeY-gTSize, gSizeZ-gTSize); line(gTSize, gTSize, 0, gSizeX-gTSize, gTSize, 0); // inner, bottom horizontals line(gTSize, gTSize, 0, gTSize, gSizeY-gTSize, 0); line(gSizeX-gTSize, gSizeY-gTSize, 0, gSizeX-gTSize, gTSize, 0); line(gSizeX-gTSize, gSizeY-gTSize, 0, gTSize, gSizeY-gTSize, 0); line(gTSize, gTSize, gSizeZ-gTSize, gSizeX-gTSize, gTSize, gSizeZ-gTSize); // inner, upper horizontals line(gTSize, gTSize, gSizeZ-gTSize, gTSize, gSizeY-gTSize, gSizeZ-gTSize); line(gSizeX-gTSize, gSizeY-gTSize, gSizeZ-gTSize, gSizeX-gTSize, gTSize, gSizeZ-gTSize); line(gSizeX-gTSize, gSizeY-gTSize, gSizeZ-gTSize, gTSize, gSizeY-gTSize, gSizeZ-gTSize); } } void printAL(ArrayList myList) { println(myList.toArray()); }