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