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, ¶ms, 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