1 /* gtkplotpolar - polar plots widget for gtk+
2  * Copyright 1999-2001  Adrian E. Feiguin <feiguin@ifir.edu.ar>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library 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 GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <math.h>
24 #include <gtk/gtk.h>
25 #include "gtkplot.h"
26 #include "gtkplotdata.h"
27 #include "gtkplotpolar.h"
28 #include "gtkpsfont.h"
29 #include "gtkplotpc.h"
30 
31 #define P_(string) string
32 
33 #ifndef PI
34 #define PI 3.14159265358979323846
35 #endif
36 
37 static void gtk_plot_polar_class_init 		(GtkPlotPolarClass *klass);
38 static void gtk_plot_polar_init 		(GtkPlotPolar *plot);
39 static void gtk_plot_polar_get_property		(GObject      *object,
40                                                  guint            prop_id,
41                                                  GValue          *value,
42                                                  GParamSpec      *pspec);
43 static void gtk_plot_polar_set_property		(GObject      *object,
44                                                  guint            prop_id,
45                                                  const GValue          *value,
46                                                  GParamSpec      *pspec);
47 static void gtk_plot_polar_real_paint 		(GtkWidget *widget);
48 static void gtk_plot_polar_draw_grids           (GtkPlotPolar *plot);
49 static void gtk_plot_polar_draw_axis		(GtkPlotPolar *plot,
50 					 	 GtkPlotAxis *axis,
51                                                  GtkPlotVector tick_direction);
52 static void gtk_plot_polar_draw_circle		(GtkPlotPolar *polar);
53 static void gtk_plot_polar_draw_labels		(GtkPlotPolar *plot,
54 						 GtkPlotAxis *axis,
55                                                  GtkPlotVector tick_direction );
56 static void gtk_plot_polar_real_get_pixel	(GtkWidget *widget,
57                           			 gdouble x,
58 						 gdouble y,
59                           			 gdouble *px,
60 						 gdouble *py);
61 static void gtk_plot_polar_real_get_point	(GtkWidget *widget,
62 						 gint px,
63 						 gint py,
64                           			 gdouble *x,
65 						 gdouble *y);
66 extern gint roundint			(gdouble x);
67 
68 static GtkPlotClass *parent_class = NULL;
69 
70 enum
71 {
72   ARG_0,
73   ARG_ROTATION,
74 };
75 
76 GtkType
gtk_plot_polar_get_type(void)77 gtk_plot_polar_get_type (void)
78 {
79   static GtkType plot_type = 0;
80 
81   if (!plot_type)
82     {
83       GtkTypeInfo plot_info =
84       {
85 	"GtkPlotPolar",
86 	sizeof (GtkPlotPolar),
87 	sizeof (GtkPlotPolarClass),
88 	(GtkClassInitFunc) gtk_plot_polar_class_init,
89 	(GtkObjectInitFunc) gtk_plot_polar_init,
90 	/* reserved 1*/ NULL,
91         /* reserved 2 */ NULL,
92         (GtkClassInitFunc) NULL,
93       };
94 
95       plot_type = gtk_type_unique (gtk_plot_get_type(), &plot_info);
96     }
97   return plot_type;
98 }
99 
100 static void
gtk_plot_polar_class_init(GtkPlotPolarClass * klass)101 gtk_plot_polar_class_init (GtkPlotPolarClass *klass)
102 {
103   GObjectClass *gobject_class;
104   GtkWidgetClass *widget_class;
105   GtkPlotClass *plot_class;
106 
107   parent_class = gtk_type_class (gtk_plot_get_type ());
108 
109   gobject_class = G_OBJECT_CLASS(klass);
110   widget_class = (GtkWidgetClass *) klass;
111   plot_class = (GtkPlotClass *) klass;
112 
113   gobject_class->set_property = gtk_plot_polar_set_property;
114   gobject_class->get_property = gtk_plot_polar_get_property;
115 
116   plot_class->plot_paint = gtk_plot_polar_real_paint;
117   plot_class->get_point = gtk_plot_polar_real_get_point;
118   plot_class->get_pixel = gtk_plot_polar_real_get_pixel;
119 
120   g_object_class_install_property (gobject_class,
121                            ARG_ROTATION,
122   g_param_spec_double ("rotation",
123                            P_("Angle"),
124                            P_("Rotation Angle"),
125                            -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
126                            G_PARAM_READABLE|G_PARAM_WRITABLE));
127 }
128 
129 
130 static void
gtk_plot_polar_init(GtkPlotPolar * plot)131 gtk_plot_polar_init (GtkPlotPolar *plot)
132 {
133   GTK_PLOT(plot)->legends_attr.transparent = FALSE;
134 
135   GTK_PLOT(plot)->xmin = 0;
136   GTK_PLOT(plot)->xmax = 360;
137 
138   plot->r = GTK_PLOT(plot)->left;
139   plot->angle = GTK_PLOT(plot)->bottom;
140 
141   GTK_PLOT(plot)->bottom->ticks.min = 0.0;
142   GTK_PLOT(plot)->bottom->ticks.max = 360.0;
143   GTK_PLOT(plot)->bottom->ticks.step = 30.;
144   GTK_PLOT(plot)->top->ticks.min = 0.0;
145   GTK_PLOT(plot)->top->ticks.max = 360.0;
146   GTK_PLOT(plot)->top->ticks.step = 30.;
147 
148   GTK_PLOT(plot)->bottom->labels_offset = 15.;
149   GTK_PLOT(plot)->bottom->label_precision = 0;
150 
151   GTK_PLOT(plot)->ymin = 0.2;
152   GTK_PLOT(plot)->left->ticks.min = 0.2;
153   GTK_PLOT(plot)->left->ticks.step = 0.2;
154   GTK_PLOT(plot)->right->ticks.min = 0.2;
155   GTK_PLOT(plot)->right->ticks.step = 0.2;
156 
157   GTK_PLOT(plot)->left->title.angle = 0.;
158 
159   gtk_plot_axis_set_title(GTK_PLOT(plot)->left, "R");
160 
161   GTK_PLOT(plot)->top->is_visible = FALSE;
162 
163   GTK_PLOT(plot)->bottom->show_major_grid = TRUE;
164   GTK_PLOT(plot)->bottom->show_minor_grid = TRUE;
165   GTK_PLOT(plot)->left->show_major_grid = TRUE;
166   GTK_PLOT(plot)->left->show_minor_grid = TRUE;
167 
168   plot->rotation = 0.0;
169 }
170 
171 static void
gtk_plot_polar_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)172 gtk_plot_polar_get_property (GObject      *object,
173                              guint            prop_id,
174                              GValue          *value,
175                              GParamSpec      *pspec)
176 {
177   GtkPlotPolar *plot;
178 
179   plot = GTK_PLOT_POLAR (object);
180 
181   switch(prop_id){
182     case ARG_ROTATION:
183       g_value_set_double(value, plot->rotation);
184       break;
185     default:
186       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
187       break;
188   }
189 }
190 
191 static void
gtk_plot_polar_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)192 gtk_plot_polar_set_property (GObject      *object,
193                              guint            prop_id,
194                              const GValue          *value,
195                              GParamSpec      *pspec)
196 {
197   GtkPlotPolar *plot;
198 
199   plot = GTK_PLOT_POLAR (object);
200 
201   switch(prop_id){
202     case ARG_ROTATION:
203       plot->rotation = g_value_get_double(value);
204       break;
205   }
206 }
207 
208 /*
209 static void
210 gtk_plot_polar_draw (GtkWidget *widget, GdkRectangle *area)
211 {
212   gtk_plot_paint(GTK_PLOT(widget));
213   gtk_plot_refresh (GTK_PLOT(widget), area);
214 }
215 */
216 
217 static void
gtk_plot_polar_real_paint(GtkWidget * widget)218 gtk_plot_polar_real_paint (GtkWidget *widget)
219 {
220   GtkPlot *plot;
221   GtkPlotText *child_text;
222   GtkStyle *style;
223   GdkPixmap *pixmap;
224   GList *dataset;
225   GList *text;
226   gint width, height;
227   gint xoffset, yoffset ;
228   gdouble min;
229 
230   if(!GTK_WIDGET_VISIBLE(widget)) return;
231 
232   plot = GTK_PLOT(widget);
233 
234   xoffset = plot->internal_allocation.x;
235   yoffset = plot->internal_allocation.y;
236   width = plot->internal_allocation.width;
237   height = plot->internal_allocation.height;
238 
239   style = gtk_widget_get_style(widget);
240 
241   pixmap = plot->drawable;
242 
243   gtk_plot_pc_gsave(plot->pc);
244   gtk_plot_pc_set_color(plot->pc, &plot->background);
245 
246   if(!gtk_plot_is_transparent(GTK_PLOT(plot)))
247     gtk_plot_pc_draw_rectangle (plot->pc, TRUE,
248                                xoffset, yoffset,
249                                width , height);
250 
251   /* draw frame to guide the eyes*/
252 /*  gdk_draw_rectangle (pixmap, gc, FALSE,
253                       xoffset, yoffset,
254                       width , height);
255 */
256 
257   /* draw the ticks & grid lines */
258 
259   min = plot->left->ticks.min;
260   plot->left->ticks.min = 0.0;
261   gtk_plot_axis_ticks_recalc(plot->left);
262   gtk_plot_axis_ticks_recalc(plot->bottom);
263   plot->left->ticks.min = min;
264 
265   if(plot->left->is_visible)
266     {
267       GtkPlotVector tick_direction;
268 
269       tick_direction.x = 1.;
270       tick_direction.y = 0.;
271       plot->left->origin.x = (gfloat)width*plot->left_align;
272       plot->left->origin.y = height;
273       gtk_plot_polar_draw_axis(GTK_PLOT_POLAR(plot), plot->left, tick_direction);
274       gtk_plot_polar_draw_labels(GTK_PLOT_POLAR(plot), plot->left, tick_direction);
275     }
276 
277 
278   if(plot->top->is_visible)
279     {
280       GtkPlotVector tick_direction;
281 
282       tick_direction.x = 0.;
283       tick_direction.y = 1.;
284       plot->left->direction.x = 1;
285       plot->left->direction.y = 0;
286       plot->left->origin.x = 0;
287       plot->left->origin.y = (gfloat)height*plot->left_align;
288       gtk_plot_polar_draw_axis(GTK_PLOT_POLAR(plot), plot->left, tick_direction);
289       gtk_plot_polar_draw_labels(GTK_PLOT_POLAR(plot), plot->left, tick_direction);
290       plot->left->direction.x = 0;
291       plot->left->direction.y = -1;
292     }
293 
294   if(plot->bottom->is_visible)
295     {
296       gtk_plot_polar_draw_circle(GTK_PLOT_POLAR(plot));
297     }
298 
299   gtk_plot_polar_draw_grids(GTK_PLOT_POLAR(plot));
300 
301   dataset = plot->data_sets;
302   while(dataset)
303    {
304      GTK_PLOT_DATA_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(dataset->data)))->draw_data(GTK_PLOT_DATA(dataset->data));
305      dataset = dataset->next;
306    }
307 
308   text = plot->text;
309   while(text)
310    {
311      child_text = (GtkPlotText *) text->data;
312      gtk_plot_draw_text(plot, *child_text);
313      text = text->next;
314    }
315 
316   GTK_PLOT_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(plot)))->draw_legends(widget);
317 
318   gtk_plot_pc_grestore(plot->pc);
319 }
320 
321 
322 GtkWidget*
gtk_plot_polar_new(GdkDrawable * drawable)323 gtk_plot_polar_new (GdkDrawable *drawable)
324 {
325   GtkPlotPolar *plot;
326 
327   plot = gtk_type_new (gtk_plot_polar_get_type ());
328 
329   gtk_plot_polar_construct(GTK_PLOT_POLAR(plot), drawable);
330 
331   return GTK_WIDGET (plot);
332 }
333 
334 GtkWidget*
gtk_plot_polar_new_with_size(GdkDrawable * drawable,gdouble width,gdouble height)335 gtk_plot_polar_new_with_size (GdkDrawable *drawable, gdouble width, gdouble height)
336 {
337   GtkWidget *plot;
338 
339   plot = gtk_type_new (gtk_plot_polar_get_type ());
340 
341   gtk_plot_polar_construct_with_size(GTK_PLOT_POLAR(plot), drawable,
342 				     width, height);
343 
344   return(plot);
345 }
346 
347 void
gtk_plot_polar_construct(GtkPlotPolar * plot,GdkDrawable * drawable)348 gtk_plot_polar_construct(GtkPlotPolar *plot, GdkDrawable *drawable)
349 {
350   GTK_PLOT(plot)->drawable = drawable;
351 }
352 
353 void
gtk_plot_polar_construct_with_size(GtkPlotPolar * plot,GdkDrawable * drawable,gdouble width,gdouble height)354 gtk_plot_polar_construct_with_size(GtkPlotPolar *plot, GdkDrawable *drawable, gdouble width, gdouble height)
355 {
356   GTK_PLOT(plot)->drawable = drawable;
357   gtk_plot_resize (GTK_PLOT(plot), width, height);
358 }
359 
360 static void
gtk_plot_polar_draw_grids(GtkPlotPolar * polar)361 gtk_plot_polar_draw_grids(GtkPlotPolar *polar)
362 {
363   GtkWidget *widget;
364   GtkPlot *plot;
365   gdouble ix, iy;
366   gdouble x1, y1, x2, y2;
367   gdouble width, height, size;
368   gdouble xp, yp;
369   gint ntick;
370   gdouble ox, oy;
371   gdouble rotation;
372 
373   widget = GTK_WIDGET(polar);
374   plot = GTK_PLOT(polar);
375 
376   rotation = polar->rotation;
377 
378   xp = plot->internal_allocation.x;
379   yp = plot->internal_allocation.y;
380   width = plot->internal_allocation.width;
381   height = plot->internal_allocation.height;
382 
383   ox = xp + width / 2.;
384   oy = yp + height / 2.;
385   size = MIN(width, height) / 2.;
386 
387   if(plot->bottom->show_minor_grid)
388     {
389           for(ntick = 0; ntick < plot->bottom->ticks.nticks; ntick++){
390             if(!plot->bottom->ticks.values[ntick].minor) continue;
391             if(plot->bottom->ticks.values[ntick].value >= plot->bottom->ticks.min){
392               gtk_plot_get_pixel(plot,
393                                  plot->ymax,
394                                  plot->bottom->ticks.values[ntick].value,
395                                  &x1, &y1);
396               gtk_plot_get_pixel(plot,
397                                  plot->ymin,
398                                  plot->bottom->ticks.values[ntick].value,
399                                  &x2, &y2);
400               gtk_plot_draw_line(plot, plot->bottom->minor_grid,
401                                  x1, y1, x2, y2);
402             }
403           }
404     }
405   if(plot->bottom->show_major_grid)
406     {
407           for(ntick = 0; ntick < plot->bottom->ticks.nticks; ntick++){
408            if(plot->bottom->ticks.values[ntick].minor) continue;
409            if(plot->bottom->ticks.values[ntick].value >= plot->bottom->ticks.min){
410               gtk_plot_get_pixel(plot,
411                                  plot->ymax,
412                                  plot->bottom->ticks.values[ntick].value,
413                                  &x1, &y1);
414               gtk_plot_get_pixel(plot,
415                                  plot->ymin,
416                                  plot->bottom->ticks.values[ntick].value,
417                                  &x2, &y2);
418               gtk_plot_draw_line(plot, plot->bottom->major_grid,
419                                  x1, y1, x2, y2);
420            }
421           }
422     }
423   if(plot->left->show_minor_grid)
424     {
425           gtk_plot_set_line_attributes(plot, plot->left->minor_grid);
426           for(ntick = 0; ntick < plot->left->ticks.nticks; ntick++){
427             if(!plot->left->ticks.values[ntick].minor) continue;
428             if(plot->left->ticks.values[ntick].value >= plot->left->ticks.min){
429               gtk_plot_get_pixel(plot,
430                                  plot->left->ticks.values[ntick].value,
431                                  90.0 - rotation,
432                                  &ix, &iy);
433               iy = fabs(oy - iy);
434               gtk_plot_pc_draw_circle (plot->pc,
435                                       FALSE,
436                                       ox, oy,
437                                       2 * iy);
438             }
439           }
440     }
441   if(plot->left->show_major_grid)
442 
443     {
444           gtk_plot_set_line_attributes(plot, plot->left->major_grid);
445           for(ntick = 0; ntick < plot->left->ticks.nticks; ntick++){
446             if(plot->left->ticks.values[ntick].minor) continue;
447             if(plot->left->ticks.values[ntick].value >= plot->left->ticks.min){
448               gtk_plot_get_pixel(plot,
449                                  plot->left->ticks.values[ntick].value,
450                                  90.0 - rotation,
451                                  &ix, &iy);
452               iy = fabs(oy - iy);
453               gtk_plot_pc_draw_circle (plot->pc,
454                                       FALSE,
455                                       ox, oy,
456                                       2 * iy);
457             }
458           }
459     }
460 
461 }
462 
463 static void
gtk_plot_polar_draw_axis(GtkPlotPolar * polar,GtkPlotAxis * axis,GtkPlotVector tick_direction)464 gtk_plot_polar_draw_axis(GtkPlotPolar *polar,
465                          GtkPlotAxis *axis, GtkPlotVector tick_direction)
466 {
467   GtkWidget *widget;
468   GtkPlot *plot;
469   gdouble x, y;
470   gdouble xx, yy;
471   gdouble x_tick;
472   gdouble xp, yp, width, height, size;
473   gint ntick;
474   gdouble m;
475   gdouble x1, y1;
476   gdouble ox, oy;
477   gdouble x0, y0;
478 
479   widget = GTK_WIDGET(polar);
480   plot = GTK_PLOT(polar);
481 
482   m = plot->magnification;
483 
484   xp = plot->internal_allocation.x;
485   yp = plot->internal_allocation.y;
486   width = plot->internal_allocation.width;
487   height = plot->internal_allocation.height;
488 
489   size = MIN(width, height);
490 
491   ox = width / 2.;
492   oy = height / 2.;
493 
494   x = xp + ox * axis->direction.x + axis->origin.x;
495   y = yp + oy * axis->direction.y + axis->origin.y;
496 
497   if(axis->direction.x == 0)
498     gtk_plot_get_pixel(plot, 0, -polar->rotation+90, &x0, &y0);
499   else
500     gtk_plot_get_pixel(plot, 0, -polar->rotation, &y0, &x0);
501 
502   gtk_plot_draw_line(plot, axis->line,
503                 x - size / 2.0 * axis->direction.x,
504                 y - size / 2.0 * axis->direction.y,
505                 x + axis->direction.x * size / 2.0,
506                 y + axis->direction.y * size / 2.0);
507   gtk_plot_pc_set_lineattr(plot->pc, axis->ticks_width, 0, 1, 0);
508 
509   for(ntick = 0; ntick < axis->ticks.nticks; ntick++){
510     x_tick = axis->ticks.values[ntick].value;
511     if(axis->direction.x == 0)
512       gtk_plot_get_pixel(plot, x_tick, -polar->rotation+90, &xx, &yy);
513     else
514       gtk_plot_get_pixel(plot, x_tick, -polar->rotation, &yy, &xx);
515 
516     yy = yy - y0;
517     if(!axis->ticks.values[ntick].minor && x_tick >= axis->ticks.min){
518       if(axis->major_mask & GTK_PLOT_TICKS_IN){
519          x1 = x + yy * axis->direction.x;
520          y1 = y + yy * axis->direction.y;
521          gtk_plot_pc_draw_line(plot->pc,
522                        x1,
523                        y1,
524                        x1 + tick_direction.x * m * axis->ticks_length,
525                        y1 + tick_direction.y * m * axis->ticks_length);
526          x1 = x - yy * axis->direction.x;
527          y1 = y - yy * axis->direction.y;
528          gtk_plot_pc_draw_line(plot->pc,
529                        x1,
530                        y1,
531                        x1 + tick_direction.x * m * axis->ticks_length,
532                        y1 + tick_direction.y * m * axis->ticks_length);
533       }
534       if(axis->major_mask & GTK_PLOT_TICKS_OUT){
535          x1 = x + yy * axis->direction.x;
536          y1 = y + yy * axis->direction.y;
537          gtk_plot_pc_draw_line(plot->pc,
538                        x1,
539                        y1,
540                        x1 - tick_direction.x * m * axis->ticks_length,
541                        y1 - tick_direction.y * m * axis->ticks_length);
542          x1 = x - yy * axis->direction.x;
543          y1 = y - yy * axis->direction.y;
544          gtk_plot_pc_draw_line(plot->pc,
545                        x1,
546                        y1,
547                        x1 - tick_direction.x * m * axis->ticks_length,
548                        y1 - tick_direction.y * m * axis->ticks_length);
549       }
550     }
551     if(axis->ticks.values[ntick].minor && x_tick >= axis->ticks.min){
552       if(axis->minor_mask & GTK_PLOT_TICKS_IN){
553          x1 = x + yy * axis->direction.x;
554          y1 = y + yy * axis->direction.y;
555          gtk_plot_pc_draw_line(plot->pc,
556                        x1,
557                        y1,
558                        x1 + tick_direction.x * m * axis->ticks_length/2.,
559                        y1 + tick_direction.y * m * axis->ticks_length/2.);
560          x1 = x - yy * axis->direction.x;
561          y1 = y - yy * axis->direction.y;
562          gtk_plot_pc_draw_line(plot->pc,
563                        x1,
564                        y1,
565                        x1 + tick_direction.x * m * axis->ticks_length/2.,
566                        y1 + tick_direction.y * m * axis->ticks_length/2.);
567       }
568       if(axis->minor_mask & GTK_PLOT_TICKS_OUT){
569          x1 = x + yy * axis->direction.x;
570          y1 = y + yy * axis->direction.y;
571          gtk_plot_pc_draw_line(plot->pc,
572                        x1,
573                        y1,
574                        x1 - tick_direction.x * m * axis->ticks_length/2.,
575                        y1 - tick_direction.y * m * axis->ticks_length/2.);
576          x1 = x - yy * axis->direction.x;
577          y1 = y - yy * axis->direction.y;
578          gtk_plot_pc_draw_line(plot->pc,
579                        x1,
580                        y1,
581                        x1 - tick_direction.x * m * axis->ticks_length/2.,
582                        y1 - tick_direction.y * m * axis->ticks_length/2.);
583       }
584     }
585   }
586 
587 }
588 
589 
590 static void
gtk_plot_polar_draw_labels(GtkPlotPolar * polar,GtkPlotAxis * axis,GtkPlotVector tick_direction)591 gtk_plot_polar_draw_labels(GtkPlotPolar *polar,
592                            GtkPlotAxis *axis,
593                            GtkPlotVector tick_direction)
594 {
595   GtkWidget *widget;
596   GtkPlot *plot;
597   GtkPlotText title, tick;
598   gchar label[100];
599   gdouble x_tick;
600   gint x, y;
601   gdouble xx, yy;
602   gint ox, oy;
603   gint text_height, text_width, ascent, descent;
604   gint xp, yp, width, height;
605   gint ntick;
606   gdouble m;
607   gboolean veto = FALSE;
608   gdouble x0, y0;
609 
610   widget = GTK_WIDGET(polar);
611   plot = GTK_PLOT(polar);
612 
613   m = plot->magnification;
614 
615   xp = plot->internal_allocation.x;
616   yp = plot->internal_allocation.y;
617   width = plot->internal_allocation.width;
618   height = plot->internal_allocation.height;
619 
620   ox = width / 2.;
621   oy = height / 2.;
622 
623   x = xp + ox * axis->direction.x + axis->origin.x;
624   y = yp + oy * axis->direction.y + axis->origin.y;
625 
626   gtk_plot_pc_set_color(plot->pc, &axis->labels_attr.fg);
627 
628   gtk_plot_text_get_size("0", 0, axis->labels_attr.font, roundint(axis->labels_attr.height * m), &text_width, &text_height, &ascent, &descent);
629 
630   switch(axis->labels_attr.angle){
631     case 0:
632            y += text_height / 2.;
633            break;
634     case 90:
635            break;
636     case 180:
637            y -= text_height / 2.;
638            break;
639     case 270:
640            break;
641   }
642 
643   if(axis->direction.x == 0)
644     gtk_plot_get_pixel(plot, 0, -polar->rotation+90, &x0, &y0);
645   else
646     gtk_plot_get_pixel(plot, 0, -polar->rotation, &y0, &x0);
647 
648   tick = axis->labels_attr;
649   for(ntick = 0; ntick < axis->ticks.nticks; ntick++){
650     if(axis->ticks.values[ntick].minor) continue;
651     x_tick = axis->ticks.values[ntick].value;
652     if(axis->direction.x == 0)
653       gtk_plot_get_pixel(plot, x_tick, -polar->rotation+90, &xx, &yy);
654     else
655       gtk_plot_get_pixel(plot, x_tick, -polar->rotation, &yy, &xx);
656     yy = yy - y0;
657     xx = axis->direction.x * yy;
658     yy = axis->direction.y * yy;
659     if(x_tick >= axis->ticks.min-1.e-9){
660       if(!axis->custom_labels){
661         gtk_plot_axis_parse_label(axis, x_tick, axis->label_precision, axis->label_style, label);
662       }
663       else
664       {
665         gtk_signal_emit_by_name(GTK_OBJECT(axis), "tick_label",
666                                 &x_tick, label, &veto);
667         if(!veto)
668           gtk_plot_axis_parse_label(axis, x_tick, axis->label_precision, axis->label_style, label);
669       }
670       tick.text = label;
671 
672       if(axis->label_mask & GTK_PLOT_LABEL_IN){
673          tick.x = x + xx;
674          tick.y = y + yy;
675          tick.x = tick.x + tick_direction.x*roundint(axis->labels_offset * m);
676          tick.y = tick.y + tick_direction.y*roundint(axis->labels_offset * m);
677          tick.x = (gdouble)tick.x / (gdouble)widget->allocation.width;
678          tick.y = (gdouble)tick.y / (gdouble)widget->allocation.height;
679          gtk_plot_draw_text(plot, tick);
680          tick.x = x - xx;
681          tick.y = y - yy;
682          tick.x = tick.x + tick_direction.x*roundint(axis->labels_offset * m);
683          tick.y = tick.y + tick_direction.y*roundint(axis->labels_offset * m);
684          tick.x = (gdouble)tick.x / (gdouble)widget->allocation.width;
685          tick.y = (gdouble)tick.y / (gdouble)widget->allocation.height;
686          gtk_plot_draw_text(plot, tick);
687       }
688       if(axis->label_mask & GTK_PLOT_LABEL_OUT){
689          tick.x = x + xx;
690          tick.y = y + yy;
691          tick.x = tick.x - tick_direction.x*roundint(axis->labels_offset * m);
692          tick.y = tick.y - tick_direction.y*roundint(axis->labels_offset * m);
693          tick.x = (gdouble)tick.x / (gdouble)widget->allocation.width;
694          tick.y = (gdouble)tick.y / (gdouble)widget->allocation.height;
695          gtk_plot_draw_text(plot, tick);
696          tick.x = x - xx;
697          tick.y = y - yy;
698          tick.x = tick.x - tick_direction.x*roundint(axis->labels_offset * m);
699          tick.y = tick.y - tick_direction.y*roundint(axis->labels_offset * m);
700          tick.x = (gdouble)tick.x / (gdouble)widget->allocation.width;
701          tick.y = (gdouble)tick.y / (gdouble)widget->allocation.height;
702          gtk_plot_draw_text(plot, tick);
703       }
704     }
705   }
706   if(axis->title_visible && axis->title.text)
707        {
708          title = axis->title;
709          gtk_plot_draw_text(plot, title);
710        }
711 }
712 
713 static void
gtk_plot_polar_draw_circle(GtkPlotPolar * polar)714 gtk_plot_polar_draw_circle(GtkPlotPolar *polar)
715 {
716   GtkWidget *widget;
717   GtkPlot *plot;
718   GtkPlotAxis *axis, perp;
719   GtkPlotText tick;
720   gchar label[100];
721   gdouble x, y;
722   gint line_width;
723   gdouble xp, yp, width, height, size;
724   gint ntick;
725   gdouble m;
726   gdouble x_tick = 0.;
727   gdouble x1, y1;
728   gdouble ox, oy;
729   gint text_height, text_width, ascent, descent;
730   gdouble rotation;
731   gboolean veto = FALSE;
732   gint sign = 1;
733 
734   widget = GTK_WIDGET(polar);
735   plot = GTK_PLOT(polar);
736 
737   m = plot->magnification;
738   rotation = polar->rotation;
739   if(plot->reflect_y) sign = -1;
740 
741   xp = plot->internal_allocation.x;
742   yp = plot->internal_allocation.y;
743   width = plot->internal_allocation.width;
744   height = plot->internal_allocation.height;
745 
746   ox = width / 2.;
747   oy = height / 2.;
748 
749   x = xp + ox;
750   y = yp + oy;
751 
752   axis = plot->bottom;
753 
754   line_width = axis->line.line_width;
755   gtk_plot_pc_set_color(plot->pc, &axis->line.color);
756 
757   gtk_plot_pc_set_lineattr(plot->pc, axis->line.line_width, 0, 3, 0);
758 
759   gtk_plot_get_pixel(plot,
760                      plot->ymax,
761                      90.0 - rotation,
762                      &x1, &size);
763   size = fabs(size - y);
764   gtk_plot_pc_draw_circle (plot->pc,
765                           FALSE,
766                           x, y,
767                           2 * size);
768 
769   gtk_plot_pc_set_lineattr(plot->pc, axis->ticks_width, 0, 1, 0);
770 
771   gtk_plot_text_get_size("0", 0, axis->labels_attr.font, roundint(axis->labels_attr.height * m), &text_width, &text_height, &ascent, &descent);
772 
773   for(ntick = 0; ntick < axis->ticks.nticks; ntick++){
774     x_tick = axis->ticks.values[ntick].value;
775     if(!axis->ticks.values[ntick].minor && x_tick >= axis->ticks.min){
776 
777       if(!axis->custom_labels){
778         gtk_plot_axis_parse_label(axis, x_tick, axis->label_precision, axis->label_style, label);
779       }
780       else
781       {
782         gtk_signal_emit_by_name(GTK_OBJECT(axis), "tick_label",
783                                 &x_tick, label, &veto);
784         if(!veto)
785           gtk_plot_axis_parse_label(axis, x_tick, axis->label_precision, axis->label_style, label);
786       }
787 
788       gtk_plot_get_pixel(plot,
789                          plot->ymax,
790                          x_tick,
791                          &x1, &y1);
792 
793       x_tick += rotation;
794 
795       if(axis->major_mask & GTK_PLOT_TICKS_IN){
796          perp.direction.x = cos(x_tick * PI / 180. * sign);
797          perp.direction.y = -sin(x_tick * PI / 180. * sign);
798          gtk_plot_pc_draw_line(plot->pc,
799                        x1,
800                        y1,
801                        x1 + perp.direction.x*m*axis->ticks_length,
802                        y1 + perp.direction.y*m*axis->ticks_length);
803       }
804       if(axis->major_mask & GTK_PLOT_TICKS_OUT){
805          perp.direction.x = -cos(x_tick * PI / 180. * sign);
806          perp.direction.y = sin(x_tick * PI / 180. * sign);
807          gtk_plot_pc_draw_line(plot->pc,
808                        x1,
809                        y1,
810                        x1 - perp.direction.x*m*axis->ticks_length,
811                        y1 - perp.direction.y*m*axis->ticks_length);
812       }
813 
814       tick = axis->labels_attr;
815       tick.text = label;
816 
817       if((x_tick >= 0.0 && x_tick < 90.0) || (x_tick > 270.0 && x_tick <= 360.0))
818                                   tick.justification = GTK_JUSTIFY_LEFT;
819       if(x_tick > 90.0 && x_tick < 270.0)
820                                   tick.justification = GTK_JUSTIFY_RIGHT;
821       if(x_tick == 90.0 || x_tick == 270.0)
822                                   tick.justification = GTK_JUSTIFY_CENTER;
823       y1 += text_height / 2;
824 
825       if((x_tick - rotation) != 360.0 && axis->label_mask != 0){
826          perp.direction.x = -cos(x_tick * PI / 180. * sign);
827          perp.direction.y = sin(x_tick * PI / 180. * sign);
828          tick.x = x1;
829          tick.y = y1;
830          tick.x -= roundint(perp.direction.x*axis->labels_offset * m);
831          tick.y -= roundint(perp.direction.y*axis->labels_offset * m);
832          tick.x = (gdouble)tick.x / (gdouble)widget->allocation.width;
833          tick.y = (gdouble)tick.y / (gdouble)widget->allocation.height;
834          gtk_plot_draw_text(plot, tick);
835       }
836 
837     }
838     if(axis->ticks.values[ntick].minor && x_tick >= axis->ticks.min){
839 
840       gtk_plot_get_pixel(plot,
841                          plot->ymax,
842                          x_tick,
843                          &x1, &y1);
844 
845       x_tick += rotation;
846 
847       if(axis->minor_mask & GTK_PLOT_TICKS_IN){
848          perp.direction.x = cos(x_tick * PI / 180. * sign);
849          perp.direction.y = -sin(x_tick * PI / 180. * sign);
850          gtk_plot_pc_draw_line(plot->pc,
851                        x1,
852                        y1,
853                        x1 + perp.direction.x*m*axis->ticks_length/2.,
854                        y1 + perp.direction.y*m*axis->ticks_length/2.);
855       }
856       if(axis->minor_mask & GTK_PLOT_TICKS_OUT){
857          perp.direction.x = -cos(x_tick * PI / 180. * sign);
858          perp.direction.y = sin(x_tick * PI / 180. * sign);
859          gtk_plot_pc_draw_line(plot->pc,
860                        x1,
861                        y1,
862                        x1 - perp.direction.x*m*axis->ticks_length/2.,
863                        y1 - perp.direction.y*m*axis->ticks_length/2.);
864       }
865     }
866   }
867 }
868 
869 static void
gtk_plot_polar_real_get_pixel(GtkWidget * widget,gdouble x,gdouble y,gdouble * px,gdouble * py)870 gtk_plot_polar_real_get_pixel(GtkWidget *widget,
871                               gdouble x, gdouble y,
872                               gdouble *px, gdouble *py)
873 {
874     GtkPlot *plot;
875     GtkPlotPolar *polar;
876     gdouble xp, yp, width, height, size;
877     gdouble ox, oy;
878     gint sign = 1;
879     gdouble min;
880 
881     plot = GTK_PLOT(widget);
882     polar = GTK_PLOT_POLAR(widget);
883 
884     if(plot->reflect_y) sign = -1;
885 
886     xp = plot->internal_allocation.x;
887     yp = plot->internal_allocation.y;
888     width = plot->internal_allocation.width;
889     height = plot->internal_allocation.height;
890 
891     size = MIN(width, height) / 2.;
892 
893     ox = xp + width / 2.0;
894     oy = yp + height / 2.0;
895 
896     min = plot->left->ticks.min;
897     plot->left->ticks.min = 0.0;
898     x = gtk_plot_axis_ticks_transform(plot->left, x)*size;
899     plot->left->ticks.min = min;
900 
901     *px = ox + x * cos((y + polar->rotation) / 180. * PI * sign);
902     *py = oy - x * sin((y + polar->rotation)/ 180. * PI * sign);
903 
904 }
905 
906 static void
gtk_plot_polar_real_get_point(GtkWidget * widget,gint px,gint py,gdouble * x,gdouble * y)907 gtk_plot_polar_real_get_point(GtkWidget *widget,
908                               gint px, gint py,
909                               gdouble *x, gdouble *y)
910 {
911     GtkPlot *plot;
912     gint xp, yp, width, height;
913     gdouble r = 0;
914     gdouble angle = 0;
915     gint ox, oy, size;
916     gdouble rotation;
917 
918     plot = GTK_PLOT(widget);
919     xp = plot->internal_allocation.x;
920     yp = plot->internal_allocation.y;
921     width = plot->internal_allocation.width;
922     height = plot->internal_allocation.height;
923 
924     rotation = GTK_PLOT_POLAR(widget)->rotation;
925 
926     ox = xp + width / 2;
927     oy = yp + height / 2;
928 
929     size = MIN(width, height);
930 
931     px = px - ox;
932     py = oy - py;
933 
934     if(px == 0){
935       if(py >= 0) angle = 90.0 - rotation;
936       if(py < 0) angle = 270.0 - rotation;
937     }
938     else {
939       angle = (gdouble) abs(py) / (gdouble) abs(px);
940       angle = atan(angle);
941       angle = angle * 180.0 / PI;
942       if(px >= 0 && py < 0) angle = 360.0 - angle;
943       if(px < 0 && py >= 0) angle = 180.0 - angle;
944       if(px < 0 && py < 0) angle += 180.0;
945       angle -= rotation;
946     }
947 
948     if(angle >= 360.0) angle -= 360.0;
949     if(angle < 0.0) angle = 360.0 + angle;
950 
951     r = sqrt(px * px + py * py);
952 
953     *x = 2.0 * r * plot->ymax / (gdouble) size;
954     *y = plot->reflect_y ? -angle : angle;
955 }
956 
957 
958 /*******************************************
959  * gtk_plot_polar_rotate
960  *******************************************/
961 void
gtk_plot_polar_rotate(GtkPlotPolar * polar,gdouble angle)962 gtk_plot_polar_rotate(GtkPlotPolar *polar, gdouble angle)
963 {
964   polar->rotation = angle;
965 
966   gtk_signal_emit_by_name(GTK_OBJECT(polar), "update", TRUE);
967   gtk_signal_emit_by_name(GTK_OBJECT(polar), "changed");
968 }
969 
970 
971 gdouble
gtk_plot_polar_get_angle(GtkPlotPolar * polar)972 gtk_plot_polar_get_angle(GtkPlotPolar *polar)
973 {
974   return polar->rotation;
975 }
976 
977