shikharyashmaurya commited on
Commit
49549db
1 Parent(s): 0f3e9cb

Upload sketch.js

Browse files
Files changed (1) hide show
  1. sketch.js +257 -0
sketch.js ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let boundaries = [];
2
+ let balls = [];
3
+ let drawingBoundary = false;
4
+ let boundaryDrawn = false;
5
+ let w, h;
6
+ let entropyGraph = [];
7
+ let startTime;
8
+
9
+ function setup() {
10
+ w = windowWidth;
11
+ h = windowHeight;
12
+ canvas = createCanvas(w, h);
13
+ startTime = millis();
14
+ }
15
+
16
+ function draw() {
17
+ background(0);
18
+
19
+ // Draw the boundaries
20
+ stroke(255);
21
+ strokeWeight(2);
22
+ if (boundaries.length >= 3) {
23
+ beginShape();
24
+ for (let v of boundaries) {
25
+ vertex(v.x, v.y);
26
+ }
27
+ endShape(CLOSE);
28
+ }
29
+
30
+ // Update and draw the balls
31
+ for (let ball of balls) {
32
+ ball.move();
33
+ ball.checkBoundaryCollision();
34
+ ball.display();
35
+ }
36
+
37
+ // Calculate and display entropy
38
+ if (boundaryDrawn && balls.length > 0) {
39
+ let entropy = calculateEntropy();
40
+ entropyGraph.push(entropy);
41
+ displayEntropyGraph();
42
+ }
43
+
44
+ // Display instructions
45
+ displayInstructions();
46
+ }
47
+
48
+ function mouseDragged() {
49
+ if (!drawingBoundary && !boundaryDrawn) {
50
+ boundaries = [];
51
+ drawingBoundary = true;
52
+ }
53
+ if (drawingBoundary) {
54
+ boundaries.push({ x: mouseX, y: mouseY });
55
+ }
56
+ }
57
+
58
+ function mouseReleased() {
59
+ drawingBoundary = false;
60
+ boundaryDrawn = true;
61
+ }
62
+
63
+ function mouseClicked() {
64
+ if (boundaryDrawn) {
65
+ balls.push(new Ball());
66
+ }
67
+ }
68
+
69
+ class Ball {
70
+ constructor() {
71
+ this.x = mouseX;
72
+ this.y = mouseY;
73
+ this.vx = random(-2, 2);
74
+ this.vy = random(-2, 2);
75
+ this.radius = 2;
76
+ this.color = color(random(100, 255), random(100, 255), random(100, 255));
77
+ }
78
+
79
+ move() {
80
+ this.x += this.vx;
81
+ this.y += this.vy;
82
+ }
83
+
84
+ checkBoundaryCollision() {
85
+ let isOutside = !this.isPointInPolygon(boundaries, this.x, this.y);
86
+
87
+ if (isOutside) {
88
+ let closestEdge = this.findClosestEdge(boundaries);
89
+ let edgeNormal = p5.Vector.fromAngle(closestEdge.angle + HALF_PI);
90
+ let reflectedVelocity = this.reflectVector(createVector(this.vx, this.vy), edgeNormal);
91
+ this.vx = reflectedVelocity.x;
92
+ this.vy = reflectedVelocity.y;
93
+
94
+ // Move the ball back inside the boundary
95
+ this.x = constrain(this.x, closestEdge.x1, closestEdge.x2);
96
+ this.y = constrain(this.y, closestEdge.y1, closestEdge.y2);
97
+ }
98
+ }
99
+
100
+ // findClosestEdge(polygon) {
101
+ // // ... (keep the existing implementation)
102
+ // }
103
+
104
+ // distanceToLine(edge) {
105
+ // // ... (keep the existing implementation)
106
+ // }
107
+
108
+ // reflectVector(vector, normal) {
109
+ // // ... (keep the existing implementation)
110
+ // }
111
+
112
+ // isPointInPolygon(polygon, px, py) {
113
+ // // ... (keep the existing implementation)
114
+ // }
115
+
116
+ findClosestEdge(polygon) {
117
+ let closestEdge = null;
118
+ let closestDistance = Infinity;
119
+
120
+ for (let i = 0; i < polygon.length; i++) {
121
+ let j = (i + 1) % polygon.length;
122
+ let x1 = polygon[i].x;
123
+ let y1 = polygon[i].y;
124
+ let x2 = polygon[j].x;
125
+ let y2 = polygon[j].y;
126
+
127
+ let edge = { x1, y1, x2, y2 };
128
+ let distance = this.distanceToLine(edge);
129
+
130
+ if (distance < closestDistance) {
131
+ closestDistance = distance;
132
+ closestEdge = edge;
133
+ }
134
+ }
135
+
136
+ let dx = closestEdge.x2 - closestEdge.x1;
137
+ let dy = closestEdge.y2 - closestEdge.y1;
138
+ closestEdge.angle = atan2(dy, dx);
139
+
140
+ return closestEdge;
141
+ }
142
+
143
+ distanceToLine(edge) {
144
+ let x1 = edge.x1;
145
+ let y1 = edge.y1;
146
+ let x2 = edge.x2;
147
+ let y2 = edge.y2;
148
+
149
+ let dx = x2 - x1;
150
+ let dy = y2 - y1;
151
+ let a = dy;
152
+ let b = -dx;
153
+ let c = dx * y1 - dy * x1;
154
+
155
+ let dist = Math.abs(a * this.x + b * this.y + c) / Math.sqrt(a * a + b * b);
156
+ return dist;
157
+ }
158
+
159
+ reflectVector(vector, normal) {
160
+ let dotProduct = vector.x * normal.x + vector.y * normal.y;
161
+ let reflectedVector = p5.Vector.sub(vector, p5.Vector.mult(normal, 2 * dotProduct));
162
+ return reflectedVector;
163
+ }
164
+
165
+ isPointInPolygon(polygon, px, py) {
166
+ const epsilon = 0.01; // Adjust this value as needed
167
+ const radius = this.radius;
168
+
169
+ let isInside = false;
170
+ let j = polygon.length - 1;
171
+
172
+ for (let i = 0; i < polygon.length; i++) {
173
+ let x1 = polygon[i].x;
174
+ let y1 = polygon[i].y;
175
+ let x2 = polygon[j].x;
176
+ let y2 = polygon[j].y;
177
+
178
+ if ((y1 > py + radius + epsilon) !== (y2 > py + radius + epsilon) &&
179
+ px + radius + epsilon < ((x2 - x1) * (py + radius + epsilon - y1)) / (y2 - y1) + x1) {
180
+ isInside = !isInside;
181
+ }
182
+
183
+ j = i;
184
+ }
185
+
186
+ return isInside;
187
+ }
188
+
189
+
190
+ display() {
191
+ fill(this.color);
192
+ noStroke();
193
+ ellipse(this.x, this.y, this.radius * 2, this.radius * 2);
194
+ }
195
+ }
196
+
197
+ function calculateEntropy() {
198
+ const gridSize = 10;
199
+ const grid = {};
200
+ const totalBalls = balls.length;
201
+
202
+ for (let ball of balls) {
203
+ const gridX = Math.floor(ball.x / gridSize);
204
+ const gridY = Math.floor(ball.y / gridSize);
205
+ const key = `${gridX},${gridY}`;
206
+ grid[key] = (grid[key] || 0) + 1;
207
+ }
208
+
209
+ let entropy = 0;
210
+ for (let count of Object.values(grid)) {
211
+ const probability = count / totalBalls;
212
+ entropy -= probability * Math.log2(probability);
213
+ }
214
+
215
+ return entropy;
216
+ }
217
+
218
+ function displayEntropyGraph() {
219
+ const graphWidth = 200;
220
+ const graphHeight = 100;
221
+ const x = width - graphWidth - 10;
222
+ const y = height - graphHeight - 10;
223
+
224
+ fill(0, 150);
225
+ rect(x, y, graphWidth, graphHeight);
226
+
227
+ stroke(255);
228
+ noFill();
229
+ beginShape();
230
+ for (let i = 0; i < entropyGraph.length; i++) {
231
+ const px = map(i, 0, entropyGraph.length - 1, x, x + graphWidth);
232
+ const py = map(entropyGraph[i], 0, 5, y + graphHeight, y);
233
+ vertex(px, py);
234
+ }
235
+ endShape();
236
+
237
+ fill(255);
238
+ noStroke();
239
+ textAlign(RIGHT);
240
+ text(`Entropy: ${entropyGraph[entropyGraph.length - 1].toFixed(2)}`, x + graphWidth, y - 5);
241
+ }
242
+
243
+ function displayInstructions() {
244
+ fill(255);
245
+ noStroke();
246
+ textAlign(LEFT);
247
+ textSize(14);
248
+ text("1. Draw a boundary by dragging the mouse", 10, 20);
249
+ text("2. Click inside the boundary to add balls", 10, 40);
250
+ text("3. Observe the entropy graph in the bottom right", 10, 60);
251
+ }
252
+
253
+ function windowResized() {
254
+ w = windowWidth;
255
+ h = windowHeight;
256
+ resizeCanvas(w, h);
257
+ }