tioga 1.11 → 1.13
Sign up to get free protection for your applications and to get access to all the features.
- data/Tioga_README +58 -35
- data/{split/scripts → bin}/tioga +1 -1
- data/{split → ext/Dobjects}/Dtable/dtable.c +81 -15
- data/{split → ext/Dobjects}/Dtable/dtable_intern.h +0 -0
- data/ext/Dobjects/Dtable/extconf.rb +7 -0
- data/{split → ext/Dobjects}/Dtable/include/dtable.h +0 -0
- data/{split → ext/Dobjects}/Dvector/dvector.c +361 -51
- data/{split → ext/Dobjects}/Dvector/dvector_intern.h +0 -0
- data/ext/Dobjects/Dvector/extconf.rb +22 -0
- data/{split/Dtable → ext/Dobjects/Dvector/include}/dvector.h +0 -0
- data/ext/Dobjects/Function/extconf.rb +7 -0
- data/{split → ext/Dobjects}/Function/function.c +636 -11
- data/{split → ext/Dobjects}/Function/joint_qsort.c +0 -0
- data/ext/Flate/extconf.rb +26 -0
- data/{split → ext}/Flate/flate.c +7 -3
- data/{split → ext}/Flate/flate_intern.h +0 -0
- data/{split → ext}/Flate/include/flate.h +0 -0
- data/ext/Flate/zlib/adler32.c +149 -0
- data/ext/Flate/zlib/compress.c +79 -0
- data/ext/Flate/zlib/crc32.c +423 -0
- data/ext/Flate/zlib/crc32.h +441 -0
- data/ext/Flate/zlib/deflate.c +1736 -0
- data/ext/Flate/zlib/deflate.h +331 -0
- data/ext/Flate/zlib/gzio.c +1026 -0
- data/ext/Flate/zlib/infback.c +623 -0
- data/ext/Flate/zlib/inffast.c +318 -0
- data/ext/Flate/zlib/inffast.h +11 -0
- data/ext/Flate/zlib/inffixed.h +94 -0
- data/ext/Flate/zlib/inflate.c +1368 -0
- data/ext/Flate/zlib/inflate.h +115 -0
- data/ext/Flate/zlib/inftrees.c +329 -0
- data/ext/Flate/zlib/inftrees.h +55 -0
- data/ext/Flate/zlib/trees.c +1219 -0
- data/ext/Flate/zlib/trees.h +128 -0
- data/ext/Flate/zlib/uncompr.c +61 -0
- data/ext/Flate/zlib/zlib.h +1357 -0
- data/ext/Flate/zlib/zutil.c +318 -0
- data/ext/Flate/zlib/zutil.h +269 -0
- data/ext/Tioga/FigureMaker/__shared_axes.c +1373 -0
- data/ext/Tioga/FigureMaker/__shared_makers.c +1303 -0
- data/{split/Tioga/pdf_font_dicts.c → ext/Tioga/FigureMaker/__shared_pdf_font_dicts.c} +0 -0
- data/{split/Tioga/pdfcolor.c → ext/Tioga/FigureMaker/__shared_pdfcolor.c} +0 -0
- data/{split/Tioga/pdfcoords.c → ext/Tioga/FigureMaker/__shared_pdfcoords.c} +0 -0
- data/{split/Tioga/pdffile.c → ext/Tioga/FigureMaker/__shared_pdffile.c} +0 -0
- data/{split/Tioga/pdfimage.c → ext/Tioga/FigureMaker/__shared_pdfimage.c} +0 -0
- data/{split/Tioga/pdfpath.c → ext/Tioga/FigureMaker/__shared_pdfpath.c} +0 -0
- data/{split/Tioga/pdftext.c → ext/Tioga/FigureMaker/__shared_pdftext.c} +0 -0
- data/{split/Tioga/texout.c → ext/Tioga/FigureMaker/__shared_texout.c} +0 -0
- data/ext/Tioga/FigureMaker/extconf.rb +7 -0
- data/{split/Tioga → ext/Tioga/FigureMaker}/figures.c +14 -2
- data/{split/Tioga → ext/Tioga/FigureMaker}/figures.h +0 -0
- data/{split/Tioga → ext/Tioga/FigureMaker}/generic.c +1 -2
- data/{split/Tioga → ext/Tioga/FigureMaker}/generic.h +0 -1
- data/{split/Tioga → ext/Tioga/FigureMaker}/init.c +0 -0
- data/{split/Tioga → ext/Tioga/FigureMaker}/pdfs.h +0 -0
- data/{split/Tioga → ext/Tioga/FigureMaker/shared}/axes.c +32 -7
- data/{split/Tioga → ext/Tioga/FigureMaker/shared}/makers.c +2 -2
- data/ext/Tioga/FigureMaker/shared/pdf_font_dicts.c +18253 -0
- data/ext/Tioga/FigureMaker/shared/pdfcolor.c +904 -0
- data/ext/Tioga/FigureMaker/shared/pdfcoords.c +518 -0
- data/ext/Tioga/FigureMaker/shared/pdffile.c +451 -0
- data/ext/Tioga/FigureMaker/shared/pdfimage.c +539 -0
- data/ext/Tioga/FigureMaker/shared/pdfpath.c +766 -0
- data/ext/Tioga/FigureMaker/shared/pdftext.c +710 -0
- data/ext/Tioga/FigureMaker/shared/texout.c +533 -0
- data/{split/Tioga → ext/Tioga/FigureMaker}/wrappers.c +5 -5
- data/{split/Tioga → ext/Tioga/FigureMaker}/wrappers.h +0 -0
- data/{split/Dtable → ext/includes}/defs.h +0 -0
- data/{split/Dtable → ext/includes}/namespace.h +0 -0
- data/{split/Dtable → ext/includes}/safe_double.h +0 -0
- data/{split → ext/includes}/symbols.c +0 -1
- data/{split/Dtable → ext/includes}/symbols.h +0 -0
- data/{split/Dtable/lib → lib/Dobjects}/Dtable_extras.rb +0 -0
- data/{split/Dvector/lib → lib/Dobjects}/Dvector_extras.rb +1 -0
- data/{split/Function/lib → lib/Dobjects}/Function_extras.rb +0 -0
- data/{split/Dvector/lib → lib/Dobjects}/Numeric_extras.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Arcs_and_Circles.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/ColorConstants.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Colorbars.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Colormaps.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Coordinate_Conversions.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Creating_Paths.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Doc.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Executive.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/FigMkr.rb +13 -70
- data/{split/Tioga/lib → lib/Tioga}/FigureConstants.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Figures_and_Plots.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Images.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Legends.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/MarkerConstants.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Markers.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Page_Frame_Bounds.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Rectangles.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Shading.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Special_Paths.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Strokes.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/TeX_Text.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/TexPreamble.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Titles_and_Labels.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Transparency.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Using_Paths.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/Utils.rb +74 -0
- data/{split/Tioga/lib → lib/Tioga}/X_and_Y_Axes.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/irb_tioga.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/maker.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/tioga.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/tioga_ui.rb +0 -0
- data/{split/Tioga/lib → lib/Tioga}/tioga_ui_cmds.rb +0 -0
- data/tests/Icon_Test.pdf +0 -0
- data/tests/benchmark_dvector_reads.rb +20 -42
- data/tests/tc_Dvector.rb +45 -4
- data/tests/tc_Flate.rb +4 -5
- data/tests/tc_Function.rb +79 -0
- data/tests/vg.log +1453 -0
- metadata +141 -122
- data/split/Dtable/extconf.rb +0 -4
- data/split/Dvector/defs.h +0 -39
- data/split/Dvector/extconf.rb +0 -4
- data/split/Dvector/include/dvector.h +0 -77
- data/split/Dvector/namespace.h +0 -59
- data/split/Dvector/safe_double.h +0 -104
- data/split/Dvector/symbols.h +0 -52
- data/split/Flate/defs.h +0 -39
- data/split/Flate/extconf.rb +0 -19
- data/split/Flate/namespace.h +0 -59
- data/split/Flate/safe_double.h +0 -104
- data/split/Flate/symbols.h +0 -52
- data/split/Function/defs.h +0 -39
- data/split/Function/dvector.h +0 -77
- data/split/Function/extconf.rb +0 -4
- data/split/Function/namespace.h +0 -59
- data/split/Function/safe_double.h +0 -104
- data/split/Function/symbols.h +0 -52
- data/split/Tioga/defs.h +0 -39
- data/split/Tioga/dtable.h +0 -35
- data/split/Tioga/dvector.h +0 -77
- data/split/Tioga/extconf.rb +0 -4
- data/split/Tioga/flate.h +0 -98
- data/split/Tioga/mk_tioga_sty.rb +0 -53
- data/split/Tioga/namespace.h +0 -59
- data/split/Tioga/safe_double.h +0 -104
- data/split/Tioga/symbols.h +0 -52
- data/split/defs.h +0 -39
- data/split/extconf.rb +0 -125
- data/split/mkmf2.rb +0 -1623
- data/split/namespace.h +0 -59
- data/split/safe_double.h +0 -104
- 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
|
+
}
|