Project 1: art study

Exploring fractals, The Vitruvian Man, and Sacred Geometry

Anushka Sharma

INTD 350

  • Influence in history:

    • part mathematical diagram that explores proportions

    • "everything connects to everything else"- impetus

  • Visual elements:

    • Circle - connection

    • Technical measurements, precision

  • ​Connection to Sacred Geometry

Chosen Artwork

Leonardo da Vinci, “The Vitruvian Man” (ca. 1492)

  • Sacred Geometry 
    • Concept of having symbolic and sacred meanings to certain geometric shapes, and geometric proportion. 
    • Belief that a god is the geometer of the world. 
    • Torus Yantra
  • Underlying Geometry of the natural world : 
    • Fractals

Connection

"Torus Yantra"

Exploring fractals

  • I followed a code tutorial and tried to understand how fractals worked - it was too high concept for me, but it was a fun project to explore anyway, and it made me more comfortable with code.
    • ​Following this, I tried to pursue Sacred Geometry.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset ="UTF-8">
</head>
<body>
  <canvas id="my_canvas" width="1000" height="800">
  </canvas>
    <script>
      var myCanvas = document.getElementById("my_canvas")
      var ctx = myCanvas.getContext("2d");
      function draw(startX, startY, len, angle, branchWidth)
  {
        ctx. lineWidth = branchWidth;

        ctx.beginPath();
        ctx.save();

        ctx.strokeStyle = "LightCoral";
        ctx.fillStyle = "LightCoral";

        ctx.translate(startX, startY);
        ctx.rotate(angle * Math.PI/115);
        ctx.moveTo(0,0);
        ctx.lineTo(0,-len);
        ctx.stroke();

        ctx.shadowBlur = 15;
        ctx.shadowColor = "rgba(0,0,0,0.8)";

        if(len < 10) {
          ctx.restore();
          return;
        }

        draw(0, -len, len*0.8, -15, branchWidth*0.8);
        draw(0, -len, len*0.8, +15, branchWidth*0.8);

        ctx.restore();
      }
      draw(500, 700, 150, 0, 10)
    </script>
</body>
</html>

Exploring Sacred Geometry

  • Similarly, I followed a tutorial for this code, and although I preferred the end result, it was also too hard to grasp, a lot of the content wasn't something we had explore.
  • It introduced: waves!
    • ​Waves become more easy to understand, as I still remember a lot of trig I did in highschool, and this set up the basis for my project.
var allPetals = []
var canvasDimensions = {width: 800, height: 800}
var ellipseOrigin = {x: canvasDimensions.width/2, y: canvasDimensions.height/2}
var ellipseRadius = 55
var fillColorArray = [
  [50, 60, 50, 0.1],
  [100, 60, 50, 0.1],
  [150, 60, 50, 0.1],
  [200, 60, 50, 0.1],
  [250, 60, 50, 0.1],
  [300, 60, 50, 0.1]
]
var strokeColor = [100, 0, 0, 1]
var diameterIterator = 0.2

class Petal {
 constructor(index, x, y, diameter, round, fillColor, strokeColor) {
   this.index = index
   this.x = x
   this.y = y
   this.diameter = diameter
   this.angle = getPetalAngle(x, y)
   this.round = round
   this.fillColor = fillColor
   this.strokeColor = strokeColor
 } 
 
  drawPetal() {
   stroke(this.strokeColor)
   fill(this.fillColor)
   ellipse(this.x, this.y, this.diameter)
  }
}

// Start p5
function setup() {
  createCanvas(canvasDimensions.width, canvasDimensions.height)
  angleMode(DEGREES)
  colorMode(HSB)
  getPetalPositions()
}

function draw() {
  background(80)
  allPetals.forEach(position => {

    if(position.diameter > ellipseRadius * 3) diameterIterator = -0.2
       if(position.diameter < ellipseRadius) diameterIterator = 0.2

    position.diameter += diameterIterator
    position.fillColor[0] = (position.fillColor[0] + 0.05) % 360
    position.drawPetal()
  })
}

