Category Archives: Uncategorized

Wanfang Diao

23 Jan 2014

7970C6C7-9D25-4CC4-92EB-41B2C55E587B

3 sticks connected by one point at the center. That’s my understanding of Y. So I made the point as an fixed axis and 3 sticks roll around it. The coordinate seems confusing to me at first, after several trials and adjustment, the result is a  little bit different then I thought but approach the sense of 3D rolling in my mind.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
 * Register your submission and choose a character
 * For more information check out the documentation
 * http://anitype.com/documentation
 */
Anitype.register('Y', {
 
  // Enter your name
  author: 'Wanfang',
 
  // Enter a personal website, must have http
  website: 'http://dropr.com/wanfangdiao',
 
  // Make your animation here
  construct: function(two, points) {
 
    // Reference to instance
    var anitype = this;
 
    // Change duration of animation
    //this.duration = 2000;
 
    // Create a Two.Polygon
    var polygon = anitype.makePolygon(points);
 
   //console.log(polygon.vertices);
 
    // Set an initial state
 
    anitype.addTween(polygon.vertices[0], {
      to: { x: -186  },
      easing: Anitype.Easing.Quadratic.InOut,
      duration: 0.25, // Value from 0 - 1
      start: 0,        // Value from 0 - 1
      complete: function(){
        anitype.addTween(polygon.vertices[0], {
          to: {x:109 },
          easing: Anitype.Easing.Quadratic.InOut,
          duration: 0.25, // Value from 0 - 1
          start: 0.26,
          complete: function(){
            anitype.addTween(polygon.vertices[0], {
              to: {x: -288 },
              easing: Anitype.Easing.Quadratic.InOut,
              duration: 0.25, // Value from 0 - 1
              start: .51,
            complete: function(){
              anitype.addTween(polygon.vertices[0], {
                to: {x: -186 },
                easing: Anitype.Easing.Quadratic.InOut,
                duration: 0.24, // Value from 0 - 1
                start: .76
              });
            }
            });
          }
        });
      }
    });
     anitype.addTween(polygon.vertices[2], {
      to: { x: 186  },
      easing: Anitype.Easing.Quadratic.InOut,
      duration: 0.25, // Value from 0 - 1
      start: 0,        // Value from 0 - 1
      complete: function(){
        anitype.addTween(polygon.vertices[2], {
          to: {x:-109 },
          easing: Anitype.Easing.Quadratic.InOut,
          duration: 0.25, // Value from 0 - 1
          start: 0.26,
          complete: function(){
            anitype.addTween(polygon.vertices[2], {
              to: {x: 288 },
              easing: Anitype.Easing.Quadratic.InOut,
              duration: 0.25, // Value from 0 - 1
              start: .51,
            complete: function(){
              anitype.addTween(polygon.vertices[2], {
                to: {x: 186 },
                easing: Anitype.Easing.Quadratic.InOut,
                duration: 0.24, // Value from 0 - 1
                start: .76
              });
            }
            });
          }
        });
      }
    });
    anitype.addTween(polygon.vertices[4], {
      to: { x: -150  },
      easing: Anitype.Easing.Quadratic.InOut,
      duration: 0.25, // Value from 0 - 1
      start: 0,        // Value from 0 - 1
      complete: function(){
        anitype.addTween(polygon.vertices[4], {
          to: {x:0 },
          easing: Anitype.Easing.Quadratic.InOut,
          duration: 0.25, // Value from 0 - 1
          start: 0.26,
          complete: function(){
            anitype.addTween(polygon.vertices[4], {
              to: {x: 150 },
              easing: Anitype.Easing.Quadratic.InOut,
              duration: 0.25, // Value from 0 - 1
              start: .51,
            complete: function(){
              anitype.addTween(polygon.vertices[4], {
                to: {x: 0 },
                easing: Anitype.Easing.Quadratic.InOut,
                duration: 0.24, // Value from 0 - 1
                start: .76
              });
            }
            });
          }
        });
      }
    });
 
    // Return your polygon wrapped in a group.
    return two.makeGroup(polygon);
 
  }
 
});

W looks like wave. So my idea is to make it soft and shake like a string. As a beginner of javascript, I tried to find a similar example first. I began with forking the work of Chris as shown below. After being familiar with the code structure, I found that the reason it looks like 2 string but one is that the formula of vert.x is a simple cos. Sp I changed the main  formula to 2*cos(t)-cos(2*t);I adjust the several parameters until it looks like one string waving by holding two ends.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* Register your submission and choose a character
* For more information check out the documentation
* http://anitype.com/documentation
*/
Anitype.register('W', {
 
author: 'Wanfang Diao',
 
website: 'http://dropr.com/wanfangdiao',
 
construct: function(two, points) {
 
var anitype = this;
 
var polygon = anitype.makePolygon(points).subdivide();
var dimensions = polygon.getBoundingClientRect();
var angleStep = (Math.PI * 2 / polygon.vertices.length);
 
_.each(polygon.vertices, function(vert, i){
var time = { value:0 };
vert.oX = vert.x;
vert.oAngle = Math.cos((vert.x / dimensions.width / 2) + (i*angleStep));
anitype.addTween(time, {
to: { value: 0.5 },
easing: Anitype.Easing.Linear.None,
duration: 0.74,
start: 0.25,
update: function() {
var angle = vert.oAngle + (this.value * Math.PI * 4);
vert.x = (Math.cos(angle)-Math.cos(2*angle) )* vert.oX;
}
});
});
 
return two.makeGroup(polygon);
}
});

		

Andrew Russell

22 Jan 2014

rescue timeGoogle Location History

Similar to Open Paths but run by Google. I have been using Google Location history since March 2012. I have traveled across the continent many times with it enabled and have lots of interested data to parse. To help me parse this data, I will be using Journey to the Moon, which gives basic metrics. However, I am more interested in parsing recent data, to figure out how many kilometers I have biked, and during what time frames do I bike. To do so, I will have to write a program to parse the data myself, and look for how fast I was travelling.

location_month

My location history for the last 30 days

Rescue Time

As someone with a degree in Software Engineering, my life would be incomplete without knowing how I spend my time online. This is where Rescue Time comes in. It is a webapp / browser extension that tracks every website you go to, and how long you are on each one. It then has a categorization for all popular websites, and shows you how productive / unproductive you are when you use the internet. Unfortunately, my old account was deleted due to inactivity, so I will be starting fresh for this semester.

rescue time

Datum

I have an addiction. It is to bagels. Which is why I am going to track every bagel I eat, where it came from (homemade, bagel factory, etc.), and what type it is. I am also going to track bike maintenance to see how often I pump my tires, get flats, oil the chain, etc. I may track other data (guitar time?, video game time?) but have not decided yet.

Lenticular Animation

For my lenticular animation, I thought it would be interesting to work on traditional computational patterns, such as the penrose pattern, generated by an L-system. Printing and having a physical representation of such a pattern is very appealing to me. I started with a simple penrose algorithm and played with different parameters and colors using randomness to derive different patterns. I settled on certain parameters that will make the generated image look like a snow flake.

 

snowflakeg

 

As for my process, I initially had some sketches of different designs and patterns. I found and implemented a few generative algorithms and started varying certain parameters to create patterns I like. Rather than a serial process of drawing a design then implementing, I was constantly sketching different alternatives. Mostly, my sketches were influenced by the output of the algorithms I wrote down. I can’t say that the output was something that I had sketched out initially then implemented, it was a more random and exploratory process. In that sense, the process was largely influenced by the algorithms I was using rather than the other way around.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
 
//===================================================
// Global variables. 
 
int     nFramesInLoop = 30; // for lenticular export, change this to 10!
int     nElapsedFrames;
boolean bRecording; 
 
String  myName = "mayakreidieh";
 
float[][] nse = new float [5000][2];
 
//===================================================
// Penrose pattern generator
String axiom = "[X]++[X]++[X]++[X]++[X]";
String W = "YF++ZF4-XF[-YF4-WF]++";
String X = "+YF--ZF[3-WF--XF]+";
String Y = "-WF++XF[+++YF++ZF]-";
String Z = "--YF++++WF[+ZF++++XF]--XF";
String F = "";
float step_len = 15*30.0;
int steps = 0;
float theta = radians(36); 
String generated = "";
 
void generate() {
  generated = axiom;
  for (int j = 0; j < 3; j++) {
    String temp = "";
    for (int i = 0; i < generated.length(); i++) {
      char step = generated.charAt(i);
      switch(step) {
        case 'W': temp = temp + W; break;
        case 'X': temp = temp + X; break;
        case 'Y': temp = temp + Y; break;
        case 'Z': temp = temp + Z; break;
        case 'F': temp = temp + F; break;
        default: temp = temp + step; break;
      }
    }
    step_len = step_len * 0.5;
    generated = temp;
    println(generated);
  }
}
void render() {
  translate(width/2, height/2);
  int pushes = 0;
  int repeats = 1;
  steps = (steps + 30) % generated.length();          
  for (int i = 0; i < steps; i++) {
    char step = generated.charAt(i);
    switch(step) {
      case 'F':
        strokeWeight(2);
        stroke(random(200), random(0,100), 255, 40);
        for (int j = 0; j < repeats; j++) {
          line(0, 0, 0 , - (step_len*noise(nse[i][1])*5) );
          ellipse(0,0,10*noise(nse[i][0]),4*noise(nse[i][0]));
          noFill();
          translate( 0 , -step_len);
          nse[i][0]+=2;
          nse[i][1]+=0.01;
        }
        repeats = 1; break;
      case '+': 
        for (int j = 0; j < repeats; j++) {
          rotate(theta);
        }
        repeats = 1; break;
      case '-': 
        for (int j =0; j < repeats; j++) {
          rotate(-theta);
        }
        repeats = 1; break;
      case '[': pushes++; pushMatrix(); break;
      case ']': popMatrix(); pushes--; break;
      case '3': repeats = 3; break;
      case '4': repeats = 4; break;
      default: break;
    }
  }
 
  while (pushes > 0) {
    popMatrix();
    pushes--;
  }
}
 
 
//===================================================
void setup() {
  size(500, 500);
  for (int i=0;i&lt;5000;i++){
   nse[i][0] = random(10); 
   nse[i][1] = random(10); 
  }
  generate();
}
 
void keyPressed() { 
  // Press a key to export frames to the output folder
  bRecording = true;
  nElapsedFrames = 0;
}
 
void draw() {
  background(255);
  render();
 
  // If we're recording the output, save the frame to a file. 
  if (bRecording) {
    saveFrame("output/"+ myName + "-loop-" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames == nFramesInLoop) {
      bRecording = false;
    }
  }
}

