Seeking Fidelity New Haven, CT 2018

Along with 30 other architecture firms and designers we contributed a drawing to the Yale School of Architecture’s exhibit: ‘Tempietto Exemplum’. Our drawing questions how we take for granted what we believe is primitive geometry to formally distill projects. Bramante’s Tempietto is often celebrated and studied for its composition of discrete elements that come together in various geometric orders. By imagining how an insect or autonomous vacuum might see the Tempietto we hope to give perspective to our predispositions as architects.

Below you will find our drawing on the right and a video of how the drawing was generated on the right along with the text that goes along with our drawing. We also included the processing code used to generate variations of our drawing.

Bramante’s Tempietto is consistently recognized as one of the best examples of High Renaissance architecture. It is a synthesis of various discrete parts into a harmonious whole. In a way, it is a composite of various styles, details, and geometries. In particular, primitive geometric forms are often described as sacred elements that come together to form an ideal whole. This drawing is a counterpoint to typical geometric or formal analysis and unpacks what might be considered an ideal composite. Analysis regularly seeks to distill a building or project to a set of fundamental rules, proportions, geometries, etc. The purpose of this ranges from understanding the spatial relationships of the parts to the whole to distilling the composite ideal into a set of rules or relationships so they can potentially be recreated in a different context. Regardless of the intentions, this type of analysis either directly or indirectly reinforces the predetermined meaning we associate with geometry and its ordering systems.

As a remarkable example of the High Renaissance style, the Tempietto’s legible geometric hierarchy makes it a great project to question the typical modes of using drawing–or rather measuring and projection–as an analytical tool. This drawing is not meant to undermine the architectural quality of the Tempietto or its relevance, but to question the underpinnings of what constitutes an ideal architecture and how that is reinforced through methods and conventions we take for granted when we distill a project into geometric or compositional primitives. The goal was to produce a representation that is agnostic to historical and cultural context and/or references as well as more fundamental organizing principles such as composition, proportion, and order. It is not meant to be the right approach, but to highlight the possibilities we often preclude by not questioning the partial nature of developed conventions.

As a remarkable example of the High Renaissance style, the Tempietto’s legible geometric hierarchy makes it a great project to question the typical modes of using drawing–or rather measuring and projection–as an analytical tool. This drawing is not meant to undermine the architectural quality of the Tempietto or its relevance, but to question the underpinnings of what constitutes an ideal architecture and how that is reinforced through methods and conventions we take for granted when we distill a project into geometric or compositional primitives. The goal was to produce a representation that is agnostic to historical and cultural context and/or references as well as more fundamental organizing principles such as composition, proportion, and order. It is not meant to be the right approach, but to highlight the possibilities we often preclude by not questioning the partial nature of developed conventions. 

While architects often rely on geometric primitives and the relationships between them to analyze a project through what is typically referred to as formal analysis, many other industries and disciplines from autonomous vehicles to robotic vacuum cleaners use various forms of what they call spatial recognition. This is the departure point for this drawing: to look at the Tempietto through a lens that doesn’t account for normative architecture formal analysis. Just as the building is generated through a set of rules, the drawing uses a crude algorithm that is somewhere between the behavior of an insect and the logic of an autonomous vacuum. The algorithm operates on a two-dimensional plane in order to “discover” the perimeter of a space through a series of collisions. In this case, the seeking element lowers its capacity to travel long distances when a collision with the perimeter occurs allowing it to explore that area more rigorously. The results are similar to the analog process of a charcoal rubbing, more “material” is deposited along the edges while leaving a lighter trace of the process throughout the drawing. Just as a rubbing, every drawing is different. The process can be carried out in any plan or figure leaving neither the process or the Tempietto as the protagonist in the generation of the drawing. What is left is simply a trace of a process that relies on idiosyncratic behavior as a mechanism for possible discovery. 01:23:47:19 (hour:minute:second:frame) is the time it took to generate this particular version. The only criteria for ending the algorithm was a noticeable fidelity of the original composite. 

The drawing was created using a simple Brownian motion algorithm on the left and the figure-ground plan of the Tempietto on the right. The algorithm randomly moves a point around in a two-dimensional coordinate system. With every new position, the corresponding pixel coordinate is sampled in the plan image. If the pixel sampled is black that position s recorded with a small black circle and the agent turns around. The agents travel distance is also lowered when it “collides” with the poche. By lowering its travel distance the agent can “crawl” when it’s close to the wall to produce more collisions and fidelity. With each new position where the agent does not encounter a black pixel, the travel distance inversely increases so it can move to another area quicker if it finds itself in open space. The processing code below generates the drawing. You will need to download and place the plan image above in the data folder. The line segments that represent the travel of the agent are also coded based on distance using a color spectrum. You can make your own or download this spectrum image and place that in the data folder of your sketch as well.

import processing.pdf.*;

IntList xpos;
IntList ypos;

IntList colx;
IntList coly;

IntList radm;
FloatList tangle;

boolean record;

IntList lwt;

