kerjos-Asemic

For this project, I wanted to pursue a personal interest of mine, which is the conflation of connecting wires, pipes, and construction material in drawings of buildings. Typically, what I mean by this is a drawing of an x-ray of the pipes of a building, in which the lines representing the pipes transition into lines representing electrical wires.

I thought that buildings could begin to be thought of as a form of language, with their own grammars. The construction of words, or in this case, of rooms, is predicted by their type: kitchens have many electrical appliances; bathrooms have a lot of plumbing. Sentences — in this case buildings — must contain noun and verb pairings: kitchens and bathrooms.

I was also attentive to the fact that the plotter would be drawing my design in real time, and so I took care in my program to have the buildings be executed as one (nearly!) contiguous line. It’s not something you can appreciate when your design is just immediately rendered on your screen.

// see https://processing.org/reference/libraries/pdf/index.html
import processing.pdf.*;
import java.util.ArrayList;
boolean bRecordingPDF;
int pdfOutputCount = 0; 
 
void setup() {
  size(1500, 1125);
  noLoop();
  bRecordingPDF = true;
}
 
void keyPressed() {
  // When you press a key, it will initiate a PDF export
  bRecordingPDF = true;
}
 
float roomSize = 50;
float margin = 20;
float roomsPerLine = 5;
float pageMargin = 100;
float spacing = 4;
 
float[][][] getStartCoords(float roomSize, float margin, float roomsPerLine, float pageMargin) {
  float cols = floor((width-2*pageMargin)/(roomSize+margin));
  float rows = floor((height-2*pageMargin)/(roomSize*roomsPerLine));
  float[][][] startCoords;
  startCoords = new float[int(cols)][int(rows)][2];
  for (int i=0; i<cols; i++) {
    float k = 0;
    for (int j=0; j<rows; j++) {
      float x = pageMargin + i*(roomSize+margin);
      //float y = j*roomSize;
      float y;
      if (j%2==0) { //Even Row
       y = floor(height/2) + k*roomSize*roomsPerLine;
       k++;
      } else { //Odd Row
       y = floor(height/2) - k*roomSize*roomsPerLine;
      }
      float[] coord = {x,y};
      startCoords[i][j] = coord;
    }
  }
  return startCoords;
}
 
public class Appliance {
  float type;
  public Appliance(float applianceType) {
    type = applianceType;
  }
}
 
Appliance[] getAppliances(int numAppliances, int roomNum, Building[][] buildings, int wordType) {
  Appliance[] appliances;
  appliances = new Appliance[4];
 
  if (wordType == 0) { //Default: random
    for (int i=0; i<numAppliances; i++) { int applianceLocation = getAppLocation(appliances); //betw 0 and 3 float applianceType = floor(random(1,4)); //0 means none //-----Pairs Toilets and Sinks----------- /*if ((applianceType == 2) && ((applianceLocation == 0) || (applianceLocation == 2))) { //It's a toilet. if (applianceLocation == 0) { Appliance appliance = new Appliance(3); appliances[2] = appliance; } else { Appliance appliance = new Appliance(3); appliances[0] = appliance; } }*/ if ((applianceType == 3) && ((applianceLocation == 0) || (applianceLocation == 2))) { //It's a sink. if (applianceLocation == 0) { Appliance appliance = new Appliance(2); appliances[2] = appliance; } else { Appliance appliance = new Appliance(2); appliances[0] = appliance; } } //------------------------------------------ Appliance appliance = new Appliance(applianceType); appliances[applianceLocation] = appliance; } } else if (wordType == 1) { //Left Toilet or Sink. Always. Appliance appliance = new Appliance(floor(random(2,4))); appliances[0] = appliance; } else if (wordType == 2) { //Sink-Toilet pair topped with a Floor Lamp. if (roomNum == 0) { appliances[0] = new Appliance(floor(random(2,4))); appliances[2] = new Appliance(floor(random(2,4))); } else if (roomNum == 1) { appliances[3] = new Appliance(3); } } else if (wordType == 3) { if (roomNum > 2) {
      for (int i=0; i<numAppliances; i++) { int applianceLocation = getAppLocation(appliances); float applianceType = floor(random(1,4)); appliances[applianceLocation] = new Appliance(applianceType); } } else if (roomNum == 2) { appliances[1] = new Appliance(2); } else if (roomNum == 3) { appliances[0] = new Appliance(floor(random(2,4))); appliances[2] = new Appliance(floor(random(2,4))); if (random(0,1) > 0.5) {
        appliances[1] = new Appliance(2);
      } else {
        appliances[3] = new Appliance(3);
      }
    }
  }
 
  return appliances;
}
 
