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.
- 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
|
+
}
|