1 #include <gtk/gtk.h>
2 #include "ggobi.h"
3 #include "externs.h"
4 #include "GGobiAPI.h"
5
6 #include <stdio.h>
7
8 #include "plugin.h"
9 #include "graphact.h"
10
11 /*
12 My earlier strategy of using 'visibleEdges' fails because it
13 doesn't take into account the case where there's a single in
14 edge and a single out edge, but the endpoint is the same. In
15 other words, it looks like two edges in the code but one edge
16 on the screen.
17 */
18
19 #if 0
20 void
21 count_visible_edges (PluginInstance *inst)
22 {
23 graphactd *ga = (graphactd *) inst->data;
24 GGobiData *d = ga->d;
25 GGobiData *e = ga->e;
26 gint m, i, k, a, b, edgeid;
27 endpointsd *endpoints;
28
29 if (e == NULL) {
30 quick_message ("You haven't designated a set of edges.", false);
31 /**/return;
32 }
33 endpoints = resolveEdgePoints(e, d);
34 if (endpoints == NULL) {
35 g_printerr ("failed to resolve edges. d: %s, e: %s\n", d->name, e->name);
36 /**/return;
37 }
38
39 if (ga->nInEdgesVisible.nels != ga->nnodes) {
40 vectori_realloc (&ga->nInEdgesVisible, ga->nnodes);
41 vectori_realloc (&ga->nOutEdgesVisible, ga->nnodes);
42 }
43 vectori_zero (&ga->nInEdgesVisible);
44 vectori_zero (&ga->nOutEdgesVisible);
45
46 /*
47 * I don't really need to distinguish between inEdges and outEdges
48 * for anything I'm going to do for a while, but why not?
49 */
50 /*-- --*/
51 for (m=0; m<d->nrows_in_plot; m++) {
52 i = d->rows_in_plot.els[m];
53 for (k=0; k<ga->inEdges[i].nels; k++) {
54 edgeid = ga->inEdges[i].els[k];
55 a = endpoints[edgeid].a;
56 /*-- no need for b, because i = b --*/
57 if (e->sampled.els[edgeid] && !e->hidden_now.els[edgeid] &&
58 !d->hidden_now.els[a] && !d->hidden_now.els[i])
59 {
60 ga->nInEdgesVisible.els[i]++;
61 }
62 }
63 for (k=0; k<ga->outEdges[i].nels; k++) {
64 edgeid = ga->outEdges[i].els[k];
65 b = endpoints[edgeid].b;
66 /*-- no need for a, because i = a --*/
67 if (e->sampled.els[edgeid] && !e->hidden_now.els[edgeid] &&
68 !d->hidden_now.els[b] && !d->hidden_now.els[i])
69 {
70 ga->nOutEdgesVisible.els[i]++;
71 }
72 }
73 }
74
75 /*
76 for (i=0; i<ga->nnodes; i++)
77 g_printerr ("%d %d\n",
78 ga->nInEdgesVisible.els[i],
79 ga->nOutEdgesVisible.els[i]);
80 */
81 }
82 #endif
83
84 void
hide_inEdge(gint i,PluginInstance * inst)85 hide_inEdge (gint i, PluginInstance *inst)
86 {
87 gint k, edgeid, a;
88 graphactd *ga = graphactFromInst (inst);
89 GGobiData *d = ga->d;
90 GGobiData *e = ga->e;
91 ggobid *gg = inst->gg;
92 gint nd = g_slist_length (gg->d);
93 endpointsd *endpoints;
94
95 if (e == NULL) {
96 quick_message ("You haven't designated a set of edges.", false);
97 /**/return;
98 }
99 endpoints = resolveEdgePoints(e, d);
100 if (endpoints == NULL) {
101 g_printerr ("failed to resolve edges. d: %s, e: %s\n", d->name, e->name);
102 /**/return;
103 }
104
105 for (k=0; k<ga->inEdges[i].nels; k++) {
106 edgeid = ga->inEdges[i].els[k];
107 a = endpoints[edgeid].a;
108 /*-- no need for b, because i = b --*/
109
110 e->hidden_now.els[edgeid] = e->hidden.els[edgeid] = true;
111 d->hidden_now.els[i] = d->hidden.els[i] = true;
112
113 if (!gg->linkby_cv && nd > 1) {
114 symbol_link_by_id (true, i, d, gg);
115 symbol_link_by_id (true, edgeid, e, gg);
116 }
117 /*
118 ga->nInEdgesVisible.els[i] = 0;
119 ga->nOutEdgesVisible.els[a]--;
120 */
121 }
122 }
123 void
hide_outEdge(gint i,PluginInstance * inst)124 hide_outEdge (gint i, PluginInstance *inst)
125 {
126 gint k, edgeid, b;
127 graphactd *ga = graphactFromInst (inst);
128 GGobiData *d = ga->d;
129 GGobiData *e = ga->e;
130 ggobid *gg = inst->gg;
131 gint nd = g_slist_length (gg->d);
132 endpointsd *endpoints;
133
134 if (e == NULL) {
135 quick_message ("You haven't designated a set of edges.", false);
136 /**/return;
137 }
138 endpoints = resolveEdgePoints(e, d);
139 if (endpoints == NULL) {
140 g_printerr ("failed to resolve edges. d: %s, e: %s\n", d->name, e->name);
141 /**/return;
142 }
143
144 for (k=0; k<ga->outEdges[i].nels; k++) {
145 edgeid = ga->outEdges[i].els[k];
146 b = endpoints[edgeid].b;
147
148 e->hidden_now.els[edgeid] = e->hidden.els[edgeid] = true;
149 d->hidden_now.els[i] = d->hidden.els[i] = true;
150
151 if (!gg->linkby_cv && nd > 1)
152 symbol_link_by_id (true, i, d, gg);
153 /*
154 ga->nOutEdgesVisible.els[i] = 0;
155 ga->nInEdgesVisible.els[b]--;
156 */
157 }
158 }
159
160 void
ga_leaf_hide_cb(GtkWidget * btn,PluginInstance * inst)161 ga_leaf_hide_cb (GtkWidget *btn, PluginInstance *inst)
162 {
163 ggobid *gg = inst->gg;
164 graphactd *ga = graphactFromInst (inst);
165 GGobiData *d = ga->d;
166 GGobiData *e = ga->e;
167 gboolean changing;
168 gboolean need_to_link_p = false;
169 gint i, m;
170 endpointsd *endpoints;
171
172 if (e == NULL) {
173 quick_message ("You haven't designated a set of edges.", false);
174 /**/return;
175 }
176 endpoints = resolveEdgePoints(e, d);
177 if (endpoints == NULL) {
178 g_printerr ("failed to resolve edges. d: %s, e: %s\n", d->name, e->name);
179 /**/return;
180 }
181
182 /*
183 count_visible_edges (inst);
184
185 while (changing) {
186 changing = false;
187 nvisible = 0;
188 for (m=0; m<d->nrows_in_plot; m++) {
189 i = d->rows_in_plot.els[m];
190 if (ga->nInEdgesVisible.els[i] + ga->nOutEdgesVisible.els[i] == 1) {
191 *-- leaf node; hide the node and the edge; decrease a counter --*
192 if (ga->nInEdgesVisible.els[i] == 1) {
193 hide_inEdge (i, inst);
194 } else {
195 hide_outEdge (i, inst);
196 }
197 changing = true;
198 need_to_link_p = true;
199 } else {
200 if (nvisible < 1)
201 nvisible = MAX (nvisible,
202 (ga->nInEdgesVisible.els[i] + ga->nOutEdgesVisible.els[i]));
203 }
204 }
205 if (nvisible < 2) break;
206 }
207 */
208
209 changing = true;
210 while (changing) {
211 gint ida, a, idb, b;
212 changing = false;
213 for (m=0; m<d->nrows_in_plot; m++) {
214 i = d->rows_in_plot.els[m];
215 if (!d->hidden_now.els[i]) {
216 if (ga->inEdges[i].nels == 0 && ga->outEdges[i].nels == 0) {
217 ;
218 } else if (ga->inEdges[i].nels <= 1 && ga->outEdges[i].nels <= 1) {
219 /* is this the same edge in the other direction? */
220 if (ga->inEdges[i].nels == 1 && ga->outEdges[i].nels == 1) {
221 ida = ga->inEdges[i].els[0];
222 a = endpoints[ida].a;
223 idb = ga->outEdges[i].els[0];
224 b = endpoints[idb].b;
225 if (a == b) {
226 if (e->sampled.els[ida] && !e->hidden_now.els[ida] &&
227 !d->hidden_now.els[a])
228 {
229 hide_inEdge (i, inst);
230 changing = true;
231 }
232 if (e->sampled.els[idb] && !e->hidden_now.els[idb] &&
233 !d->hidden_now.els[b])
234 {
235 hide_outEdge (i, inst);
236 changing = true;
237 }
238 }
239 /* or a singleton in one direction or the other? */
240 } else if (ga->inEdges[i].nels == 1) {
241 hide_inEdge (i, inst);
242 changing = true;
243 } else if (ga->outEdges[i].nels == 1) {
244 hide_outEdge (i, inst);
245 changing = true;
246 }
247 }
248 if (changing) need_to_link_p = true;
249 }
250 }
251 }
252
253 if (need_to_link_p) {
254 }
255
256 displays_tailpipe (FULL, gg);
257 }
258
259 void
ga_orphans_hide_cb(GtkWidget * btn,PluginInstance * inst)260 ga_orphans_hide_cb (GtkWidget *btn, PluginInstance *inst)
261 {
262 ggobid *gg = inst->gg;
263 graphactd *ga = graphactFromInst (inst);
264 GGobiData *d = gg->current_display->d;
265 GGobiData *e = gg->current_display->e;
266 gint m, i, k, edgeid, a, b;
267 gboolean included;
268 endpointsd *endpoints;
269 gint nd = g_slist_length (gg->d);
270
271 if (e == NULL) {
272 quick_message ("You haven't designated a set of edges.", false);
273 /**/return;
274 }
275 endpoints = resolveEdgePoints(e, d);
276 if (endpoints == NULL) {
277 g_printerr ("failed to resolve edges. d: %s, e: %s\n", d->name, e->name);
278 /**/return;
279 }
280
281 for (m=0; m<d->nrows_in_plot; m++) {
282 i = d->rows_in_plot.els[m];
283 included = false;
284 for (k=0; k<ga->inEdges[i].nels; k++) {
285 edgeid = ga->inEdges[i].els[k];
286 a = endpoints[edgeid].a;
287 /*-- no need for b, because i = b --*/
288 if (e->sampled.els[edgeid] && !e->excluded.els[edgeid] &&
289 !e->hidden.els[edgeid] &&
290 !d->excluded.els[a] && !d->hidden.els[a] && !d->excluded.els[i])
291 {
292 included = true;
293 break;
294 }
295 }
296 if (!included) {
297 for (k=0; k<ga->outEdges[i].nels; k++) {
298 edgeid = ga->outEdges[i].els[k];
299 b = endpoints[edgeid].b;
300 /*-- no need for a, because i = a --*/
301 if (e->sampled.els[edgeid] && !e->excluded.els[edgeid] &&
302 !e->hidden.els[edgeid] &&
303 !d->excluded.els[b] && !d->hidden.els[b] && !d->excluded.els[i])
304 {
305 included = true;
306 break;
307 }
308 }
309 }
310 if (!included) {
311 d->hidden_now.els[i] = d->hidden.els[i] = true;
312 if (!gg->linkby_cv && nd > 1)
313 symbol_link_by_id (true, i, d, gg);
314 }
315 }
316 displays_tailpipe (FULL, gg);
317 }
318
319 void
ga_nodes_show_cb(GtkWidget * btn,PluginInstance * inst)320 ga_nodes_show_cb (GtkWidget *btn, PluginInstance *inst)
321 {
322 graphactd *ga = graphactFromInst (inst);
323 GGobiData *d = ga->d;
324 GGobiData *e = ga->e;
325 gint i;
326 ggobid *gg = inst->gg;
327 gint nd = g_slist_length (gg->d);
328
329 for (i=0; i<d->nrows; i++) {
330 d->hidden_now.els[i] = d->hidden.els[i] = d->hidden_prev.els[i] = false;
331 if (!gg->linkby_cv && nd > 1)
332 symbol_link_by_id (true, i, d, gg);
333 }
334 for (i=0; i<e->nrows; i++) {
335 e->hidden_now.els[i] = e->hidden.els[i] = e->hidden_prev.els[i] = false;
336 if (!gg->linkby_cv && nd > 1)
337 symbol_link_by_id (true, i, e, gg);
338 }
339
340 displays_tailpipe (FULL, gg);
341 }
342
343 /*---------------------------------------------------------------------*/
344 /* Neighbors routines */
345 /*---------------------------------------------------------------------*/
346
neighborhood_depth_cb(GtkWidget * w,gpointer cbd)347 void neighborhood_depth_cb (GtkWidget *w, gpointer cbd)
348 {
349 PluginInstance *inst = (PluginInstance *) g_object_get_data(G_OBJECT (w),
350 "PluginInst");
351 graphactd *ga = (graphactd *) inst->data;
352 ga->neighborhood_depth = GPOINTER_TO_INT (cbd) + 1;
353 }
354
ga_all_hide(GGobiData * d,GGobiData * e,PluginInstance * inst)355 void ga_all_hide (GGobiData *d, GGobiData *e, PluginInstance *inst)
356 {
357 gint i;
358
359 for (i=0; i<d->nrows; i++)
360 d->hidden_now.els[i] = d->hidden.els[i] = true;
361 for (i=0; i<e->nrows; i++)
362 e->hidden_now.els[i] = e->hidden.els[i] = true;
363 }
364
365 void
show_neighbors(gint nodeid,gint edgeid,gint depth,GGobiData * d,GGobiData * e,PluginInstance * inst)366 show_neighbors (gint nodeid, gint edgeid, gint depth,
367 GGobiData *d, GGobiData *e, PluginInstance *inst)
368 {
369 gint a, b, neighbor, k, eid;
370 graphactd *ga = (graphactd *) inst->data;
371 endpointsd *endpoints;
372
373 if (e == NULL) {
374 quick_message ("You haven't designated a set of edges.", false);
375 /**/return;
376 }
377 endpoints = resolveEdgePoints(e, d);
378 if (endpoints == NULL) {
379 g_printerr ("failed to resolve edges. d: %s, e: %s\n", d->name, e->name);
380 /**/return;
381 }
382
383 edge_endpoints_get (edgeid, &a, &b, d, endpoints, e);
384
385 e->hidden_now.els[edgeid] = e->hidden.els[edgeid] = false;
386 d->hidden_now.els[a] = d->hidden.els[a] = false;
387 d->hidden_now.els[b] = d->hidden.els[b] = false;
388
389
390 if (depth-1) {
391 neighbor = (nodeid == a) ? b : a;
392 for (k=0; k<ga->inEdges[neighbor].nels; k++) {
393 eid = ga->inEdges[neighbor].els[k];
394 if (eid != edgeid)
395 show_neighbors (neighbor, eid, depth-1, d, e, inst);
396 }
397 for (k=0; k<ga->outEdges[neighbor].nels; k++) {
398 eid = ga->outEdges[neighbor].els[k];
399 if (eid != edgeid)
400 show_neighbors (neighbor, eid, depth-1, d, e, inst);
401 }
402 }
403 }
404
405 /*
406 * Find the neighbors of node 'index' and show them; hide
407 * all others.
408 */
show_neighbors_sticky_cb(ggobid * gg,gint index,gint state,GGobiData * d,void * data)409 void show_neighbors_sticky_cb (ggobid *gg, gint index, gint state,
410 GGobiData *d, void *data)
411 {
412 PluginInstance *inst = (PluginInstance *)data;
413 graphactd *ga = (graphactd *) inst->data;
414 GGobiData *e = ga->e;
415 gint k, edgeid;
416 gint nd = g_slist_length (gg->d);
417 gint i;
418 endpointsd *endpoints;
419 /*GGobiData *d = ga->d;*/
420 enum {GRAPH_VIEW, EDGE_DATA_VIEW} idview = GRAPH_VIEW;
421 displayd *display = gg->current_display;
422
423 if (e == NULL) {
424 quick_message ("You haven't designated a set of edges.", false);
425 /**/return;
426 }
427
428 /*
429 If I'm in the graph (map) view, display->d = ga->d
430 and display->e = ga->e.
431
432 If I'm in the scatterplot of the edge data (variogram cloud),
433 then display->d = ga->e. Don't do anything with this one for
434 now.
435 */
436 if (display->d == ga->d) {
437 idview = GRAPH_VIEW;
438 } else if (display->d == ga->e) {
439 idview = EDGE_DATA_VIEW;
440 }
441 if (idview == EDGE_DATA_VIEW)
442 /**/return;
443
444 endpoints = resolveEdgePoints(e, d);
445 if (endpoints == NULL) {
446 g_printerr ("failed to resolve edges. d: %s, e: %s\n", d->name, e->name);
447 /**/return;
448 }
449
450 if (index == -1)
451 return;
452
453
454 /*
455 * This is now being executed in the same way whether 'index' is
456 * becoming sticky or unsticky.
457 */
458
459 ga_all_hide (d, e, inst);
460
461 for (k=0; k<ga->inEdges[index].nels; k++) {
462 edgeid = ga->inEdges[index].els[k];
463 show_neighbors (index, edgeid, ga->neighborhood_depth, d, e, inst);
464 }
465 for (k=0; k<ga->outEdges[index].nels; k++) {
466 edgeid = ga->outEdges[index].els[k];
467 show_neighbors (index, edgeid, ga->neighborhood_depth, d, e, inst);
468 }
469
470 /*-- <now> do the linking --*/
471 if (!gg->linkby_cv && nd > 1) {
472 for (i=0; i<d->nrows; i++)
473 symbol_link_by_id (true, i, d, gg);
474 }
475 if (!gg->linkby_cv && nd > 2) {
476 for (i=0; i<e->nrows; i++)
477 symbol_link_by_id (true, i, e, gg);
478 }
479
480 displays_tailpipe (FULL, gg);
481 }
482
483 void
show_neighbors_toggle_cb(GtkToggleButton * button,PluginInstance * inst)484 show_neighbors_toggle_cb (GtkToggleButton *button, PluginInstance *inst)
485 {
486 graphactd *ga = (graphactd *) inst->data;
487
488 if (ga->neighbors_find_p) {
489 g_signal_handlers_disconnect_by_func(G_OBJECT(inst->gg),
490 G_CALLBACK (show_neighbors_sticky_cb), inst);
491 ga->neighbors_find_p = false;
492 } else {
493 g_signal_connect (G_OBJECT(inst->gg),
494 "sticky_point_added", G_CALLBACK(show_neighbors_sticky_cb), inst);
495 g_signal_connect (G_OBJECT(inst->gg),
496 "sticky_point_removed", G_CALLBACK(show_neighbors_sticky_cb), inst);
497 ga->neighbors_find_p = true;
498 }
499 }
500
501 /*--------- Tidy -------------*/
502 void
ga_edge_tidy_cb(GtkWidget * w,PluginInstance * inst)503 ga_edge_tidy_cb (GtkWidget *w, PluginInstance *inst)
504 {
505 graphactd *ga = (graphactd *) inst->data;
506 GGobiData *d = ga->d;
507 GGobiData *e = ga->e;
508 endpointsd *endpoints;
509 gint a, b, k;
510
511 /* Loop over edges. If either endpoint is hidden, hide the edge */
512
513 if (e == NULL) {
514 quick_message ("You haven't designated a set of edges.", false);
515 /**/return;
516 }
517 endpoints = resolveEdgePoints(e, d);
518 if (endpoints == NULL) {
519 g_printerr ("failed to resolve edges. d: %s, e: %s\n", d->name, e->name);
520 /**/return;
521 }
522
523 for (k=0; k<e->edge.n; k++) {
524 edge_endpoints_get (k, &a, &b, d, endpoints, e);
525 if (d->hidden_now.els[a] || d->hidden_now.els[b]) {
526 e->hidden_now.els[k] = true;
527 }
528 }
529 displays_tailpipe (FULL, inst->gg);
530 }
531