int getAppLocation(Appliance[] appliances) {
  ArrayList availableLocations = new ArrayList(0);
  for (int i=0;i<appliances.length;i++) {
    if (appliances[i] != null) {
      continue;
    } else {
      availableLocations.add(i);
    }
  }
  int location = floor(random(0,availableLocations.size()));
  return availableLocations.get(location);
}
 
public class Room {
   Appliance[] appliances;
   public Room(Appliance[] applianceArray) {
     appliances = applianceArray;
   }
}
 
Room[] getRooms(int numRooms, Building[][] buildings, int wordType) {
  Room[] rooms;
  rooms = new Room[numRooms];
  for (int i=0; i<numRooms; i++) { int numAppliances = floor(random(1,4)); if (wordType == 1) { numAppliances = 1; } else if (wordType == 2) { if (i==0) { numAppliances = 2; } else if (i==1) { numAppliances = 1; } } else if (wordType == 3) { if (i>2) {
        numAppliances = 2;
      } else if (i==2) {
        numAppliances = 1;
      } else if (i==3) {
        numAppliances = 3;
      }
    }
    Appliance[] appliances;
    appliances = getAppliances(numAppliances,i,buildings,wordType);
    Room room = new Room(appliances);
    rooms[i] = room;
  }
  return rooms;
}
 
public class Building {
  float[] startCoord;
  Room[] rooms;
  int type;
  public Building(float[] coord, Room[] roomsArray, int wordType) {
   startCoord = coord;
   rooms = roomsArray;
   type = wordType;
  }
}
 
Building[][] getBuildings(float[][][] startCoords) {
  int numSites = startCoords.length;
  int numLines = startCoords[0].length;
  Building[][] buildings;
  buildings = new Building[numSites][numLines];
  println("numSites="+numSites);
  println("numLines="+numLines);
  int[] lengthOfSentence = new int[numLines];
  for (int i=0; i<numLines; i++) {
    lengthOfSentence[i] = floor(random(0,3));
  }
  for (int site=0; site<numSites; site++) {
    for (int line=0; line<numLines; line++) { int numRooms; int wordType = 0; //Never a building: numRooms = 0; wordType = 0; //Default: random building, rooms, appliances //First building: if (site==0) { numRooms = 1; wordType = 1; } else { Building last = buildings[site-1][line]; int l = last.rooms.length; int lastType = last.type; if (l > 0) { //Increased chance based off there being a building before:
          float rand = random(0,1);
          if (l == 1) {
            if (rand > 0.5) {
             numRooms = 3; 
            } else if (rand > 0.1) {
              numRooms = floor(random(3,4));
            } else {
              numRooms = 0;
            }
 
          } else if (l == 2) {
            numRooms = floor(random(1,4));
 
          } else if (l == 3) {
            if (rand > 0.9) {
              numRooms = floor(random(3,4));
            } else if (rand > 0.1) {
              numRooms = floor(random(1,3));
            } else {
              numRooms = 0;
            }
 
          } else if (l == 4) {
            println(4);
            numRooms = 3;
          }
        } else { //Regular chance is 50/50:
          numRooms = 1;
          wordType = 1;
        }
        if (lengthOfSentence[line] > 4) {
          numRooms = 0;
          //wordType = 0;
          lengthOfSentence[line] = 0;
        }
      }
      Room[] roomsArray;
      roomsArray = getRooms(numRooms,buildings,wordType);
      Building building = new Building(startCoords[site][line],roomsArray,wordType);
      buildings[site][line] = building;
      lengthOfSentence[line] += 1;
    }
  }
  return buildings;
}
 
void draw() {
  if (bRecordingPDF) {
    background(255); // this should come BEFORE beginRecord()
    beginRecord(PDF, "kerjos_" + pdfOutputCount + ".pdf");
 
    //--------------------------
    float[][][] startCoords;
    startCoords = getStartCoords(roomSize,margin,roomsPerLine,pageMargin);
    fill(0);
    stroke(0);
     textSize(8);
    for (int i=0;i<startCoords.length;i++) {
     for (int j=0;j<startCoords[i].length;j++) {
       //text("("+i+","+j+")",startCoords[i][j][0],startCoords[i][j][1]);
      //ellipse(startCoords[i][j][0],startCoords[i][j][1],10,10);
     }
    }
    Building[][] buildings;
    buildings = getBuildings(startCoords);
    stroke(0);
    noFill();
    drawBuildings(buildings);
    //--------------------------
 
    endRecord();
    bRecordingPDF = false;
    pdfOutputCount++;
  }
}
 