function getPetalPositions() {
  var firstIntersection = 0
  var petalCount = 0
  var offset, petal
  
  for (let roundCount = 0; roundCount < 7; roundCount++){
    offset = 360 / (roundCount * 6) 
    
    if (roundCount === 0) {
      petal = new Petal(petalCount, ellipseOrigin.x, ellipseOrigin.y, ellipseRadius * 2, roundCount, fillColorArray[(roundCount + fillColorArray.length - 1) % fillColorArray.length], strokeColor)     
      allPetals.push(petal)
      petalCount++
    }
    
    for (let i = 0; i < roundCount * 6; i++) {
      var offset, petal
      
      if (roundCount === 1 && i === 0) {
        petal = new Petal(petalCount, ellipseOrigin.x + ellipseRadius * cos(0), ellipseOrigin.y + ellipseRadius * sin(0), ellipseRadius * 2, roundCount, fillColorArray[(roundCount + fillColorArray.length - 1) % fillColorArray.length], strokeColor)
      } else {
        let intersectionCoordinates = getIntersection(allPetals[petalCount - 1], allPetals[firstIntersection], ellipseRadius)
        petal = new Petal(petalCount, intersectionCoordinates.x, intersectionCoordinates.y, ellipseRadius * 2, roundCount, fillColorArray[(roundCount + fillColorArray.length - 1) % fillColorArray.length], strokeColor)
      }

      allPetals.push(petal)
      petalCount++

      let vertexCalc = (petal.angle + offset) % 60 > 1

      if (i === roundCount * 6 - 1) {
        firstIntersection++
      } else if(vertexCalc){
        firstIntersection++
      }
    }
  }
}

function getIntersection(originator, intersected, radius) {
  var a, dx, dy, d, h, rx, ry;
  var x2, y2;

  dx = intersected.x - originator.x;
  dy = intersected.y - originator.y;
  
  d = Math.hypot(dx, dy);
  if (d > (radius + radius)) {
    return false;
    }
  
  if (d < Math.abs(radius - radius)) {
    return false;
  }

  a = ((radius*radius) - (radius*radius) + (d*d)) / (2.0 * d) ;

  x2 = originator.x + (dx * a/d);
  y2 = originator.y + (dy * a/d);

  h = Math.sqrt((radius*radius) - (a*a));
  rx = -dy * (h/d);
  ry = dx * (h/d);

  var intersection = {
    x: x2 - rx,
    y: y2 - ry
  }
  return intersection;
}

function getPetalAngle(petalX, petalY){
  let theta = Math.atan2(petalY - ellipseOrigin.y, petalX - ellipseOrigin.x) 
  theta *= 180 / Math.PI
  if (theta < 0) theta = 360 + theta
  
  theta = Math.round(theta)

  return theta
}

I also watched a few tutorials on waves, cos/sin functions in Processing, and referred back to general interaction like the MousePressed function to set up my project.

Exploratory Research:

Background Trig:

I went back to Geogebra to better understand Trig functions again, and referred to this when implementing the cos and sin functions on processing.

End result:

float angle;
float dia = 20;
float y = 100;
float x = 100;
float h = random(0,360);

void setup() {
  size(700,700);
  colorMode(HSB,360,100,100);
}

void draw () {
  background(#151515);
  
  translate(width/2, height/2);
  for (float a = 0; a <360; a +=8) {
    pushMatrix();
    rotate(radians(a));
    noFill();
    
      if(mousePressed) {
      stroke(h,80,80); 
      h = (h+6) %270;
      
    } else {
      stroke(255); }
      
     ellipse(x*sin(radians(angle)), y, 300, 300);
     ellipse(x, y*sin(radians(angle)), 300, 300);

    popMatrix();
  }
  angle++;
}