1 /*****************************************************************************
2   FILE           : $Source: /projects/higgs1/SNNS/CVS/SNNS/xgui/sources/d3_main.c,v $
3   SHORTNAME      : main.c
4   SNNS VERSION   : 4.2
5 
6   PURPOSE        : contains the main routine to draw the net
7   NOTES          :
8 
9   AUTHOR         : Ralf Huebner
10   DATE           : 1.12.1991
11 
12   CHANGED BY     : Niels Mache
13   RCS VERSION    : $Revision: 2.13 $
14   LAST CHANGE    : $Date: 1998/03/13 16:31:48 $
15 
16     Copyright (c) 1990-1995  SNNS Group, IPVR, Univ. Stuttgart, FRG
17     Copyright (c) 1996-1998  SNNS Group, WSI, Univ. Tuebingen, FRG
18 
19 ******************************************************************************/
20 #include <config.h>
21 
22 
23 #include <math.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <ctype.h>
28 
29 #include <X11/Xlib.h>
30 
31 #include "ui.h"
32 
33 #include "glob_typ.h"	/*  Kernel constant and type definitions  */
34 #include "d3_global.h"
35 #include "d3_draw.h"
36 #include "d3_anageo.h"
37 #include "d3_graph.h"
38 #include "d3_fonts.h"
39 #include "d3_point.h"
40 
41 #include "kr_ui.h"	/*  Kernel interface functions	*/
42 
43 #include "d3_zgraph.h"
44 #include "ui_setup.h"
45 #include "ui_color.h"
46 
47 #include "d3_main.ph"
48 
49 
50 /*****************************************************************************
51   FUNCTION : d3_getColorValue
52 
53   PURPOSE  : get the value of an unit for a selected mode
54   RETURNS  : -1.0 <= value <= 1.0
55   NOTES    :
56 
57   UPDATE   :
58 ******************************************************************************/
d3_getColorValue(int mode,int unitNo,float * value)59 void d3_getColorValue (int mode, int unitNo, float *value)
60 
61 {
62     switch (mode) {
63          case activation_on :  *value = krui_getUnitActivation (unitNo);
64                                break;
65          case init_act_on   :  *value = krui_getUnitInitialActivation (unitNo);
66                                break;
67          case output_on     :  *value = krui_getUnitOutput (unitNo);
68                                break;
69          case bias_on       :  *value = krui_getUnitBias (unitNo);
70                                break;
71          default            :  *value = krui_getUnitActivation (unitNo);
72                                break;
73     }
74     if (*value > 1.0)
75         *value = 1.0;
76     if (*value < -1.0)
77         *value = -1.0;
78 }
79 
80 
81 /*****************************************************************************
82   FUNCTION : get_unit_pos_vector
83 
84   PURPOSE  : calculates the 3d vector form the 2d representation
85   RETURNS  : the vector
86   NOTES    : this is the only interface to get a 3d vector
87 
88   UPDATE   :
89 ******************************************************************************/
get_unit_pos_vector(int unit,vector v)90 static void get_unit_pos_vector (int unit, vector v)
91 
92 {
93     struct PosType unit_pos;
94     int  x, y;
95 
96     krui_getUnitPosition (unit, &unit_pos);
97     krui_xyTransTable( OP_TRANSTABLE_GET, &x, &y, unit_pos.z );
98 
99     v[0]= (unit_pos.x - x) * grid_size;
100     v[1] = (unit_pos.y - y) * grid_size;
101 
102     v[2] = unit_pos.z * grid_size;
103     v[3] = 1.0;
104 }
105 
106 
107 /*****************************************************************************
108   FUNCTION : unit_transformation
109 
110   PURPOSE  : multipies a matrix with an unit cube
111   RETURNS  : the transformed cube
112   NOTES    :
113 
114   UPDATE   :
115 ******************************************************************************/
unit_transformation(cube c,matrix m)116 static void unit_transformation (cube c, matrix m)
117 
118 {
119     int i;
120 
121     for (i=0; i<ANZ_VECS; i++)
122       d3_multMatrixVector (c[i], m, d3_e_cube[i]);
123 }
124 
125 
126 /*****************************************************************************
127   FUNCTION : get_net_extrema
128 
129   PURPOSE  : calculates the dimensions of a net
130   RETURNS  : two vectors containing the minimum and the maximum of the net
131   NOTES    :
132 
133   UPDATE   :
134 ******************************************************************************/
get_net_extrema(vector min,vector max)135 static void get_net_extrema (vector min, vector max)
136 
137 {
138     vector p;
139     int act_unit, i;
140 
141     act_unit = krui_getFirstUnit ();
142     if (act_unit != 0)
143       {
144         get_unit_pos_vector (act_unit, min);
145         get_unit_pos_vector (act_unit, max);
146         act_unit = krui_getNextUnit ();
147         while (act_unit != 0)
148         {
149              get_unit_pos_vector (act_unit, p);
150              for (i=0; i<3; i++)
151                {
152                  if (p[i] < min[i])
153                    min[i] = p[i];
154                  if (p[i] > max[i])
155                    max[i] = p[i];
156  	       }
157              act_unit = krui_getNextUnit ();
158 	  }
159       }
160  }
161 
162 
163 /*****************************************************************************
164   FUNCTION : insert_center_vector
165 
166   PURPOSE  : stores the center of a cube
167   RETURNS  : void
168   NOTES    :
169 
170   UPDATE   :
171 ******************************************************************************/
insert_center_vector(cube c,int unit)172 static void insert_center_vector (cube c, int unit)
173 
174 {
175     struct PositionVector pv;
176 
177     pv.x = c[CENTER_VECTOR][0];
178     pv.y = c[CENTER_VECTOR][1];
179     pv.z = c[CENTER_VECTOR][2];
180     krui_setUnitCenters (unit, d3_currentDisplay, &pv);
181 }
182 
183 
184 /*****************************************************************************
185   FUNCTION : get_size_vector
186 
187   PURPOSE  : get the value of an unit to calculate the size
188   RETURNS  : a vector containing the size
189   NOTES    : only positive values are returned
190 
191   UPDATE   :
192 ******************************************************************************/
get_size_vector(vector v,int unitNo)193 static bool get_size_vector (vector v, int unitNo)
194 
195 {
196      float value;
197 
198      switch (d3_state.unit_mode.size)
199        {
200          case activation_on :  value = krui_getUnitActivation (unitNo);
201                                break;
202          case init_act_on   :  value = krui_getUnitInitialActivation(unitNo);
203                                break;
204          case output_on     :  value = krui_getUnitOutput(unitNo);
205                                break;
206          case bias_on       :  value = krui_getUnitBias(unitNo);
207                                break;
208          case nothing_on    :  value = 1.0;
209                                break;
210          default            :  value = 1.0;
211        }
212      if (value > 1.0)
213        value = 1.0;
214      v[0] = v[1] = v[2] = value;
215      return (value >= 0.1);
216 }
217 
218 
219 /*****************************************************************************
220   FUNCTION : get_label_string
221 
222   PURPOSE  : gets the label for an unit
223   RETURNS  : the string
224   NOTES    :
225 
226   UPDATE   :
227 ******************************************************************************/
get_label_string(int label,int unitNo)228 static char *get_label_string (int label, int unitNo)
229 
230 {
231     char *fmt_string = "%.3f", *str;
232     struct PosType pos;
233 
234     str = malloc (255);
235     switch (label) {
236          case activation_on :  sprintf (str, fmt_string,
237                                         krui_getUnitActivation (unitNo));
238                                break;
239          case init_act_on   :  sprintf (str, fmt_string,
240                                         krui_getUnitInitialActivation (unitNo));
241                                break;
242          case output_on     :  sprintf (str, fmt_string,
243                                         krui_getUnitOutput (unitNo));
244                                break;
245          case bias_on       :  sprintf (str, fmt_string,
246                                         krui_getUnitBias (unitNo));
247                                break;
248          case number_on     :  sprintf (str, "%d", unitNo);
249                                break;
250          case zvalue_on     :  krui_getUnitPosition (unitNo, &pos);
251                                sprintf (str, "%d", pos.z);
252                                break;
253          case name_on       :  sprintf (str, "%s", krui_getUnitName(unitNo));
254                                if (str == NULL)
255                                    sprintf (str, " ");
256                                break;
257          default            :  sprintf (str, "%s", "nothing");
258                                break;
259     }
260     return (str);
261 
262 }
263 
264 
265 /*****************************************************************************
266   FUNCTION : d3_labelUnit
267 
268   PURPOSE  : draws a string at the specified vertex of a cube
269   RETURNS  : void
270   NOTES    :
271 
272   UPDATE   :
273 ******************************************************************************/
d3_labelUnit(cube c,int unitNo,int vert,int label,bool toplabel_flag)274 static void d3_labelUnit (cube c, int unitNo, int vert, int label,
275 			  bool toplabel_flag)
276 
277 {
278     int x, y;
279     float z;
280     char *label_string;
281 
282     x = c[vert][0];
283     y = c[vert][1];
284     z = c[vert][2];
285     if (toplabel_flag)
286         y = y - d3_fontYsize;
287     label_string = get_label_string (label, unitNo);
288     d3_draw_string (x, y, z, label_string);
289 }
290 
291 
292 /*****************************************************************************
293   FUNCTION : get_vert_index
294 
295   PURPOSE  : calculates the neatest vertex for a given vector
296   RETURNS  : the index in the vertex structure
297   NOTES    :
298 
299   UPDATE   :
300 ******************************************************************************/
get_vert_index(cube c,vector corner)301 static int get_vert_index (cube c, vector corner)
302 
303 {
304     cube vert_diff;
305     float length, vert_len;
306     int index, i, j;
307 
308     for (i=0; i<8; i++) {
309         for (j=0; j<3; j++) {
310             vert_diff[i][j] = corner[j] - c[i][j];
311 	}
312     }
313     length = vert_diff[0][0]*vert_diff[0][0] + vert_diff[0][1]*vert_diff[0][1] +
314              vert_diff[0][2]*vert_diff[0][2];
315     index = 0;
316     for (i=1; i<8; i++) {
317         vert_len = vert_diff[i][0]*vert_diff[i][0] +
318 	           vert_diff[i][1]*vert_diff[i][1] +
319                    vert_diff[i][2]*vert_diff[i][2];
320         if (vert_len < length) {
321              length = vert_len;
322              index = i;
323 	}
324     }
325     return (index);
326 }
327 
328 
329 /*****************************************************************************
330   FUNCTION : get_label_vert_indices
331 
332   PURPOSE  : gets the vertex indices of the upper right and the lower right
333              vertex for a given rotation
334   RETURNS  : the two indices
335   NOTES    :
336 
337   UPDATE   :
338 ******************************************************************************/
get_label_vert_indices(vector rot_vec,int * top_index,int * bott_index)339 static void get_label_vert_indices (vector rot_vec, int *top_index,
340 				    int *bott_index)
341 
342 {
343     static vector upper_corner = {0.0, -0.5, -0.5, 1.0};
344     static vector lower_corner = {0.0, 0.5, -0.5, 1.0};
345     cube c;
346 
347     d3_rotateCube (c, rot_vec, d3_e_cube);
348     *top_index = get_vert_index (c, upper_corner);
349     *bott_index = get_vert_index (c, lower_corner);
350 }
351 
352 
353 /*****************************************************************************
354   FUNCTION : calc_transformed_cube
355 
356   PURPOSE  : multplies all matices for the viewing pipeline
357   RETURNS  : the transformed cube
358   NOTES    :
359 
360   UPDATE   :
361 ******************************************************************************/
calc_transformed_cube(matrix unit_trans_mat,matrix world_center_mat,matrix unit_scale_mat,matrix unit_activ_mat,matrix world_scale_mat,matrix world_trans_mat,vector viewpoint,cube transformed_cube)362 static void calc_transformed_cube (matrix unit_trans_mat,
363 				   matrix world_center_mat,
364                                    matrix unit_scale_mat,
365 				   matrix unit_activ_mat,
366                                    matrix world_scale_mat,
367 				   matrix world_trans_mat,
368                                    vector viewpoint, cube transformed_cube)
369 
370 {
371     matrix trans_mat, scale_mat, unit_mat, world_mat, global_mat;
372     cube c1, c2;
373     int i,j;
374 
375     for(i=0;i<4;i++)
376 	for(j=0;j<ANZ_VECS;j++)
377 	    c1[j][i] = c2[j][i] = transformed_cube[j][i] = 0.0;
378 
379 
380     d3_multMatrix (trans_mat, world_center_mat, unit_trans_mat);
381     d3_multMatrix (scale_mat, unit_activ_mat, unit_scale_mat);
382     d3_multMatrix (unit_mat, trans_mat, scale_mat);
383     d3_multMatrix (world_mat, world_trans_mat, world_scale_mat);
384     d3_multMatrix (global_mat, world_mat, unit_mat);
385 
386     unit_transformation (c1, global_mat);
387 
388     d3_rotateCube (c2, d3_state.rot_vec, c1);
389 
390     d3_shiftCube (transformed_cube, c2, trans_x, trans_y);
391     if (d3_state.projection_mode == central)
392        d3_projection (transformed_cube, viewpoint, transformed_cube);
393 }
394 
395 
396 /*****************************************************************************
397   FUNCTION : draw_units
398 
399   PURPOSE  : draw all units of the net
400   RETURNS  : void
401   NOTES    : the centers of the the units are stored
402 
403   UPDATE   :
404 ******************************************************************************/
draw_units(void)405 static void draw_units (void)
406 
407 {
408     cube transformed_cube;
409     vector min, max, center, p, unit_scale, activ_vec, vp, lp;
410     matrix world_center_mat, world_scale_mat, world_trans_mat;
411     matrix unit_scale_mat, unit_trans_mat, unit_activ_mat;
412     int act_unit, i, top_vert_index, bott_vert_index, do_draw;
413 
414     d3_shiftVector (vp, d3_state.viewpoint, trans_x, trans_y);
415     d3_shiftVector (lp, d3_state.light.position, trans_x, trans_y);
416 
417     get_net_extrema (min, max);
418     for (i=0; i<3; i++)
419       center[i] = -(max[i] - min[i]) / 2.0 - min[i];
420     center[3] = 1.0;
421     d3_transMatrix (world_center_mat, center);
422     unit_scale[0] = unit_scale[1] = unit_scale[2] = grid_size *
423            d3_state.unit_aspect;
424     d3_scaleMatrix (unit_scale_mat, unit_scale);
425     d3_scaleMatrix (world_scale_mat, d3_state.scale_vec);
426     d3_transMatrix (world_trans_mat, d3_state.trans_vec);
427 
428     get_label_vert_indices(d3_state.rot_vec, &top_vert_index, &bott_vert_index);
429 
430     act_unit = krui_getFirstUnit ();
431     while (act_unit != 0) {
432          get_unit_pos_vector (act_unit, p);
433          d3_transMatrix (unit_trans_mat, p);
434          do_draw = get_size_vector (activ_vec, act_unit);
435          d3_scaleMatrix (unit_activ_mat, activ_vec);
436          calc_transformed_cube (unit_trans_mat, world_center_mat,
437                                 unit_scale_mat,
438                                 unit_activ_mat, world_scale_mat,
439                                 world_trans_mat, vp, transformed_cube);
440          insert_center_vector (transformed_cube, act_unit);
441          if (do_draw) {
442               if (d3_state.model_mode == wire_frame)
443                   d3_draw_wireframeCube (transformed_cube);
444               else {
445 
446                   d3_draw_solidCube (transformed_cube, vp, lp, act_unit);
447 	      }
448               if (d3_state.unit_mode.top_label != nothing_on)
449                   d3_labelUnit (transformed_cube, act_unit, top_vert_index,
450                                 d3_state.unit_mode.top_label, TRUE);
451               if (d3_state.unit_mode.bottom_label != nothing_on)
452                   d3_labelUnit (transformed_cube, act_unit, bott_vert_index,
453                                d3_state.unit_mode.bottom_label, FALSE);
454 	 }
455          act_unit = krui_getNextUnit ();
456     }
457 }
458 
459 
460 /*****************************************************************************
461   FUNCTION : d3_labelLink
462 
463   PURPOSE  : draws the weight of a link
464   RETURNS  : void
465   NOTES    :
466 
467   UPDATE   :
468 ******************************************************************************/
d3_labelLink(vector v1,vector v2,float * weight)469 static void d3_labelLink (vector v1, vector v2, float *weight)
470 
471 {
472     char string[40];
473     int dx, dy;
474     float dz;
475 
476     dx = floor (v1[0] + (v2[0] - v1[0]) / 2);
477     dy = floor (v1[1] + (v2[1] - v1[1]) / 2);
478     dz = v1[2] + (v2[2] - v1[2]) / 2;
479     sprintf (string, "%.3f", *weight);
480     d3_setBlackColor ();
481     d3_draw_string (dx, dy, dz, string);
482     d3_setColor (linkColor);
483 }
484 
485 
486 /*****************************************************************************
487   FUNCTION : draw_links
488 
489   PURPOSE  : draws all links of the net
490   RETURNS  : void
491   NOTES    :
492 
493   UPDATE   : 8.3.93  Link Trigger
494 ******************************************************************************/
draw_links(void)495 static void draw_links (void)
496 
497 {
498     int act_unit, pred_unit;
499     FlintType str;    /* old style: FlintType *str */
500     struct PositionVector *start_vec, *end_vec;
501     vector v1, v2;
502 
503     if (d3_state.model_mode == solid) {
504          d3_setColor (linkColor);
505          if (d3_state.color_mode == mono_mode) {
506               d3_setBlackColor ();
507               d3_intens = 0.0;
508 	 }
509     } else {
510          d3_setBlackColor ();
511          d3_intens = 0.0;
512     }
513 
514     act_unit = krui_getFirstUnit ();
515     while (act_unit != 0) {
516          pred_unit = krui_getFirstPredUnit (&str);
517          while (pred_unit != 0) {
518               krui_getUnitCenters (act_unit, d3_currentDisplay, &start_vec);
519               krui_getUnitCenters (pred_unit, d3_currentDisplay, &end_vec);
520               v1[0] = start_vec->x;
521               v1[1] = start_vec->y;
522               v1[2] = start_vec->z;
523               v1[3] = 0.0;
524               v2[0] = end_vec->x;
525               v2[1] = end_vec->y;
526               v2[2] = end_vec->z;
527               v2[3] = 0.0;
528 
529               if ((str >= d3_state.pos_link_trigger)
530                    OR (str <= -d3_state.neg_link_trigger)) {
531                   if (d3_state.model_mode == wire_frame)
532                       d3_draw_wireframeLine (v1, v2);
533                   else {
534                       if ((d3_state.link_mode == links_color) &&
535                           (d3_state.color_mode == rgb_mode))
536                           d3_setLinkColor (&str);
537                       if (d3_state.color_mode == mono_mode)
538                           d3_setBlackColor ();
539                       d3_draw_solidLine (v1, v2);
540         	  }
541                   if (d3_state.link_mode == links_label)
542                       d3_labelLink (v1, v2, &str);
543 	      }
544               pred_unit = krui_getNextPredUnit (&str);
545          }
546          act_unit = krui_getNextUnit ();
547     }
548     if (d3_state.model_mode == solid)
549         d3_flushPixels ();
550 }
551 
552 
553 /*****************************************************************************
554   FUNCTION : d3_drawNet
555 
556   PURPOSE  : draws the whole net
557   RETURNS  : void
558   NOTES    : this routine is called by every redraw request
559 
560   UPDATE   :
561 ******************************************************************************/
d3_drawNet(void)562 void d3_drawNet (void)
563 
564 {
565     if (d3_freeze)
566         return;
567     if (d3_displayIsReady) {
568         if (d3_state.model_mode == solid)
569             d3_clearZbuffer ();
570         else
571             d3_setBlackColor ();
572         d3_clearDisplay ();   /* old style: d3_clearDispaly */
573         draw_units ();
574         if (d3_state.link_mode != links_off)
575             draw_links ();
576     }
577 
578 }
579 
580 
581 /*****************************************************************************
582   FUNCTION : d3_recenter_window
583 
584   PURPOSE  : calculate the new dimensions if the window is resized by the user
585   RETURNS  : new dimension values
586   NOTES    : called by the X-Event Handler
587 
588   UPDATE   :
589 ******************************************************************************/
d3_recenter_window(int width,int height)590 void d3_recenter_window (int width, int height)
591 
592 {
593    if ((width != d3_displayXsize) || (height != d3_displayYsize)) {
594       d3_displayXsize = width;
595       d3_displayYsize = height;
596       trans_x = width / 2;
597       trans_y = height / 2;
598       d3_setClipWindow (0, 0, d3_displayXsize, d3_displayYsize);
599    }
600 }
601 
602 
603 /*****************************************************************************
604   FUNCTION : d3_resetDisplay
605 
606   PURPOSE  : set all translations, scalings and rotations to zero
607   RETURNS  : void
608   NOTES    :
609 
610   UPDATE   :
611 ******************************************************************************/
d3_resetDisplay(void)612 void d3_resetDisplay (void)
613 
614 {
615     int i;
616 
617     if (d3_freeze)
618         return;
619     for (i=0; i<3; i++)
620       {
621          d3_state.scale_vec [i] = 1.0;
622          d3_state.trans_vec [i] = 0.0;
623          d3_state.rot_vec [i] = 0.0;
624       }
625     d3_drawNet ();
626 }
627 
628 
629 /*****************************************************************************
630   FUNCTION : d3_clear_xyTranslationTable
631 
632   PURPOSE  : clears the Translation Table for the 2d -> 3d mapping
633   RETURNS  : the cleared Table
634   NOTES    :
635 
636   UPDATE   :
637 ******************************************************************************/
d3_clear_xyTranslationTable(void)638 void d3_clear_xyTranslationTable (void)
639 
640 {
641     krui_xyTransTable( OP_TRANSTABLE_CLEAR, NULL, NULL, 0 );
642 }
643 
644 
645 /*****************************************************************************
646   FUNCTION : d3_init_main
647 
648   PURPOSE  : this is the initialization for the Translation Table, the Fonts,
649              the color, and the dimensions
650   RETURNS  : void
651   NOTES    : only called one time by ui_init
652 
653   UPDATE   :
654 ******************************************************************************/
d3_init_main(void)655 void d3_init_main (void)
656 {
657     trans_x = d3_displayXsize / 2.0;
658     trans_y = d3_displayYsize / 2.0;
659 
660     d3_setClipWindow (0, 0, d3_displayXsize, d3_displayYsize);
661 
662     if (ui_col_monochromeMode)
663         d3_state.color_mode = mono_mode;
664     else
665         d3_state.color_mode = rgb_mode;
666 
667     d3_select_font (fnt8x14);
668     d3_get_font_size (&d3_fontXsize, &d3_fontYsize);
669 }
670 /* end of file */
671 
672