void drawBuildings(Building[][] buildings) {
  for (int line=0; line<buildings[0].length; line++) {
    beginShape();
    for (int site=0; site<buildings.length; site++) { Building building = buildings[site][line]; float[] start = building.startCoord; vertex(start[0],start[1]); //There's no building: if (building.rooms.length == 0) { continue; } else { //There is a building: int startIndex = 0; drawRooms(building, start, startIndex); } } endShape(); } } void drawRooms(Building building, float[] start, int startIndex) { Room room = building.rooms[startIndex]; if (room == null) { return; } else { //There's a room to draw! Appliance a0 = room.appliances[0]; //Left wall Appliance a1 = room.appliances[1]; //Ceiling Appliance a2 = room.appliances[2]; //Right Wall Appliance a3 = room.appliances[3]; //Floor boolean drawSmallerRight = false; if (a0 != null) { //Left Wall vertex(start[0],start[1]); vertex(start[0],start[1]-roomSize); if (building.rooms.length > startIndex+1) { //Check for room above.
         float[] newStart = {start[0],start[1]-roomSize};
         drawRooms(building, newStart, startIndex+1);
         vertex(start[0]+roomSize,start[1]-roomSize);
         vertex(start[0]+roomSize,start[1]-roomSize+spacing);
         vertex(start[0]+roomSize-spacing,start[1]-roomSize+spacing);
         //Draw Ceiling Appliance:
         if ((a1 != null) && (a1.type == 2)) {
           drawCeilingLight(start);           
         }
         //Check for right wall:
         if (a2 != null) {
           drawSmallerRight = true;
         }
      } else if (a1 != null) { //Check for ceiling.
        vertex(start[0]+roomSize,start[1]-roomSize);
        vertex(start[0]+roomSize,start[1]-roomSize+spacing);
        vertex(start[0]+roomSize-spacing,start[1]-roomSize+spacing);
        //Draw Appliance:
        if (a1.type == 2) {
           drawCeilingLight(start);           
         }
        //Check for right wall:
        if (a2 != null) {
          drawSmallerRight = true;
        }
      } else { //There's no ceiling and there's no room above us.
        vertex(start[0]+spacing,start[1]-roomSize);
      }
      vertex(start[0]+spacing,start[1]-roomSize+spacing);
      //Draw Left Wall Appliance:
      if (a0.type == 2) {
        drawLeftToilet(start);        
      } else if (a0.type == 3) {
        drawLeftSink(start);
      }
      vertex(start[0]+spacing,start[1]);
 
      if (drawSmallerRight) { //Draw the Right Wall at the end
        vertex(start[0]+roomSize-spacing,start[1]);
 
        if (a2.type == 2) {
          drawRightToilet(start);
        } else if (a2.type == 3) {
          drawRightSink(start);
        }
 
        vertex(start[0]+roomSize-spacing,start[1]-roomSize+2*spacing);
        vertex(start[0]+roomSize,start[1]-roomSize+2*spacing);
        vertex(start[0]+roomSize,start[1]);
      }
 
    } else if (a3 != null) { //Floor
        //Draw Appliance:
        if (a3.type == 2) {
          //drawFloorRadiator(start);
        } else if (a3.type == 3) {
          drawFloorLamp(start);
        }
        vertex(start[0]+roomSize-spacing,start[1]);
 
    } else if (a2 != null) { //Right Wall
      vertex(start[0]+roomSize-spacing,start[1]);
      //Draw Appliance:
      if (a2.type == 2) {
        drawRightToilet(start);
      } else if (a2.type == 3) {
        drawRightSink(start);
      }
      vertex(start[0]+roomSize-spacing,start[1]-roomSize+spacing);
      if (building.rooms.length > startIndex+1) { //Check for room above.
        //Accomodation for a point that must come before the start of the room:
        Room room2 = building.rooms[startIndex+1];
        if ((room2.appliances[0] != null) ||
            ((room2.appliances[1] != null) && !((room2.appliances[0] != null) || (room2.appliances[2] != null))) ||
             (room2.appliances[3] != null)) {
           vertex(start[0],start[1]-roomSize+spacing);
           if (room2.appliances[3] != null) {
             vertex(start[0],start[1]-roomSize);
           }
         }
         //Draw the room:
         float[] newStart = {start[0],start[1]-roomSize};
         drawRooms(building, newStart, startIndex+1);
      } else if (a1 != null) {
        if (a1.type == 2) {
           drawCeilingLight(start);           
        }
        vertex(start[0],start[1]-roomSize+spacing);
        vertex(start[0],start[1]-roomSize);
      } else { //There's no ceiling and there's no room above us.
        vertex(start[0]+roomSize-spacing,start[1]-roomSize);
      }
      vertex(start[0]+roomSize,start[1]-roomSize);
      vertex(start[0]+roomSize,start[1]);
 
    } else if (a1 != null) { //Ceiling but no wall appliances defined.
      vertex(start[0],start[1]);
      vertex(start[0],start[1]-roomSize);
      if (building.rooms.length > startIndex+1) { //Check for room above.
         float[] newStart = {start[0],start[1]-roomSize};
         drawRooms(building, newStart, startIndex+1);
      }
      vertex(start[0]+roomSize,start[1]-roomSize);
      vertex(start[0]+roomSize,start[1]);
      quad(start[0]+spacing,start[1], start[0]+spacing,start[1]-roomSize+spacing,
           start[0]+roomSize-spacing,start[1]-roomSize+spacing, start[0]+roomSize-spacing,start[1]);
    }
  }
}
 
