12 double speedOff = 0.001;
14 double speedBonus = 0.001;
16 double thickFactor = 0.01;
17 double dispThresh = 0.001;
21 typedef struct Pos Pos;
22 typedef struct List List;
23 typedef struct Node Node;
24 typedef struct Pack Pack;
39 int die, ref, targref;
54 double *dist, *path, *speed, *speedn;
66 sysfatal("malloc: %r");
67 setmalloctag(v, getcallerpc(&size));
75 screen->r.min.x + (screen->r.max.x - screen->r.min.x) *
76 ((p->x - minx) / (maxx - minx)),
77 screen->r.min.y + (screen->r.max.y - screen->r.min.y) *
78 ((p->y - minx) / (maxx - minx))};
85 minx + (maxx - minx) *
86 ((double)(p.x - screen->r.min.x) / (screen->r.max.x - screen->r.min.x)),
87 miny + (maxy - miny) *
88 ((double)(p.y - screen->r.min.y) / (screen->r.max.y - screen->r.min.y))};
92 rect(Pos *p, int size, Image *col)
98 r = insetrect(Rpt(poi, poi), -size);
99 draw(screen, r, col, nil, ZP);
103 add(List *head, List *obj)
105 obj->prev = head->prev;
107 ((List*)head->prev)->next = obj;
115 ((List*)obj->prev)->next = obj->next;
116 ((List*)obj->next)->prev = obj->prev;
126 dist = realloc(dist, sizeof(*dist) * nnode * nnode);
127 path = realloc(path, sizeof(*path) * nnode * nnode);
128 nextn = realloc(nextn, sizeof(*nextn) * nnode * nnode);
129 for(i = 0; i < nnode; i++)
130 for(j = 0; j < nnode; j++){
131 if(nodes[j].die == 2){
132 dist[i * nnode + j] = Inf(1);
135 dx = nodes[i].x - nodes[j].x;
136 dy = nodes[i].y - nodes[j].y;
137 dist[i * nnode + j] = sqrt(dx * dx + dy * dy);
144 int c[3] = {0, 255, 0};
157 return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | 0xFF;
167 for(i = 0; i < ncolours; i++)
168 col[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, randomcol());
169 grey = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x888888FF);
171 nodes = emallocz(sizeof(*nodes) * nnode);
172 for(i = 0; i < nnode; i++){
173 nodes[i].x = frand() * (maxx - minx) + minx;
174 nodes[i].y = frand() * (maxy - miny) + miny;
177 speed = emallocz(sizeof(*speed) * nnode * nnode);
178 speedn = emallocz(sizeof(*speedn) * nnode * nnode);
182 resizespeed(int diff)
186 nnode1 = nnode - diff;
187 speedn = realloc(speedn, sizeof(*speedn) * nnode * nnode);
188 for(i = 0; i < nnode; i++)
189 for(j = 0; j < nnode; j++)
190 if(i < nnode1 && j < nnode1)
191 speedn[i * nnode + j] = speed[i * nnode1 + j];
193 speedn[i * nnode + j] = 0;
194 speed = realloc(speed, sizeof(*speedn) * nnode * nnode);
195 memcpy(speed, speedn, sizeof(*speedn) * nnode * nnode);
203 p = emallocz(sizeof(*p));
205 p->q = rand() % nnode;
206 p->targ = rand() % nnode;
207 }while(p->q == p->targ || nodes[p->q].die || nodes[p->targ].die);
209 nodes[p->targ].targref++;
211 p->Pos = nodes[p->q].Pos;
212 p->c = col[rand() % ncolours];
217 getpath(int i, int j)
222 while((k = nextn[i + j]) != j)
233 for(i = 0; i < nnode; i++)
234 for(j = 0; j < nnode; j++){
235 path[i * nnode + j] = dist[i * nnode + j] / (speedOff + speed[i * nnode + j]);
236 nextn[i * nnode + j] = j;
238 for(k = 0; k < nnode; k++)
239 for(i = 0; i < nnode; i++)
240 for(j = 0; j < nnode; j++){
241 a = path[i * nnode + k] + path[k * nnode + j];
242 b = path + i * nnode + j;
245 nextn[i * nnode + j] = k;
256 for(i = 0; i < nnode; i++){
257 if(nodes[i].Pos.x == p.x && nodes[i].Pos.y == p.y)
259 if(nodes[i].die == 3 && j == nnode)
263 nodes = realloc(nodes, sizeof(*nodes) * ++nnode);
269 nodes[j].targref = 0;
275 advancepacket(Pack *p)
282 p->q = getpath(p->q, p->targ);
285 p->v = (speedOff + speed[p->p * nnode + p->q]) / dist[p->p * nnode + p->q];
289 speedn[p->p * nnode + p->q] += speedBonus;
290 speedn[p->q * nnode + p->p] += speedBonus;
296 nodes[p->q].targref--;
300 p->Pos = nodes[p->q].Pos;
306 p->x = np->x * (1 - p->λ) + nq->x * p->λ;
307 p->y = np->y * (1 - p->λ) + nq->y * p->λ;
317 semrelease(&sync, 1);
329 for(p = plist.next; p != &plist; )
330 p = advancepacket(p);
331 for(i = 0; i < nnode; i++){
332 if(nodes[i].die == 1 && nodes[i].targref == 0){
336 if(nodes[i].die == 2 && nodes[i].ref == 0){
338 for(j = 0; j < nnode; j++)
339 speedn[i * nnode + j] = speedn[i + j * nnode] = 0;
342 for(i = 0; i < nnode * nnode; i++)
343 speed[i] = speedn[i] *= decay;
346 regen = rand() % regenRate;
361 if(nbrecv(mctl->resizec, &i) == 1)
362 if(getwindow(display, Refnone) < 0)
363 sysfatal("getwindow: %r");
366 if(lastbut & 4 && !(m.buttons & 4))
367 for(i = 0; i < nnode; i++){
368 poi = convert(&nodes[i]);
371 d = sqrt(dx * dx + dy * dy);
377 if(lastbut & 1 && !(m.buttons & 1))
378 createnode(deconvert(m.xy));
384 fprint(2, "USAGE: %s options\n", argv0);
385 fprint(2, " -n number of nodes [40]\n");
386 fprint(2, " -o speed of unused connections [0.001]\n");
387 fprint(2, " -d decay rate [0.99]\n");
388 fprint(2, " -b speed bonus per packet [0.001]\n");
389 fprint(2, " -r packet generation period [5]\n");
390 fprint(2, " -t line thickness factor [0.01]\n");
391 fprint(2, " -T display threshold [0.001]\n");
396 threadmain(int argc, char **argv)
403 case 'n': nnode = atoi(EARGF(usage())); break;
404 case 'o': speedOff = atof(EARGF(usage())); break;
405 case 'd': decay = atof(EARGF(usage())); break;
406 case 'b': speedBonus = atof(EARGF(usage())); break;
407 case 'r': regenRate = atoi(EARGF(usage())); break;
408 case 't': thickFactor = atof(EARGF(usage())); break;
409 case 'T': dispThresh = atof(EARGF(usage())); break;
413 initdraw(nil, nil, nil);
414 mctl = initmouse(nil, screen);
418 proccreate(timing, nil, mainstacksize);
421 draw(screen, screen->r, display->white, nil, ZP);
422 for(i = 0; i < nnode; i++)
423 for(j = 0; j < i; j++)
424 if(speed[i * nnode + j] >= dispThresh)
425 line(screen, convert(nodes + i), convert(nodes + j), 0, 0, speed[i * nnode + j] / thickFactor, display->black, ZP);
426 for(n = nodes; n < nodes + nnode; n++)
427 if(!n->die || n->ref)
428 rect(n, 3, n->die ? grey : display->black);
429 for(p = plist.next; p != &plist; p = p->next)
431 flushimage(display, 1);
433 semacquire(&sync, 1);