Andrew Sweet

21 Jan 2014

Assigned Letter: D

I was assigned the letter D to animate. After some thought on the shape itself, I ultimately came up with a wipe design, do to the fact that a lower case d has a line on the right, and the capital has it on the left. I then began planning out the evolving curvature from a backwards “C” to a “o” to animate the arc of the D. I kept trying to visualize an aesthetically pleasing version of that part of the animation, and ultimately decided that simple was better in this case. Turns out that making the circle was much more difficult that I previously imagined, I had to learn a lot about bezier handles and anchoring the curves to achieve a circular object that could be wiped and not simply drawn as a solid circle.


Letter Choice: H

After the success of the D, I decided if I did it with another letter, I could potentially start a trend. Animating between capital and lowercase. Obviously x, w, v, o, u, s, z, and c are very easy options (just growing or shrinking the lettering). I ultimately decided the letter H was capable of the mirror animation to D, and began work on that.


sketch

/**
 * Register your submission and choose a character
 * For more information check out the documentation
 * http://anitype.com/documentation
 */
Anitype.register('D', {
 
  // Enter your name
  author: 'Andrew Sweet',
 
  // Enter a personal website, must have http
  website: 'http://www.linkedin.com/pub/andrew-sweet/58/93/735/',
 
  // Make your animation here
  construct: function(two, points) {
 
    // Reference to instance
    var anitype = this;
 
    // Create a Two.Polygon
    //var polygon = anitype.makePolygon(points);
 
    var leftD = points[0].x;
    var rightD = points[3].x;
 
    var p0 = points[0];
    var p1 = points[1];
    var p2 = points[2];
    var p3 = points[3];
    var p4 = points[4];
 
    var c0 = points[1].clone();
 
    var midY = (p1.y + p4.y)/2.0;
    var radius = (p4.y - midY)/2.0;
 
    c0.x = rightD;
    c0.y = p4.y;
 
    var c1 = c0.clone();
    var c2 = c0.clone();
    var c3 = c0.clone();
 
    var midX = c0.x - radius;
    midY = c0.y - radius;
 
    var bezDist  = radius/2.3;
 
    var anchorBR = new Two.Anchor(c0.x, c0.y);
    var anchorBL = new Two.Anchor(c0.x - (2 * radius), c0.y);
    var anchorTL = new Two.Anchor(c0.x - (2 * radius), c0.y - (2 * radius));
    var anchorTR = new Two.Anchor(c0.x, c0.y - (2 * radius));
 
    c0 = new Two.Anchor(c0.x, c0.y, anchorTR.x, anchorTR.y + bezDist, 
                        anchorBR.x, anchorBR.y - bezDist, Two.Commands.curve);
 
    c1 = new Two.Anchor(c1.x, c1.y, anchorBR.x - bezDist, anchorBR.y, 
                        anchorBL.x + bezDist, anchorBL.y, Two.Commands.curve);
 
    c2 = new Two.Anchor(c2.x, c2.y, anchorBL.x, anchorBL.y - bezDist, 
                        anchorTL.x, anchorTL.y + bezDist, Two.Commands.curve);
 
    c3 = new Two.Anchor(c3.x, c3.y, anchorTL.x + bezDist, anchorTL.y, 
                        anchorTR.x - bezDist, anchorTR.y, Two.Commands.curve);
 
    c0.y -= radius;
    c1.x -= radius;
    c2.x -= 2 * radius;
    c2.y -= radius;
    c3.x -= radius;
    c3.y -= 2 * radius;
 
    var delay = 0.3;
 
    var circle = anitype.makePolygon([c0, c1, c2, c3, c0]);
    circle.beginning = 0;
    circle.ending = 0;
 
    var poly1 = anitype.makePolygon([p0, p1]);
 
    // Move Line
    anitype.addTween(poly1.translation, {
        to: { x:rightD + 174},
        easing: Anitype.Easing.Sinusoidal.InOut,
        duration: 0.3,
        start: 0.0 + delay
        });
 
    // Create a Two.Polygon
    var poly2 = anitype.makePolygon([p1, p2, p3, p4]).subdivide(20);
    circle = circle.subdivide(20);
 
    var offset = 0.03;
 
    // Handle Wipes
    var time = {value:0};
    anitype.addTween(time, {
      to: { value: 0.98 },
      duration: 0.3, 
      start: 0.02 + delay,
      update:function(){
          if (this.value &lt; 0.9){
          poly2.beginning = this.value/3.0;// * 2;
          poly2.ending = 1 - (this.value/3.0) + 0.02;
 
          circle.beginning = 0.5 - offset - (this.value/2);
          circle.ending = 0.5 + offset + (this.value/2);
 
          } else {
            poly2.beginning = 1;
            circle.beginning = 0.03;
            circle.ending = 0.97;
          }
      }
    });
 
    // Return your polygon wrapped in a group.
    return two.makeGroup(poly1, poly2, circle);
 
  }
 
});
/**
 * Register your submission and choose a character
 * For more information check out the documentation
 * http://anitype.com/documentation
 */
