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