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.c
21  *
22  *  Drawing routines for xnec2c
23  */
24 
25 #include "draw.h"
26 #include "shared.h"
27 
28 /*-----------------------------------------------------------------------*/
29 
30 /* Set_Gdk_Segment()
31  *
32  *  Calculates window x,y co-ordinates of a GdkSegment for
33  *  drawing on Screen. Input data is a line in the xyz frame
34  */
35 void
Set_Gdk_Segment(GdkSegment * segm,projection_parameters_t * params,double x1,double y1,double z1,double x2,double y2,double z2)36 Set_Gdk_Segment(
37 	GdkSegment *segm,
38 	projection_parameters_t *params,
39 	double x1, double y1, double z1,
40 	double x2, double y2, double z2 )
41 {
42   double x, y;
43 
44   /* Project end 1 of seg in xyz frame to screen frame */
45   Project_on_Screen( params, x1, y1, z1, &x, &y );
46   segm->x1 = (gint)(params->x_center + x*params->xy_scale);
47   segm->y1 = params->pixmap_height -
48 	(gint)(params->y_center + y*params->xy_scale);
49 
50   /* Project end 2 of seg in xyz frame to screen frame */
51   Project_on_Screen( params, x2, y2, z2, &x, &y );
52   segm->x2 = (gint)(params->x_center + x*params->xy_scale);
53   segm->y2 = params->pixmap_height -
54 	(gint)(params->y_center + y*params->xy_scale);
55 
56 } /* Set_Gdk_Segment() */
57 
58 /*-----------------------------------------------------------------------*/
59 
60 /*  Project_on_Screen()
61  *
62  *  Projects a point in the x,y,z co-ordinate
63  *  frame of NEC2 to the x,y frame of the Screen
64  */
65 void
Project_on_Screen(projection_parameters_t * params,double x,double y,double z,double * xs,double * ys)66 Project_on_Screen(
67 	projection_parameters_t *params,
68 	double x, double y, double z,
69 	double *xs, double *ys )
70 {
71   *xs = y*params->cos_wr - x*params->sin_wr;
72   *ys = z*params->cos_wi - params->sin_wi *
73 	(x*params->cos_wr + y*params->sin_wr);
74 
75 } /* Project_on_Screen() */
76 
77 /*-----------------------------------------------------------------------*/
78 
79 /*  Project_XYZ_Axes()
80  *
81  *  Sets GdkSegment data to project xyz axes on Screen
82  */
83 void
Project_XYZ_Axes(GdkPixmap * pixmap,projection_parameters_t * params,GdkSegment * segment)84 Project_XYZ_Axes(
85 	GdkPixmap *pixmap,
86 	projection_parameters_t *params,
87 	GdkSegment *segment )
88 {
89   double x, y;
90   PangoLayout *layout;
91   GdkSegment *segm = segment;
92 
93   /* cairo context */
94   cairo_t *cr = gdk_cairo_create( pixmap );
95   cairo_set_source_rgb( cr, WHITE );
96 
97   layout =
98 	gtk_widget_create_pango_layout( structure_drawingarea, "x" );
99 
100   segm->x1 = (gint)params->x_center;
101   segm->y1 = params->pixmap_height - (gint)(params->y_center);
102   Project_on_Screen( params, params->r_max, 0.0, 0.0, &x, &y );
103   segm->x2 = (gint)(params->x_center + x*params->xy_scale);
104   segm->y2 = params->pixmap_height -
105 	(gint)(params->y_center + y*params->xy_scale);
106   cairo_move_to( cr, (double)segm->x2, (double)segm->y2 );
107   pango_cairo_show_layout( cr, layout );
108 
109   segm++;
110   segm->x1 = (gint)params->x_center;
111   segm->y1 = params->pixmap_height - (gint)params->y_center;
112   Project_on_Screen( params, 0.0, params->r_max, 0.0, &x, &y );
113   segm->x2 = (gint)(params->x_center + x*params->xy_scale);
114   segm->y2 = params->pixmap_height -
115 	(gint)(params->y_center + y*params->xy_scale);
116   pango_layout_set_text( layout, "y", -1 );
117   cairo_move_to( cr, (double)segm->x2, (double)segm->y2 );
118   pango_cairo_show_layout( cr, layout );
119 
120   segm++;
121   segm->x1 = (gint)params->x_center;
122   segm->y1 = params->pixmap_height - (gint)params->y_center;
123   Project_on_Screen( params, 0.0, 0.0, params->r_max, &x, &y );
124   segm->x2 = (gint)(params->x_center + x*params->xy_scale);
125   segm->y2 = params->pixmap_height -
126 	(gint)(params->y_center + y*params->xy_scale);
127   pango_layout_set_text( layout, " z", -1 );
128   cairo_move_to( cr, (double)segm->x2, (double)segm->y2 );
129   pango_cairo_show_layout( cr, layout );
130   g_object_unref( layout );
131 
132   cairo_destroy( cr );
133 } /* Project_XYZ_Axes() */
134 
135 /*-----------------------------------------------------------------------*/
136 
137 /*  Draw_XYZ_Axes()
138  *
139  *  Draws the xyz axes to Screen
140  */
141   void
Draw_XYZ_Axes(GdkPixmap * pixmap,projection_parameters_t params)142 Draw_XYZ_Axes( GdkPixmap *pixmap, projection_parameters_t params )
143 {
144   static GdkSegment seg[3];
145   cairo_t *cr = gdk_cairo_create( pixmap );
146   cairo_set_source_rgb( cr, WHITE );
147 
148   /* Calcualte Screen co-ordinates of xyz axes */
149   Project_XYZ_Axes( pixmap, &params, seg );
150 
151   /* Draw xyz axes */
152   Cairo_Draw_Segments( cr, seg, 3 );
153 
154   cairo_destroy( cr );
155 } /* Draw_XYZ_Axes() */
156 
157 /*-----------------------------------------------------------------------*/
158 
159 /*  New_Projection_Parameters()
160  *
161  *  Calculates values for some projection parameters when
162  *  a new backing pixmap is created after window resize or
163  *  new wire or patch data is entered.
164  */
165 void
New_Projection_Parameters(int width,int height,projection_parameters_t * params)166 New_Projection_Parameters(
167 	int width, int height,
168 	projection_parameters_t *params )
169 {
170   double size2;
171 
172   if( width < height )
173 	size2 = (double)width/2.0;
174   else
175 	size2 = (double)height/2.0;
176 
177   /* This defines the center of the drawing areas. For the x co-ordinate
178    * half the size of the drawing area is right (for widths of odd number
179    * of pixels, so that there are even and equal number of pixels either
180    * side of center). But for the y co-ordinate we need to round up as
181    * y is from the top down and the y co-ordinate of center is calculated
182    * from height - y_center and this leads to a 1-pixel error */
183   params->x_center = size2;
184   params->y_center = size2 + 0.5;
185 
186   if( params->r_max == 0.0 )
187 	params->xy_scale1 = 1.0;
188   else
189 	params->xy_scale1 = size2 / params->r_max;
190   params->xy_scale = params->xy_scale1 * params->xy_zoom;
191 
192   params->pixmap_width  = width;
193   params->pixmap_height = height;
194 
195 } /* New_Projection_Parameters() */
196 
197 /*-----------------------------------------------------------------------*/
198 
199 /* Value_to_Color()
200  *
201  * Produces an rgb color to represent an
202  * input value relative to a maximum value
203  */
204   void
Value_to_Color(double * red,double * grn,double * blu,double val,double max)205 Value_to_Color( double *red, double *grn, double *blu, double val, double max )
206 {
207   int ival;
208 
209   /* Scale val so that normalized ival is 0-1279 */
210   ival = (int)(1279.0 * val / max);
211 
212   /* Color hue according to imag value */
213   switch( ival/256 )
214   {
215 	case 0: /* 0-255 : magenta to blue */
216 	  *red = 255.0 - (double)ival;
217 	  *grn = 0.0;
218 	  *blu = 255.0;
219 	  break;
220 
221 	case 1: /* 256-511 : blue to cyan */
222 	  *red = 0.0;
223 	  *grn = (double)ival - 256.0;
224 	  *blu = 255.0;
225 	  break;
226 
227 	case 2: /* 512-767 : cyan to green */
228 	  *red = 0.0;
229 	  *grn = 255.0;
230 	  *blu = 767.0 - (double)ival;
231 	  break;
232 
233 	case 3: /* 768-1023 : green to yellow */
234 	  *red = (double)ival - 768.0;
235 	  *grn = 255.0;
236 	  *blu = 0.0;
237 	  break;
238 
239 	case 4: /* 1024-1279 : yellow to red */
240 	  *red = 255.0;
241 	  *grn = 1279.0 - (double)ival;
242 	  *blu = 0.0;
243 
244   } /* switch( imag / 256 ) */
245 
246   /* Scale values between 0.0-1.0 */
247   *red /= 255.0;
248   *grn /= 255.0;
249   *blu /= 255.0;
250 
251 } /* Value_to_Color() */
252 
253 /*-----------------------------------------------------------------------*/
254 
255 /* Cairo_Draw_Polygon()
256  *
257  * Draws a polygon, given a number of points
258  */
259   void
Cairo_Draw_Polygon(cairo_t * cr,GdkPoint * points,int npoints)260 Cairo_Draw_Polygon( cairo_t* cr, GdkPoint *points, int npoints )
261 {
262   int idx;
263 
264   cairo_move_to( cr, (double)points[0].x, (double)points[0].y );
265   for( idx = 1; idx < npoints; idx++ )
266 	cairo_line_to( cr, (double)points[idx].x, (double)points[idx].y );
267   cairo_close_path( cr );
268 
269 } /* Cairo_Draw_Polygon() */
270 
271 /*-----------------------------------------------------------------------*/
272 
273 /* Cairo_Draw_Segments()
274  *
275  * Draws a number of line segments
276  */
277   void
Cairo_Draw_Segments(cairo_t * cr,GdkSegment * segm,int nseg)278 Cairo_Draw_Segments( cairo_t *cr, GdkSegment *segm, int nseg )
279 {
280   int idx;
281 
282   for( idx = 0; idx < nseg; idx++ )
283   {
284 	cairo_move_to( cr, (double)segm[idx].x1, (double)segm[idx].y1 );
285 	cairo_line_to( cr, (double)segm[idx].x2, (double)segm[idx].y2 );
286   }
287   cairo_stroke( cr );
288 } /* Cairo_Draw_Segments() */
289 
290 /*-----------------------------------------------------------------------*/
291 
292 /* Cairo_Draw_Line()
293  *
294  * Draws a line between to x,y co-ordinates
295  */
296   void
Cairo_Draw_Line(cairo_t * cr,int x1,int y1,int x2,int y2)297 Cairo_Draw_Line( cairo_t *cr, int x1, int y1, int x2, int y2 )
298 {
299   cairo_move_to( cr, (double)x1, (double)y1 );
300   cairo_line_to( cr, (double)x2, (double)y2 );
301   cairo_stroke( cr );
302 } /* Cairo_Draw_Line() */
303 
304 /*-----------------------------------------------------------------------*/
305 
306 /* Cairo_Draw_Lines()
307  *
308  * Draws lines between points
309  */
310   void
Cairo_Draw_Lines(cairo_t * cr,GdkPoint * points,int npoints)311 Cairo_Draw_Lines( cairo_t *cr, GdkPoint *points, int npoints )
312 {
313   int idx;
314 
315   cairo_move_to( cr, (double)points[0].x, (double)points[0].y );
316   for( idx = 1; idx < npoints; idx++ )
317 	cairo_line_to( cr, (double)points[idx].x, (double)points[idx].y );
318   cairo_stroke( cr );
319 } /* Cairo_Draw_Line() */
320 
321 /*-----------------------------------------------------------------------*/
322 
323