Anitype.register('H', {
 
  author: 'Andrew Sweet',
 
  // Enter a kickback website, must have http
  website: 'http://www.linkedin.com/pub/andrew-sweet/58/93/735/',
 
  construct: function(two, points) {
    var anitype = this;
 
    //Top Left
    var p0 = points[0];
    //Bottom Left
    var p1 = points[1];
 
    //Top Right
    var p2 = points[2];
    //Bottom Right
    var p3 = points[3];
 
    //Left Mid
    var p4 = points[4];
    //Right Mid
    var p5 = points[5];
 
    var leftLine = anitype.makePolygon([p0, p1]);
    var rightLine = anitype.makePolygon([p2, p3]);
    var midLine = anitype.makePolygon([p4, p5]);
 
    var c0 = p3.clone();
    var c2 = p1.clone();
    var c1 = new Two.Anchor(0, p4.y);
 
    var radius = (c0.x - c2.x)/2.0;
 
    var midX = c0.x - radius;
    midY = c0.y - radius;
 
    var bezDist = 0.1;//radius/2.3;
 
    var anchorTL = new Two.Anchor(c2.x, c1.y);
    var anchorTR = new Two.Anchor(c0.x, c1.y);
 
    c0 = new Two.Anchor(c0.x, c0.y, anchorTR.x -3, anchorTR.y + bezDist + 300, 
                        c0.x, c0.y, Two.Commands.curve);
 
    c1 = new Two.Anchor(c1.x, c1.y, anchorTR.x, anchorTR.y, 
                        anchorTL.x + bezDist, anchorTL.y, Two.Commands.curve);
 
    c2 = new Two.Anchor(c2.x, c2.y, c2.x, c2.y - bezDist, 
                        anchorTL.x, anchorTL.y, Two.Commands.curve);
 
    /*c0.command = Two.Commands.line;
    c1.command = Two.Commands.line;
    c2.command = Two.Commands.line;*/
 
    var curve = anitype.makePolygon([c0, c1, c2]);
 
    midLine = midLine.subdivide(30);
    curve = curve.subdivide(20);
 
    // Don't close the polygon
    curve.beginning = 0.02;
    curve.ending = 0;
 
    //var offset = 0.03;
    var delay = 0.3;
 
    // Move Line
    anitype.addTween(rightLine.translation, {
        to: { x: -355},
        easing: Anitype.Easing.Sinusoidal.InOut,
        duration: 0.3,
        start: delay
        });
 
    // Handle Wipes
    var time = {value:0};
    anitype.addTween(time, {
      to: { value: 0.98 },
      duration: 0.3, 
      start: delay,
      update:function(){
          midLine.ending = 1 - this.value;
          curve.ending = this.value;
      }
    });
 
    var result = two.makeGroup(leftLine, rightLine, midLine, curve);
    return result;
  }
});

Andrew Russell

21 Jan 2014

A while ago, I came upon a well thought out blog that detailed an introduction to the Fourier transform. Now, I first learned about the Fourier transform years ago myself, and have used it for years, so the introduction was repetition for me (I highly recommend this post for those who want to learn about it). However, there was one link at the bottom which was really interesting. Fourier Toy. An interactive guide to the Fourier transform by lucasvb. With this tool, you can control the amplitude and phase of eight sin/cos waves, and see the direct result to the Fourier transform through a nice visualization.

Remembering how I was able to get mesmerized by this interactive tool, I decided this was the perfect place for me to start my lenticular animation. I started by adjusting the waves in the tool to get a feel for what designs could be made with only eight waves (theoretically, any complex drawing can be made with infinite waves). After, I started to sketch designs that I thought would work with only 10 frames of animation. The results can be seen below.

IMG_20140121_091644[1]

The page of sketches show a failed design (top), the actual design (left), the design for each circle (right), and the amplitude and phases for each wave (bottom).

I plugged the amplitudes and phases into Fourier Toy to make sure that I had gotten them right. I then started working on the Processing code. I started with the idea that I will iteratively draw circles with each new iteration’s circle being based on the last iteration’s location. The code for drawing the circle was similar to Golan’s sample code to draw the spokes rotating around a square.

Here is the smooth GIF. Processing actually computed 1000 frames, but I only saved every 10th frame for a total of 100 frames. I did this since I needed more frames to make the curves between frames smoother, but 1000 frames was way too many (megabytes large GIF?? No thanks).

long

Here is the 10 frame version. The same concept as above was applied, except that every 100th frame was selected for just 10 frames. I believe that this will work even better on the lenticular animation since each frame will blur into the next one.

short

Here is the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
final int NUMBER_FRAMES = 1000;
final int TRAIL_SIZE = NUMBER_FRAMES / 5;
final boolean IS_GIF = true;
final int SIZE = 1500;
 
final float[] AMPLITUDES = {0.75, 0, 0.25, 0.947, 0.15, 0, 0.107, 0};
final float[] PHASES = {0, 0, 0, -3.3, 0, 0, 0, 0, 0};
 
int current_frame = 0;
boolean recording = false;
 
ArrayList last_px = new ArrayList();
ArrayList last_py = new ArrayList();
 
void setup() {
  size(SIZE, SIZE); 
  frameRate(NUMBER_FRAMES);
}
 
void keyPressed() {
  recording = true;
  current_frame = 0;
  last_px.clear();
  last_py.clear();
}
 
void draw() {
  float percentComplete = 0; 
  if (recording) {
    percentComplete = (float) current_frame / (float)NUMBER_FRAMES;
  } else {
    float modFrame = (float) (frameCount % NUMBER_FRAMES);
    percentComplete = modFrame / (float)NUMBER_FRAMES;
  }
 
  renderMyDesign(percentComplete);
 
  if (recording) {
    if (IS_GIF &amp;&amp; current_frame % (NUMBER_FRAMES / 10) == 0) {
      saveFrame("output/short-" + nf(current_frame, 4) + ".png");
    } else if(!IS_GIF &amp;&amp; current_frame % (NUMBER_FRAMES / 100) == 0) {
      saveFrame("output/frame-" + nf(current_frame, 4) + ".png");
    }
 
    current_frame++;
    if (current_frame == NUMBER_FRAMES + 201) {
      recording = false;
    }
  }
}
 
void renderMyDesign (float percent) {
  background(240);
  smooth();
  strokeWeight(2);
 
  fill(0, 0, 0, 0);
 
  float start_angle = -percent * TWO_PI;
  float px = SIZE / 2.0;
  float py = SIZE / 2.0;
 
  for (int i = 0; i &lt; 8; i++) {
    float angle = start_angle * (i + 1) - PHASES[i];
    float radius = AMPLITUDES[i] * (SIZE / 5.0);
    float cx = px;
    float cy = py;
 
    px = cx + radius * cos(angle);
    py = cy + radius * sin(angle);
 
    stroke(0, 0, 0, 45);
    ellipse(cx, cy, radius * 2, radius * 2);
    ellipse(cx, cy, 4, 4);
 
    stroke(200, 150, 150, 150);
    line(cx,cy, px, py);
  }
 
  last_px.add(px);
  last_py.add(py);
 
  for (int i = 1; i &lt; last_px.size(); i++) {     float opacity = i * 255.0 / TRAIL_SIZE;     stroke(0, 0, 200, opacity);     line(last_px.get(i - 1), last_py.get(i - 1), last_px.get(i), last_py.get(i));   }      while (last_px.size() &gt; TRAIL_SIZE) {
    last_px.remove(0);
    last_py.remove(0);
  }
}

Afnan Fahim

21 Jan 2014

After going through most of the suggested lenticular designs, I really liked dvdp’s art the best because of the abstract themes and the simple manipulation of figures to create entrancing effects.

I thus wanted to create something abstract. I started out with drawing what I could do with triangles and lines. My sketches looked like this.

IMG_20140121_063932

 

I liked where I was going with triangles and strips but could really envison how I would create something abstract about it. So I cut up some strips of paper and came up with technique for creating an interesting pattern by moving the triangles around in harmony. Here is the sequence I came up with.

lent1 lent2 lent3 lent4 lent5

Here I was basically moving rows of triangles to see different types of patterns which were very different from each other.

I then proceeded to code this up, here’s what my processing code looks like. I wasn’t quite satisfied at this point because I didn’t feel the abstract confuddling effect I was going for. I thus added a back and forth rotation to the animation in order to make it look like the user was going through a maze.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
 
// This is a template for creating a looping animation in Processing. 
// When you press a key, this program will export a series of images
// into an "output" directory located in its sketch folder. 
// These can then be combined into an animated GIF. 
// Prof. Golan Levin, January 2014 - CMU IACD
 
//===================================================
// Global variables. 
 
int     nFramesInLoop = 30; // for lenticular export, change this to 10!
int     nElapsedFrames;
boolean bRecording; 
 
String  myName = "AfnanFahim";
 
int xlen = 500;
int ylen = 500;
int nLines = 6;
int nTriangles = 6;
int triangleHeight = ylen/nTriangles;
int triangleWidth = (xlen/nLines) / 2;
float rotationAngle = 0.6;
float rotationOffset = 0.0025;
 
//===================================================
void setup() {
  size (500, 500, P3D); 
  bRecording = false;
  nElapsedFrames = 0;
  frameRate (nFramesInLoop);
  translate(0, -50);
 
}
//===================================================
void keyPressed() { 
  // Press a key to export frames to the output folder
  bRecording = true;
  nElapsedFrames = 0;
}
 
//===================================================
void draw() {
 
  // Compute a percentage (0...1) representing where we are in the loop.
  float percentCompleteFraction = 0; 
  if (bRecording) {
    percentCompleteFraction = (float) nElapsedFrames / (float)nFramesInLoop;
  } 
  else {
    float modFrame = (float) (frameCount % nFramesInLoop);
    percentCompleteFraction = modFrame / (float)nFramesInLoop;
  }
 
  // Render the design, based on that percentage. 
  renderMyDesign (percentCompleteFraction);
 
  // If we're recording the output, save the frame to a file. 
  if (bRecording) {
    saveFrame("output/"+ myName + "-loop-" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames == nFramesInLoop) {
      bRecording = false;
    }
  }
}
 