void drawFloorTriangle(float[] start) {
  vertex(start[0]+roomSize/2-5,start[1]);
  vertex(start[0]+roomSize/2,start[1]-5);
  vertex(start[0]+roomSize/2+5,start[1]);
}
 
void drawFloorRadiator(float[] start) {
  float h = (2*roomSize)/5;
  float w = roomSize/12;
  float b = roomSize/25;
  int rungs = 5;
  vertex(start[0]+(2*roomSize)/5, start[1]);
  vertex(start[0]+(2*roomSize)/5, start[1]-h);
  for (int i=1; i<=rungs; i+=2) {
    vertex(start[0]+(2*roomSize)/5+(i*w), start[1]-h);
    vertex(start[0]+(2*roomSize)/5+(i*w), start[1]-b);
    vertex(start[0]+(2*roomSize)/5+((i+1)*w), start[1]-b);
    vertex(start[0]+(2*roomSize)/5+((i+1)*w), start[1]-h);
  }
  vertex(start[0]+(2*roomSize)/5+((rungs+2)*w), start[1]-h);
  vertex(start[0]+(2*roomSize)/5+((rungs+2)*w), start[1]);
}
 
void drawFloorLamp(float[] start) {
  float x = (2*roomSize)/5;
  float w = (3*spacing)/4;
  vertex(start[0]+x,      start[1]);
  vertex(start[0]+x,      start[1]-(2*roomSize)/5);
  vertex(start[0]+x-w,    start[1]-(2*roomSize)/5);
  vertex(start[0]+x,      start[1]-(3*roomSize)/5);
 
  vertex(start[0]+x+w,    start[1]-(3*roomSize)/5);
  vertex(start[0]+x+(2*w),start[1]-(2*roomSize)/5);
  vertex(start[0]+x+w,    start[1]-(2*roomSize)/5);
  vertex(start[0]+x+w,    start[1]);
}
 
void drawCeilingLight(float[] start) {
  float w = (3*spacing)/4;
  vertex(start[0]+(roomSize/2)+(w/2), start[1]-roomSize+spacing);
  vertex(start[0]+(roomSize/2)+(w/2), start[1]-roomSize+spacing+((roomSize)/20));
  vertex(start[0]+(roomSize/2)+(w*2), start[1]-roomSize+spacing+((3*roomSize)/20));
 
  vertex(start[0]+(roomSize/2)-(w*2), start[1]-roomSize+spacing+((3*roomSize)/20));
  vertex(start[0]+(roomSize/2)-(w/2), start[1]-roomSize+spacing+((roomSize)/20));
  vertex(start[0]+(roomSize/2)-(w/2), start[1]-roomSize+spacing);
}
 
