thabir – Scope
I was extremely interested in the behavior of circles for this weeks assignments. I wanted to see how I could make them move and interact with each other. To this end, I made a small personal circle library with a Circle class and some methods that allowed me to stretch circles, join circles, and pull circles apart.
I then used this library to implement a design which consists of circles bouncing inside of another circle. I then also implemented a method which allows you to pull one circle out of the other while making it appear like there is some kind of cohesive force between them. I was inspired by bubbles and water droplets.
Somethings I wanted to accomplish but wasn’t able to, was to calculate intersection areas inside the large black circle and color an intersection black if it fell inside an odd number of circles and white otherwise. However, I wasn’t able to think of an efficient way to do this.
These were some of my preparatory sketches:
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 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | class Circle { int x; int y; float r; color c; int[][] samplePoints = new int[120][2]; Circle(int a, int b, float d, color e) { x = a; y = b; r = d; c = e; //sample points from the circle for(int i=0; i<samplePoints.length; i++) { float angle = radians(i*(360.0/samplePoints.length)); samplePoints[i][0] = x + round(cos(angle)*r); samplePoints[i][1] = y + round(sin(angle)*r); } } void move(int a, int b) { x = a; y = b; //sample points from the circle for(int i=0; i<samplePoints.length; i++) { float angle = radians(i*(360.0/samplePoints.length)); samplePoints[i][0] = x + round(cos(angle)*r); samplePoints[i][1] = y + round(sin(angle)*r); } } void Resize(float a) { r = a; //sample points from the circle for(int i=0; i<samplePoints.length; i++) { float angle = radians(i*(360.0/samplePoints.length)); samplePoints[i][0] = x + round(cos(angle)*r); samplePoints[i][1] = y + round(sin(angle)*r); } } //projects circle rotated around y axis void projectCircle(float angle) { fill(c); ellipse(x, y, ((cos(angle)*r)*2), (r*2)); } void drawCircle() { fill(c); ellipse(x, y, (r*2), (r*2)); } } //connects circles at the same y coordinate with the same radius with C1 being to the left of C2 void connectCircles(Circle C1, Circle C2) { C1.drawCircle(); fill(C1.c); int topLeftX = C1.samplePoints[91][0]; int topLeftY = C1.samplePoints[91][1]; int xDistance = C2.samplePoints[31][0] - topLeftX; int yDistance = C2.samplePoints[31][1] - topLeftY; rect(topLeftX, topLeftY, xDistance, yDistance); C2.drawCircle(); } //time is a ratio between 0 and 1 and angle is between -89 and 90 void splitCircle(Circle C1, Circle C2, int angle, float d1, float d2, float time) { int dist1 = round(d1*time); int dist2 = round(d2*time); pushMatrix(); translate(C1.x, C1.y); rotate(radians(angle)); Circle newC1 = new Circle(-dist1, 0, C1.r, C1.c); Circle newC2 = new Circle(dist2, 0, C2.r, C2.c); connectCircles(newC1, newC2); popMatrix(); } void joinCircle(Circle C1, Circle C2, int angle, float d1, float d2, float time) { int dist1 = round(d1*time); int dist2 = round(d2*time); int x = round(cos(radians(angle))*d1); int y = round(sin(radians(angle))*d1); pushMatrix(); translate(C1.x+x, C1.y+y); rotate(radians(angle)); Circle newC1 = new Circle(round(dist1-d1), 0, C1.r, C1.c); Circle newC2 = new Circle(round(d2-dist2), 0, C2.r, C2.c); connectCircles(newC1, newC2); popMatrix(); } //credit to Paul Bourke's method of finding the intersection points of 2 circles float[] drawIntersectionCircles(Circle C1, Circle C2, float roffset) { float r0 = C1.r+roffset; float r1 = C2.r+roffset; int x0 = C1.x; int x1 = C2.x; int y0 = C1.y; int y1 = C2.y; int d = abs(y0 - y1); int x1fin = 0; int y1fin = 0; int x2fin = 0; int y2fin = 0; float a = (pow(r0, 2)-pow(r1, 2)+pow(d, 2))/(2*d); float h = sqrt(pow(r0, 2)-pow(a, 2)); float x2 = x0 + (a*(x1-x0)/d); float y2 = y0 + (a*(y1-y0)/d); if(d<=C1.r+C2.r) { x1fin = round(x2 + (h*(y1-y0))/d); x2fin = round(x2 - (h*(y1-y0))/d); y1fin = round(y2 + (h*(x1-x0))/d); y2fin = round(y2 - (h*(x1-x0))/d); noFill(); float angle1 = atan(((y1fin-y1)*1.0)/(x1fin-x1)) + PI; float angle2 = atan(((y1fin-y0)*1.0)/(x1fin-x0)) + PI; arc(x1fin, y1fin, 2*roffset, 2*roffset, angle1, angle2); float angle3 = atan(((y2fin-y1)*1.0)/(x2fin-x1)); float angle4 = atan(((y2fin-y0)*1.0)/(x2fin-x0)); arc(x2fin, y2fin, 2*roffset, 2*roffset, angle4, angle3); float[] angles = new float[2]; angles[0] = angle1; angles[1] = angle3; return angles; } else { float[] angles = new float[2]; angles[0] = 3*PI; angles[1] = 3*PI; return angles; } } int num = 10; int r0 = 30; int rblob = 10; Circle[] circles = new Circle[0]; void init() { for(int i=0; i<num; i++) { if(i==0) { Circle C = new Circle(0, 0, r0, color(0)); circles = (Circle[])append(circles, C); } else { int r = round(circles[i-1].r * (2.0/3)); Circle C = new Circle(r-r0, 0, r, color(255)); circles = (Circle[])append(circles, C); } } } void drawBlob(int whichFrame) { int y = (2*(r0/3)+15)/5; int r = rblob/5; Circle C = new Circle(0, 0, rblob, color(255)); if(whichFrame<5) { C.y = (r0/2) + ((whichFrame+1)*y); float angles[] = drawIntersectionCircles(circles[0], C, 80.0); if(angles[0]<=2*PI && angles[1]<=2*PI) { angles[0] = (PI-angles[0])*(-1); angles[1] = PI+angles[1]; arc(C.x, C.y, 2*C.r, 2*C.r, angles[0], angles[1]); } else C.drawCircle(); } else { C.y = (r0/2)+(4*y); C.r = rblob - ((whichFrame-4)*r); C.drawCircle(); } } void drawArtFrame (int whichFrame) { pushMatrix(); rotate(PI/2); if(frameCount==1) init(); strokeWeight(2); circles[0].drawCircle(); for(int i=1; i<num; i++) { int rCenter = round(r0 - circles[i].r); float centerAngle = 360.0/(i+1); float sideAngle = radians((180-centerAngle)/2); float sideLength; if (sideAngle>0) sideLength = (rCenter * sin(radians(centerAngle)))/sin(sideAngle); else sideLength = rCenter * 2.0; float perimeter = sideLength * (i+1); float step = perimeter/10.0; float exteriorAngle = PI-(2*sideAngle); pushMatrix(); translate(-rCenter, 0); rotate(-1*sideAngle); int current = 0; for(int j=0; j<((whichFrame-i+11)%10); j++) { if(floor(current+step)<=sideLength) { current = floor(current+step); } else { float increment = step - (sideLength - current); translate(round(sideLength), 0); rotate(exteriorAngle); current = floor(increment); } } circles[i].x = current; circles[i].drawCircle(); popMatrix(); } popMatrix(); pushMatrix(); rotate(PI); drawBlob(whichFrame); popMatrix(); drawBlob((whichFrame+5)%10); } |