//===================================================
void renderMyDesign (float percent) {
 
  // This is an example of a function that renders a temporally looping design. 
  // It takes a "percent", between 0 and 1, indicating where we are in the loop. 
  // This example uses two different graphical techniques. 
  // Use or delete whatever you prefer from this example. 
  // Remember to SKETCH FIRST!
 
  //----------------------
  // here, I set the background and some other graphical properties
  background (255);
  smooth(); 
  strokeWeight (1); 
 
  //----------------------
  // Here, I assign some handy variables. 
 
  //----------------------
  // Here, I create and move the triangles
 
  fill(0);
 
  if (percent &lt; = 0.1) {
    rotationAngle = rotationAngle + rotationOffset;
    rotateX(rotationAngle);
    float offsetX = 0;
 
    //Creating Triangles
    for (int i = 0; i &lt;  xlen; i = i + (triangleWidth*2) ) {
      for (int j = -2 * triangleHeight; j &lt; ylen; j = j + triangleHeight) {          triangle(i, j,          i + triangleWidth, j + (triangleHeight/2),          i, j + (triangleHeight));          triangle(i + (triangleWidth), j - (triangleHeight/2),          i , j,          i + (triangleWidth), j + (triangleHeight/2));       }       }   }      else if (percent &gt; 0.1 &amp;&amp; percent &lt; = 0.3) {
    rotationAngle = rotationAngle + rotationOffset;
    rotateX(rotationAngle);
    float offsetX = (percent - 0.1) * 5;
 
    //Translating triangles sideways
    for (int i = 0; i &lt;  xlen; i = i + (triangleWidth*2) ) {
      for (int j = 0; j &lt; ylen; j = j + triangleHeight) {          triangle(i - (triangleWidth/2*offsetX), j,          i + triangleWidth - (triangleWidth/2*offsetX), j + (triangleHeight/2),          i - (triangleWidth/2*offsetX), j + (triangleHeight));          triangle(i + (triangleWidth) + (triangleWidth/2*offsetX), j - (triangleHeight/2),          i + (triangleWidth/2*offsetX), j,          i + (triangleWidth) + (triangleWidth/2*offsetX), j + (triangleHeight/2));       }       }   }   else if (percent &gt; 0.3 &amp;&amp; percent &lt; = 0.4) {
    rotationAngle = rotationAngle + rotationOffset;    
    rotateX(rotationAngle);
    //Pausing movement
    for (int i = 0; i &lt;  xlen; i = i + (triangleWidth*2) ) {
      for (int j = 0; j &lt; ylen; j = j + triangleHeight) {          triangle(i - (triangleWidth/2), j,          i + triangleWidth - (triangleWidth/2), j + (triangleHeight/2),          i - (triangleWidth/2), j + (triangleHeight));          triangle(i + (triangleWidth) + (triangleWidth/2), j - (triangleHeight/2),          i + (triangleWidth/2), j,          i + (triangleWidth) + (triangleWidth/2), j + (triangleHeight/2));       }       }   }      else if (percent &gt; 0.4 &amp;&amp; percent &lt; = 0.5) {
    rotationAngle = rotationAngle + rotationOffset;    
    rotateX(rotationAngle);
 
    float offsetY = (percent - 0.4) * 10;
 
    //Translating triangles downwards
    for (int i = 0; i &lt;  xlen; i = i + (triangleWidth*2) ) {
      for (int j = 0; j &lt; ylen; j = j + triangleHeight) {          triangle(i - (triangleWidth/2), j + (triangleHeight/4*offsetY),          i + triangleWidth - (triangleWidth/2), j + (triangleHeight/2) + (triangleHeight/4*offsetY),          i - (triangleWidth/2), j + (triangleHeight) + (triangleHeight/4*offsetY));          triangle(i + (triangleWidth) + (triangleWidth/2), j - (triangleHeight/2) - (triangleHeight/4*offsetY),          i + (triangleWidth/2), j - (triangleHeight/4*offsetY),          i + (triangleWidth) + (triangleWidth/2), j + (triangleHeight/2) - (triangleHeight/4*offsetY));       }       }   }   else if (percent &gt; 0.5 &amp;&amp; percent &lt; = 0.7) {
    rotationAngle = rotationAngle - rotationOffset;    
    rotateX(rotationAngle);
 
    //Pausing movement
    for (int i = 0; i &lt;  xlen; i = i + (triangleWidth*2) ) {
      for (int j = 0; j &lt; ylen; j = j + triangleHeight) {         fill(0, 0, 0);          triangle(i - (triangleWidth/2), j + (triangleHeight/4),         i + triangleWidth - (triangleWidth/2), j + (triangleHeight/2) + (triangleHeight/4),         i - (triangleWidth/2), j + (triangleHeight) + (triangleHeight/4));         triangle(i + (triangleWidth) + (triangleWidth/2), j - (triangleHeight/2) - (triangleHeight/4),         i + (triangleWidth/2), j - (triangleHeight/4),         i + (triangleWidth) + (triangleWidth/2), j + (triangleHeight/2) - (triangleHeight/4));       }       }   }   else if (percent &gt; 0.7 &amp;&amp; percent &lt; = 0.8) {
    rotationAngle = rotationAngle - rotationOffset;    
    rotateX(rotationAngle);
 
    float offsetY = (percent - 0.7) * 10;
 
    //Translating triangles downwards
    for (int i = 0; i &lt;  xlen; i = i + (triangleWidth*2) ) {
      for (int j = 0; j &lt; ylen; j = j + triangleHeight) {
         triangle(i - (triangleWidth/2), j + (triangleHeight/4) + (triangleHeight/4*offsetY),
         i + triangleWidth - (triangleWidth/2), j + (triangleHeight/2) + (triangleHeight/4) + (triangleHeight/4*offsetY),
         i - (triangleWidth/2), j + (triangleHeight) + (triangleHeight/4) + (triangleHeight/4*offsetY));
 
         triangle(i + (triangleWidth) + (triangleWidth/2), j - (triangleHeight/2) - (triangleHeight/4) - (triangleHeight/4*offsetY),
         i + (triangleWidth/2), j - (triangleHeight/4) - (triangleHeight/4*offsetY),
         i + (triangleWidth) + (triangleWidth/2), j + (triangleHeight/2) - (triangleHeight/4) - (triangleHeight/4*offsetY));
      }  
    }
  }
 
  else {
    rotationAngle = rotationAngle - rotationOffset;    
    rotateX(rotationAngle);
 
    float offsetX = (percent - 0.8) * 5;
 
    //Translating triangles sideways
    for (int i = 0; i &lt;  xlen; i = i + (triangleWidth*2) ) {
      for (int j = 0; j &lt; ylen; j = j + triangleHeight) {
         triangle(i - (triangleWidth/2) + (triangleWidth/2*offsetX), j + (triangleHeight/4) + (triangleHeight/4),
         i + triangleWidth - (triangleWidth/2) + (triangleWidth/2*offsetX), j + (triangleHeight/2) + (triangleHeight/4) + (triangleHeight/4),
         i - (triangleWidth/2) + (triangleWidth/2*offsetX), j + (triangleHeight) + (triangleHeight/4) + (triangleHeight/4));
 
         triangle(i + (triangleWidth) + (triangleWidth/2) - (triangleWidth/2*offsetX), j - (triangleHeight/2) - (triangleHeight/4) - (triangleHeight/4),
         i + (triangleWidth/2) - (triangleWidth/2*offsetX), j - (triangleHeight/4) - (triangleHeight/4),
         i + (triangleWidth) + (triangleWidth/2) - (triangleWidth/2*offsetX), j + (triangleHeight/2) - (triangleHeight/4) - (triangleHeight/4));
      }  
    }
  }
 
}

 

