tioga 1.11 → 1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }