Week 5 _ Visualizing Folklore

Concept 

We have learned so much about the nature of code and the physics behind it. For this project, I wanted to use what we learned in data visualization of Palestinian folklore. I wanted to visualize sound waves on this type of music and visualize it as similar to Palestinian embroidery. I think I aim to preserve cultural heritage digitally. Thus, I want to embed the traditional visual language of Palestinian embroidery with  Palestinian folklore.

Highlight 

 

There were a couple of challenges when mapping the data because, initially, I was getting dots and not lines, and they were not interesting or similar enough to embroidery. I spent a lot of time changing them into the concept I wanted.  I experimented with mathematical equations to reach the desired outcome. I have set the basic code for the project, but there is so much to do. I had to adjust the amplitude for the data and read it to add accurate numbers into the code so that it responds correctly. 

class particle {
  constructor(){

  this.pos = p5.Vector.random2D().mult(200);
  this.vel = createVector(0,0);
  this.acc = this.pos.copy().mult(random(0.001,0.0001));
    // this.r = 10;
    // this.lifetime = 255;
this.PW = random(1,5);
}
update(cond){
  this.vel.add(this.acc);
  this.pos.add(this.vel);
  
  if(cond){
    this.pos.add(this.vel);
    this.pos.add(this.vel);
    this.pos.add(this.vel);
    
  }
  
}
  //remove particles that were drawn 
  edges(){
    if(this.pos.x<-width/2 || this.pos.x>width/2 || this.pos.y <-height/2 || this.pos.y>height/2
     ){
       return true;
  } else {
    return false;
  }}
show(){
  noStroke();
   
    fill(204, 0, 0);
  ellipse(this.pos.x, this.pos.y,this.PW);
  
}}

Further, I made a particular class that also reacts to the sound by reading the fft energy and then moving according to the amplitude. The particles that are out of frame are deleted to avoid breaks and breakdowns.

Sketch 


Future Work 

I want to make buttons to allow the audience to pick a song from a preloaded set of songs, but I also need to work more on the aesthetics and final design of the work. I also want to add some complexity to the visualization, maybe allowing the audience to change the density of the strokes or play with textures and shades.

 

Week 4 – Dancing Wave

Concept:

For this project, I was inspired by the Memo Akten Simple Harmonic Motion project. What stood out to me in this project was the sound and how particles would change if they approached a different line or object. For this project, I decided to experiment with a Dancing wave that would function similarly.

Highlight of code:

I had so many challenges in this code and debugging and figuring out the logic behind the functionality took me some time. There are many parts that I am proud of in this code. I am particularly the flow I created of the animated video.

rotate(PI / 3);

  for (let i = 0; i < angles.length; i++) {
    beginShape();
    for (let i = 0; i < angles.length; i++) {
      let y = map(sin(angles[i]), -1, 1, -150, 150);
      let x = map(i, 0, angles.length, -350, 350);

      let particleSize = r * 0.9; // Default particle size

      // Check if the particle touches the line (y is close to 0)
      if (abs(y) < 5) {
        //draw the shape gradually on canvas

        fill(touchedLineColor); // Change color when touching
        particleSize = r * 2.5; // Increase the size of the particle
      } else {
        fill(getWaveColor(y)); // Get color based on y value
      }

      stroke(getWaveColor(y));
      strokeWeight(1);
      line(cos(x), 0, x, y); // Draw line from middle to particle
      noStroke();
      circle(x, y, particleSize); // Draw the particle
      noFill();
      vertex(x, y);

      endShape();
    }
 angleV[i] = constrain(angleV[i], -0.01, 0.5);
    angles[i] -= angleV[i];
    angleV[i] += angleA[i];
  }
}

The video starts by drawing a simple line that has a sort of random noise. This line is the point of transformation of the color of particles when they touch it. Then, I drew the wave, which gradually increases its acceleration over time. I initially wanted the wave to appear on the canvas slowly before the animation started. I tried so many ways to do that, for instance, making a static wave, then adding the animated one on it, and creating nested loops; however, none of the ways worked, so I decided to improve on it in future work.
Additionally, I am proud of being able to check if the particles are close to the invisible line so that they change color and size. Even though, though it has a simple logic, figuring it out took some time.

Embedded Sketch:


Future Work:
For future work, I want to play more with the wave’s acceleration so that it would accelerate and decelerate when I want it. I also want to experiment with different waves to see the different esthetics I can create, and finally, adding the wave gradually into the canvas would be a strong attribute to the design of this animation.

Reference:

Colorful Coding. (2021, January 22). Simple sine wave animation in p5.js | Coding Project #11 [Video]. YouTube. https://www.youtube.com/watch?v=ktPnruyC6cc

Colorful Coding. (2021b, January 30). Circular perlin noise in p5.js | Coding Project #12 [Video]. YouTube. https://www.youtube.com/watch?v=0YvPgYDR1oM