Afnan Fahim

21 Jan 2014

After graduating with a degree in computer science from Carnegie Mellon’s campus in Qatar (CMUQ), I had the fortune of becoming a fifth year scholar. What this meant was that, after graduating, I was allowed to take a year of courses at Carnegie Mellon’s campus in Pittsburgh, in addition to contributing to the Carnegie Mellon community in a meaningful way.

I’m excited about hacker culture and thus spent my senior year organizing the first hackathon held at CMUQ.

Most of my projects and previous experiences have been in the domain of mobile web development. I love HTML5 because it works cross platform and allows me to target many more people than by using any other platform. Recently I’ve been interested in both the performance and user experience aspects of detecting touch gestures on mobile web browsers.

This semester I hope to do three things: (1) delve into newer ways of both representing and interacting with information, (2) explore developing technology that serves the purpose of music, not medicine and (3) have lots of fun developing on new and exciting frameworks!

My twitter account is @AfnanFahim.

You can find my github profile here. If you’re interested, do check out my implementation of text rain. It’s built using Processing and was one of the assignments for last year’s IADC course.

As a project for a webapps course, a friend and I created historify – a media collection and visualization tool. Historify is a Map based web application that allows you to document the transformation of a city using text, pictures, audio and video.

The application features a time line that allows you to go “back in time” and click on different parts of the map to see what the area looked like in that year. You can navigate through media for a particular area using page flips.

Adding media to the application is simple – simply navigate to a date using the timeline, and drag’n’drop the media to the area you want your media to be associated with. Here’s what it looks like

Historify Home Screen

Historify Media Browser

Andre Le

21 Jan 2014

For this assignment, I’d like to examine several key metrics that make up how I spend my time.

  1. Sleep
  2. Food
  3. Productivity
  4. Location
  5. Fitness

The data gathered should ideally be as transparent as possible, meaning that I don’t want to have to worry about. All of this data may be overkill, but I would like to have more data to work with rather than fall short.

Sleep | FitBit

The FitBit claims to have sleep tracking and a sleep cycle alarm system built-in, in addition to activity tracking, which makes this a rather appealing device to use for my purposes. However, as I do not currently own a FitBit, I’ve been using Sleep Cycle below.

Sleep | Sleep Cycle
In the past, I have used Sleep Cycle to try and optimize my sleeping patterns and for its alarm clock that wakes me up at the correct time for a restful night sleep. Recently, I have gotten a new phone and have forgotten all about this app. This is an app that I would use again if the FitBits did not work out.

Food | MealSnap

This metric will take a little more effort than the rest to track, but it would be interesting to see how my eating habits have changed since I have become a graduate student. I’d also like to see what happens to my eating during crunch time. For this, I have found an app called MealSnap that claims that be able to estimate calorie count from snapshots of your food. I tend to photograph my food anyways, so this may be useful. It is created by the DailyBurn group and allows for export of data.

Productivity | RescueTime

RescueTime is an app that allows you to track time spent on websites and applications on your computer. I have seen this app a few years ago when they first started in beta. Since then, they seem to have improved quite a bit. It is unclear whether you can export your data, but may still yield some valuable insight.

Location | Google Location History

GoogleLocationHistory

 

Google has this little-known feature called Location History that allows you to view the location information that they have gathered about you. This could yield interesting information like how much time I spend on campus vs. at home and how far away do I stray from campus.

Fitness | Nike+ FuelBand SE  / FitBit

The FuelBand is a stylish fitness tracker that tracks activity in a proprietary metric called FuelPoints. Seeing that I commute by bike nearly everywhere, this would be and interesting data point for me to measure my activity level. In addition to the FuelBand, I’m hoping to get my hands on a FitBit to compare the data gathered for consistency.

Andrew Sweet

21 Jan 2014

Body

Nike Fuelband