void drawLeftToilet(float[] start) {
  vertex(start[0]+spacing,                   start[1]-(roomSize/2)+(roomSize/10));
  vertex(start[0]+(roomSize/10)+spacing,     start[1]-(roomSize/2)+(roomSize/10));
  vertex(start[0]+(roomSize/10)+spacing,     start[1]-(roomSize/2)+(2*(roomSize/10)));
  vertex(start[0]+(2*(roomSize/10))+spacing, start[1]-(roomSize/2)+(2*(roomSize/10)));
  endShape();
  bezier(start[0]+(2*(roomSize/10))+spacing, start[1]-(roomSize/2)+(2*(roomSize/10)),
         start[0]+(2*(roomSize/10))+spacing, start[1]-(roomSize/2)+(2*(roomSize/5)),
         start[0]+(2*(roomSize/10))+spacing, start[1]-(roomSize/2)+(2*(roomSize/5)),
         start[0]+spacing,                   start[1]-(roomSize/2)+(2*(roomSize/5)));
  beginShape();
  vertex(start[0]+spacing, start[1]-(roomSize/2)+(2*(roomSize/5)));
}
 
void drawRightToilet(float[] start) {
  vertex(start[0]+roomSize-spacing,                   start[1]-(roomSize/2)+(2*(roomSize/5)));
  endShape();
  bezier(start[0]+roomSize-spacing,                   start[1]-(roomSize/2)+(2*(roomSize/5)),
         start[0]+roomSize-spacing-(2*(roomSize/10)), start[1]-(roomSize/2)+(2*(roomSize/5)),
         start[0]+roomSize-spacing-(2*(roomSize/10)), start[1]-(roomSize/2)+(2*(roomSize/5)),
         start[0]+roomSize-spacing-(2*(roomSize/10)), start[1]-(roomSize/2)+(2*(roomSize/10)));
  beginShape();
  vertex(start[0]+roomSize-spacing-(2*(roomSize/10)), start[1]-(roomSize/2)+(2*(roomSize/10)));
  vertex(start[0]+roomSize-spacing-(roomSize/10),     start[1]-(roomSize/2)+(2*(roomSize/10)));
  vertex(start[0]+roomSize-spacing-(roomSize/10),     start[1]-(roomSize/2)+(roomSize/10));
  vertex(start[0]+roomSize-spacing,                   start[1]-(roomSize/2)+(roomSize/10));
}
 
void drawLeftSink(float[] start) {
  float h = (roomSize/20);
  vertex(start[0]+spacing,                   start[1]-(roomSize/2)-(roomSize/10)-(roomSize/20)+h);
  vertex(start[0]+spacing+(roomSize/10),     start[1]-(roomSize/2)-(roomSize/10)-(roomSize/20)+h);
  vertex(start[0]+spacing+(roomSize/10),     start[1]-(roomSize/2)-(roomSize/10)+h);
  vertex(start[0]+spacing,                   start[1]-(roomSize/2)-(roomSize/10)+h);
 
  vertex(start[0]+spacing,                   start[1]-(roomSize/2)+h);
  vertex(start[0]+spacing+(2*(roomSize/10)), start[1]-(roomSize/2)+h);
  vertex(start[0]+spacing+(2*(roomSize/10)), start[1]-(roomSize/2)+(roomSize/10)+h);
  vertex(start[0]+spacing+(roomSize/10),     start[1]-(roomSize/2)+(roomSize/10)+h);
  vertex(start[0]+spacing,                   start[1]-(roomSize/2)+(2*(roomSize/10))+h);
}
 
void drawRightSink(float[] start) {
  float h = (roomSize/20);
  vertex(start[0]+roomSize-spacing,                   start[1]-(roomSize/2)+(2*(roomSize/10))+h);
  vertex(start[0]+roomSize-spacing-(roomSize/10),     start[1]-(roomSize/2)+(roomSize/10)+h);
  vertex(start[0]+roomSize-spacing-(2*(roomSize/10)), start[1]-(roomSize/2)+(roomSize/10)+h);
  vertex(start[0]+roomSize-spacing-(2*(roomSize/10)), start[1]-(roomSize/2)+h);
  vertex(start[0]+roomSize-spacing,                   start[1]-(roomSize/2)+h);
 
  vertex(start[0]+roomSize-spacing,                   start[1]-(roomSize/2)-(roomSize/10)+h);
  vertex(start[0]+roomSize-spacing-(roomSize/10),     start[1]-(roomSize/2)-(roomSize/10)+h);
  vertex(start[0]+roomSize-spacing-(roomSize/10),     start[1]-(roomSize/2)-(roomSize/10)-(roomSize/20)+h);
  vertex(start[0]+roomSize-spacing,                   start[1]-(roomSize/2)-(roomSize/10)-(roomSize/20)+h);
}