update.c (5005B)
1 2 #include "ln.h" 3 #include "grid.h" 4 #include <math.h> 5 #include <assert.h> 6 #include <stdio.h> 7 8 struct node *hit_node(struct ln *ln) { 9 for (u32 i = 0; i < ln->node_count; ++i) 10 { 11 struct node *n = &ln->nodes[i]; 12 if (!n->visible) 13 continue; 14 15 const double dx = fabs(n->x - ln->mx); 16 const double dy = fabs(n->y - ln->my); 17 18 const double d = sqrt(dx*dx + dy*dy); 19 20 /* printf("%s's dx %f dy %f d %f\n", n->alias, dx, dy, d); */ 21 22 if (d <= n->size) 23 return n; 24 } 25 26 return NULL; 27 } 28 29 30 void repel_nodes(struct node *n1, struct node *n2, double dt) { 31 double dx = n2->x - n1->x; 32 double dy = n2->y - n1->y; 33 34 double d = sqrt(dx*dx + dy*dy); 35 36 static const double mindist = 200.0; 37 if (d < mindist) { 38 39 // normalized vector between two nodes 40 double nx = dx / d; 41 double ny = dy / d; 42 43 // get the distance past the minimum distance along 44 // the vector between the two nodes 45 double nnx = (d - mindist) * nx; 46 double nny = (d - mindist) * ny; 47 48 if (isnan(nnx) || isnan(nny)) 49 return; 50 51 // normalize by frame time 52 double mx = nnx * dt; 53 double my = nny * dt; 54 55 // correct for the distance by accelerating the node away 56 // from the other node 57 n1->vx += mx; 58 n1->vy += my; 59 60 // do the same in the opposite direction for the other node 61 n2->vx -= mx; 62 n2->vy -= my; 63 } 64 else { 65 const double scale = 1.0; 66 67 n1->vx += dx * scale * dt; 68 n1->vy += dy * scale * dt; 69 70 n2->vx += -dx * scale * dt; 71 n2->vy += -dy * scale * dt; 72 } 73 } 74 75 76 static void force_graph(struct ln *ln, double dt) { 77 u32 i; 78 79 // channel constraints 80 for (i = 0; i < ln->channel_count; ++i) { 81 struct channel *channel = &ln->channels[i]; 82 83 struct node *n1 = channel->nodes[0]; 84 struct node *n2 = channel->nodes[1]; 85 86 if (!n1->visible || !n2->visible) 87 continue; 88 89 repel_nodes(n1, n2, dt); 90 } 91 } 92 93 94 static void repel_nearby(struct node *node, double dt) 95 { 96 struct node *n = NULL; 97 struct cell *cell = node->cell; 98 99 // might happen the first iteration? 100 if (cell == NULL) 101 return; 102 103 // we're the only one in this cell, there's nothing to repel 104 if (cell->node_count == 1) 105 return; 106 107 for (int i = 0; i < cell->node_count; ++i) { 108 n = cell->nodes[i]; 109 110 // dont repel against ourselves 111 if (n == node) 112 continue; 113 114 assert(n); 115 assert(node); 116 repel_nodes(n, node, dt); 117 } 118 } 119 120 121 static void physics(struct ln *ln, double dt) 122 { 123 static const double friction_coeff = 0.03; 124 static const double friction = 1.0 - friction_coeff; 125 126 // physics 127 for (u32 i = 0; i < ln->node_count; i++) { 128 struct node *node = &ln->nodes[i]; 129 130 if (!node->visible) 131 continue; 132 133 /* repel_nearby(node, dt); */ 134 135 // semi-implicit euler 136 node->ax *= friction; 137 node->ay *= friction; 138 139 // update node position 140 node->vx += node->ax * dt; 141 node->vy += node->ay * dt; 142 143 // forces (testing) 144 node->vx *= friction; 145 node->vy *= friction; 146 147 node->x += node->vx * dt; 148 node->y += node->vy * dt; 149 } 150 } 151 152 153 static void print_channel_info(struct channel *chan) 154 { 155 printf("%u:%u:%hu %s %s -> %s %s (%f bits)\n", 156 chan->short_channel_id.blocknum, 157 chan->short_channel_id.txnum, 158 chan->short_channel_id.outnum, 159 chan->nodes[0]->id, 160 chan->nodes[0]->alias, 161 chan->nodes[1]->id, 162 chan->nodes[1]->alias, 163 chan->satoshis / 100.0 164 ); 165 } 166 167 168 static void handle_click(struct ln *ln) 169 { 170 // click detection 171 struct channel *chan = NULL; 172 struct node *hit = hit_node(ln); 173 174 ln->drag_target = hit; 175 ln->last_drag_target = hit; 176 177 if (!hit) 178 return; 179 180 // print some info about channels 181 printf("\nchannels\n--------\n"); 182 183 for (u32 i = 0; i < ln->channel_count; i++) { 184 chan = &ln->channels[i]; 185 chan->nodes[0]->adj_drag_target = 0; 186 chan->nodes[1]->adj_drag_target = 0; 187 } 188 189 for (u32 i = 0; i < ln->channel_count; i++) { 190 chan = &ln->channels[i]; 191 192 if (!chan->visible) 193 continue; 194 195 if (chan->nodes[0]->visible && chan->nodes[0] == ln->drag_target) 196 chan->nodes[1]->adj_drag_target |= 1; 197 else 198 chan->nodes[0]->adj_drag_target ^= 0; 199 200 if (chan->nodes[1]->visible && chan->nodes[1] == ln->drag_target) 201 chan->nodes[0]->adj_drag_target = 1; 202 else 203 chan->nodes[1]->adj_drag_target ^= 0; 204 205 if (nodeid_eq(chan->nodes[0]->id, hit->id) || 206 nodeid_eq(chan->nodes[1]->id, hit->id)) { 207 if (!chan->nodes[0]->visible || !chan->nodes[1]->visible) 208 continue; 209 print_channel_info(chan); 210 } 211 } 212 } 213 214 215 static void handle_rightclick(struct ln *ln) 216 { 217 struct node *hit = hit_node(ln); 218 if (hit != NULL) 219 filter_network(NULL, hit, ln); 220 } 221 222 223 // force graph update logic 224 void update(struct ln *ln, double dt) 225 { 226 if (ln->clicked) 227 handle_click(ln); 228 229 if (ln->right_clicked) 230 handle_rightclick(ln); 231 232 // stop dragging 233 if (!ln->mdown && ln->drag_target) { 234 ln->last_drag_target = ln->drag_target; 235 ln->drag_target = NULL; 236 } 237 238 // drag 239 if (ln->mdown && ln->drag_target) { 240 ln->drag_target->x = ln->mx; 241 ln->drag_target->y = ln->my; 242 ln->drag_target->vx = 0; 243 ln->drag_target->vy = 0; 244 } 245 246 /* force_graph(ln, dt); */ 247 248 /* physics(ln, dt); */ 249 250 /* update_grid_move_nodes(ln); */ 251 }