The Coding Train. (2021a, January 26). 3.1 Angles and rotation – Nature of code [Video],3.1-3.9 . YouTube. https://www.youtube.com/watch?v=DMg-WRfNB60

Memo Akten, Mehmet Selim Akten, The Mega Super Awesome Visuals Company. (n.d.-b). Simple Harmonic Motion (2011-). Memo Akten | Mehmet Selim Akten | the Mega Super Awesome Visuals Company. https://www.memo.tv/works/simple-harmonic-motion/

https://p5js.org/reference/

 

week3 – attractors and movers

Concept:

The concept for this project was to be able to create a recognizable pattern while also using movers and attractors. I was inspired by the flower-dotted patterns as well as Dan Gries’s work. In this project, I try to integrate what we learned in class to recreate such a pattern. However, I decided to add more forces that can disturb the pattern as if it’s almost a shadow.

Highlight of some code:

For this project, I decided to build upon the practice we had in class. I initially wrote a code similar to what we did in class and then watched the nature of the code video and added elements to that. I played around with the names to see what patterns I got. After that, I decided to create some turbulence by creating a bouncing effect when the balls reached the borders of the canvas and by creating gravity between some of the particles. I had so many issues with debugging the code because I was experimenting with it mostly to create a pattern I liked. I think the most challenging part was making the different bodies work relatively in response to one another while also creating interesting shapes as they moved around the canvas. 

These images are different iterations at different stages of my code until I reach the desired result.

class Mover {
  constructor(x, y, m) {
    this.pos = createVector(x, y);
    this.vel = p5.Vector.random2D();
     // this.vel.mult(5);
    //     the acceleration will change when forces act on it
    this.acc = createVector(0, 0);
    this.mass = m;//this store mass m of mover []
    this.r = sqrt(this.mass) * 0.15; //r=sqr m * a constant this is for the radious 
  }

  applyForce(force) {
    let f = p5.Vector.div(force, this.mass);
    this.acc.add(f); //add the forces to acceleration 
  }
//   attract to one another gravity btw diff objects
  TwoAttract(mover) {
    //this.pos-mover=vector(from mover to another mover)
    let force = p5.Vector.sub(this.pos, mover.pos); // 
    let distanceSq = constrain(force.magSq(), 1000, 10000); //limit btwn 1000 and 10000
    let G = 0.2; //gravatational constant 
    let strength = (G * (this.mass * mover.mass)) / distanceSq; //f=G*(m1m2)/d'2 law of gravity 
    force.setMag(strength); //set the force and mag as calculated 
    mover.applyForce(force); //apply calculated to mover 
  }

  update() {
    this.vel.add(this.acc);
    this.pos.add(this.vel);
    this.acc.set(0, 0);
    
        // Boundary checks 
    if (this.pos.x > width) {
      this.pos.x = width;
      this.vel.x *= -1; // Reverse horizontal velocity when hitting right edge
    } else if (this.pos.x < 0) {
      this.pos.x = 0;
      this.vel.x *= -0.1; // Reverse horizontal velocity when hitting left edge
    }
    
    if (this.pos.y > height) {
      this.pos.y = height;
      this.vel.y *= -0.2; // Reverse vertical velocity when hitting bottom edge
    } else if (this.pos.y < 0) {
      this.pos.y = 0;
      this.vel.y *= -0.2; // Reverse vertical velocity when hitting top edge
    }
    // Reset acceleration to 0 after each frame
    this.acc.mult(0);
    
    
  }
  RandomColors(){
  //     colors function
   
   let R = random(90, 100); // r is a random number between 0 - 255
   let G = random(100, 120); // g is a random number betwen 100 - 200
   let B = random(150, 200); // b is a random number between 0 - 100
  return color(R,G,B);
}

  show() {
     strokeWeight(0);
    fill(this.RandomColors());
    ellipse(this.pos.x, this.pos.y, this.r * 2);
  }
}
//class to attract objects to the attractor to show how gravity is btwn 2 objects the attractor and the objects 
class Attractor {
  constructor(x, y, m) {
    this.pos = createVector(x, y);
    this.mass = m;
    this.r = sqrt(this.mass) *115;
  }

  attract(mover) {
    let force = p5.Vector.sub(this.pos, mover.pos);
    let distanceSq = constrain(force.magSq(), 1000, 1500);
    let G = 4;
    let strength = (G * (this.mass * mover.mass)) / distanceSq;
    force.setMag(strength);
    mover.applyForce(force);
  }

  show() {
  
  }
}
let movers = [];
let twoattract;
let attractor;

function setup() {
  createCanvas(600, 600);
  //movers attracted to attracor
  for (let i = 0; i < 6; i++) {
    let x = random(width / 2);
    let y = random(height / 2);
    let m = random(50, 100);
    movers[i] = new Mover(x, y, m);
  }
  attractor = new Attractor(width / 2.5, height / 2, 100);

  background(0);
}

