tioga 1.11 → 1.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/Tioga_README +58 -35
  2. data/{split/scripts → bin}/tioga +1 -1
  3. data/{split → ext/Dobjects}/Dtable/dtable.c +81 -15
  4. data/{split → ext/Dobjects}/Dtable/dtable_intern.h +0 -0
  5. data/ext/Dobjects/Dtable/extconf.rb +7 -0
  6. data/{split → ext/Dobjects}/Dtable/include/dtable.h +0 -0
  7. data/{split → ext/Dobjects}/Dvector/dvector.c +361 -51
  8. data/{split → ext/Dobjects}/Dvector/dvector_intern.h +0 -0
  9. data/ext/Dobjects/Dvector/extconf.rb +22 -0
  10. data/{split/Dtable → ext/Dobjects/Dvector/include}/dvector.h +0 -0
  11. data/ext/Dobjects/Function/extconf.rb +7 -0
  12. data/{split → ext/Dobjects}/Function/function.c +636 -11
  13. data/{split → ext/Dobjects}/Function/joint_qsort.c +0 -0
  14. data/ext/Flate/extconf.rb +26 -0
  15. data/{split → ext}/Flate/flate.c +7 -3
  16. data/{split → ext}/Flate/flate_intern.h +0 -0
  17. data/{split → ext}/Flate/include/flate.h +0 -0
  18. data/ext/Flate/zlib/adler32.c +149 -0
  19. data/ext/Flate/zlib/compress.c +79 -0
  20. data/ext/Flate/zlib/crc32.c +423 -0
  21. data/ext/Flate/zlib/crc32.h +441 -0
  22. data/ext/Flate/zlib/deflate.c +1736 -0
  23. data/ext/Flate/zlib/deflate.h +331 -0
  24. data/ext/Flate/zlib/gzio.c +1026 -0
  25. data/ext/Flate/zlib/infback.c +623 -0
  26. data/ext/Flate/zlib/inffast.c +318 -0
  27. data/ext/Flate/zlib/inffast.h +11 -0
  28. data/ext/Flate/zlib/inffixed.h +94 -0
  29. data/ext/Flate/zlib/inflate.c +1368 -0
  30. data/ext/Flate/zlib/inflate.h +115 -0
  31. data/ext/Flate/zlib/inftrees.c +329 -0
  32. data/ext/Flate/zlib/inftrees.h +55 -0
  33. data/ext/Flate/zlib/trees.c +1219 -0
  34. data/ext/Flate/zlib/trees.h +128 -0
  35. data/ext/Flate/zlib/uncompr.c +61 -0
  36. data/ext/Flate/zlib/zlib.h +1357 -0
  37. data/ext/Flate/zlib/zutil.c +318 -0
  38. data/ext/Flate/zlib/zutil.h +269 -0
  39. data/ext/Tioga/FigureMaker/__shared_axes.c +1373 -0
  40. data/ext/Tioga/FigureMaker/__shared_makers.c +1303 -0
  41. data/{split/Tioga/pdf_font_dicts.c → ext/Tioga/FigureMaker/__shared_pdf_font_dicts.c} +0 -0
  42. data/{split/Tioga/pdfcolor.c → ext/Tioga/FigureMaker/__shared_pdfcolor.c} +0 -0
  43. data/{split/Tioga/pdfcoords.c → ext/Tioga/FigureMaker/__shared_pdfcoords.c} +0 -0
  44. data/{split/Tioga/pdffile.c → ext/Tioga/FigureMaker/__shared_pdffile.c} +0 -0
  45. data/{split/Tioga/pdfimage.c → ext/Tioga/FigureMaker/__shared_pdfimage.c} +0 -0
  46. data/{split/Tioga/pdfpath.c → ext/Tioga/FigureMaker/__shared_pdfpath.c} +0 -0
  47. data/{split/Tioga/pdftext.c → ext/Tioga/FigureMaker/__shared_pdftext.c} +0 -0
  48. data/{split/Tioga/texout.c → ext/Tioga/FigureMaker/__shared_texout.c} +0 -0
  49. data/ext/Tioga/FigureMaker/extconf.rb +7 -0
  50. data/{split/Tioga → ext/Tioga/FigureMaker}/figures.c +14 -2
  51. data/{split/Tioga → ext/Tioga/FigureMaker}/figures.h +0 -0
  52. data/{split/Tioga → ext/Tioga/FigureMaker}/generic.c +1 -2
  53. data/{split/Tioga → ext/Tioga/FigureMaker}/generic.h +0 -1
  54. data/{split/Tioga → ext/Tioga/FigureMaker}/init.c +0 -0
  55. data/{split/Tioga → ext/Tioga/FigureMaker}/pdfs.h +0 -0
  56. data/{split/Tioga → ext/Tioga/FigureMaker/shared}/axes.c +32 -7
  57. data/{split/Tioga → ext/Tioga/FigureMaker/shared}/makers.c +2 -2
  58. data/ext/Tioga/FigureMaker/shared/pdf_font_dicts.c +18253 -0
  59. data/ext/Tioga/FigureMaker/shared/pdfcolor.c +904 -0
  60. data/ext/Tioga/FigureMaker/shared/pdfcoords.c +518 -0
  61. data/ext/Tioga/FigureMaker/shared/pdffile.c +451 -0
  62. data/ext/Tioga/FigureMaker/shared/pdfimage.c +539 -0
  63. data/ext/Tioga/FigureMaker/shared/pdfpath.c +766 -0
  64. data/ext/Tioga/FigureMaker/shared/pdftext.c +710 -0
  65. data/ext/Tioga/FigureMaker/shared/texout.c +533 -0
  66. data/{split/Tioga → ext/Tioga/FigureMaker}/wrappers.c +5 -5
  67. data/{split/Tioga → ext/Tioga/FigureMaker}/wrappers.h +0 -0
  68. data/{split/Dtable → ext/includes}/defs.h +0 -0
  69. data/{split/Dtable → ext/includes}/namespace.h +0 -0
  70. data/{split/Dtable → ext/includes}/safe_double.h +0 -0
  71. data/{split → ext/includes}/symbols.c +0 -1
  72. data/{split/Dtable → ext/includes}/symbols.h +0 -0
  73. data/{split/Dtable/lib → lib/Dobjects}/Dtable_extras.rb +0 -0
  74. data/{split/Dvector/lib → lib/Dobjects}/Dvector_extras.rb +1 -0
  75. data/{split/Function/lib → lib/Dobjects}/Function_extras.rb +0 -0
  76. data/{split/Dvector/lib → lib/Dobjects}/Numeric_extras.rb +0 -0
  77. data/{split/Tioga/lib → lib/Tioga}/Arcs_and_Circles.rb +0 -0
  78. data/{split/Tioga/lib → lib/Tioga}/ColorConstants.rb +0 -0
  79. data/{split/Tioga/lib → lib/Tioga}/Colorbars.rb +0 -0
  80. data/{split/Tioga/lib → lib/Tioga}/Colormaps.rb +0 -0
  81. data/{split/Tioga/lib → lib/Tioga}/Coordinate_Conversions.rb +0 -0
  82. data/{split/Tioga/lib → lib/Tioga}/Creating_Paths.rb +0 -0
  83. data/{split/Tioga/lib → lib/Tioga}/Doc.rb +0 -0
  84. data/{split/Tioga/lib → lib/Tioga}/Executive.rb +0 -0
  85. data/{split/Tioga/lib → lib/Tioga}/FigMkr.rb +13 -70
  86. data/{split/Tioga/lib → lib/Tioga}/FigureConstants.rb +0 -0
  87. data/{split/Tioga/lib → lib/Tioga}/Figures_and_Plots.rb +0 -0
  88. data/{split/Tioga/lib → lib/Tioga}/Images.rb +0 -0
  89. data/{split/Tioga/lib → lib/Tioga}/Legends.rb +0 -0
  90. data/{split/Tioga/lib → lib/Tioga}/MarkerConstants.rb +0 -0
  91. data/{split/Tioga/lib → lib/Tioga}/Markers.rb +0 -0
  92. data/{split/Tioga/lib → lib/Tioga}/Page_Frame_Bounds.rb +0 -0
  93. data/{split/Tioga/lib → lib/Tioga}/Rectangles.rb +0 -0
  94. data/{split/Tioga/lib → lib/Tioga}/Shading.rb +0 -0
  95. data/{split/Tioga/lib → lib/Tioga}/Special_Paths.rb +0 -0
  96. data/{split/Tioga/lib → lib/Tioga}/Strokes.rb +0 -0
  97. data/{split/Tioga/lib → lib/Tioga}/TeX_Text.rb +0 -0
  98. data/{split/Tioga/lib → lib/Tioga}/TexPreamble.rb +0 -0
  99. data/{split/Tioga/lib → lib/Tioga}/Titles_and_Labels.rb +0 -0
  100. data/{split/Tioga/lib → lib/Tioga}/Transparency.rb +0 -0
  101. data/{split/Tioga/lib → lib/Tioga}/Using_Paths.rb +0 -0
  102. data/{split/Tioga/lib → lib/Tioga}/Utils.rb +74 -0
  103. data/{split/Tioga/lib → lib/Tioga}/X_and_Y_Axes.rb +0 -0
  104. data/{split/Tioga/lib → lib/Tioga}/irb_tioga.rb +0 -0
  105. data/{split/Tioga/lib → lib/Tioga}/maker.rb +0 -0
  106. data/{split/Tioga/lib → lib/Tioga}/tioga.rb +0 -0
  107. data/{split/Tioga/lib → lib/Tioga}/tioga_ui.rb +0 -0
  108. data/{split/Tioga/lib → lib/Tioga}/tioga_ui_cmds.rb +0 -0
  109. data/tests/Icon_Test.pdf +0 -0
  110. data/tests/benchmark_dvector_reads.rb +20 -42
  111. data/tests/tc_Dvector.rb +45 -4
  112. data/tests/tc_Flate.rb +4 -5
  113. data/tests/tc_Function.rb +79 -0
  114. data/tests/vg.log +1453 -0
  115. metadata +141 -122
  116. data/split/Dtable/extconf.rb +0 -4
  117. data/split/Dvector/defs.h +0 -39
  118. data/split/Dvector/extconf.rb +0 -4
  119. data/split/Dvector/include/dvector.h +0 -77
  120. data/split/Dvector/namespace.h +0 -59
  121. data/split/Dvector/safe_double.h +0 -104
  122. data/split/Dvector/symbols.h +0 -52
  123. data/split/Flate/defs.h +0 -39
  124. data/split/Flate/extconf.rb +0 -19
  125. data/split/Flate/namespace.h +0 -59
  126. data/split/Flate/safe_double.h +0 -104
  127. data/split/Flate/symbols.h +0 -52
  128. data/split/Function/defs.h +0 -39
  129. data/split/Function/dvector.h +0 -77
  130. data/split/Function/extconf.rb +0 -4
  131. data/split/Function/namespace.h +0 -59
  132. data/split/Function/safe_double.h +0 -104
  133. data/split/Function/symbols.h +0 -52
  134. data/split/Tioga/defs.h +0 -39
  135. data/split/Tioga/dtable.h +0 -35
  136. data/split/Tioga/dvector.h +0 -77
  137. data/split/Tioga/extconf.rb +0 -4
  138. data/split/Tioga/flate.h +0 -98
  139. data/split/Tioga/mk_tioga_sty.rb +0 -53
  140. data/split/Tioga/namespace.h +0 -59
  141. data/split/Tioga/safe_double.h +0 -104
  142. data/split/Tioga/symbols.h +0 -52
  143. data/split/defs.h +0 -39
  144. data/split/extconf.rb +0 -125
  145. data/split/mkmf2.rb +0 -1623
  146. data/split/namespace.h +0 -59
  147. data/split/safe_double.h +0 -104
  148. data/split/symbols.h +0 -52
