1 /*
2  *  xnec2c - GTK2-based version of nec2c, the C translation of NEC2
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 /*
20  *  draw_structure.c
21  *
22  *  Structure drawing routines for xnec2c
23  */
24 
25 #include "draw_structure.h"
26 #include "shared.h"
27 
28 /*-----------------------------------------------------------------------*/
29 
30 /*  Draw_Structure()
31  *
32  *  Draws xyz axes, wire segments and patches
33  */
34   void
Draw_Structure(GtkWidget * drawingarea)35 Draw_Structure( GtkWidget *drawingarea )
36 {
37   /* Abort if xnec2c may be quit by user */
38   if( isFlagSet(MAIN_QUIT) )
39 	return;
40 
41   /* Cairo context */
42   cairo_t *cr = gdk_cairo_create( structure_pixmap );
43 
44   /* Clear pixmap */
45   cairo_set_source_rgb( cr, BLACK );
46   cairo_rectangle(
47 	  cr, 0.0, 0.0,
48 	  (double)structure_proj_params.pixmap_width,
49 	  (double)structure_proj_params.pixmap_height);
50   cairo_fill( cr );
51 
52   /* Process and draw geometry if available, else clear screen */
53   Process_Wire_Segments();
54   Process_Surface_Patches();
55   Draw_XYZ_Axes( structure_pixmap, structure_proj_params );
56   Draw_Surface_Patches( structure_segs+data.n, data.m );
57   Draw_Wire_Segments( structure_segs, data.n );
58 
59   /* Show gain in direction of viewer */
60   Show_Viewer_Gain( main_window,
61 	  "main_gain_entry", structure_proj_params );
62 
63   /* Render pixmap to screen */
64   gdk_window_set_back_pixmap(
65 	  drawingarea->window, structure_pixmap, FALSE );
66   gdk_window_clear( drawingarea->window );
67 
68   /* Reset "new current data" flag */
69   crnt.newer = 0;
70 
71   /* Display frequency step */
72   Display_Fstep( structure_fstep_entry, calc_data.fstep );
73 
74   /* Wait for GTK to complete its tasks */
75   while( g_main_context_iteration(NULL, FALSE) );
76 
77   cairo_destroy( cr );
78 
79 } /* Draw_Structure() */
80 
81 /*-----------------------------------------------------------------------*/
82 
83 /*  New_Wire_Data()
84  *
85  *  Calculates some projection parameters
86  *  when new wire segment data is created
87  */
88   void
New_Wire_Data(void)89 New_Wire_Data( void )
90 {
91   /* Abort if no wire data */
92   if( data.n == 0 )	return;
93 
94   double
95 	r,	   /* Distance of a point from XYZ origin */
96 	r_max; /* Maximum value of above */
97 
98   int idx;
99 
100   /* Find segment end furthest from xyz axes origin */
101   r_max = 0.0;
102   for( idx = 0; idx < data.n; idx++ )
103   {
104 	r = sqrt(
105 		(double)data.x1[idx] * (double)data.x1[idx] +
106 		(double)data.y1[idx] * (double)data.y1[idx] +
107 		(double)data.z1[idx] * (double)data.z1[idx] );
108 	if( r > r_max )
109 	  r_max = r;
110 
111 	r = sqrt(
112 		(double)data.x2[idx] * (double)data.x2[idx] +
113 		(double)data.y2[idx] * (double)data.y2[idx] +
114 		(double)data.z2[idx] * (double)data.z2[idx] );
115 	if( r > r_max )
116 	  r_max = r;
117 
118   } /* for( idx = 0; idx < data.n; idx++ ) */
119 
120   /* Max value of segment r saved if appropriate */
121   if( r_max > structure_proj_params.r_max )
122 	structure_proj_params.r_max = r_max;
123 
124   /* Redraw structure on screen */
125   New_Projection_Parameters(
126 	  structure_pixmap_width,
127 	  structure_pixmap_height,
128 	  &structure_proj_params );
129 
130 } /* New_Wire_Data() */
131 
132 /*-----------------------------------------------------------------------*/
133 
134 /*  New_Patch_Data()
135  *
136  *  Calculates some projection parameters
137  *  when new surface patch data is created
138  */
139   void
New_Patch_Data(void)140 New_Patch_Data( void )
141 {
142   /* Abort if no patch data */
143   if( data.m == 0 )	return;
144 
145   double
146 	s,			/* Side/2 of a square that will represent a patch  */
147 	sx, sy, sz, /* Length of components of s in the X, Y, Z axes */
148 	r,			/* Distance of points in patch from XYZ co-ordinates */
149 	r_max;		/* Maximum value of above */
150 
151   int idx, i;
152   size_t mreq;
153 
154   /* Allocate memory for patch line segments */
155   mreq = (size_t)(2 * data.m) * sizeof(double);
156   mem_realloc( (void **)&data.px1, mreq, "in draw_structure.c" );
157   mem_realloc( (void **)&data.py1, mreq, "in draw_structure.c" );
158   mem_realloc( (void **)&data.pz1, mreq, "in draw_structure.c" );
159   mem_realloc( (void **)&data.px2, mreq, "in draw_structure.c" );
160   mem_realloc( (void **)&data.py2, mreq, "in draw_structure.c" );
161   mem_realloc( (void **)&data.pz2, mreq, "in draw_structure.c" );
162 
163   /* Find point furthest from xyz axes origin */
164   r_max = 0.0;
165   for( idx = 0; idx < data.m; idx++ )
166   {
167 	i = 2 * idx;
168 
169 	/* Side/2 of square representing a patch (sqrt of patch area) */
170 	s = (double)sqrt( data.pbi[idx] ) / 2.0;
171 
172 	/* Projection of s on xyz components of t1 */
173 	sx = s * (double)data.t1x[idx];
174 	sy = s * (double)data.t1y[idx];
175 	sz = s * (double)data.t1z[idx];
176 
177 	/* End 1 of line seg parallel to t1 vector */
178 	data.px1[i] = (double)data.px[idx] + sx;
179 	data.py1[i] = (double)data.py[idx] + sy;
180 	data.pz1[i] = (double)data.pz[idx] + sz;
181 
182 	/* Its distance from XYZ origin */
183 	r = sqrt(
184 		data.px1[i]*data.px1[i] +
185 		data.py1[i]*data.py1[i] +
186 		data.pz1[i]*data.pz1[i] );
187 	if( r > r_max )
188 	  r_max = r;
189 
190 	/* End 2 of line seg parallel to t1 vector */
191 	data.px2[i] = (double)data.px[idx] - sx;
192 	data.py2[i] = (double)data.py[idx] - sy;
193 	data.pz2[i] = (double)data.pz[idx] - sz;
194 
195 	/* Its distance from XYZ origin */
196 	r = sqrt(
197 		data.px2[i]*data.px2[i] +
198 		data.py2[i]*data.py2[i] +
199 		data.pz2[i]*data.pz2[i] );
200 	if( r > r_max )
201 	  r_max = r;
202 
203 	i++;
204 
205 	/* Projection of s on xyz components of t2 */
206 	sx = s * (double)data.t2x[idx];
207 	sy = s * (double)data.t2y[idx];
208 	sz = s * (double)data.t2z[idx];
209 
210 	/* End 1 of line parallel to t2 vector */
211 	data.px1[i] = (double)data.px[idx] + sx;
212 	data.py1[i] = (double)data.py[idx] + sy;
213 	data.pz1[i] = (double)data.pz[idx] + sz;
214 
215 	/* Its distance from XYZ origin */
216 	r = sqrt(
217 		data.px1[i]*data.px1[i] +
218 		data.py1[i]*data.py1[i] +
219 		data.pz1[i]*data.pz1[i] );
220 	if( r > r_max )
221 	  r_max = r;
222 
223 	/* End 2 of line parallel to t2 vector */
224 	data.px2[i] = (double)data.px[idx] - sx;
225 	data.py2[i] = (double)data.py[idx] - sy;
226 	data.pz2[i] = (double)data.pz[idx] - sz;
227 
228 	/* Its distance from XYZ origin */
229 	r = sqrt(
230 		data.px2[i]*data.px2[i] +
231 		data.py2[i]*data.py2[i] +
232 		data.pz2[i]*data.pz2[i] );
233 	if( r > r_max )
234 	  r_max = r;
235 
236   } /* for( idx = 0; idx < data.m; idx++ ) */
237 
238   /* Max value of patch r saved if appropriate */
239   if( r_max > structure_proj_params.r_max )
240 	structure_proj_params.r_max = r_max;
241 
242   /* Redraw structure on screen */
243   New_Projection_Parameters(
244 	  structure_pixmap_width,
245 	  structure_pixmap_height,
246 	  &structure_proj_params );
247 
248 } /* New_Patch_Data() */
249 
250 /*-----------------------------------------------------------------------*/
251 
252 /*  Process_Wire_Segments()
253  *
254  *  Processes wire segment data so they can be drawn on Screen
255  */
256   void
Process_Wire_Segments(void)257 Process_Wire_Segments( void )
258 {
259   int idx;
260 
261   /* Project all wire segs from xyz frame to screen frame */
262   for( idx = 0; idx < data.n; idx++ )
263 	Set_Gdk_Segment(
264 		&structure_segs[idx],
265 		&structure_proj_params,
266 		(double)data.x1[idx],
267 		(double)data.y1[idx],
268 		(double)data.z1[idx],
269 		(double)data.x2[idx],
270 		(double)data.y2[idx],
271 		(double)data.z2[idx] );
272 
273 } /* Process_Wire_Segments() */
274 
275 /*-----------------------------------------------------------------------*/
276 
277 /*  Process_Surface_Patches()
278  *
279  *  Processes surface patch data so they can be drawn on Screen
280  */
281   void
Process_Surface_Patches(void)282 Process_Surface_Patches( void )
283 {
284   int idx, m2;
285 
286   /* Project all patch segs from xyz frame to screen frame */
287   /* Patches are represented by 2 line segs parallel to t1 */
288   /* and t2 vectors. Length of segs is sqrt of patch area  */
289   m2 = data.m * 2;
290   for( idx = 0; idx < m2; idx++ )
291 	Set_Gdk_Segment(
292 		&structure_segs[idx+data.n],
293 		&structure_proj_params,
294 		data.px1[idx],
295 		data.py1[idx],
296 		data.pz1[idx],
297 		data.px2[idx],
298 		data.py2[idx],
299 		data.pz2[idx] );
300 
301 } /* Process_Surface_Patches() */
302 
303 /*-----------------------------------------------------------------------*/
304 
305 /*  Draw_Wire_Segments()
306  *
307  *  Draws all wire segments of the input structure
308  */
309 
310 void
Draw_Wire_Segments(GdkSegment * segm,gint nseg)311 Draw_Wire_Segments(	GdkSegment *segm, gint nseg )
312 {
313   /* Abort if no wire segs or new input pending */
314   if( !nseg || isFlagSet(INPUT_PENDING) )
315 	return;
316 
317   int idx, i;
318 
319   /* Cairo context */
320   cairo_t *cr = gdk_cairo_create( structure_pixmap );
321 
322   /* Draw networks */
323   for( idx = 0; idx < netcx.nonet; idx++ )
324   {
325 	int i1, i2;
326 
327 	i1 = netcx.iseg1[idx]-1;
328 	i2 = netcx.iseg2[idx]-1;
329 
330 	switch( netcx.ntyp[idx] )
331 	{
332 	  case 1: /* Two-port network */
333 		{
334 		  GdkPoint points[4];
335 
336 		  /* Draw a box between segs to represent two-port network */
337 		  points[0].x = segm[i1].x1 + (segm[i2].x1 - segm[i1].x1)/3;
338 		  points[0].y = segm[i1].y1 + (segm[i2].y1 - segm[i1].y1)/3;
339 		  points[1].x = segm[i2].x1 + (segm[i1].x1 - segm[i2].x1)/3;
340 		  points[1].y = segm[i2].y1 + (segm[i1].y1 - segm[i2].y1)/3;
341 		  points[2].x = segm[i2].x2 + (segm[i1].x2 - segm[i2].x2)/3;
342 		  points[2].y = segm[i2].y2 + (segm[i1].y2 - segm[i2].y2)/3;
343 		  points[3].x = segm[i1].x2 + (segm[i2].x2 - segm[i1].x2)/3;
344 		  points[3].y = segm[i1].y2 + (segm[i2].y2 - segm[i1].y2)/3;
345 
346 		  cairo_set_source_rgb( cr, MAGENTA );
347 		  Cairo_Draw_Polygon( cr, points, 4 );
348 		  cairo_fill( cr );
349 
350 			/* Draw connecting lines */
351 		  Cairo_Draw_Line( cr,
352 			  segm[i1].x1, segm[i1].y1,
353 			  segm[i2].x1, segm[i2].y1 );
354 		  Cairo_Draw_Line( cr,
355 			  segm[i1].x2, segm[i1].y2,
356 			  segm[i2].x2, segm[i2].y2 );
357 		}
358 		break;
359 
360 	  case 2: /* Straight transmission line */
361 		/* Set cr attributes for transmission line */
362 		cairo_set_source_rgb( cr, CYAN );
363 
364 		Cairo_Draw_Line( cr,
365 			segm[i1].x1, segm[i1].y1,
366 			segm[i2].x1, segm[i2].y1 );
367 		Cairo_Draw_Line( cr,
368 			segm[i1].x2, segm[i1].y2,
369 			segm[i2].x2, segm[i2].y2 );
370 		break;
371 
372 	  case 3: /* Crossed transmisson line */
373 		/* Set cr attributes for transmission line */
374 		cairo_set_source_rgb( cr, CYAN );
375 
376 		Cairo_Draw_Line( cr,
377 			segm[i1].x1, segm[i1].y1,
378 			segm[i2].x2, segm[i2].y2 );
379 		Cairo_Draw_Line( cr,
380 			segm[i1].x2, segm[i1].y2,
381 			segm[i2].x1, segm[i2].y1 );
382 
383 	} /* switch( netcx.ntyp ) */
384 
385   } /* for( idx = 0; idx < netcx.nonet; idx++ ) */
386 
387   /* Draw currents/charges if enabled, return */
388   /* Current or charge calculations do not contain wavelength */
389   /* factors, since they are drawn normalized to their max value */
390   if(
391 	  (isFlagSet(DRAW_CURRENTS) ||
392 	   isFlagSet(DRAW_CHARGES)) &&
393 	  crnt.valid )
394   {
395 	static double cmax; /* Max of seg current/charge */
396 	/* To color structure segs */
397 	double red = 0.0, grn = 0.0, blu = 0.0;
398 	char label[11];
399 	size_t s = sizeof( label );
400 
401 	/* Loop over all wire segs, find max current/charge */
402 	if( crnt.newer )
403 	{
404 	  cmax = 0.0;
405 	  for( idx = 0; idx < nseg; idx++ )
406 	  {
407 		if( isFlagSet(DRAW_CURRENTS) )
408 		  /* Calculate segment current magnitude */
409 		  cmag[idx] = (double)cabs( crnt.cur[idx] );
410 		else
411 		  /* Calculate segment charge density */
412 		  cmag[idx] = (double)cabs( cmplx(crnt.bii[idx], crnt.bir[idx]) );
413 
414 		/* Find max current/charge magnitude */
415 		if( cmag[idx] > cmax )
416 		  cmax = cmag[idx];
417 	  }
418 
419 	  /* Show max value in color code label */
420 	  if( isFlagSet(DRAW_CURRENTS) )
421 		snprintf( label, s, "%10.3E", cmax * (double)data.wlam );
422 	  else
423 		snprintf( label, s, "%10.3E", cmax * 1.0E-6/(double)calc_data.fmhz );
424 	  gtk_label_set_text(
425 		  GTK_LABEL(lookup_widget(structure_drawingarea,
426 			  "main_colorcode_maxlabel")), label );
427 
428 	} /* if( crnt.newer ) */
429 
430 	/* Draw segments in color code according to current */
431 	for( idx = 0; idx < nseg; idx++ )
432 	{
433 	  /* Calculate RGB value for seg current */
434 	  Value_to_Color( &red, &grn, &blu, cmag[idx], cmax );
435 
436 	  /* Set cr attributes for segment */
437 	  cairo_set_source_rgb( cr, red, grn, blu );
438 
439 	  /* Draw segment */
440 	  Cairo_Draw_Line( cr,
441 		  segm[idx].x1, segm[idx].y1,
442 		  segm[idx].x2, segm[idx].y2 );
443 	} /* for( idx = 0; idx < nseg; idx++ ) */
444 
445 	cairo_destroy( cr );
446 	return;
447   } /* if( isFlagSet(DRAW_CURRENTS) || isFlagSet(DRAW_CHARGES) ) */
448 
449   /* Draw segs if not all loaded */
450   cairo_set_line_width( cr, 2.0 );
451   if( zload.nldseg != nseg )
452   {
453 	/* Set gc attributes for segments */
454 	if( isFlagSet(OVERLAY_STRUCT) &&
455 		(structure_proj_params.type == RDPATTERN_DRAWINGAREA) )
456 	  cairo_set_source_rgb( cr, WHITE );
457 	else
458 	  cairo_set_source_rgb( cr, BLUE );
459 
460 	/* Draw wire segments */
461 	Cairo_Draw_Segments( cr, segm, nseg );
462   }
463 
464   /* Draw lumped loaded segments */
465   cairo_set_source_rgb( cr, YELLOW );
466   cairo_set_line_width( cr, 9.0 );
467   for( idx = 0; idx < zload.nldseg; idx++ )
468   {
469 	if( zload.ldtype[idx] != 5 )
470 	{
471 	  i = zload.ldsegn[idx]-1;
472 	  Cairo_Draw_Line( cr,
473 		  segm[i].x1, segm[i].y1,
474 		  segm[i].x2, segm[i].y2 );
475 	}
476   }
477 
478   /* Set gc attributes for excitation */
479   cairo_set_source_rgb( cr, RED );
480   cairo_set_line_width( cr, 5.0 );
481 
482   /* Draw excitation sources */
483   for( idx = 0; idx < vsorc.nsant; idx++ )
484   {
485 	i = vsorc.isant[idx]-1;
486 	Cairo_Draw_Line( cr,
487 		segm[i].x1, segm[i].y1,
488 		segm[i].x2, segm[i].y2 );
489   }
490 
491   for( idx = 0; idx < vsorc.nvqd; idx++ )
492   {
493 	i = vsorc.ivqd[idx]-1;
494 	Cairo_Draw_Line( cr,
495 		segm[i].x1, segm[i].y1,
496 		segm[i].x2, segm[i].y2 );
497   }
498 
499   /* Draw resistivity loaded segments */
500   cairo_set_source_rgb( cr, YELLOW );
501   cairo_set_line_width( cr, 2.0 );
502   for( idx = 0; idx < zload.nldseg; idx++ )
503   {
504 	if( zload.ldtype[idx] == 5 )
505 	{
506 	  i = zload.ldsegn[idx]-1;
507 	  Cairo_Draw_Line( cr,
508 		  segm[i].x1, segm[i].y1,
509 		  segm[i].x2, segm[i].y2 );
510 	}
511   }
512 
513   cairo_destroy( cr );
514 } /* Draw_Wire_Segments() */
515 
516 /*-----------------------------------------------------------------------*/
517 
518 /*  Draw_Surface_Patches()
519  *
520  *  Draws the line segments that represent surface patches
521  */
522 void
Draw_Surface_Patches(GdkSegment * segm,gint npatch)523 Draw_Surface_Patches( GdkSegment *segm, gint npatch )
524 {
525   /* Abort if no patches */
526   if( ! npatch )
527 	return;
528 
529   /* Cairo context */
530   cairo_t *cr = gdk_cairo_create( structure_pixmap );
531 
532   /* Draw currents if enabled, return */
533   if( isFlagSet(DRAW_CURRENTS) && crnt.valid )
534   {
535 	/* Buffers for t1,t2 currents below */
536 	static double cmax;
537 
538 	/* Current along x,y,z and t1,t2 vector directions */
539 	complex double cx, cy, cz, ct1, ct2;
540 
541 	double red = 0.0, grn = 0.0, blu = 0.0;
542 
543 	int i, j;
544 
545 	/* Find max value of patch current magnitude */
546 	if( crnt.newer )
547 	{
548 	  j= data.n;
549 	  cmax = 0.0;
550 
551 	  for( i = 0; i < npatch; i++ )
552 	  {
553 		/* Calculate current along x,y,z vectors */
554 		cx = (complex double)crnt.cur[j];
555 		cy = (complex double)crnt.cur[j+1];
556 		cz = (complex double)crnt.cur[j+2];
557 
558 		/* Calculate current along t1 and t2 tangent vectors */
559 		ct1 = cx*(double)data.t1x[i] +
560 		  cy*(double)data.t1y[i] +
561 		  cz*(double)data.t1z[i];
562 		ct2 = cx*(double)data.t2x[i] +
563 		  cy*(double)data.t2y[i] +
564 		  cz*(double)data.t2z[i];
565 
566 		/* Save current magnitudes */
567 		ct1m[i] = (double)cabs( ct1 );
568 		ct2m[i] = (double)cabs( ct2 );
569 
570 		/* Find current magnitude max */
571 		if( ct1m[i] > cmax ) cmax = ct1m[i];
572 		if( ct2m[i] > cmax ) cmax = ct2m[i];
573 
574 		j += 3;
575 
576 	  } /* for( i = 0; i < npatch; i++ ) */
577 
578 	} /* if( crnt.newer ) */
579 
580 	/* Draw patches in color code according to current */
581 	for( i = 0; i < npatch; i++ )
582 	{
583 	  j = 2 * i;
584 
585 	  /* Calculate RGB value for patch t1 current */
586 	  Value_to_Color( &red, &grn, &blu, ct1m[i], cmax );
587 
588 	  /* Set cr attributes for patch t1 */
589 	  cairo_set_source_rgb( cr, red, grn, blu );
590 
591 	  /* Draw patch t1 */
592 	  Cairo_Draw_Line( cr,
593 		  segm[j].x1, segm[j].y1,
594 		  segm[j].x2, segm[j].y2 );
595 
596 	  /* Calculate RGB value for patch t2 current */
597 	  Value_to_Color( &red, &grn, &blu, ct2m[i], cmax );
598 
599 	  /* Set cr attributes for patch t2 */
600 	  cairo_set_source_rgb( cr, red, grn, blu );
601 
602 	  /* Draw patch t2 */
603 	  j++;
604 	  Cairo_Draw_Line( cr,
605 		  segm[j].x1, segm[j].y1,
606 		  segm[j].x2, segm[j].y2 );
607 
608 	} /* for( idx = 0; idx < npatch; idx++ ) */
609 
610   } /* if( isFlagSet(DRAW_CURRENTS) ) */
611   else
612   {
613 	int idx;
614 
615 	/* Set gc attributes for patches */
616 	if( isFlagSet(OVERLAY_STRUCT) &&
617 		(structure_proj_params.type == RDPATTERN_DRAWINGAREA) )
618 	  cairo_set_source_rgb( cr, WHITE );
619 	else cairo_set_source_rgb( cr, BLUE );
620 
621 	/* Draw patch segments */
622 	int nsg = 2 * npatch;
623 	for( idx = 0; idx < nsg; idx++ )
624 	{
625 	  Cairo_Draw_Line( cr,
626 		  segm[idx].x1, segm[idx].y1,
627 		  segm[idx].x2, segm[idx].y2 );
628 	}
629   }
630 
631   cairo_destroy( cr );
632 } /* Draw_Surface_Patches() */
633 
634 /*-----------------------------------------------------------------------*/
635 
636 /* Redo_Currents()
637  *
638  * Refreshes plots on new frequency in spinbutton
639  */
640   gboolean
Redo_Currents(gpointer udata)641 Redo_Currents( gpointer udata )
642 {
643   /* Abort if no geometry data */
644   if( ((data.n == 0) && (data.m == 0)) ||
645 	  isFlagClear(ENABLE_EXCITN) )
646 	return FALSE;
647 
648   /* Makes calcs use the extra buffer in rad_pattern */
649   calc_data.fstep = calc_data.nfrq;
650   save.last_freq = 0.0;
651   New_Frequency();
652 
653   /* Display freq data in entry widgets */
654   if( isFlagSet(PLOT_FREQ_LINE) )
655 	Plot_Frequency_Data();
656 
657   /* Redraw structure on screen */
658   if( (structure_drawingarea != NULL) &&
659 	  (isFlagSet(DRAW_CURRENTS) || isFlagSet(DRAW_CHARGES)) )
660 	Draw_Structure( structure_drawingarea );
661 
662   return FALSE;
663 } /* Redo_Currents() */
664 
665 /*-----------------------------------------------------------------------*/
666 
667 /*  New_Structure_Projection_Angle()
668  *
669  *  Calculates new projection parameters when a
670  *  structure projection angle (Wr or Wi) changes
671  */
672   void
New_Structure_Projection_Angle(void)673 New_Structure_Projection_Angle(void)
674 {
675   /* sin and cos of structure rotation and inclination angles */
676   structure_proj_params.sin_wr = sin(structure_proj_params.Wr/(double)TD);
677   structure_proj_params.cos_wr = cos(structure_proj_params.Wr/(double)TD);
678   structure_proj_params.sin_wi = sin(structure_proj_params.Wi/(double)TD);
679   structure_proj_params.cos_wi = cos(structure_proj_params.Wi/(double)TD);
680 
681   /* Trigger a redraw of structure drawingarea */
682   if( isFlagClear(INPUT_PENDING) )
683 	Draw_Structure( structure_drawingarea );
684 
685   /* Trigger a redraw of plots drawingarea */
686   if( isFlagSet(PLOT_ENABLED) && isFlagSet(PLOT_GVIEWER) )
687 	Plot_Frequency_Data();
688 
689 } /* New_Structure_Projection_Angle() */
690 
691 /*-----------------------------------------------------------------------*/
692 
693 /*  Init_Struct_Drawing()
694  *
695  *  Initializes drawing parameters after geometry input
696  */
697   void
Init_Struct_Drawing(void)698 Init_Struct_Drawing( void )
699 {
700   /* We need n segs for wires + 2m for patces */
701   size_t mreq = (size_t)(data.n + 2*data.m) * sizeof(GdkSegment);
702   mem_realloc( (void **)&structure_segs, mreq, "in draw_structure.c" );
703   New_Wire_Data();
704   New_Patch_Data();
705 }
706 
707 /*-----------------------------------------------------------------------*/
708 
709 /* Show_Viewer_Gain()
710  *
711  * Shows gain in direction of viewer
712  */
713   void
Show_Viewer_Gain(GtkWidget * window,const char * widget,projection_parameters_t proj_params)714 Show_Viewer_Gain(
715 	GtkWidget *window,
716 	const char *widget,
717 	projection_parameters_t proj_params )
718 {
719   if( isFlagSet(DRAW_CURRENTS)	||
720 	  isFlagSet(DRAW_CHARGES)	||
721 	  isFlagSet(DRAW_GAIN)		||
722 	  isFlagSet(FREQ_LOOP_RUNNING) )
723   {
724 	char txt[8];
725 
726 	if( isFlagSet(ENABLE_RDPAT) && (calc_data.fstep >= 0) )
727 	{
728 	  snprintf( txt, sizeof(txt), "%7.2f",
729 		  Viewer_Gain(proj_params, calc_data.fstep) );
730 	  gtk_entry_set_text(
731 		  GTK_ENTRY(lookup_widget(window, widget)), txt );
732 	}
733   }
734 
735 } /* Show_Viewer_Gain() */
736 
737 /*-----------------------------------------------------------------------*/
738 
739