function draw() {
  //3 movers attracted to each other
  for (let t = 0; t < 4; t++) {
    movers[t].update();
    movers[t].show();
    //attractor applies force to each other
    attractor.attract(movers[t]);

    for (let u = 0; u < 6; u++) {
      for (let other of movers) {
        if (t !== u) {
          movers[t].TwoAttract(movers[u]);
        }
      }
    }
  }

  attractor.show();
}

 

Embedded sketch:

Reflection and Future Work:

I am happy with the result of this project; however, I think there is room for improvement.  I think the forces acting on the objects and the attraction more coherent with one another to make them feel a little more pattern would create even more pleasing results. Further, I want to experiment with other shapes rather than circles maybe lines or triangles that would potential;;y create other patterns as they move.

Resources:

https://www.researchgate.net/publication/258499541_Classification_of_symmetry_groups_for_planar_n-body_choreographies

https://dangries.com/rectangleworld/demos/nBody/

https://github.com/nature-of-code/noc-book-2/tree/main/content/examples/01_vectors/example_1_9_motion_101_velocity_and_random_acceleration

https://thecodingtrain.com/tracks/the-nature-of-code-2/noc/2-forces/6-mutual-attraction

Week 2 – Rain

Your concept:

Rain always brings me peace; therefore, for this project, I created a scene of rainfall to reflect the feeling I get when it rains. I had some ideas before I settled into this one, such as sunset and sunrise, moving waves, and birds. However, replicating rainfall spoke to me the most. 

I began this assignment by reviewing the materials for this week and watching inspirational videos of things that move. Then, I read a little about the physics behind rainfall, its average acceleration relative to its size, and velocity. I had to do some conversions and basic math to make it logical on a computer screen. For the scene, I used a PNG image for the mountains, a gradient for the sky, rain audio, and some stars to enhance the theme.

Highlight of code:

I tried to make my code neat and clean for this project by creating a different class file and functions whenever possible. The most challenging part of this project was figuring out logical numbers for the line length, acceleration, and velocity so that the rain looks similar to real life. I also had some trouble figuring out how to make sure the lines were straight and not move in any other direction, so I also experimented with it.

class RainDrop {
  constructor(x, y) {
    this.position = createVector(x, y);
    // make the numbers more logical when it comes to rain in pixcels
    this.velocity = createVector(0, random(0.6, 0.9));
    this.acceleration = createVector(0.001, 0.9);
    this.length = random(10, 20);
    this.Colorstrength = random(20, 255); //form od depth
  }
  show() {
    stroke(200, this.Colorstrength);
    //     subtracting x from the length to create a vertical line if i dont it looks weird
    line(
      this.position.x,
      this.position.y,
      this.position.x,
      this.position.y - this.length
    );
  }

  update() {
    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);
  }
}

 

Embedded sketch:

Future work:

While this project satisfies what I have learned so far, in the future, I want to add other factors that affect the acceleration of a raindrop, like the force of air and its density. I also want to add more depth so that the sketch resembles real life and to enhance the experience. Furthermore, I want to loop the sound and create a button for the user to have the power to play and stop the audio.

Resources:

https://hypertextbook.com/facts/2007/EvanKaplan.shtml#:~:text=When%20a%20raindrop%20falls%20to,as%20would%20any%20falling%20body.

https://hypertextbook.com/facts/2007/EvanKaplan.shtml#:~:text=When%20a%20raindrop%20falls%20to,as%20would%20any%20falling%20body.

https://p5js.org/reference/p5.Element/show/

https://p5js.org/reference/p5/lerpColor/

 

Self-Avoiding Walker _ Week 1

Concept:

In the first week of classes, I decided to make a self-avoiding walker with randomized RGB colors for the background, lines, and points of the walker and Gaussian random point size. I took this assignment to review my prior knowledge of P5Js and build upon it.  For the point, I made sure I used noise to randomize the color to make it more organic, playfull, and aesthetically pleasing.

Highlight of some code:

To successfully make this project, I had to research a little about self-avoiding walkers, and I came across the Coding Trian video where he transforms the random walker we made in class into a self-avoiding one. For my code, I followed the same logic as he did but I also added my own into it. I also explored noise and Gaussian random a lot in this assignment. I also decided to add some text indicating that the pattern has stopped so that the user can reload the code if they want another pattern.

 

// global variable to store the data in the left right up and dawn, each objects stores an element of direction
let allDirections = [
  { dx: 1, dy: 0 }, //right
  { dx: -1, dy: 0 }, //left
  { dx: 0, dy: 1 }, //dawn
  { dx: 0, dy: -1 }, //up
];

let x;
let y;

// randomize the color of stokes
let Clr = 0;

let grid;
let spacing = 20;
let cols, rows; //variables for the colombs and rows to store info

//
function GridArray(cols, rows) {
  let arr = new Array(cols);
  for (let i = 0; i < arr.length; i++) {
    arr[i] = new Array(rows);
  }
  return arr;
}

function setup() {
  createCanvas(400, 400);
  //colums and raws for the 2d array
  cols = floor(width / spacing);
  rows = floor(height / spacing);
  x = cols / 2;
  y = rows / 2;
  //random Background color
  r = random(200, 160);
  g = random(200, 160);
  b = random(200, 160);
  background(r, g, b);
  //make an array to store the grid data in to save it and set it intially to false if it did not go there
  grid = GridArray(cols, rows);
  for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      grid[i][j] = false;
    }
  }
  //   set to true when walker has been there
  grid[x][y] = true;
}

//create a function to check validity to go to a specific spot
function isValid(i, j) {
  if (i < 0 || i >= cols || j < 0 || j >= rows) {
    return false;
  }
  return !grid[i][j];
}

function draw() {
  // make dot size based on random gaussian
  let w = randomGaussian(8, 4);
  strokeWeight(w);

  // make stroke color based on noise
  let n = noise(Clr);
  let n2 = noise(Clr + 80);
  let n3 = noise(Clr + 50);
  Clr += 0.75;
  let c1 = map(n, 0, 1, 0, 255);
  let c2 = map(n2, 0, 1, 0, 255);
  let c3 = map(n3, 0, 1, 0, 255);
  let c = color(c1, c2, 160 + c3);

  //plot the point
  stroke(c);
  point(x * spacing, y * spacing);

  //make array and put all directions in the array then check if its valid
  let options = [];
  for (let option of allDirections) {
    let newX = x + option.dx;
    let newY = y + option.dy;
    if (isValid(newX, newY)) {
      options.push(option);
    }
  }

  if (options.length > 0) {
    let step = random(options);

    strokeWeight(5);
    stroke(c);

    beginShape();
    //     line
    vertex(x * spacing, y * spacing);
    x += step.dx;
    y += step.dy;
    vertex(x * spacing, y * spacing);
    endShape();
    grid[x][y] = true;
  } else {
    console.log(`Walked this path!`);
    textSize(14);
    fill(255);
    text('OOPS... almost walked on myself',100,200)
    noLoop();
  }
}

One part of the code I am particularly proud of is making the color for the stroke. Here, I created 3 Perlin noise variables. Then, I incremented Clr by 0.75 to ensure a smooth and gradual transition in color. Then, I mapped the noise values to the color ones understood by P5. Finally, when I made the variable c for color, I  made sure that the blue color was more dominant by adding 160 to it.

Embedded sketch:

Reflection and ideas for future work or improvements:

I am really happy with the outcome. This assignment was an opportunity to review what I previously learned in P5Js and add new knowledge to it.  However, I think there is always room for improvement. For instance, I need to figure out how to restrict the walker within the canvas boundaries. Further, I want it to be a little more interactive. For instance, if the mouse is pressed or the space bar is clicked, I want the walker to re-load and then make another randomized walker and change colors.

Resources:

Wikipedia contributors. (2024, August 7). Self-avoiding walk. Wikipedia. https://en.wikipedia.org/wiki/Self-avoiding_walk

1.1 What is a Vector? (n.d.). https://thecodingtrain.com/tracks/the-nature-of-code-2/noc/1-vectors/1-what-is-a-vector

The Coding Train. (2021, June 10). Coding Challenge 162: Self-Avoiding Walk [Video]. YouTube. https://www.youtube.com/watch?v=m6-cm6GZ1iw

The Computational Beauty of Nature – Week 1

 

In The Computational Beuty of Nature, Flake transforms how I thought about nature and the world from an extremely complex perspective into a simpler one. In this chapter, Flake explores ways in which the world’s complexity can be simplified. From his definition of Reduction, I tried to understand how things work and behave. For instance, when coding something hard I began by thinking of the different elements it encompaces, and put it in simpler words. Through this reading, I realized that the world is like a puzzle. Small pieces of it come together to make something more complex. Additionally, in this book,  he argues that there is a significant importance in looking at the world through other different lenses, such as holism and parallelism.

“Choas shows us that even in deterministic systems, predictability is not guaranteed”.

Further, I liked his comparison between natural selection and algorithm because even though someone knows how specific algorithms work and the creator knows how natural selection works we, as users, often do not know. As a result, I think this creates a form of randomness, and he will explain further in chapter three about chaos where algorithmic systems can produce seemingly random outcomes.

Even though the chapter focuses on how to see the world it also briefly introduces the different chapters of the book where he draws a connection to the relationship between the various chapters in understanding one another and nature.
I think this chapter formulates a foundation for the book and how via computation one can understand the complexity of our world.