float newpulsex = 0;
float newpulsey = 0;

PGraphics pg;
PGraphics pgsp;

PImage img;

PImage spec;

int ctim = 0;


int value = 1;
int value2 = 0;

float randomc = 60;

int mx = 0;

void setup (){
  size(1200,1200);
  
  pg = createGraphics(height, width);
  pgsp = createGraphics(height, width);
  
  xpos = new IntList();
  ypos = new IntList();
  
  colx = new IntList();
  coly = new IntList();
  tangle = new FloatList();
  
  radm = new IntList();
  
  lwt = new IntList();
  
  xpos.append(int(width/2));
  ypos.append(int(height/2));
  lwt.append(1);
  
  img = loadImage("tempietto-proposed-1200.jpg");
  spec = loadImage("spectrum-400.jpg");
}

void draw (){
  
    if (record) {
      // Note that #### will be replaced with the frame number. Fancy!
      beginRecord(PDF, "frame-####.pdf"); 
    }
    background(255);
    pg.beginDraw();
    pg.image(img, 0, 0);
    pg.endDraw();
    pgsp.beginDraw();
    pgsp.image(spec, 0, 0);
    pgsp.endDraw();
    if(value == 0){
      image(pg,0,0);
    }
    
    if(mx == 0){
    int newx = round(random(-(randomc),randomc));
    int newy = round(random(-(randomc),randomc));
    
    //int newx = 300;
    //int newy = 200;
    
    int lastx = xpos.get(xpos.size()-1);
    int lasty = ypos.get(ypos.size()-1);
    
    //int ploc = (newx+lastx) + ((newy+lasty) * width);
    //println(red(img.pixels[ploc]));
    
    float limit = 320.0;
    
    float stepx = (newx)/limit;
    float stepy = (newy)/limit;

    //println(stepx);
  
    int ch = 0;
    for(int i = 0; i < limit+1; i++){
      //println(i);
      color c = pg.get(int((stepx * i+lastx)),int((stepy * i+lasty)));
      //println(ploc);
      //println(stepx);
      if(red(c) > 100){
        //xpos.append(newx+lastx);
        //ypos.append(newy+lasty);
      }else{
        colx.append(int(stepx*i+lastx));
        coly.append(int(stepy*i+lasty));
        
        float tt = atan2(newx ,newy );
        tt = -tt + PI/2;
        tangle.append(tt);
        //println(tt);
        radm.append(int(dist(int(stepx*i+lastx),int(stepy*i+lasty),lastx,lasty)));
        xpos.append(int(stepx*(i-1)+lastx));
        ypos.append(int(stepy*(i-1)+lasty));
        lwt.append(int(dist(lastx,lasty,stepx*i+lastx,stepy*i+lasty)));
        ch = 1;
        randomc = 0;
        i = int(limit+2); 
        mx = 0;
      }
    }
    
    if(ch == 0){
      xpos.append(newx+lastx);
      ypos.append(newy+lasty);
      lwt.append(int(randomc));
    }
    }
    if(randomc < 320){
      if(randomc < 20){
        randomc = randomc + 1;
      }else{
        if(randomc < 40){
          randomc = randomc + 3;
        }else{
          randomc = randomc + 6;
        }
      }
    }
    
    for(int i = 0; i < xpos.size() - 1; i++){
     color c2 = pgsp.get(599,8);
     if(lwt.get(i) > 75){
       c2 = pgsp.get(599,8);
     }else{
       c2 = pgsp.get(lwt.get(i)*8,8);
     }
     stroke(c2);
     strokeWeight(1);
     noFill();
     line(xpos.get(i), ypos.get(i),xpos.get(i+1), ypos.get(i+1));
  }
  //println(colx.size());
  for(int i = 0; i < colx.size(); i++){
     noFill();
     stroke(255,0,0);
     strokeWeight(1);
     if(value2 == 0){
       stroke(160);
       noFill();
     float ppx = colx.get(i) + radm.get(i)/2.0 * cos(tangle.get(i));
     float ppy = coly.get(i) + radm.get(i)/2.0 * sin(tangle.get(i));
     
     strokeWeight(2);

     strokeWeight(1);
     //line(colx.get(i), coly.get(i),ppx,ppy);
     
     ppx = colx.get(i) + 20 * cos(tangle.get(i));
     ppy = coly.get(i) + 20 * sin(tangle.get(i));
     
     stroke(100);
    }
    noStroke();
    fill(0);
    ellipse(colx.get(i), coly.get(i),3,3);
  }
  if (record) {
    endRecord();
  record = false;
  }
  
  if(ctim > 50){
    saveFrame("line-#######.png");
    ctim = 0;
  }
  ctim++;
}

void keyPressed() {
  if(keyCode == ENTER){
    if (value2 == 0) {
      value2 = 1;
    } else {
      value2 = 0;
    }
  }
    if (value == 0) {
      value = 1;
    } else {
      value = 0;
    }
}

void mousePressed() {
  record = true;
}