Considering I’ve already started collecting data this way, I will be interning at Nike this summer, and I’ve made it a goal of mine to get into better shape this semester, I’ve decided to continue tracking my activity for the semester with the Nike Fuelband.

Communication

TextMessages

I’m really interested in seeing habits of mine in choice of words and communication. I’m likely going to download all of my text messages and Facebook messages, since these are my most used forms of communication, and perform some analytics and likely use a data visualization tool to figure out words I use a lot, how much my language varies amongst different groups of people, and how clustered that variation can become.

Schedule

Screen Shot 2014-01-21 at 1.39.46 AM

Right now, I’m somebody who pretty heavily uses my Google Calendar. If it’s not on there, I’m more than likely going to forget I’ve made a commitment to do something. For this semester, I’m going to use the Calendar just a bit more heavily, mapping every event I do outside of my home. It sounds like an unbearable task, but it really isn’t that different from what I currently do, I just have to be slightly more meticulous about the times of things and remembering to put impromptu events on the calendar as well, perhaps retroactively.

Kevyn McPhail

21 Jan 2014

FinalGIF_500

 

As someone who has only touched processing here and there, this project was a tiny bit challenging at first. However as I formulated a more concrete Idea of the motions that I wanted to create, and peeked at a bit of inspiration, the juices began to flow. I had some early ideas, as shown in the sketches, of having the GIF have a focal point, with a static or dynamic background, that emphasized the focal point.

2014-01-21 00.41.12

So, the concept that I had for this project was inspired by the “All Seeing Eye”, as the title shows. I tried to replicate the feel of an ominous, omnipotent being, ever-fixated on you. I also set out to give the GIF a sort of hypnotic feel, which is achieved by the rotation and the pulsating ring. The most difficult part of this project for me was getting the timing right for the outer rings of circles so that they loop while each ring maintains its own varied speed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//Kevyn McPhail
//Interactive Art and Computational Design
//Lenticular Animation
 
int nFrames = 30;
int elapsedFrames; 
boolean isRecording;
 
void setup(){
size(500,500);
elapsedFrames = 0;
frameRate (nFrames); 
}
 
void keyPressed(){
isRecording = true;
elapsedFrames = 0;
}
 
void draw(){
float percentCompleted = 0;
if (isRecording){
percentCompleted = (float) elapsedFrames / (float) nFrames;
}
else{
float modFrame = (float) (frameCount % nFrames);
percentCompleted = modFrame / (float) nFrames;
}
 
renderGIF(percentCompleted); 
 
if(isRecording) {
saveFrame("output/" + "kmcphail" + "-loop" + nf(elapsedFrames, 4) + ".png");
elapsedFrames ++;
if (elapsedFrames == nFrames) {
isRecording = false;
}
}
}
 
// Redners Gif
void renderGIF(float percent){
 
//Fading Background
if (percent < 0.5){
background(percent*255);
}else{
background(255 - (percent*255));
}
//background(255);
smooth();
 
float cx = width/2; 
float cy = height/2;
 
int numSpokes = 20;
 
//Shooting Circles
for (int i=0; i<numSpokes; i++){
float armAngle = (percent + i) * (TWO_PI/numSpokes); 
float px = cx + (percent*width)*cos(armAngle); 
float py = cy + (percent*height)*sin(armAngle); 
fill(0,255-(255*percent*2));
noStroke();
ellipse(px,py,(percent*(width/5)),(percent*(height/5)));
}
 
//Orbiting Rings
int numRings = 20;
for (int i=0; i<numRings; i++){
for (int j=0; j<20; j++){
float armAngle = (percent + j) * (TWO_PI/(10*i));
float px = cx + ((width/2.5)+((width/17)*i))*cos(armAngle); 
float py = cy + ((height/2.5)+((height/17)*i))*sin(armAngle); 
if (percent > 0.5){
fill(percent*255);
}else{
fill(255 - (percent*255));
}
ellipse(px,py,width/25,height/25);
}
}
 
//Rotating Eye
pushMatrix();
fill(0);
translate(cx,cy);
rotate(radians(-12*(map(percent,0,1,1,30))));
float a = map(percent,0,1,1,30);
println(a);
ellipse(0,0,width/3,height/6);
popMatrix();
fill(255);
ellipse(cx,cy,width/6.5,height/6.5);
fill(0);
ellipse(cx,cy,width/12,height/12);
 
//Orbiting Eyes
for (int i=0; i<15; i++){
float armAngle = (percent + i) * (TWO_PI/(15));
float px = cx + (width/4)*cos(armAngle); 
float py = cy + (height/4)*sin(armAngle); 
float px_2 = cx + (width/17)*cos(armAngle); 
float py_2 = cy + (height/17)*sin(armAngle);
if (percent > 0.5){
stroke(percent*255);
}else{
stroke(255 - (percent*255));
} 
strokeWeight(width/200);
line(px,py,px_2,py_2);
}
 
//InnerArc
pushMatrix();
fill(0);
translate(cx,cy);
rotate(radians(-12*(map(percent,0,1,1,30))));
noFill();
strokeWeight(width/100);
arc(0,0,width/1.75,width/1.75,0,PI);
popMatrix();
 
//Outer Arc
pushMatrix();
fill(0);
translate(cx,cy);
rotate(radians(12*(map(percent,0,1,1,30))));
noFill();
strokeWeight(width/100);
arc(0,0,width/1.5,width/1.5,0,PI);
popMatrix();
}