@@ -0,0 +1,1373 @@
1
+ /* -*- c-basic-offset: 3; -*- */
2
+ /* axes.c */
3
+ /*
4
+ Copyright (C) 2005 Bill Paxton
5
+ Copyright (C) 2008 Vincent Fourmond
6
+
7
+ This file is part of Tioga.
8
+
9
+ Tioga is free software; you can redistribute it and/or modify
10
+ it under the terms of the GNU General Library Public License as published
11
+ by the Free Software Foundation; either version 2 of the License, or
12
+ (at your option) any later version.
13
+
14
+ Tioga is distributed in the hope that it will be useful,
15
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ GNU Library General Public License for more details.
18
+
19
+ You should have received a copy of the GNU Library General Public License
20
+ along with Tioga; if not, write to the Free Software
21
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
+ */
23
+ #include <math.h>
24
+
25
+ #include "figures.h"
26
+ #include "pdfs.h"
27
+
28
+
29
+
30
+ /*
31
+ Here is my (Vincent) big TODO-list for the axes stuff:
32
+ * BUG fix: apparently, two calls to the axes stuff do no return the
33
+ same thing, so I'll need to have a careful look at that
34
+ */
35
+
36
+ typedef struct {
37
+ int type;
38
+ int other_axis_type;
39
+ double line_width;
40
+
41
+ /* Stroke color... */
42
+ double stroke_color_R;
43
+ double stroke_color_G;
44
+ double stroke_color_B;
45
+
46
+ /* Tick labels color */
47
+ double labels_color_R;
48
+ double labels_color_G;
49
+ double labels_color_B;
50
+
51
+ double major_tick_width; // same units as line_width
52
+ double minor_tick_width; // same units as line_width
53
+ double major_tick_length; // in units of numeric label char heights
54
+ double minor_tick_length; // in units of numeric label char heights
55
+ bool log_vals;
56
+ bool ticks_inside; // inside frame or toward larger x or y value for specific location
57
+ bool ticks_outside; // inside frame or toward smaller x or y value for specific location
58
+ double tick_interval; // set to 0 to use default
59
+ double min_between_major_ticks; // in units of numeric label char heights
60
+ int number_of_minor_intervals; // set to 0 to use default
61
+ OBJ_PTR locations_for_major_ticks; // set to nil to use defaults
62
+ OBJ_PTR locations_for_minor_ticks; // set to nil to use defaults
63
+ bool use_fixed_pt;
64
+ int digits_max;
65
+ OBJ_PTR tick_labels; // set to nil to use defaults
66
+ double numeric_label_scale;
67
+ double numeric_label_shift; // in char heights, positive for out from edge (or toward larger x or y value)
68
+ double numeric_label_angle;
69
+ int numeric_label_alignment;
70
+ int numeric_label_justification;
71
+ int numeric_label_frequency;
72
+ int numeric_label_phase;
73
+ int numeric_label_decimal_digits; // set to 0 to use default
74
+ double *majors; /* if not NULL, then points to array of places where major ticks should appear (in figure coords) */
75
+ int nmajors; /* if majors != NULL, then this tells how many entries it contains */
76
+ bool free_majors;
77
+ char **labels; /* if not null, then points to array of strings to use for labels at major ticks */
78
+ /* labels[i] goes with majors[i], so this is only valid if majors is not null */
79
+ bool free_strings_for_labels;
80
+ double x0, y0, x1, y1, length, axis_min, axis_max; // in figure coords
81
+ bool vertical;
82
+ bool reversed;
83
+ bool top_or_right;
84
+ bool other_axis_reversed;
85
+ int num_minors; // number of minor intervals
86
+ double interval; // tick interval
87
+ int location;
88
+ bool vincent_or_bill; /* True if we use Vincent's algorithm
89
+ for picking major ticks
90
+ */
91
+ } PlotAxis;
92
+
93
+ static void figure_moveto(OBJ_PTR fmkr, FM *p, double x, double y, int *ierr) // figure coords
94
+ {
95
+ c_moveto(fmkr, p, convert_figure_to_output_x(p,x), convert_figure_to_output_y(p,y), ierr);
96
+ }
97
+
98
+ static void figure_lineto(OBJ_PTR fmkr, FM *p, double x, double y, int *ierr) // figure coords
99
+ {
100
+ c_lineto(fmkr, p, convert_figure_to_output_x(p,x), convert_figure_to_output_y(p,y), ierr);
101
+ }
102
+
103
+ static void figure_join(OBJ_PTR fmkr, FM *p,
104
+ double x0, double y0, double x1, double y1, int *ierr) // figure coords
105
+ {
106
+ figure_moveto(fmkr, p, x0, y0, ierr);
107
+ figure_lineto(fmkr, p, x1, y1, ierr);
108
+ }
109
+
110
+ static void axis_stroke(OBJ_PTR fmkr, FM *p, int *ierr)
111
+ {
112
+ c_stroke(fmkr,p, ierr);
113
+ }
114
+
115
+ static void figure_join_and_stroke(OBJ_PTR fmkr, FM *p,
116
+ double x0, double y0, double x1, double y1, int *ierr) // figure coords
117
+ {
118
+ figure_join(fmkr, p, x0, y0, x1, y1, ierr);
119
+ c_stroke(fmkr,p, ierr);
120
+ }
121
+
122
+ static void Get_xaxis_Specs(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
123
+ {
124
+ s->free_majors = s->free_strings_for_labels = false;
125
+ s->stroke_color_R = 0.0; s->stroke_color_G = 0.0; s->stroke_color_B = 0.0;
126
+ s->majors = NULL;
127
+ s->labels = NULL;
128
+ s->type = p->xaxis_type;
129
+ s->other_axis_type = p->yaxis_type;
130
+ s->line_width = p->xaxis_line_width; // for axis line
131
+ s->stroke_color_R = p->xaxis_stroke_color_R; // for axis line and tick marks
132
+ s->stroke_color_G = p->xaxis_stroke_color_G;
133
+ s->stroke_color_B = p->xaxis_stroke_color_B;
134
+
135
+ s->labels_color_R = p->xaxis_labels_color_R; // for axis line and tick marks
136
+ s->labels_color_G = p->xaxis_labels_color_G;
137
+ s->labels_color_B = p->xaxis_labels_color_B;
138
+
139
+ s->major_tick_width = p->xaxis_major_tick_width; // same units as line_width
140
+ s->minor_tick_width = p->xaxis_minor_tick_width; // same units as line_width
141
+ s->major_tick_length = p->xaxis_major_tick_length; // in units of numeric label char heights
142
+ s->minor_tick_length = p->xaxis_minor_tick_length; // in units of numeric label char heights
143
+ s->log_vals = p->xaxis_log_values;
144
+ s->ticks_inside = p->xaxis_ticks_inside; // inside frame or toward larger x or y value for specific location
145
+ s->ticks_outside = p->xaxis_ticks_outside; // inside frame or toward smaller x or y value for specific location
146
+ s->tick_interval = p->xaxis_tick_interval; // set to 0 to use default
147
+ s->min_between_major_ticks = p->xaxis_min_between_major_ticks; // in units of numeric label char heights
148
+ s->number_of_minor_intervals = p->xaxis_number_of_minor_intervals; // set to 0 to use default
149
+ s->locations_for_major_ticks = Get_xaxis_locations_for_major_ticks(fmkr, ierr);
150
+ s->locations_for_minor_ticks = Get_xaxis_locations_for_minor_ticks(fmkr, ierr);
151
+ s->use_fixed_pt = p->xaxis_use_fixed_pt;
152
+ s->digits_max = p->xaxis_digits_max;
153
+ s->tick_labels = Get_xaxis_tick_labels(fmkr, ierr);
154
+ s->numeric_label_decimal_digits = p->xaxis_numeric_label_decimal_digits; // set to negative to use default
155
+ s->numeric_label_scale = p->xaxis_numeric_label_scale;
156
+ s->numeric_label_shift = p->xaxis_numeric_label_shift; // in char heights, positive for out from edge (or toward larger x or y value)
157
+ s->numeric_label_angle = p->xaxis_numeric_label_angle;
158
+ s->numeric_label_alignment = p->xaxis_numeric_label_alignment;
159
+ s->numeric_label_justification = p->xaxis_numeric_label_justification;
160
+ s->numeric_label_frequency = p->xaxis_numeric_label_frequency;
161
+ s->numeric_label_phase = p->xaxis_numeric_label_phase;
162
+
163
+ s->vincent_or_bill = p->vincent_or_bill;
164
+ }
165
+
166
+ static void Get_yaxis_Specs(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
167
+ {
168
+ s->free_majors = s->free_strings_for_labels = false;
169
+ s->stroke_color_R = 0.0; s->stroke_color_G = 0.0; s->stroke_color_B = 0.0;
170
+ s->majors = NULL;
171
+ s->labels = NULL;
172
+ s->type = p->yaxis_type;
173
+ s->other_axis_type = p->xaxis_type;
174
+ s->line_width = p->yaxis_line_width; // for axis line
175
+
176
+ s->stroke_color_R = p->yaxis_stroke_color_R; // for axis line and tick marks
177
+ s->stroke_color_G = p->yaxis_stroke_color_G;
178
+ s->stroke_color_B = p->yaxis_stroke_color_B;
179
+
180
+ s->labels_color_R = p->yaxis_labels_color_R; // for axis line and tick marks
181
+ s->labels_color_G = p->yaxis_labels_color_G;
182
+ s->labels_color_B = p->yaxis_labels_color_B;
183
+
184
+ s->major_tick_width = p->yaxis_major_tick_width; // same units as line_width
185
+ s->minor_tick_width = p->yaxis_minor_tick_width; // same units as line_width
186
+ s->major_tick_length = p->yaxis_major_tick_length; // in units of numeric label char heights
187
+ s->minor_tick_length = p->yaxis_minor_tick_length; // in units of numeric label char heights
188
+ s->log_vals = p->yaxis_log_values;
189
+ s->ticks_inside = p->yaxis_ticks_inside; // inside frame or toward larger x or y value for specific location
190
+ s->ticks_outside = p->yaxis_ticks_outside; // inside frame or toward smaller x or y value for specific location
191
+ s->tick_interval = p->yaxis_tick_interval; // set to 0 to use default
192
+ s->min_between_major_ticks = p->yaxis_min_between_major_ticks; // in units of numeric label char heights
193
+ s->number_of_minor_intervals = p->yaxis_number_of_minor_intervals; // set to 0 to use default
194
+ s->locations_for_major_ticks = Get_yaxis_locations_for_major_ticks(fmkr, ierr);
195
+ s->locations_for_minor_ticks = Get_yaxis_locations_for_minor_ticks(fmkr, ierr);
196
+ s->tick_labels = Get_yaxis_tick_labels(fmkr, ierr);
197
+ s->use_fixed_pt = p->yaxis_use_fixed_pt;
198
+ s->digits_max = p->yaxis_digits_max;
199
+ s->numeric_label_decimal_digits = p->yaxis_numeric_label_decimal_digits; // set to negative to use default
200
+ s->numeric_label_scale = p->yaxis_numeric_label_scale;
201
+ s->numeric_label_shift = p->yaxis_numeric_label_shift; // in char heights, positive for out from edge (or toward larger x or y value)
202
+ s->numeric_label_angle = p->yaxis_numeric_label_angle;
203
+ s->numeric_label_alignment = p->yaxis_numeric_label_alignment;
204
+ s->numeric_label_justification = p->yaxis_numeric_label_justification;
205
+ s->numeric_label_frequency = p->yaxis_numeric_label_frequency;
206
+ s->numeric_label_phase = p->yaxis_numeric_label_phase;
207
+
208
+ s->vincent_or_bill = p->vincent_or_bill;
209
+ }
210
+
211
+ /*======================================================================*/
212
+
213
+ /*
214
+ Internal values for axis locations.
215
+ */
216
+ #define AXIS_FREE_LOCATION 1000
217
+
218
+ /* Prepares the various coordinates according to the axis location */
219
+ static void prepare_axis_coordinates(OBJ_PTR fmkr, FM *p,
220
+ int location, PlotAxis *s, int *ierr)
221
+ {
222
+ switch (location) {
223
+ case LEFT:
224
+ s->x0 = p->bounds_left;
225
+ s->x1 = p->bounds_left;
226
+ s->y0 = p->bounds_bottom;
227
+ s->y1 = p->bounds_top;
228
+ s->length = p->bounds_height;
229
+ s->axis_min = p->bounds_ymin;
230
+ s->axis_max = p->bounds_ymax;
231
+ s->vertical = true;
232
+ s->reversed = p->yaxis_reversed;
233
+ s->other_axis_reversed = p->xaxis_reversed;
234
+ s->top_or_right = false;
235
+ break;
236
+ case RIGHT:
237
+ s->x0 = p->bounds_right;
238
+ s->x1 = p->bounds_right;
239
+ s->y0 = p->bounds_bottom;
240
+ s->y1 = p->bounds_top;
241
+ s->length = p->bounds_height;
242
+ s->axis_min = p->bounds_ymin;
243
+ s->axis_max = p->bounds_ymax;
244
+ s->vertical = true;
245
+ s->reversed = p->yaxis_reversed;
246
+ s->other_axis_reversed = p->xaxis_reversed;
247
+ s->top_or_right = true;
248
+ break;
249
+ case TOP:
250
+ s->x0 = p->bounds_left;
251
+ s->x1 = p->bounds_right;
252
+ s->y0 = p->bounds_top;
253
+ s->y1 = p->bounds_top;
254
+ s->length = p->bounds_width;
255
+ s->axis_min = p->bounds_xmin;
256
+ s->axis_max = p->bounds_xmax;
257
+ s->vertical = false;
258
+ s->reversed = p->xaxis_reversed;
259
+ s->other_axis_reversed = p->yaxis_reversed;
260
+ s->top_or_right = true;
261
+ break;
262
+ case BOTTOM:
263
+ s->x0 = p->bounds_left;
264
+ s->x1 = p->bounds_right;
265
+ s->y0 = p->bounds_bottom;
266
+ s->y1 = p->bounds_bottom;
267
+ s->length = p->bounds_width;
268
+ s->axis_min = p->bounds_xmin;
269
+ s->axis_max = p->bounds_xmax;
270
+ s->vertical = false;
271
+ s->reversed = p->xaxis_reversed;
272
+ s->other_axis_reversed = p->yaxis_reversed;
273
+ s->top_or_right = false;
274
+ break;
275
+ case AT_X_ORIGIN:
276
+ s->x0 = 0.0;
277
+ s->x1 = 0.0;
278
+ s->y0 = p->bounds_bottom;
279
+ s->y1 = p->bounds_top;
280
+ s->length = p->bounds_height;
281
+ s->axis_min = p->bounds_ymin;
282
+ s->axis_max = p->bounds_ymax;
283
+ s->vertical = true;
284
+ s->reversed = p->yaxis_reversed;
285
+ s->other_axis_reversed = p->xaxis_reversed;
286
+ s->top_or_right = false;
287
+ break;
288
+ case AT_Y_ORIGIN:
289
+ s->x0 = p->bounds_left;
290
+ s->x1 = p->bounds_right;
291
+ s->y0 = 0.0;
292
+ s->y1 = 0.0;
293
+ s->length = p->bounds_width;
294
+ s->axis_min = p->bounds_xmin;
295
+ s->axis_max = p->bounds_xmax;
296
+ s->vertical = false;
297
+ s->reversed = p->xaxis_reversed;
298
+ s->other_axis_reversed = p->yaxis_reversed;
299
+ s->top_or_right = false;
300
+ break;
301
+ case AXIS_FREE_LOCATION:
302
+ /* Nothing to be done here. */
303
+ break;
304
+ }
305
+ }
306
+
307
+ static void draw_axis_line(OBJ_PTR fmkr, FM *p, int location,
308
+ PlotAxis *s, int *ierr)
309
+ {
310
+ prepare_axis_coordinates(fmkr, p, location, s, ierr);
311
+ c_line_width_set(fmkr, p, s->line_width, ierr);
312
+ figure_join_and_stroke(fmkr, p, s->x0, s->y0, s->x1, s->y1, ierr);
313
+ }
314
+
315
+ static char *Create_Label(double val, int scale, int prec,
316
+ bool log_vals, bool use_fixed_pt, char *postfix, PlotAxis *s, int *ierr)
317
+ { // val in figure coords
318
+ char buff[100], form[100], *string;
319
+ int exponent = ROUND(val);
320
+ buff[0] = 0;
321
+ if (log_vals && use_fixed_pt) { /* Logarithmic */
322
+ double sav_val = val, pow_val;
323
+ val = pow(10.0, exponent);
324
+ pow_val = pow(10.0, sav_val);
325
+ if (exponent < 0) {
326
+ int numdig = ABS(exponent)+1;
327
+ snprintf(form, sizeof(form), (s->vertical)? "\\tiogayaxisnumericlabel{%%.%df}" : "\\tiogaxaxisnumericlabel{%%.%df}", numdig);
328
+ snprintf(buff, sizeof(buff), form, pow_val);
329
+ } else if (abs(val - pow_val) > 0.1) {
330
+ snprintf(buff, sizeof(buff), (s->vertical)? "\\tiogayaxisnumericlabel{%0.2f}" : "\\tiogaxaxisnumericlabel{%0.2f}", pow_val);
331
+ } else {
332
+ snprintf(buff, sizeof(buff), (s->vertical)? "\\tiogayaxisnumericlabel{%d}" : "\\tiogaxaxisnumericlabel{%d}", (int) val);
333
+ }
334
+ } else if (log_vals) {
335
+ /* Exponential, i.e. 10^-1, 1, 10, 10^2, etc */
336
+ double abs_diff = fabs(val - exponent);
337
+ if (abs_diff > 0.1) snprintf(buff, sizeof(buff), (s->vertical)? "\\tiogayaxisnumericlabel{10^{%0.1f}}" : "\\tiogaxaxisnumericlabel{10^{%0.1f}}", val);
338
+ else if (exponent == 0) strcpy(buff, "1");
339
+ else if (exponent == 1) strcpy(buff, "10");
340
+ else snprintf(buff, sizeof(buff), (s->vertical)? "\\tiogayaxisnumericlabel{10^{%d}}" : "\\tiogaxaxisnumericlabel{10^{%d}}", exponent);
341
+ } else { /* Linear */
342
+ double scale2;
343
+ int precis = s->numeric_label_decimal_digits; // use this precision if it is >= 0
344
+ if (precis >= 0) prec = precis;
345
+ if (scale) val /= pow(10.,(double)scale);
346
+ /* This is necessary to prevent labels like "-0.0" on some systems */
347
+ scale2 = pow(10., prec);
348
+ val = floor((val * scale2) + .5) / scale2;
349
+ snprintf(form, sizeof(form), (s->vertical)? "\\tiogayaxisnumericlabel{%%.%df}" : "\\tiogaxaxisnumericlabel{%%.%df}", (int) prec);
350
+ snprintf(buff, sizeof(buff), form, val);
351
+ }
352
+ int len = strlen(buff);
353
+ if (postfix != NULL) { strcpy(buff+len, postfix); len = strlen(buff); }
354
+ string = ALLOC_N_char(len+1);
355
+ strcpy(string, buff);
356
+ return string;
357
+ }
358
+
359
+ /* vincent: I wonder what this function is doing here ;-)... */
360
+ char *Get_String(OBJ_PTR ary, int index, int *ierr) {
361
+ OBJ_PTR s = Array_Entry(ary,index,ierr);
362
+ if (*ierr != 0) return NULL;
363
+ return String_Ptr(s,ierr);
364
+ }
365
+
366
+ #define MAX_FIXDIG_POS 6
367
+ #define MAX_FIXDIG_NEG 6
368
+ #define DIGMAX_DEF 6
369
+
370
+ static void Pick_Label_Precision(double vmin, double vmax, double tick, bool use_fixed_pt,
371
+ int *mode, int *prec, int digmax, int *scale, int *ierr) {
372
+ double chosen, notchosen, vmod, t0, shifted;
373
+ int msd, notmsd, np, digmin, digfix;
374
+ *mode = *scale = 0;
375
+ if (digmax == 0) digmax = DIGMAX_DEF;
376
+ /* Choose vmin or vmax depending on magnitudes of vmin and vmax. */
377
+ if (ABS(vmax) >= ABS(vmin)) { chosen = vmax; notchosen = vmin; }
378
+ else { chosen = vmin; notchosen = vmax; }
379
+ /* Magnitute of chosen to get number of significant digits */
380
+
381
+ if(ABS(chosen) > 0.) {
382
+ vmod = ABS(chosen);
383
+ t0 = (double) log10(vmod);
384
+ msd = (int) floor(t0);
385
+ }
386
+ else {
387
+ /* this branch occurs only when 0. --- 0. range put in */
388
+ vmod = 1.;
389
+ t0 = (double) log10(vmod);
390
+ msd = (int) floor(t0);
391
+ }
392
+ if (ABS(notchosen) > 0.) notmsd = (int) floor( (double) log10(ABS(notchosen)));
393
+ else notmsd = msd;
394
+ /* Autoselect the mode flag */
395
+ /* 'digmin' is the minimum number of places taken up by the label */
396
+
397
+ if (msd >= 0) {
398
+ /* n.b. no decimal point in the minimal case */
399
+ digmin = msd + 1;
400
+ digfix = MAX_FIXDIG_POS;
401
+ if (digmax > 0) digfix = MIN(digmax, MAX_FIXDIG_POS);
402
+ }
403
+ else {
404
+ /* adjust digmin to account for leading 0 and decimal point */
405
+ digmin = -msd + 2;
406
+ digfix = MAX_FIXDIG_NEG;
407
+ if (digmax > 0) digfix = MIN(digmax, MAX_FIXDIG_NEG);
408
+ }
409
+ /* adjust digmin to account for sign on the chosen end of axis or sign on the
410
+ * nonchosen end of axis if notmsd = msd or (msd <= 0 and notmsd < 0)
411
+ * For the latter case the notchosen label starts with "-0."
412
+ * For checking for the latter case, the notmsd < 0 condition is redundant
413
+ * since notmsd <= msd always and the equal part is selected by the first
414
+ * condition.
415
+ */
416
+ if(chosen < 0.0 || (notchosen < 0. && (notmsd == msd || msd <= 0))) digmin++;
417
+
418
+ if (digmin > digfix && !use_fixed_pt) { *mode = 1; *scale = msd; }
419
+
420
+ /* Establish precision. */
421
+ /* It must be fine enough to resolve the tick spacing */
422
+
423
+ shifted = tick; np = 0;
424
+ while (ABS(shifted) < 1.0 && np > -6) { np--; shifted *= 10.0; }
425
+ for (; np > -6; np--, shifted *= 10.0) {
426
+ if (ABS(shifted - floor(shifted)) < 0.1) break;
427
+ }
428
+
429
+ if (*mode != 0) *prec = msd - np;
430
+ else *prec = MAX(-np, 0);
431
+
432
+ /* One last hack required: if exponent < 0, i.e. number has leading '0.',
433
+ * it's better to change to floating point form if the number of digits
434
+ * is insufficient to represent the tick spacing.
435
+ */
436
+ if (*mode == 0 && digmax > 0 && !use_fixed_pt) {
437
+ if (t0 < 0.0) {
438
+ if (digmax - 2 - *prec < 0) { *mode = 1; *scale = msd; }
439
+ } else *prec = MAX(MIN(*prec, digmax - msd - 1), 0);
440
+ }
441
+ if (*mode != 0) {
442
+ *prec = msd - np;
443
+ *prec = *scale - floor(log10(tick));
444
+ *prec = MIN(*prec,MAX(0,*prec));
445
+ }
446
+
447
+ }
448
+
449
+ static char **Get_Labels(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
450
+ {
451
+ char **labels = (char **)ALLOC_N_pointer(s->nmajors);
452
+ char postfix[50], *ps;
453
+ int i, k, j;
454
+ k = s->numeric_label_frequency;
455
+ j = s->numeric_label_phase;
456
+ if (s->tick_labels==OBJ_NIL) { // create label strings
457
+ int mode, prec, scale;
458
+ Pick_Label_Precision(s->axis_min, s->axis_max, s->interval,
459
+ s->use_fixed_pt, &mode, &prec, s->digits_max, &scale, ierr);
460
+ if (*ierr != 0) return NULL;
461
+ int i;
462
+ int upper_right = (s->reversed)? 0 : s->nmajors-1;
463
+ int lower_left = (s->reversed)? s->nmajors-1 : 0;
464
+ for (i = 0; i < s->nmajors; i++) {
465
+ ps = NULL;
466
+ if (i == upper_right && !s->log_vals && mode && scale)
467
+ snprintf(ps = postfix, sizeof(postfix),
468
+ (s->vertical)? "$\\times$\\tiogayaxisnumericlabel{10^{%d}}" : "$\\times$\\tiogaxaxisnumericlabel{10^{%d}}",
469
+ scale);
470
+ if ((i+j) % k != 0) {
471
+ labels[i] = NULL;
472
+ } else if (i == lower_left && s->nmajors >= 2 && s->vertical &&
473
+ (s->majors[i] == ((s->reversed)? s->axis_max : s->axis_min)) &&
474
+ (s->other_axis_type == AXIS_WITH_MAJOR_TICKS_AND_NUMERIC_LABELS ||
475
+ s->other_axis_type == AXIS_WITH_TICKS_AND_NUMERIC_LABELS)) {
476
+ labels[i] = NULL;
477
+ } else {
478
+ labels[i] = Create_Label(s->majors[i], scale, prec, s->log_vals, s->use_fixed_pt, ps, s, ierr);
479
+ if (*ierr != 0) return NULL;
480
+ }
481
+ }
482
+ s->free_strings_for_labels = true;
483
+ } else { // use the given label strings
484
+ int len = Array_Len(s->tick_labels,ierr);
485
+ if (*ierr != 0) return NULL;
486
+ if (len != s->nmajors) {
487
+ RAISE_ERROR("Sorry: must have same number of labels as major ticks", ierr);
488
+ return NULL;
489
+ }
490
+ for (i = 0; i < s->nmajors; i++) {
491
+ labels[i] = Get_String(s->tick_labels, i, ierr);
492
+ if (*ierr != 0) return NULL;
493
+ }
494
+ s->free_strings_for_labels = false;
495
+ }
496
+ return labels;
497
+ }
498
+
499
+ static int Pick_Number_of_Minor_Intervals(double length, int *ierr)
500
+ {
501
+ double t1, fuzz, newlen;
502
+ int np, num_subintervals, inewlen;
503
+ if (length < 10.0 && length > 1.0) {
504
+ newlen = length;
505
+ } else {
506
+ t1 = (double) log10(length);
507
+ np = (int) floor(t1);
508
+ t1 -= np;
509
+ newlen = pow(10.0, t1);
510
+ }
511
+ inewlen = (int) floor(newlen + 0.5);
512
+ fuzz = newlen - inewlen;
513
+ fuzz = abs(fuzz);
514
+ num_subintervals = 4;
515
+ if (fuzz < 1e-2) {
516
+ switch (inewlen) {
517
+ case 0: case 1: case 2: num_subintervals = 4; break;
518
+ case 4: break;
519
+ case 8: case 10: num_subintervals = 2; break;
520
+ case 3: case 6: case 9: num_subintervals = 3; break;
521
+ default: num_subintervals = 5;
522
+ }
523
+ } else {
524
+ if (newlen > 5.0) num_subintervals = 4;
525
+ else if (newlen > 3.0) num_subintervals = 5;
526
+ else if (newlen > 1.5) num_subintervals = 5;
527
+ }
528
+ return num_subintervals;
529
+ }
530
+
531
+ /* Refactoring of the axis location picking code */
532
+
533
+ /* First, Bill's point of view */
534
+
535
+ static double *Pick_Locations_for_Major_Ticks(double interval,
536
+ double axis_min, double axis_max, int *num_locations, int *ierr)
537
+ {
538
+ double next_tick, prev_tick, starting_tick;
539
+ double *majors;
540
+ int nmajors, i;
541
+ while (true) {
542
+ nmajors = 0;
543
+ starting_tick = interval * floor(axis_min / interval);
544
+ if (starting_tick == axis_min) starting_tick -= interval;
545
+ prev_tick = starting_tick;
546
+ while (true) {
547
+ next_tick = prev_tick + interval;
548
+ if (next_tick > axis_max) break;
549
+ nmajors++;
550
+ prev_tick = next_tick;
551
+ }
552
+ if (nmajors > 1) break;
553
+ interval *= 0.5;
554
+ }
555
+ majors = ALLOC_N_double(nmajors);
556
+ prev_tick = starting_tick;
557
+ for (i=0; i < nmajors; i++) {
558
+ majors[i] = prev_tick += interval;
559
+ }
560
+ *num_locations = nmajors;
561
+ return majors;
562
+ }
563
+
564
+ static void Pick_Major_Tick_Interval(OBJ_PTR fmkr, FM *p,
565
+ double tick_min, double tick_gap, double length, bool log_vals, double *tick, int *ierr)
566
+ {
567
+ double t1, t2, tick_reasonable, base_interval;
568
+ int np, i;
569
+ /* Magnitude of min/max difference to get tick spacing */
570
+ t1 = (double) log10(length);
571
+ np = (int) floor(t1);
572
+ t1 -= np;
573
+ t1 = pow(10.0, t1);
574
+ /* Get tick spacing. */
575
+ if (t1 > 6.0) t2 = 2.0;
576
+ else if (t1 > 3.0) t2 = 1.0;
577
+ else if (t1 > 1.5) { t2 = 5.0; np--; }
578
+ else { t2 = 2.0; np--; }
579
+ /* Now compute reasonable tick spacing */
580
+ if (log_vals) {
581
+ tick_reasonable = 1.0;
582
+ } else {
583
+ base_interval = pow(10.0, (double) np);
584
+ if (t2 == 2.0 && t2 * base_interval < tick_gap) t2 = 1.0;
585
+ i = 0;
586
+ while (i < 100) {
587
+ tick_reasonable = t2 * base_interval;
588
+ if (tick_reasonable >= tick_min) break;
589
+ t2++; i++;
590
+ }
591
+ }
592
+ if (*tick == 0) *tick = tick_reasonable;
593
+ else { // check the given interval compared to the default
594
+ *tick = ABS(*tick);
595
+ if(*tick < 1.e-4*tick_reasonable) {
596
+ RAISE_ERROR_g("Sorry: magnitude of specified tick interval (%g) is too small", *tick, ierr);
597
+ return;
598
+ }
599
+ }
600
+ }
601
+
602
+ static double * pick_major_ticks_positions_Bill(OBJ_PTR fmkr, FM *p,
603
+ double axis_min,
604
+ double axis_max,
605
+ int *num_locations,
606
+ double tick_min,
607
+ double tick_gap,
608
+ double length,
609
+ bool log_vals,
610
+ double *tick,
611
+ int *ierr)
612
+ {
613
+ /* This code is using Bill's initial implementation */
614
+ Pick_Major_Tick_Interval(fmkr, p, tick_min, tick_gap,
615
+ length, log_vals, tick, ierr);
616
+ /* printf("Tick gap: %f, length: %f, tick_min: %f, tick interval: %f\n", */
617
+ /* tick_gap, length, tick_min, *tick); */
618
+ if (*ierr != 0)
619
+ return NULL;
620
+ return Pick_Locations_for_Major_Ticks(*tick, axis_min, axis_max,
621
+ num_locations, ierr);
622
+ }
623
+
624
+ /* Then, Vincent's point of view ;-) ... */
625
+
626
+ static double natural_distances[] = { 1.0, 2.0, /*2.5,*/ 5.0, 10.0 };
627
+ const int nb_natural_distances = sizeof(natural_distances)/sizeof(double);
628
+
629
+ static double * pick_major_ticks_positions_Vincent(OBJ_PTR fmkr, FM *p,
630
+ double axis_min,
631
+ double axis_max,
632
+ int *num_locations,
633
+ double tick_min,
634
+ double tick_gap,
635
+ double length,
636
+ bool log_vals,
637
+ double *tick,
638
+ int *ierr)
639
+ {
640
+ /* I like Bill's way of handling log scale */
641
+ if(log_vals)
642
+ return pick_major_ticks_positions_Bill(fmkr,p,
643
+ axis_min, axis_max,
644
+ num_locations, tick_min,
645
+ tick_gap, length, log_vals,
646
+ tick, ierr);
647
+ if(tick_min < 0)
648
+ tick_min = - tick_min;
649
+
650
+ /* The factor by which you need to divide to get
651
+ the tick_min within [1,10[ */
652
+ double factor = pow(10, floor(log10(tick_min)));
653
+ double norm_tick_min = tick_min/factor;
654
+ int i;
655
+ int done = 0;
656
+
657
+ /* In principle, the loop below show run at most twice, but a
658
+ safeguard is not too expensive ;-)... */
659
+ int nb_tries = 0;
660
+
661
+ /* printf("axis_min: %g\taxis_max: %g\n", axis_min, axis_max); */
662
+ /* We get the one just above tick_min */
663
+ do {
664
+ nb_tries ++;
665
+ for(i = 0; i < nb_natural_distances; i++)
666
+ if(natural_distances[i] >= norm_tick_min)
667
+ break;
668
+ /* Now, there is a corner case when there is not enough */
669
+
670
+ *tick = natural_distances[i] * factor;
671
+
672
+ /* If the there is room for at most one tick here, there is a
673
+ problem, so take the size down. */
674
+ if( (axis_max - axis_min) < 2.0 * *tick) {
675
+ factor = pow(10, floor(log10(tick_min/2)));
676
+ norm_tick_min = tick_min/(2*factor);
677
+ }
678
+ else
679
+ done = 1;
680
+ } while(! done && nb_tries < 3);
681
+
682
+ double first_tick = ceil(axis_min /(*tick)) * (*tick);
683
+ double last_tick = floor(axis_max /(*tick)) * (*tick);
684
+
685
+ *num_locations = (int)round((last_tick - first_tick)/(*tick));
686
+ *num_locations += 1;
687
+
688
+ double *majors = ALLOC_N_double(*num_locations);
689
+ for (i = 0; i < *num_locations; i++)
690
+ majors[i] = first_tick + (*tick) * i;
691
+
692
+ return majors;
693
+ }
694
+
695
+
696
+ /* This functions fills the majors attribute of the PlotAxis object
697
+ with the position of major ticks
698
+ */
699
+ static void compute_major_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
700
+ {
701
+ if (s->locations_for_major_ticks != OBJ_NIL) {
702
+ long len;
703
+ s->majors = Vector_Data_for_Read(s->locations_for_major_ticks, &len, ierr);
704
+ if (*ierr != 0) return;
705
+ s->nmajors = len;
706
+ if (len > 1) {
707
+ s->interval = s->majors[1] - s->majors[0];
708
+ if (s->interval < 0.0) { s->interval = -s->interval; }
709
+ }
710
+ } else { // calculate major tick locations
711
+ s->interval = s->tick_interval;
712
+ double height = ((s->vertical)? p->default_text_height_dy : p->default_text_height_dx);
713
+ double tick_min = s->min_between_major_ticks * height;
714
+ double tick_gap = 10.0 * height;
715
+
716
+ s->majors = (s->vincent_or_bill ?
717
+ pick_major_ticks_positions_Vincent(fmkr, p,
718
+ s->axis_min,
719
+ s->axis_max, &s->nmajors,
720
+ tick_min, tick_gap,
721
+ s->length, s->log_vals,
722
+ &s->interval, ierr) :
723
+ pick_major_ticks_positions_Bill(fmkr, p, s->axis_min,
724
+ s->axis_max, &s->nmajors,
725
+ tick_min, tick_gap,
726
+ s->length, s->log_vals,
727
+ &s->interval, ierr));
728
+
729
+ if(*ierr || ! s->majors)
730
+ return;
731
+ s->free_majors = true;
732
+ }
733
+ }
734
+
735
+ static void draw_major_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
736
+ {
737
+ s->num_minors = s->number_of_minor_intervals;
738
+
739
+ /* Get the major ticks position in s->majors */
740
+ compute_major_ticks(fmkr, p, s, ierr);
741
+ if(*ierr != 0) return;
742
+
743
+ int i;
744
+ double inside=0.0, outside=0.0, length;
745
+ bool did_line = false;
746
+ length = s->major_tick_length * ((s->vertical)? p->default_text_height_dx : p->default_text_height_dy);
747
+ if (s->ticks_inside) inside = length;
748
+ if (s->ticks_outside) outside = -length;
749
+ if (s->top_or_right) { inside = -inside; outside = -outside; }
750
+ if (s->line_width != s->major_tick_width) {
751
+ c_line_width_set(fmkr, p, s->line_width = s->major_tick_width, ierr);
752
+ if (*ierr != 0) return;
753
+ }
754
+ for (i=0; i < s->nmajors; i++) {
755
+ if (s->vertical)
756
+ figure_join(fmkr, p, s->x0+inside, s->majors[i], s->x0+outside, s->majors[i], ierr);
757
+ else
758
+ figure_join(fmkr, p, s->majors[i], s->y0+inside, s->majors[i], s->y0+outside, ierr);
759
+ did_line = true;
760
+ if (*ierr != 0) return;
761
+ }
762
+ if (did_line) axis_stroke(fmkr,p, ierr);
763
+ }
764
+
765
+ static double log_subintervals[8] = {
766
+ 0.301030, 0.477121, 0.602060, 0.698970,
767
+ 0.778151, 0.845098, 0.903090, 0.954243 };
768
+
769
+
770
+ /* A function that returns a double array *TO BE FREED* containing
771
+ the position of the minor ticks for the given axis.
772
+
773
+ The number of ticks is stored in the cnt (long) parameter.
774
+
775
+ Returns NULL in case of problems
776
+ */
777
+ static double * get_minor_ticks_location(OBJ_PTR fmkr, FM *p,
778
+ PlotAxis *s, long * cnt)
779
+ {
780
+ double * target = NULL;
781
+ int ierr = 0;
782
+ *cnt = 0;
783
+
784
+ /* First, pick up the number of ticks to be used */
785
+ if (s->number_of_minor_intervals <= 0) {
786
+ if (s->log_vals) {
787
+ double interval = s->majors[1] - s->majors[0];
788
+ s->number_of_minor_intervals = (abs(interval) != 1.0 || s->nmajors > 10)? 1 : 9;
789
+ } else {
790
+ s->number_of_minor_intervals = Pick_Number_of_Minor_Intervals(s->interval, &ierr);
791
+ if (ierr != 0) return NULL;
792
+ }
793
+ }
794
+ int i, j, nsub = s->number_of_minor_intervals;
795
+
796
+ if (s->log_vals && nsub > 9) nsub = 9;
797
+
798
+ /* First case: user-supplied position of minor ticks */
799
+ if (s->locations_for_minor_ticks != OBJ_NIL) {
800
+ double *locs = Vector_Data_for_Read(s->locations_for_minor_ticks,
801
+ cnt, &ierr);
802
+ if (ierr != 0)
803
+ return NULL;
804
+ target = ALLOC_N_double(*cnt);
805
+ long i;
806
+ for(i = 0; i < *cnt; i++)
807
+ target[i] = locs[i];
808
+ return target;
809
+ } else {
810
+ /* We allocate sligthly more space than should be necessary: */
811
+ target = ALLOC_N_double(nsub * (s->nmajors + 1));
812
+ for (i=0; i <= s->nmajors; i++) {
813
+ double loc = (i==0)? s->majors[0] - s->interval : s->majors[i-1];
814
+ double next_loc = (i==s->nmajors)? loc + s->interval : s->majors[i];
815
+ double subinterval = (next_loc - loc) / nsub;
816
+ if (subinterval <= 0.0) continue;
817
+ for (j = 1; j < nsub; j++) {
818
+ double subloc = loc + ((!s->log_vals) ? (j * subinterval) : log_subintervals[j-1]);
819
+ if (subloc >= next_loc) break;
820
+ if (subloc <= s->axis_min || subloc >= s->axis_max) continue;
821
+
822
+ /* We add one */
823
+ target[*cnt] = subloc;
824
+ (*cnt)++;
825
+ }
826
+ }
827
+ return target;
828
+ }
829
+ }
830
+
831
+
832
+ static void draw_minor_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
833
+ {
834
+ long number;
835
+ double * locs = get_minor_ticks_location(fmkr, p, s, &number);
836
+ if(! locs) {
837
+ *ierr = 1;
838
+ return ;
839
+ }
840
+ long i;
841
+ double inside=0.0, outside=0.0, length;
842
+ bool did_line = false;
843
+
844
+ /* Initialization of the various lengths */
845
+ length = s->minor_tick_length * ((s->vertical)? p->default_text_height_dx : p->default_text_height_dy);
846
+ if (s->ticks_inside) inside = length;
847
+ if (s->ticks_outside) outside = -length;
848
+ if (s->top_or_right) { inside = -inside; outside = -outside; }
849
+ if (s->line_width != s->minor_tick_width) {
850
+ c_line_width_set(fmkr, p, s->line_width = s->minor_tick_width, ierr);
851
+ if (*ierr != 0) return;
852
+ }
853
+
854
+ /* Now, we stroke the ticks */
855
+ for(i = 0; i < number; i++) {
856
+ if (s->vertical)
857
+ figure_join(fmkr, p, s->x0+inside, locs[i],
858
+ s->x0+outside, locs[i], ierr);
859
+ else
860
+ figure_join(fmkr, p, locs[i], s->y0+inside, locs[i],
861
+ s->y0+outside, ierr);
862
+ did_line = true;
863
+ }
864
+ /* And we free the array returned by get_minor_ticks_location */
865
+ free(locs);
866
+ if (did_line)
867
+ axis_stroke(fmkr,p, ierr);
868
+ }
869
+
870
+ static void show_numeric_label(OBJ_PTR fmkr, FM *p, PlotAxis *s,
871
+ char *text, int location, double position, double shift, int *ierr)
872
+ {
873
+ /* We need a buffer to implement the color */
874
+ long len = strlen(text) + 100; /* Should be enough overhead ! */
875
+ char * buffer = ALLOC_N_char(len);
876
+ snprintf(buffer, len, "\\textcolor[rgb]{%0.2f,%0.2f,%0.2f}{%s}",
877
+ s->labels_color_R, s->labels_color_G, s->labels_color_B,
878
+ text);
879
+
880
+ if(location == AXIS_FREE_LOCATION) {
881
+ /* We convert the tick position into frame position */
882
+ double x,y, ft_ht = p->default_text_scale *
883
+ s->numeric_label_scale * p->default_font_size;
884
+ double angle;
885
+ /* Defaults to angle = +90, left side of the axis */
886
+ if(s->vertical) {
887
+ y = position;
888
+ x = s->x0 + convert_output_to_figure_dx(p,(s->reversed ? 1.0 : -1.0) *
889
+ ft_ht * ENLARGE * shift);
890
+
891
+
892
+ angle = 90;
893
+ }
894
+ else {
895
+ angle = 0;
896
+ x = position;
897
+ y = s->y0 + convert_output_to_figure_dy(p,(s->reversed ? 1.0 : -1.0) *
898
+ ft_ht * ENLARGE * shift);
899
+ }
900
+
901
+ c_show_rotated_label(fmkr, p, buffer, x, y,
902
+ s->numeric_label_scale,
903
+ s->numeric_label_angle + angle,
904
+ s->numeric_label_justification,
905
+ s->numeric_label_alignment, OBJ_NIL, ierr);
906
+
907
+ }
908
+ else {
909
+ // position is in figure coords and must be converted to frame coords
910
+ double pos = ((!s->reversed)? (position - s->axis_min) : (s->axis_max - position)) / s->length;
911
+ c_show_rotated_text(fmkr, p, buffer, location, shift, pos,
912
+ s->numeric_label_scale, s->numeric_label_angle, s->numeric_label_justification, s->numeric_label_alignment, OBJ_NIL, ierr);
913
+ }
914
+ free(buffer);
915
+ }
916
+
917
+ static void draw_numeric_labels(OBJ_PTR fmkr, FM *p, int location, PlotAxis *s, int *ierr)
918
+ {
919
+ int i;
920
+ double shift = (s->ticks_outside) ? s->major_tick_length : 0.5; // default shift
921
+ shift += s->numeric_label_shift;
922
+ s->labels = Get_Labels(fmkr, p, s, ierr);
923
+ for (i=0; i < s->nmajors; i++) {
924
+ if (s->labels[i] != NULL) {
925
+ show_numeric_label(fmkr, p, s, s->labels[i], location, s->majors[i], shift, ierr);
926
+ if (*ierr != 0) return;
927
+ }
928
+ }
929
+ }
930
+
931
+ /* Frees all temporarily allocated memory */
932
+ static void free_allocated_memory(PlotAxis *s)
933
+ {
934
+ int i;
935
+ if (s->free_majors) free(s->majors);
936
+ if (s->labels != NULL) {
937
+ if (s->free_strings_for_labels) {
938
+ for (i = 0; i < s->nmajors; i++)
939
+ if (s->labels[i] != NULL) free(s->labels[i]);
940
+ }
941
+ free(s->labels);
942
+ }
943
+ }
944
+
945
+ static void c_show_side(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr) {
946
+ if (s->type == AXIS_HIDDEN) return;
947
+ Start_Axis_Standard_State(fmkr, p,
948
+ s->stroke_color_R, s->stroke_color_G, s->stroke_color_B,
949
+ s->line_width * p->default_line_scale, ierr);
950
+ if (*ierr != 0) return;
951
+ draw_axis_line(fmkr, p, s->location, s, ierr);
952
+ if (*ierr != 0) return;
953
+ if (s->type == AXIS_LINE_ONLY) goto done;
954
+ draw_major_ticks(fmkr, p, s, ierr);
955
+ if (*ierr != 0) return;
956
+ if (s->type == AXIS_WITH_MAJOR_TICKS_ONLY) goto done;
957
+ if (s->type == AXIS_WITH_MAJOR_TICKS_AND_NUMERIC_LABELS) {
958
+ draw_numeric_labels(fmkr, p, s->location, s, ierr);
959
+ if (*ierr != 0) return;
960
+ goto done;
961
+ }
962
+ draw_minor_ticks(fmkr, p, s, ierr);
963
+ if (*ierr != 0) return;
964
+ if (s->type == AXIS_WITH_TICKS_ONLY) goto done;
965
+ draw_numeric_labels(fmkr, p, s->location, s, ierr);
966
+ if (*ierr != 0) return;
967
+ done:
968
+ End_Axis_Standard_State(); // grestore
969
+ free_allocated_memory(s);
970
+ }
971
+
972
+
973
+ void c_show_edge(OBJ_PTR fmkr, FM *p, int location, int *ierr)
974
+ {
975
+ PlotAxis axis;
976
+ switch (location) {
977
+ case LEFT:
978
+ if (!p->left_edge_visible) return;
979
+ Get_yaxis_Specs(fmkr, p, &axis, ierr); axis.type = p->left_edge_type;
980
+ break;
981
+ case RIGHT:
982
+ if (!p->right_edge_visible) return;
983
+ Get_yaxis_Specs(fmkr, p, &axis, ierr); axis.type = p->right_edge_type;
984
+ break;
985
+ case BOTTOM:
986
+ if (!p->bottom_edge_visible) return;
987
+ Get_xaxis_Specs(fmkr, p, &axis, ierr); axis.type = p->bottom_edge_type;
988
+ break;
989
+ case TOP:
990
+ if (!p->top_edge_visible) return;
991
+ Get_xaxis_Specs(fmkr, p, &axis, ierr); axis.type = p->top_edge_type;
992
+ break;
993
+ default:
994
+ RAISE_ERROR_i(
995
+ "Sorry: invalid 'loc' for edge: must be one of LEFT, RIGHT, TOP, or BOTTOM: is (%i)", location, ierr);
996
+ }
997
+ if (*ierr != 0) return;
998
+ axis.location = location;
999
+ c_show_side(fmkr, p, &axis, ierr);
1000
+ }
1001
+
1002
+
1003
+ void c_no_title(OBJ_PTR fmkr, FM *p, int *ierr)
1004
+ {
1005
+ p->title_visible = false;
1006
+ }
1007
+
1008
+ void c_no_xlabel(OBJ_PTR fmkr, FM *p, int *ierr)
1009
+ {
1010
+ p->xlabel_visible = false;
1011
+ }
1012
+
1013
+ void c_no_ylabel(OBJ_PTR fmkr, FM *p, int *ierr)
1014
+ {
1015
+ p->ylabel_visible = false;
1016
+ }
1017
+
1018
+ void c_no_xaxis(OBJ_PTR fmkr, FM *p, int *ierr)
1019
+ {
1020
+ p->xaxis_visible = false;
1021
+ }
1022
+
1023
+ void c_no_yaxis(OBJ_PTR fmkr, FM *p, int *ierr)
1024
+ {
1025
+ p->yaxis_visible = false;
1026
+ }
1027
+
1028
+ void c_no_left_edge(OBJ_PTR fmkr, FM *p, int *ierr)
1029
+ {
1030
+ p->left_edge_visible = false;
1031
+ }
1032
+
1033
+ void c_no_right_edge(OBJ_PTR fmkr, FM *p, int *ierr)
1034
+ {
1035
+ p->right_edge_visible = false;
1036
+ }
1037
+
1038
+ void c_no_top_edge(OBJ_PTR fmkr, FM *p, int *ierr)
1039
+ {
1040
+ p->top_edge_visible = false;
1041
+ }
1042
+
1043
+ void c_no_bottom_edge(OBJ_PTR fmkr, FM *p, int *ierr)
1044
+ {
1045
+ p->bottom_edge_visible = false;
1046
+ }
1047
+
1048
+
1049
+ /* Prepares the PlotAxis object for a standard use.
1050
+ Returns 1 if the corresponding axis is marked as
1051
+ visible and 0 if not.
1052
+
1053
+ This function will be used later to get the exact same PlotAxis
1054
+ object so as to get information about the ticks, for instance.
1055
+ */
1056
+ static int prepare_standard_PlotAxis(OBJ_PTR fmkr, FM *p,
1057
+ int location, PlotAxis * axis,
1058
+ int *ierr)
1059
+ {
1060
+ axis->location = location;
1061
+ if (location == LEFT || location == RIGHT || location == AT_X_ORIGIN) {
1062
+ Get_yaxis_Specs(fmkr, p, axis, ierr);
1063
+ if (!p->yaxis_visible) return 0;
1064
+ }
1065
+ else if (location == TOP || location == BOTTOM || location == AT_Y_ORIGIN) {
1066
+ Get_xaxis_Specs(fmkr, p, axis, ierr);
1067
+ if (!p->xaxis_visible) return 0;
1068
+ }
1069
+ else
1070
+ RAISE_ERROR_i("Sorry: invalid 'loc' for axis: must be one of LEFT,"
1071
+ "RIGHT, TOP, BOTTOM, AT_X_ORIGIN, or AT_Y_ORIGIN: is (%i)",
1072
+ location, ierr);
1073
+ if (*ierr != 0)
1074
+ return 0;
1075
+ return 1;
1076
+ }
1077
+
1078
+
1079
+ void c_show_axis(OBJ_PTR fmkr, FM *p, int location, int *ierr)
1080
+ {
1081
+ PlotAxis axis;
1082
+ if(prepare_standard_PlotAxis(fmkr, p, location, &axis, ierr)) {
1083
+ c_show_side(fmkr, p, &axis, ierr);
1084
+ }
1085
+ }
1086
+
1087
+ /* This function prepares a PlotAxis object based on the information
1088
+ given in the dict argument.
1089
+ */
1090
+ static int prepare_dict_PlotAxis(OBJ_PTR fmkr, FM *p,
1091
+ OBJ_PTR axis_spec, PlotAxis * axis,
1092
+ int *ierr)
1093
+ {
1094
+ /* First, we get default from the location or from style.
1095
+ Too many things need to be checked if we don't get default values
1096
+ from a given point
1097
+ */
1098
+ if(Hash_Has_Key(axis_spec, "location")) {
1099
+ int location = Number_to_int(Hash_Get_Obj(axis_spec, "location"), ierr);
1100
+ if (location == LEFT || location == RIGHT || location == AT_X_ORIGIN) {
1101
+ Get_yaxis_Specs(fmkr, p, axis, ierr);
1102
+ }
1103
+ else if (location == TOP || location == BOTTOM ||
1104
+ location == AT_Y_ORIGIN) {
1105
+ Get_xaxis_Specs(fmkr, p, axis, ierr);
1106
+ }
1107
+ axis->location = location;
1108
+ }
1109
+ else {
1110
+ if(Hash_Has_Key(axis_spec, "from") && Hash_Has_Key(axis_spec, "to")) {
1111
+ long dummy;
1112
+ double *from = Vector_Data_for_Read(Hash_Get_Obj(axis_spec, "from"),
1113
+ &dummy, ierr);
1114
+ double *to = Vector_Data_for_Read(Hash_Get_Obj(axis_spec, "to"),
1115
+ &dummy, ierr);
1116
+ axis->x0 = from[0];
1117
+ axis->x1 = to[0];
1118
+ axis->y0 = from[1];
1119
+ axis->y1 = to[1];
1120
+
1121
+ /* We now determine various parameters attached to the axis:
1122
+ * its length
1123
+ * its min/max boundaries
1124
+ * whether it is reversed
1125
+ */
1126
+ if(axis->y0 != axis->y1) {
1127
+ Get_yaxis_Specs(fmkr, p, axis, ierr);
1128
+ if(axis->x0 != axis->x1) {
1129
+ RAISE_ERROR("show_axis: sorry, axes must be horizontal or "
1130
+ "vertical", ierr);
1131
+ }
1132
+ else {
1133
+ if(axis->y0 > axis->y1) {
1134
+ axis->reversed = true;
1135
+ axis->axis_min = axis->y1;
1136
+ axis->axis_max = axis->y0;
1137
+ axis->length = axis->y0 - axis->y1;
1138
+ }
1139
+ else {
1140
+ axis->reversed = false;
1141
+ axis->axis_min = axis->y0;
1142
+ axis->axis_max = axis->y1;
1143
+ axis->length = axis->y1 - axis->y0;
1144
+ }
1145
+ axis->vertical = true;
1146
+ axis->location = AXIS_FREE_LOCATION;
1147
+ }
1148
+ }
1149
+ else {
1150
+ Get_xaxis_Specs(fmkr, p, axis, ierr);
1151
+ if(axis->x0 > axis->x1) {
1152
+ axis->reversed = true;
1153
+ axis->axis_min = axis->x1;
1154
+ axis->axis_max = axis->x0;
1155
+ axis->length = axis->x0 - axis->x1;
1156
+ }
1157
+ else {
1158
+ axis->reversed = false;
1159
+ axis->axis_min = axis->x0;
1160
+ axis->axis_max = axis->x1;
1161
+ axis->length = axis->x1 - axis->x0;
1162
+ }
1163
+ axis->vertical = false;
1164
+ axis->location = AXIS_FREE_LOCATION;
1165
+ }
1166
+ }
1167
+ else {
1168
+ RAISE_ERROR("show_axis: there must be 'location' or 'to' and 'from'", ierr);
1169
+ }
1170
+ }
1171
+
1172
+ /* Some generic overrides */
1173
+ if(Hash_Has_Key(axis_spec, "type"))
1174
+ axis->type = Number_to_int(Hash_Get_Obj(axis_spec, "type"), ierr);
1175
+
1176
+ if(Hash_Has_Key(axis_spec, "ticks_inside")) {
1177
+ OBJ_PTR val = Hash_Get_Obj(axis_spec, "ticks_inside");
1178
+ if(val == OBJ_NIL || val == OBJ_FALSE)
1179
+ axis->ticks_inside = false;
1180
+ else
1181
+ axis->ticks_inside = true;
1182
+ }
1183
+
1184
+ if(Hash_Has_Key(axis_spec, "ticks_outside")) {
1185
+ OBJ_PTR val = Hash_Get_Obj(axis_spec, "ticks_outside");
1186
+ if(val == OBJ_NIL || val == OBJ_FALSE)
1187
+ axis->ticks_outside = false;
1188
+ else
1189
+ axis->ticks_outside = true;
1190
+ }
1191
+
1192
+ if(Hash_Has_Key(axis_spec, "major_ticks"))
1193
+ axis->locations_for_major_ticks = Hash_Get_Obj(axis_spec, "major_ticks");
1194
+ if(Hash_Has_Key(axis_spec, "minor_ticks"))
1195
+ axis->locations_for_minor_ticks = Hash_Get_Obj(axis_spec, "minor_ticks");
1196
+ if(Hash_Has_Key(axis_spec, "labels"))
1197
+ axis->tick_labels = Hash_Get_Obj(axis_spec, "labels");
1198
+
1199
+
1200
+ /* Various tick label attributes */
1201
+ if(Hash_Has_Key(axis_spec, "shift"))
1202
+ axis->numeric_label_shift = Hash_Get_Double(axis_spec, "shift");
1203
+ if(Hash_Has_Key(axis_spec, "scale"))
1204
+ axis->numeric_label_scale = Hash_Get_Double(axis_spec, "scale");
1205
+ if(Hash_Has_Key(axis_spec, "angle"))
1206
+ axis->numeric_label_angle = Hash_Get_Double(axis_spec, "angle");
1207
+ if(Hash_Has_Key(axis_spec, "justification"))
1208
+ axis->numeric_label_justification =
1209
+ Hash_Get_Double(axis_spec, "justification");
1210
+ if(Hash_Has_Key(axis_spec, "alignment"))
1211
+ axis->numeric_label_alignment =
1212
+ Hash_Get_Double(axis_spec, "alignment");
1213
+
1214
+ /* Ticks attributes */
1215
+ if(Hash_Has_Key(axis_spec, "major_tick_width"))
1216
+ axis->major_tick_width = Hash_Get_Double(axis_spec, "major_tick_width");
1217
+ if(Hash_Has_Key(axis_spec, "minor_tick_width"))
1218
+ axis->minor_tick_width = Hash_Get_Double(axis_spec, "minor_tick_width");
1219
+ if(Hash_Has_Key(axis_spec, "major_tick_length"))
1220
+ axis->major_tick_length = Hash_Get_Double(axis_spec, "major_tick_length");
1221
+ if(Hash_Has_Key(axis_spec, "minor_tick_length"))
1222
+ axis->minor_tick_length = Hash_Get_Double(axis_spec, "minor_tick_length");
1223
+
1224
+ /* Stroke color */
1225
+ if(Hash_Has_Key(axis_spec, "stroke_color") ||
1226
+ Hash_Has_Key(axis_spec, "color")) {
1227
+ OBJ_PTR color = (Hash_Has_Key(axis_spec, "stroke_color") ?
1228
+ Hash_Get_Obj(axis_spec, "stroke_color") :
1229
+ Hash_Get_Obj(axis_spec, "color") );
1230
+ int err;
1231
+ axis->stroke_color_R = Array_Entry_double(color, 0, &err);
1232
+ axis->stroke_color_G = Array_Entry_double(color, 1, &err);
1233
+ axis->stroke_color_B = Array_Entry_double(color, 2, &err);
1234
+ }
1235
+
1236
+ /* Labels color */
1237
+ if(Hash_Has_Key(axis_spec, "labels_color") ||
1238
+ Hash_Has_Key(axis_spec, "color")) {
1239
+ OBJ_PTR color = (Hash_Has_Key(axis_spec, "labels_color") ?
1240
+ Hash_Get_Obj(axis_spec, "labels_color") :
1241
+ Hash_Get_Obj(axis_spec, "color") );
1242
+ int err;
1243
+ axis->labels_color_R = Array_Entry_double(color, 0, &err);
1244
+ axis->labels_color_G = Array_Entry_double(color, 1, &err);
1245
+ axis->labels_color_B = Array_Entry_double(color, 2, &err);
1246
+ }
1247
+
1248
+ /* Log scale: */
1249
+ if(Hash_Has_Key(axis_spec, "log")) {
1250
+ OBJ_PTR val = Hash_Get_Obj(axis_spec, "log");
1251
+ if(val == OBJ_NIL || val == OBJ_FALSE)
1252
+ axis->log_vals = 0;
1253
+ else
1254
+ axis->log_vals = 1;
1255
+ }
1256
+
1257
+
1258
+ return 1;
1259
+ }
1260
+
1261
+
1262
+ /* This function does nearly the same job as c_show_axis, but takes
1263
+ a full hash instead of getting information from the FigureMaker object,
1264
+ it retrieves them from the axis_spec hash. Following keys are
1265
+ understood:
1266
+ - location: position, as in show_axis. Can be omitted, if you
1267
+ provide the position yourself
1268
+
1269
+ This function bypasses the axis_visible checks. Use with caution !
1270
+ */
1271
+ void c_show_axis_generic(OBJ_PTR fmkr, FM *p, OBJ_PTR axis_spec, int *ierr)
1272
+ {
1273
+ PlotAxis axis;
1274
+ if(prepare_dict_PlotAxis(fmkr, p, axis_spec, &axis, ierr)) {
1275
+ c_show_side(fmkr, p, &axis, ierr);
1276
+ }
1277
+ }
1278
+
1279
+
1280
+ /*
1281
+ This function takes an axis specification (either integer or
1282
+ hash) and returns a hash containing the following keys:
1283
+ * 'major_ticks' : position of all major ticks
1284
+ * 'minor_ticks' : position of all major ticks
1285
+ * 'labels' : the names of all labels
1286
+ * 'vertical' : if the axis is vertical or horizontal
1287
+ * 'line_width' : the line width
1288
+ * 'major_tick_width', 'major_tick_length' : the major tick width and length
1289
+ * 'minor_tick_width', 'minor_tick_length' : the minor tick width and length
1290
+ * 'scale', 'shift' and 'angle': the scale, shift and angle of numeric
1291
+ labels
1292
+ * 'x0', 'y0', 'x1', 'y1': the position of the axis in figure coordinates
1293
+ * 'stroke_color': the color to use for drawing lines.
1294
+ * 'labels_color': the color to use for drawing tick labels.
1295
+ */
1296
+ OBJ_PTR c_axis_get_information(OBJ_PTR fmkr, FM *p, OBJ_PTR axis_spec,
1297
+ int *ierr)
1298
+ {
1299
+ PlotAxis axis;
1300
+ OBJ_PTR hash = Hash_New(), ar;
1301
+ int i;
1302
+ if(Is_Kind_of_Integer(axis_spec))
1303
+ prepare_standard_PlotAxis(fmkr, p, Number_to_int(axis_spec, ierr),
1304
+ &axis, ierr);
1305
+ else
1306
+ prepare_dict_PlotAxis(fmkr, p, axis_spec, &axis, ierr);
1307
+
1308
+ /* First, major ticks positions */
1309
+ prepare_axis_coordinates(fmkr, p, axis.location, &axis, ierr);
1310
+ compute_major_ticks(fmkr, p, &axis, ierr);
1311
+ Hash_Set_Obj(hash, "major_ticks", Vector_New(axis.nmajors, axis.majors));
1312
+
1313
+ /* Then, minor ticks positions */
1314
+ double * minor;
1315
+ long count;
1316
+ OBJ_PTR color;
1317
+ minor = get_minor_ticks_location(fmkr, p, &axis, &count);
1318
+ if(minor) {
1319
+ Hash_Set_Obj(hash, "minor_ticks", Vector_New(count, minor));
1320
+ free(minor);
1321
+ }
1322
+
1323
+ /* Then, labels */
1324
+ ar = Array_New(axis.nmajors);
1325
+ axis.labels = Get_Labels(fmkr, p, &axis, ierr);
1326
+ for (i=0; i < axis.nmajors; i++) {
1327
+ if (axis.labels[i])
1328
+ Array_Store(ar, i, String_From_Cstring(axis.labels[i]), ierr);
1329
+ else
1330
+ Array_Store(ar, i, OBJ_NIL, ierr);
1331
+ }
1332
+
1333
+ Hash_Set_Obj(hash, "labels", ar);
1334
+
1335
+ Hash_Set_Obj(hash, "vertical", axis.vertical ? OBJ_TRUE : OBJ_FALSE);
1336
+
1337
+ Hash_Set_Double(hash, "line_width", axis.line_width);
1338
+ Hash_Set_Double(hash, "major_tick_width", axis.major_tick_width);
1339
+ Hash_Set_Double(hash, "minor_tick_width", axis.major_tick_width);
1340
+ Hash_Set_Double(hash, "major_tick_length", axis.major_tick_length);
1341
+ Hash_Set_Double(hash, "minor_tick_length", axis.major_tick_length);
1342
+ Hash_Set_Double(hash, "shift", axis.numeric_label_shift);
1343
+ Hash_Set_Double(hash, "scale", axis.numeric_label_scale);
1344
+ Hash_Set_Double(hash, "angle", axis.numeric_label_angle);
1345
+
1346
+ /* Positions of the axis */
1347
+ Hash_Set_Double(hash, "x0", axis.x0);
1348
+ Hash_Set_Double(hash, "x1", axis.x1);
1349
+ Hash_Set_Double(hash, "y0", axis.y0);
1350
+ Hash_Set_Double(hash, "y1", axis.y1);
1351
+
1352
+ /* Log values */
1353
+ Hash_Set_Obj(hash, "log", axis.log_vals ? OBJ_TRUE : OBJ_FALSE);
1354
+
1355
+ /* Stroke color */
1356
+ color = Array_New(3);
1357
+ Array_Store(color, 0, Float_New(axis.stroke_color_R),ierr);
1358
+ Array_Store(color, 1, Float_New(axis.stroke_color_G),ierr);
1359
+ Array_Store(color, 2, Float_New(axis.stroke_color_B),ierr);
1360
+ Hash_Set_Obj(hash, "stroke_color", color);
1361
+
1362
+ /* Tick labels color */
1363
+ color = Array_New(3);
1364
+ Array_Store(color, 0, Float_New(axis.labels_color_R),ierr);
1365
+ Array_Store(color, 1, Float_New(axis.labels_color_G),ierr);
1366
+ Array_Store(color, 2, Float_New(axis.labels_color_B),ierr);
1367
+ Hash_Set_Obj(hash, "labels_color", color);
1368
+
1369
+
1370
+
1371
+ free_allocated_memory(&axis);
1372
+ return hash;
1373
+ }