tioga 1.4
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 +372 -0
- data/lgpl.txt +504 -0
- data/split/Dtable/defs.h +33 -0
- data/split/Dtable/dtable.c +1928 -0
- data/split/Dtable/dtable_intern.h +144 -0
- data/split/Dtable/dvector.h +61 -0
- data/split/Dtable/extconf.rb +4 -0
- data/split/Dtable/include/dtable.h +35 -0
- data/split/Dtable/lib/Dtable_extras.rb +90 -0
- data/split/Dtable/namespace.h +47 -0
- data/split/Dtable/safe_double.h +104 -0
- data/split/Dtable/symbols.c +92 -0
- data/split/Dtable/symbols.h +52 -0
- data/split/Dvector/defs.h +33 -0
- data/split/Dvector/dvector.c +5486 -0
- data/split/Dvector/dvector_intern.h +142 -0
- data/split/Dvector/extconf.rb +4 -0
- data/split/Dvector/include/dvector.h +61 -0
- data/split/Dvector/lib/Dvector_extras.rb +328 -0
- data/split/Dvector/lib/Numeric_extras.rb +134 -0
- data/split/Dvector/namespace.h +47 -0
- data/split/Dvector/safe_double.h +104 -0
- data/split/Dvector/symbols.c +92 -0
- data/split/Dvector/symbols.h +52 -0
- data/split/Flate/defs.h +33 -0
- data/split/Flate/extconf.rb +19 -0
- data/split/Flate/flate.c +156 -0
- data/split/Flate/flate_intern.h +97 -0
- data/split/Flate/include/flate.h +98 -0
- data/split/Flate/namespace.h +47 -0
- data/split/Flate/safe_double.h +104 -0
- data/split/Flate/symbols.c +92 -0
- data/split/Flate/symbols.h +52 -0
- data/split/Function/defs.h +33 -0
- data/split/Function/dvector.h +61 -0
- data/split/Function/extconf.rb +4 -0
- data/split/Function/function.c +988 -0
- data/split/Function/joint_qsort.c +258 -0
- data/split/Function/lib/Function_extras.rb +44 -0
- data/split/Function/namespace.h +47 -0
- data/split/Function/safe_double.h +104 -0
- data/split/Function/symbols.c +92 -0
- data/split/Function/symbols.h +52 -0
- data/split/Tioga/axes.c +774 -0
- data/split/Tioga/defs.h +33 -0
- data/split/Tioga/dtable.h +35 -0
- data/split/Tioga/dvector.h +61 -0
- data/split/Tioga/extconf.rb +4 -0
- data/split/Tioga/figures.c +672 -0
- data/split/Tioga/figures.h +855 -0
- data/split/Tioga/flate.h +98 -0
- data/split/Tioga/init.c +524 -0
- data/split/Tioga/lib/Arcs_and_Circles.rb +64 -0
- data/split/Tioga/lib/ColorConstants.rb +274 -0
- data/split/Tioga/lib/Colorbars.rb +10 -0
- data/split/Tioga/lib/Colormaps.rb +105 -0
- data/split/Tioga/lib/Coordinate_Conversions.rb +194 -0
- data/split/Tioga/lib/Creating_Paths.rb +94 -0
- data/split/Tioga/lib/Doc.rb +91 -0
- data/split/Tioga/lib/Executive.rb +515 -0
- data/split/Tioga/lib/FigMkr.rb +2224 -0
- data/split/Tioga/lib/FigureConstants.rb +125 -0
- data/split/Tioga/lib/Figures_and_Plots.rb +268 -0
- data/split/Tioga/lib/Images.rb +278 -0
- data/split/Tioga/lib/Legends.rb +190 -0
- data/split/Tioga/lib/MarkerConstants.rb +122 -0
- data/split/Tioga/lib/Markers.rb +129 -0
- data/split/Tioga/lib/Page_Frame_Bounds.rb +567 -0
- data/split/Tioga/lib/Rectangles.rb +94 -0
- data/split/Tioga/lib/Shading.rb +100 -0
- data/split/Tioga/lib/Special_Paths.rb +307 -0
- data/split/Tioga/lib/Strokes.rb +129 -0
- data/split/Tioga/lib/TeX_Text.rb +454 -0
- data/split/Tioga/lib/TexPreamble.rb +358 -0
- data/split/Tioga/lib/Titles_and_Labels.rb +306 -0
- data/split/Tioga/lib/Transparency.rb +89 -0
- data/split/Tioga/lib/Using_Paths.rb +164 -0
- data/split/Tioga/lib/Utils.rb +74 -0
- data/split/Tioga/lib/X_and_Y_Axes.rb +749 -0
- data/split/Tioga/lib/irb_tioga.rb +122 -0
- data/split/Tioga/lib/tioga.rb +1 -0
- data/split/Tioga/lib/tioga_ui.rb +5 -0
- data/split/Tioga/lib/tioga_ui_cmds.rb +793 -0
- data/split/Tioga/makers.c +989 -0
- data/split/Tioga/mk_tioga_sty.rb +53 -0
- data/split/Tioga/namespace.h +47 -0
- data/split/Tioga/pdf_font_dicts.c +18253 -0
- data/split/Tioga/pdfcolor.c +486 -0
- data/split/Tioga/pdfcoords.c +505 -0
- data/split/Tioga/pdffile.c +342 -0
- data/split/Tioga/pdfimage.c +536 -0
- data/split/Tioga/pdfpath.c +914 -0
- data/split/Tioga/pdfs.h +229 -0
- data/split/Tioga/pdftext.c +443 -0
- data/split/Tioga/safe_double.h +104 -0
- data/split/Tioga/symbols.c +92 -0
- data/split/Tioga/symbols.h +52 -0
- data/split/Tioga/texout.c +380 -0
- data/split/defs.h +33 -0
- data/split/extconf.rb +107 -0
- data/split/mkmf2.rb +1612 -0
- data/split/namespace.h +47 -0
- data/split/safe_double.h +104 -0
- data/split/scripts/tioga +4 -0
- data/split/symbols.c +92 -0
- data/split/symbols.h +52 -0
- data/tests/dtable_test.data +6 -0
- data/tests/dvector_read_test.data +1 -0
- data/tests/dvector_test.data +101 -0
- data/tests/tc_Dtable.rb +221 -0
- data/tests/tc_Dvector.rb +791 -0
- data/tests/tc_FMkr.rb +162 -0
- data/tests/tc_Flate.rb +45 -0
- data/tests/tc_Function.rb +111 -0
- data/tests/ts_Tioga.rb +38 -0
- metadata +163 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2006 Vincent Fourmond
|
|
3
|
+
|
|
4
|
+
Symbols is free software; you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU General Library Public License as published
|
|
6
|
+
by the Free Software Foundation; either version 2 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
Symbols is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU Library General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU Library General Public License
|
|
15
|
+
along with Dvector; if not, write to the Free Software
|
|
16
|
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
/* Simple code for sharing C symbols across different Ruby libraries */
|
|
21
|
+
|
|
22
|
+
#include <ruby.h>
|
|
23
|
+
#include <intern.h>
|
|
24
|
+
|
|
25
|
+
#include <namespace.h>
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
/* MV stands for Module Variable */
|
|
29
|
+
#define MV_SYMBOLS "@_exported_C_symbols"
|
|
30
|
+
/* modified to use instance variables instead of global class variables:
|
|
31
|
+
this way, children don't overwrite the parent's export table
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
/* makes sure that the hash is registered for the given
|
|
36
|
+
module and returns it */
|
|
37
|
+
static VALUE get_symbol_hash(VALUE module)
|
|
38
|
+
{
|
|
39
|
+
VALUE hash;
|
|
40
|
+
ID mv_id = rb_intern(MV_SYMBOLS);
|
|
41
|
+
if(RTEST(rb_ivar_defined(module, mv_id)))
|
|
42
|
+
{
|
|
43
|
+
hash = rb_ivar_get(module, mv_id);
|
|
44
|
+
Check_Type(hash, T_HASH);
|
|
45
|
+
return hash;
|
|
46
|
+
}
|
|
47
|
+
else
|
|
48
|
+
{
|
|
49
|
+
/* module variable uninitialized, we need to make sure it's here */
|
|
50
|
+
hash = rb_hash_new();
|
|
51
|
+
rb_ivar_set(module, mv_id, hash);
|
|
52
|
+
return hash;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* registers a symbol in the given module. This one is the internal
|
|
57
|
+
function */
|
|
58
|
+
PRIVATE void rb_export_symbol(VALUE module, const char * symbol_name,
|
|
59
|
+
void * symbol)
|
|
60
|
+
{
|
|
61
|
+
VALUE hash = get_symbol_hash(module);
|
|
62
|
+
rb_hash_aset(hash, rb_str_new2(symbol_name),LONG2NUM((long) symbol));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
PRIVATE void * rb_import_symbol_no_raise(VALUE module,
|
|
66
|
+
const char * symbol_name)
|
|
67
|
+
{
|
|
68
|
+
VALUE hash = rb_iv_get(module, MV_SYMBOLS);
|
|
69
|
+
if(TYPE(hash) != T_HASH)
|
|
70
|
+
return NULL; /* doesn't fail, but the importing module
|
|
71
|
+
should definitely check the return value. Beware
|
|
72
|
+
of segfaults ! */
|
|
73
|
+
VALUE symbol = rb_hash_aref(hash, rb_str_new2(symbol_name));
|
|
74
|
+
|
|
75
|
+
if(TYPE(symbol) == T_FIXNUM || TYPE(symbol) == T_BIGNUM)
|
|
76
|
+
return (void *) NUM2LONG(symbol);
|
|
77
|
+
return NULL;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* same as before, but raises something is the return value is NULL,
|
|
81
|
+
which is probably best as a default behavior*/
|
|
82
|
+
PRIVATE void * rb_import_symbol(VALUE module, const char * symbol_name)
|
|
83
|
+
{
|
|
84
|
+
void * symbol = rb_import_symbol_no_raise(module, symbol_name);
|
|
85
|
+
if(symbol)
|
|
86
|
+
return symbol;
|
|
87
|
+
/* we get the name of the module: */
|
|
88
|
+
VALUE module_name = rb_funcall(module, rb_intern("to_s"), 0);
|
|
89
|
+
rb_raise(rb_eRuntimeError, "The symbol %s was not found in "
|
|
90
|
+
"module %s", symbol_name,
|
|
91
|
+
rb_string_value_cstr(&module_name));
|
|
92
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#ifndef _SYMBOLS_H
|
|
2
|
+
#define _SYMBOLS_H
|
|
3
|
+
|
|
4
|
+
#include <ruby.h>
|
|
5
|
+
/* A small layer for exporting and importing symbols from
|
|
6
|
+
a compiled module */
|
|
7
|
+
|
|
8
|
+
#include <namespace.h>
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
PRIVATE void rb_export_symbol(VALUE module, const char * symbol_name,
|
|
12
|
+
void * symbol);
|
|
13
|
+
PRIVATE void * rb_import_symbol(VALUE module, const char * symbol_name);
|
|
14
|
+
PRIVATE void * rb_import_symbol_no_raise(VALUE module,
|
|
15
|
+
const char * symbol_name);
|
|
16
|
+
|
|
17
|
+
/* a shortcut for exporting something with the same name */
|
|
18
|
+
#define RB_EXPORT_SYMBOL(module, name) \
|
|
19
|
+
rb_export_symbol(module, #name, name)
|
|
20
|
+
|
|
21
|
+
/* A shortcut for getting a symbol */
|
|
22
|
+
|
|
23
|
+
#define DECLARE_SYMBOL(ret_type,name,args) \
|
|
24
|
+
typedef ret_type (*rb_export_##name##_type) args;\
|
|
25
|
+
PRIVATE rb_export_##name##_type name
|
|
26
|
+
|
|
27
|
+
#define IMPLEMENT_SYMBOL(name)\
|
|
28
|
+
PRIVATE rb_export_##name##_type name = 0;
|
|
29
|
+
|
|
30
|
+
#define RB_IMPORT_SYMBOL(module, name) \
|
|
31
|
+
name = (rb_export_##name##_type) rb_import_symbol(module, #name)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
/* These three macro enable a simple use of function declaration: this way,
|
|
35
|
+
you can type in a header file that is used by the importer:
|
|
36
|
+
|
|
37
|
+
DECLARE_SYMBOL(int, biniou, (int, int));
|
|
38
|
+
|
|
39
|
+
in one file of the importer code, you write
|
|
40
|
+
|
|
41
|
+
IMPLEMENT_SYMBOL(biniou);
|
|
42
|
+
|
|
43
|
+
and in the Init_... function, you write:
|
|
44
|
+
|
|
45
|
+
RB_IMPORT_SYMBOL(module, biniou);
|
|
46
|
+
|
|
47
|
+
and you can just use biniou as if it was a function declared as
|
|
48
|
+
usual in the header file
|
|
49
|
+
*/
|
|
50
|
+
#endif
|
|
51
|
+
|
|
52
|
+
|
data/split/Tioga/axes.c
ADDED
|
@@ -0,0 +1,774 @@
|
|
|
1
|
+
/* axes.c */
|
|
2
|
+
/*
|
|
3
|
+
Copyright (C) 2005 Bill Paxton
|
|
4
|
+
|
|
5
|
+
This file is part of Tioga.
|
|
6
|
+
|
|
7
|
+
Tioga is free software; you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU General Library Public License as published
|
|
9
|
+
by the Free Software Foundation; either version 2 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
Tioga is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU Library General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU Library General Public License
|
|
18
|
+
along with Tioga; if not, write to the Free Software
|
|
19
|
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
20
|
+
*/
|
|
21
|
+
#include "figures.h"
|
|
22
|
+
#include "pdfs.h"
|
|
23
|
+
|
|
24
|
+
typedef struct {
|
|
25
|
+
int type;
|
|
26
|
+
int other_axis_type;
|
|
27
|
+
double line_width;
|
|
28
|
+
VALUE stroke_color;
|
|
29
|
+
double major_tick_width; // same units as line_width
|
|
30
|
+
double minor_tick_width; // same units as line_width
|
|
31
|
+
double major_tick_length; // in units of numeric label char heights
|
|
32
|
+
double minor_tick_length; // in units of numeric label char heights
|
|
33
|
+
bool log_values;
|
|
34
|
+
bool ticks_inside; // inside frame or toward larger x or y value for specific location
|
|
35
|
+
bool ticks_outside; // inside frame or toward smaller x or y value for specific location
|
|
36
|
+
double tick_interval; // set to 0 to use default
|
|
37
|
+
double min_between_major_ticks; // in units of numeric label char heights
|
|
38
|
+
int number_of_minor_intervals; // set to 0 to use default
|
|
39
|
+
VALUE locations_for_major_ticks; // set to nil to use defaults
|
|
40
|
+
VALUE locations_for_minor_ticks; // set to nil to use defaults
|
|
41
|
+
bool use_fixed_pt;
|
|
42
|
+
int digits_max;
|
|
43
|
+
VALUE tick_labels; // set to nil to use defaults
|
|
44
|
+
double numeric_label_scale;
|
|
45
|
+
double numeric_label_shift; // in char heights, positive for out from edge (or toward larger x or y value)
|
|
46
|
+
double numeric_label_angle;
|
|
47
|
+
int numeric_label_alignment;
|
|
48
|
+
int numeric_label_justification;
|
|
49
|
+
int numeric_label_decimal_digits; // set to 0 to use default
|
|
50
|
+
double *majors; /* if not NULL, then points to array of places where major ticks should appear (in figure coords) */
|
|
51
|
+
int nmajors; /* if majors != NULL, then this tells how many entries it contains */
|
|
52
|
+
bool free_majors;
|
|
53
|
+
char **labels; /* if not null, then points to array of strings to use for labels at major ticks */
|
|
54
|
+
/* labels[i] goes with majors[i], so this is only valid if majors is not null */
|
|
55
|
+
bool free_strings_for_labels;
|
|
56
|
+
double x0, y0, x1, y1, length, axis_min, axis_max; // in figure coords
|
|
57
|
+
bool vertical;
|
|
58
|
+
bool reversed;
|
|
59
|
+
bool top_or_right;
|
|
60
|
+
bool other_axis_reversed;
|
|
61
|
+
int num_minors; // number of minor intervals
|
|
62
|
+
double interval; // tick interval
|
|
63
|
+
int location;
|
|
64
|
+
} PlotAxis;
|
|
65
|
+
|
|
66
|
+
static void Init_PlotAxis_struct(PlotAxis *s) {
|
|
67
|
+
s->free_majors = s->free_strings_for_labels = false;
|
|
68
|
+
s->stroke_color = s->locations_for_major_ticks = s->locations_for_minor_ticks = s->tick_labels = Qnil;
|
|
69
|
+
s->majors = NULL;
|
|
70
|
+
s->labels = NULL;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static void axis_stroke(FM *p);
|
|
74
|
+
void figure_moveto(FM *p, double x, double y) // figure coords
|
|
75
|
+
{
|
|
76
|
+
c_moveto(p, convert_figure_to_output_x(p,x), convert_figure_to_output_y(p,y));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
void figure_lineto(FM *p, double x, double y) // figure coords
|
|
80
|
+
{
|
|
81
|
+
c_lineto(p, convert_figure_to_output_x(p,x), convert_figure_to_output_y(p,y));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
void figure_join(FM *p, double x0, double y0, double x1, double y1) // figure coords
|
|
85
|
+
{
|
|
86
|
+
figure_moveto(p, x0, y0);
|
|
87
|
+
figure_lineto(p, x1, y1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static void axis_stroke(FM *p)
|
|
91
|
+
{
|
|
92
|
+
FM_stroke(p->fm);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
void figure_join_and_stroke(FM *p, double x0, double y0, double x1, double y1) // figure coords
|
|
96
|
+
{
|
|
97
|
+
figure_join(p, x0, y0, x1, y1);
|
|
98
|
+
FM_stroke(p->fm);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static void Get_xaxis_Specs(FM *p, PlotAxis *s)
|
|
102
|
+
{
|
|
103
|
+
s->type = p->xaxis_type;
|
|
104
|
+
s->other_axis_type = p->yaxis_type;
|
|
105
|
+
s->line_width = p->xaxis_line_width; // for axis line
|
|
106
|
+
s->stroke_color = p->xaxis_stroke_color; // for axis line and tick marks
|
|
107
|
+
s->major_tick_width = p->xaxis_major_tick_width; // same units as line_width
|
|
108
|
+
s->minor_tick_width = p->xaxis_minor_tick_width; // same units as line_width
|
|
109
|
+
s->major_tick_length = p->xaxis_major_tick_length; // in units of numeric label char heights
|
|
110
|
+
s->minor_tick_length = p->xaxis_minor_tick_length; // in units of numeric label char heights
|
|
111
|
+
s->log_values = p->xaxis_log_values;
|
|
112
|
+
s->ticks_inside = p->xaxis_ticks_inside; // inside frame or toward larger x or y value for specific location
|
|
113
|
+
s->ticks_outside = p->xaxis_ticks_outside; // inside frame or toward smaller x or y value for specific location
|
|
114
|
+
s->tick_interval = p->xaxis_tick_interval; // set to 0 to use default
|
|
115
|
+
s->min_between_major_ticks = p->xaxis_min_between_major_ticks; // in units of numeric label char heights
|
|
116
|
+
s->number_of_minor_intervals = p->xaxis_number_of_minor_intervals; // set to 0 to use default
|
|
117
|
+
s->locations_for_major_ticks = p->xaxis_locations_for_major_ticks; // set to nil to use defaults
|
|
118
|
+
s->locations_for_minor_ticks = p->xaxis_locations_for_minor_ticks; // set to nil to use defaults
|
|
119
|
+
s->use_fixed_pt = p->xaxis_use_fixed_pt;
|
|
120
|
+
s->digits_max = p->xaxis_digits_max;
|
|
121
|
+
s->tick_labels = p->xaxis_tick_labels; // set to nil to use defaults. else must have a label for each major tick
|
|
122
|
+
s->numeric_label_decimal_digits = p->xaxis_numeric_label_decimal_digits; // set to negative to use default
|
|
123
|
+
s->numeric_label_scale = p->xaxis_numeric_label_scale;
|
|
124
|
+
s->numeric_label_shift = p->xaxis_numeric_label_shift; // in char heights, positive for out from edge (or toward larger x or y value)
|
|
125
|
+
s->numeric_label_angle = p->xaxis_numeric_label_angle;
|
|
126
|
+
s->numeric_label_alignment = p->xaxis_numeric_label_alignment;
|
|
127
|
+
s->numeric_label_justification = p->xaxis_numeric_label_justification;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
static void Get_yaxis_Specs(FM *p, PlotAxis *s)
|
|
131
|
+
{
|
|
132
|
+
s->type = p->yaxis_type;
|
|
133
|
+
s->other_axis_type = p->xaxis_type;
|
|
134
|
+
s->line_width = p->yaxis_line_width; // for axis line
|
|
135
|
+
s->stroke_color = p->yaxis_stroke_color; // for axis line and tick marks
|
|
136
|
+
s->major_tick_width = p->yaxis_major_tick_width; // same units as line_width
|
|
137
|
+
s->minor_tick_width = p->yaxis_minor_tick_width; // same units as line_width
|
|
138
|
+
s->major_tick_length = p->yaxis_major_tick_length; // in units of numeric label char heights
|
|
139
|
+
s->minor_tick_length = p->yaxis_minor_tick_length; // in units of numeric label char heights
|
|
140
|
+
s->log_values = p->yaxis_log_values;
|
|
141
|
+
s->ticks_inside = p->yaxis_ticks_inside; // inside frame or toward larger x or y value for specific location
|
|
142
|
+
s->ticks_outside = p->yaxis_ticks_outside; // inside frame or toward smaller x or y value for specific location
|
|
143
|
+
s->tick_interval = p->yaxis_tick_interval; // set to 0 to use default
|
|
144
|
+
s->min_between_major_ticks = p->yaxis_min_between_major_ticks; // in units of numeric label char heights
|
|
145
|
+
s->number_of_minor_intervals = p->yaxis_number_of_minor_intervals; // set to 0 to use default
|
|
146
|
+
s->locations_for_major_ticks = p->yaxis_locations_for_major_ticks; // set to nil to use defaults
|
|
147
|
+
s->locations_for_minor_ticks = p->yaxis_locations_for_minor_ticks; // set to nil to use defaults
|
|
148
|
+
s->use_fixed_pt = p->yaxis_use_fixed_pt;
|
|
149
|
+
s->digits_max = p->yaxis_digits_max;
|
|
150
|
+
s->tick_labels = p->yaxis_tick_labels; // set to nil to use defaults. else must have a label for each major tick
|
|
151
|
+
s->numeric_label_decimal_digits = p->yaxis_numeric_label_decimal_digits; // set to negative to use default
|
|
152
|
+
s->numeric_label_scale = p->yaxis_numeric_label_scale;
|
|
153
|
+
s->numeric_label_shift = p->yaxis_numeric_label_shift; // in char heights, positive for out from edge (or toward larger x or y value)
|
|
154
|
+
s->numeric_label_angle = p->yaxis_numeric_label_angle;
|
|
155
|
+
s->numeric_label_alignment = p->yaxis_numeric_label_alignment;
|
|
156
|
+
s->numeric_label_justification = p->yaxis_numeric_label_justification;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/*======================================================================*/
|
|
160
|
+
|
|
161
|
+
static void draw_axis_line(FM *p, int location, PlotAxis *s)
|
|
162
|
+
{
|
|
163
|
+
switch (location) {
|
|
164
|
+
case LEFT:
|
|
165
|
+
s->x0 = p->bounds_left;
|
|
166
|
+
s->x1 = p->bounds_left;
|
|
167
|
+
s->y0 = p->bounds_bottom;
|
|
168
|
+
s->y1 = p->bounds_top;
|
|
169
|
+
s->length = p->bounds_height;
|
|
170
|
+
s->axis_min = p->bounds_ymin;
|
|
171
|
+
s->axis_max = p->bounds_ymax;
|
|
172
|
+
s->vertical = true;
|
|
173
|
+
s->reversed = p->yaxis_reversed;
|
|
174
|
+
s->other_axis_reversed = p->xaxis_reversed;
|
|
175
|
+
s->top_or_right = false;
|
|
176
|
+
break;
|
|
177
|
+
case RIGHT:
|
|
178
|
+
s->x0 = p->bounds_right;
|
|
179
|
+
s->x1 = p->bounds_right;
|
|
180
|
+
s->y0 = p->bounds_bottom;
|
|
181
|
+
s->y1 = p->bounds_top;
|
|
182
|
+
s->length = p->bounds_height;
|
|
183
|
+
s->axis_min = p->bounds_ymin;
|
|
184
|
+
s->axis_max = p->bounds_ymax;
|
|
185
|
+
s->vertical = true;
|
|
186
|
+
s->reversed = p->yaxis_reversed;
|
|
187
|
+
s->other_axis_reversed = p->xaxis_reversed;
|
|
188
|
+
s->top_or_right = true;
|
|
189
|
+
break;
|
|
190
|
+
case TOP:
|
|
191
|
+
s->x0 = p->bounds_left;
|
|
192
|
+
s->x1 = p->bounds_right;
|
|
193
|
+
s->y0 = p->bounds_top;
|
|
194
|
+
s->y1 = p->bounds_top;
|
|
195
|
+
s->length = p->bounds_width;
|
|
196
|
+
s->axis_min = p->bounds_xmin;
|
|
197
|
+
s->axis_max = p->bounds_xmax;
|
|
198
|
+
s->vertical = false;
|
|
199
|
+
s->reversed = p->xaxis_reversed;
|
|
200
|
+
s->other_axis_reversed = p->yaxis_reversed;
|
|
201
|
+
s->top_or_right = true;
|
|
202
|
+
break;
|
|
203
|
+
case BOTTOM:
|
|
204
|
+
s->x0 = p->bounds_left;
|
|
205
|
+
s->x1 = p->bounds_right;
|
|
206
|
+
s->y0 = p->bounds_bottom;
|
|
207
|
+
s->y1 = p->bounds_bottom;
|
|
208
|
+
s->length = p->bounds_width;
|
|
209
|
+
s->axis_min = p->bounds_xmin;
|
|
210
|
+
s->axis_max = p->bounds_xmax;
|
|
211
|
+
s->vertical = false;
|
|
212
|
+
s->reversed = p->xaxis_reversed;
|
|
213
|
+
s->other_axis_reversed = p->yaxis_reversed;
|
|
214
|
+
s->top_or_right = false;
|
|
215
|
+
break;
|
|
216
|
+
case AT_X_ORIGIN:
|
|
217
|
+
s->x0 = 0.0;
|
|
218
|
+
s->x1 = 0.0;
|
|
219
|
+
s->y0 = p->bounds_bottom;
|
|
220
|
+
s->y1 = p->bounds_top;
|
|
221
|
+
s->length = p->bounds_height;
|
|
222
|
+
s->axis_min = p->bounds_ymin;
|
|
223
|
+
s->axis_max = p->bounds_ymax;
|
|
224
|
+
s->vertical = true;
|
|
225
|
+
s->reversed = p->yaxis_reversed;
|
|
226
|
+
s->other_axis_reversed = p->xaxis_reversed;
|
|
227
|
+
s->top_or_right = false;
|
|
228
|
+
break;
|
|
229
|
+
case AT_Y_ORIGIN:
|
|
230
|
+
s->x0 = p->bounds_left;
|
|
231
|
+
s->x1 = p->bounds_right;
|
|
232
|
+
s->y0 = 0.0;
|
|
233
|
+
s->y1 = 0.0;
|
|
234
|
+
s->length = p->bounds_width;
|
|
235
|
+
s->axis_min = p->bounds_xmin;
|
|
236
|
+
s->axis_max = p->bounds_xmax;
|
|
237
|
+
s->vertical = false;
|
|
238
|
+
s->reversed = p->xaxis_reversed;
|
|
239
|
+
s->other_axis_reversed = p->yaxis_reversed;
|
|
240
|
+
s->top_or_right = false;
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
c_line_width_set(p, s->line_width);
|
|
244
|
+
figure_join_and_stroke(p, s->x0, s->y0, s->x1, s->y1);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
static char *Create_Label(double value, int scale, int prec, bool log_values, bool use_fixed_pt, char *postfix, PlotAxis *s)
|
|
248
|
+
{ // value in figure coords
|
|
249
|
+
char buff[100], *string;
|
|
250
|
+
int exponent = ROUND(value);
|
|
251
|
+
buff[0] = 0;
|
|
252
|
+
if (log_values && use_fixed_pt) { /* Logarithmic */
|
|
253
|
+
double sav_val = value, pow_val;
|
|
254
|
+
value = pow(10.0, exponent);
|
|
255
|
+
pow_val = pow(10.0, sav_val);
|
|
256
|
+
if (exponent < 0) {
|
|
257
|
+
char form[60];
|
|
258
|
+
int numdig = ABS(exponent)+1;
|
|
259
|
+
sprintf(form, (s->vertical)? "\\tiogayaxisnumericlabel{%%.%df}" : "\\tiogaxaxisnumericlabel{%%.%df}", numdig);
|
|
260
|
+
sprintf(buff, form, pow_val);
|
|
261
|
+
} else if (abs(value - pow_val) > 0.1) {
|
|
262
|
+
sprintf(buff, (s->vertical)? "\\tiogayaxisnumericlabel{%0.2f}" : "\\tiogaxaxisnumericlabel{%0.2f}", pow_val);
|
|
263
|
+
} else {
|
|
264
|
+
sprintf(buff, (s->vertical)? "\\tiogayaxisnumericlabel{%d}" : "\\tiogaxaxisnumericlabel{%d}", (int) value);
|
|
265
|
+
}
|
|
266
|
+
} else if (log_values) {
|
|
267
|
+
/* Exponential, i.e. 10^-1, 1, 10, 10^2, etc */
|
|
268
|
+
double abs_diff = fabs(value - exponent);
|
|
269
|
+
if (abs_diff > 0.1) sprintf(buff, (s->vertical)? "\\tiogayaxisnumericlabel{10^{%0.1f}}" : "\\tiogaxaxisnumericlabel{10^{%0.1f}}", value);
|
|
270
|
+
else if (exponent == 0) strcpy(buff, "1");
|
|
271
|
+
else if (exponent == 1) strcpy(buff, "10");
|
|
272
|
+
else sprintf(buff, (s->vertical)? "\\tiogayaxisnumericlabel{10^{%d}}" : "\\tiogaxaxisnumericlabel{10^{%d}}", exponent);
|
|
273
|
+
} else { /* Linear */
|
|
274
|
+
char form[10];
|
|
275
|
+
double scale2;
|
|
276
|
+
int precis = s->numeric_label_decimal_digits; // use this precision if it is >= 0
|
|
277
|
+
if (precis >= 0) prec = precis;
|
|
278
|
+
if (scale) value /= pow(10.,(double)scale);
|
|
279
|
+
/* This is necessary to prevent labels like "-0.0" on some systems */
|
|
280
|
+
scale2 = pow(10., prec);
|
|
281
|
+
value = floor((value * scale2) + .5) / scale2;
|
|
282
|
+
sprintf(form, (s->vertical)? "\\tiogayaxisnumericlabel{%%.%df}" : "\\tiogaxaxisnumericlabel{%%.%df}", (int) prec);
|
|
283
|
+
sprintf(buff, form, value);
|
|
284
|
+
}
|
|
285
|
+
int len = strlen(buff);
|
|
286
|
+
if (postfix != NULL) { strcpy(buff+len, postfix); len = strlen(buff); }
|
|
287
|
+
string = ALLOC_N(char, len+1);
|
|
288
|
+
strcpy(string, buff);
|
|
289
|
+
return string;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
char *Get_String(VALUE ary, int index) {
|
|
293
|
+
VALUE string = rb_ary_entry(ary, index);
|
|
294
|
+
return StringValuePtr(string);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
#define MIN_FLTDIG 3
|
|
298
|
+
#define MAX_FIXDIG_POS 6
|
|
299
|
+
#define MAX_FIXDIG_NEG 4
|
|
300
|
+
#define DIGMAX_DEF 5
|
|
301
|
+
|
|
302
|
+
static void Pick_Label_Precision(double vmin, double vmax, double tick, bool use_fixed_pt,
|
|
303
|
+
int *mode, int *prec, int digmax, int *scale) {
|
|
304
|
+
double chosen, notchosen, vmod, t0, shifted;
|
|
305
|
+
int msd, notmsd, np, digmin, digfix;
|
|
306
|
+
*mode = *scale = 0;
|
|
307
|
+
if (digmax == 0) digmax = DIGMAX_DEF;
|
|
308
|
+
/* Choose vmin or vmax depending on magnitudes of vmin and vmax. */
|
|
309
|
+
if (ABS(vmax) >= ABS(vmin)) { chosen = vmax; notchosen = vmin; }
|
|
310
|
+
else { chosen = vmin; notchosen = vmax; }
|
|
311
|
+
/* Magnitute of chosen to get number of significant digits */
|
|
312
|
+
|
|
313
|
+
if(ABS(chosen) > 0.) {
|
|
314
|
+
vmod = ABS(chosen);
|
|
315
|
+
t0 = (double) log10(vmod);
|
|
316
|
+
msd = (int) floor(t0);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
/* this branch occurs only when 0. --- 0. range put in */
|
|
320
|
+
vmod = 1.;
|
|
321
|
+
t0 = (double) log10(vmod);
|
|
322
|
+
msd = (int) floor(t0);
|
|
323
|
+
}
|
|
324
|
+
if (ABS(notchosen) > 0.) notmsd = (int) floor( (double) log10(ABS(notchosen)));
|
|
325
|
+
else notmsd = msd;
|
|
326
|
+
/* Autoselect the mode flag */
|
|
327
|
+
/* 'digmin' is the minimum number of places taken up by the label */
|
|
328
|
+
|
|
329
|
+
if (msd >= 0) {
|
|
330
|
+
/* n.b. no decimal point in the minimal case */
|
|
331
|
+
digmin = msd + 1;
|
|
332
|
+
digfix = MAX_FIXDIG_POS;
|
|
333
|
+
if (digmax > 0) digfix = MIN(digmax, MAX_FIXDIG_POS);
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
/* adjust digmin to account for leading 0 and decimal point */
|
|
337
|
+
digmin = -msd + 2;
|
|
338
|
+
digfix = MAX_FIXDIG_NEG;
|
|
339
|
+
if (digmax > 0) digfix = MIN(digmax, MAX_FIXDIG_NEG);
|
|
340
|
+
}
|
|
341
|
+
/* adjust digmin to account for sign on the chosen end of axis or sign on the
|
|
342
|
+
* nonchosen end of axis if notmsd = msd or (msd <= 0 and notmsd < 0)
|
|
343
|
+
* For the latter case the notchosen label starts with "-0."
|
|
344
|
+
* For checking for the latter case, the notmsd < 0 condition is redundant
|
|
345
|
+
* since notmsd <= msd always and the equal part is selected by the first
|
|
346
|
+
* condition.
|
|
347
|
+
*/
|
|
348
|
+
if(chosen < 0.0 || (notchosen < 0. && (notmsd == msd || msd <= 0))) digmin++;
|
|
349
|
+
|
|
350
|
+
if (digmin > digfix && !use_fixed_pt) { *mode = 1; *scale = msd; }
|
|
351
|
+
|
|
352
|
+
/* Establish precision. */
|
|
353
|
+
/* It must be fine enough to resolve the tick spacing */
|
|
354
|
+
|
|
355
|
+
shifted = tick; np = 0;
|
|
356
|
+
while (ABS(shifted) < 1.0 && np > -6) { np--; shifted *= 10.0; }
|
|
357
|
+
for (; np > -6; np--, shifted *= 10.0) {
|
|
358
|
+
if (ABS(shifted - floor(shifted)) < 0.1) break;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (*mode != 0) *prec = msd - np;
|
|
362
|
+
else *prec = MAX(-np, 0);
|
|
363
|
+
|
|
364
|
+
/* One last hack required: if exponent < 0, i.e. number has leading '0.',
|
|
365
|
+
* it's better to change to floating point form if the number of digits
|
|
366
|
+
* is insufficient to represent the tick spacing.
|
|
367
|
+
*/
|
|
368
|
+
if (*mode == 0 && digmax > 0 && !use_fixed_pt) {
|
|
369
|
+
if (t0 < 0.0) {
|
|
370
|
+
if (digmax - 2 - *prec < 0) { *mode = 1; *scale = msd; }
|
|
371
|
+
} else *prec = MAX(MIN(*prec, digmax - msd - 1), 0);
|
|
372
|
+
}
|
|
373
|
+
if (*mode != 0) {
|
|
374
|
+
*prec = msd - np;
|
|
375
|
+
*prec = *scale - floor(log10(tick));
|
|
376
|
+
*prec = MIN(*prec,MAX(0,*prec));
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
static char **Get_Labels(FM *p, PlotAxis *s)
|
|
382
|
+
{
|
|
383
|
+
char **labels = (char **)ALLOC_N(char *, s->nmajors);
|
|
384
|
+
char postfix[50], *ps;
|
|
385
|
+
int i;
|
|
386
|
+
if (s->tick_labels==Qnil) { // create label strings
|
|
387
|
+
int mode, prec, scale;
|
|
388
|
+
Pick_Label_Precision(s->axis_min, s->axis_max, s->interval, s->use_fixed_pt, &mode, &prec, s->digits_max, &scale);
|
|
389
|
+
int i, upper_right = (s->reversed)? 0 : s->nmajors-1, lower_left = (s->reversed)? s->nmajors-1 : 0;
|
|
390
|
+
for (i = 0; i < s->nmajors; i++) {
|
|
391
|
+
ps = NULL;
|
|
392
|
+
if (i == upper_right && !s->log_values && mode && scale)
|
|
393
|
+
sprintf(ps = postfix,
|
|
394
|
+
(s->vertical)? " (x\\tiogayaxisnumericlabel{10^{%d}})" : " (x\\tiogaxaxisnumericlabel{10^{%d}})",
|
|
395
|
+
scale);
|
|
396
|
+
if (i == lower_left && s->nmajors >= 2 && s->vertical &&
|
|
397
|
+
(s->majors[i] == ((s->reversed)? s->axis_max : s->axis_min)) &&
|
|
398
|
+
(s->other_axis_type == AXIS_WITH_MAJOR_TICKS_AND_NUMERIC_LABELS ||
|
|
399
|
+
s->other_axis_type == AXIS_WITH_TICKS_AND_NUMERIC_LABELS)) {
|
|
400
|
+
labels[i] = NULL;
|
|
401
|
+
} else {
|
|
402
|
+
labels[i] = Create_Label(s->majors[i], scale, prec, s->log_values, s->use_fixed_pt, ps, s);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
s->free_strings_for_labels = true;
|
|
406
|
+
} else { // use the given label strings
|
|
407
|
+
VALUE ary = rb_Array(s->tick_labels);
|
|
408
|
+
if (RARRAY(ary)->len != s->nmajors)
|
|
409
|
+
rb_raise(rb_eArgError, "Sorry: must have same number of labels as major ticks");
|
|
410
|
+
for (i = 0; i < s->nmajors; i++) {
|
|
411
|
+
labels[i] = Get_String(ary, i);
|
|
412
|
+
}
|
|
413
|
+
s->free_strings_for_labels = false;
|
|
414
|
+
}
|
|
415
|
+
return labels;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
static double *Pick_Locations_for_Major_Ticks(double interval, double axis_min, double axis_max, int *num_locations)
|
|
419
|
+
{
|
|
420
|
+
double next_tick, prev_tick, starting_tick;
|
|
421
|
+
double *majors;
|
|
422
|
+
int nmajors, i;
|
|
423
|
+
while (true) {
|
|
424
|
+
nmajors = 0;
|
|
425
|
+
starting_tick = interval * floor(axis_min / interval);
|
|
426
|
+
if (starting_tick == axis_min) starting_tick -= interval;
|
|
427
|
+
prev_tick = starting_tick;
|
|
428
|
+
while (true) {
|
|
429
|
+
next_tick = prev_tick + interval;
|
|
430
|
+
if (next_tick > axis_max) break;
|
|
431
|
+
nmajors++;
|
|
432
|
+
prev_tick = next_tick;
|
|
433
|
+
}
|
|
434
|
+
if (nmajors > 1) break;
|
|
435
|
+
interval *= 0.5;
|
|
436
|
+
}
|
|
437
|
+
majors = ALLOC_N(double, nmajors);
|
|
438
|
+
prev_tick = starting_tick;
|
|
439
|
+
for (i=0; i < nmajors; i++) {
|
|
440
|
+
majors[i] = prev_tick += interval;
|
|
441
|
+
}
|
|
442
|
+
*num_locations = nmajors;
|
|
443
|
+
return majors;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
static int Pick_Number_of_Minor_Intervals(double length)
|
|
447
|
+
{
|
|
448
|
+
double t1, fuzz, newlen;
|
|
449
|
+
int np, num_subintervals, inewlen;
|
|
450
|
+
t1 = (double) log10(length);
|
|
451
|
+
np = (int) floor(t1);
|
|
452
|
+
t1 -= np;
|
|
453
|
+
newlen = pow(10.0, t1);
|
|
454
|
+
inewlen = (int) floor(newlen + 0.5);
|
|
455
|
+
fuzz = newlen - inewlen;
|
|
456
|
+
fuzz = abs(fuzz);
|
|
457
|
+
num_subintervals = 4;
|
|
458
|
+
if (fuzz < 1e-2) {
|
|
459
|
+
switch (inewlen) {
|
|
460
|
+
case 0: case 1: case 2: num_subintervals = 4; break;
|
|
461
|
+
case 4: break;
|
|
462
|
+
case 8: case 10: num_subintervals = 2; break;
|
|
463
|
+
case 3: case 6: case 9: num_subintervals = 3; break;
|
|
464
|
+
default: num_subintervals = 5;
|
|
465
|
+
}
|
|
466
|
+
} else {
|
|
467
|
+
if (newlen > 5.0) num_subintervals = 4;
|
|
468
|
+
else if (newlen > 3.0) num_subintervals = 5;
|
|
469
|
+
else if (newlen > 1.5) num_subintervals = 5;
|
|
470
|
+
}
|
|
471
|
+
return num_subintervals;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
static void Pick_Major_Tick_Interval(FM *p, double tick_min, double tick_gap, double length, bool log_values, double *tick)
|
|
475
|
+
{
|
|
476
|
+
double t1, t2, tick_reasonable, base_interval;
|
|
477
|
+
int np, i;
|
|
478
|
+
/* Magnitude of min/max difference to get tick spacing */
|
|
479
|
+
t1 = (double) log10(length);
|
|
480
|
+
np = (int) floor(t1);
|
|
481
|
+
t1 -= np;
|
|
482
|
+
t1 = pow(10.0, t1);
|
|
483
|
+
/* Get tick spacing. */
|
|
484
|
+
if (t1 > 6.0) t2 = 2.0;
|
|
485
|
+
else if (t1 > 3.0) t2 = 1.0;
|
|
486
|
+
else if (t1 > 1.5) { t2 = 5.0; np--; }
|
|
487
|
+
else { t2 = 2.0; np--; }
|
|
488
|
+
/* Now compute reasonable tick spacing */
|
|
489
|
+
if (log_values) {
|
|
490
|
+
tick_reasonable = 1.0;
|
|
491
|
+
} else {
|
|
492
|
+
base_interval = pow(10.0, (double) np);
|
|
493
|
+
if (t2 == 2.0 && t2 * base_interval < tick_gap) t2 = 1.0;
|
|
494
|
+
i = 0;
|
|
495
|
+
while (i < 100) {
|
|
496
|
+
tick_reasonable = t2 * base_interval;
|
|
497
|
+
if (tick_reasonable >= tick_min) break;
|
|
498
|
+
t2++; i++;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
if (*tick == 0) *tick = tick_reasonable;
|
|
502
|
+
else { // check the given interval compared to the default
|
|
503
|
+
*tick = ABS(*tick);
|
|
504
|
+
if(*tick < 1.e-4*tick_reasonable) {
|
|
505
|
+
rb_raise(rb_eArgError, "Sorry: magnitude of specified tick interval (%g) is too small", *tick);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
static void draw_major_ticks(FM *p, PlotAxis *s)
|
|
511
|
+
{
|
|
512
|
+
s->num_minors = s->number_of_minor_intervals;
|
|
513
|
+
if (s->locations_for_major_ticks != Qnil) {
|
|
514
|
+
long len;
|
|
515
|
+
s->majors = Dvector_Data_for_Read(s->locations_for_major_ticks, &len);
|
|
516
|
+
s->nmajors = len;
|
|
517
|
+
if (len > 1) {
|
|
518
|
+
s->interval = s->majors[1] - s->majors[0];
|
|
519
|
+
if (s->interval < 0.0) { s->interval = -s->interval; }
|
|
520
|
+
}
|
|
521
|
+
} else { // calculate major tick locations
|
|
522
|
+
s->interval = s->tick_interval;
|
|
523
|
+
double height = ((s->vertical)? p->default_text_height_dy : p->default_text_height_dx);
|
|
524
|
+
double tick_min = s->min_between_major_ticks * height;
|
|
525
|
+
double tick_gap = 10.0 * height;
|
|
526
|
+
Pick_Major_Tick_Interval(p, tick_min, tick_gap, s->length, s->log_values, &s->interval);
|
|
527
|
+
s->majors = Pick_Locations_for_Major_Ticks(s->interval, s->axis_min, s->axis_max, &s->nmajors);
|
|
528
|
+
s->free_majors = true;
|
|
529
|
+
}
|
|
530
|
+
int i;
|
|
531
|
+
double inside=0.0, outside=0.0, length;
|
|
532
|
+
bool did_line = false;
|
|
533
|
+
length = s->major_tick_length * ((s->vertical)? p->default_text_height_dx : p->default_text_height_dy);
|
|
534
|
+
if (s->ticks_inside) inside = length;
|
|
535
|
+
if (s->ticks_outside) outside = length;
|
|
536
|
+
if (s->top_or_right) { inside = -inside; outside = -outside; }
|
|
537
|
+
if (s->line_width != s->major_tick_width)
|
|
538
|
+
c_line_width_set(p, s->line_width = s->major_tick_width);
|
|
539
|
+
for (i=0; i < s->nmajors; i++) {
|
|
540
|
+
if (s->vertical)
|
|
541
|
+
figure_join(p, s->x0+inside, s->majors[i], s->x0+outside, s->majors[i]);
|
|
542
|
+
else
|
|
543
|
+
figure_join(p, s->majors[i], s->y0+inside, s->majors[i], s->y0+outside);
|
|
544
|
+
did_line = true;
|
|
545
|
+
}
|
|
546
|
+
if (did_line) axis_stroke(p);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
static double log_subintervals[8] =
|
|
550
|
+
{
|
|
551
|
+
0.301030, 0.477121, 0.602060, 0.698970,
|
|
552
|
+
0.778151, 0.845098, 0.903090, 0.954243
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
static void draw_minor_ticks(FM *p, PlotAxis *s)
|
|
556
|
+
{
|
|
557
|
+
if (s->number_of_minor_intervals <= 0) {
|
|
558
|
+
if (s->log_values) {
|
|
559
|
+
double interval = s->majors[1] - s->majors[0];
|
|
560
|
+
s->number_of_minor_intervals = (abs(interval) != 1.0 || s->nmajors > 4)? 1 : 9;
|
|
561
|
+
} else s->number_of_minor_intervals = Pick_Number_of_Minor_Intervals(s->interval);
|
|
562
|
+
}
|
|
563
|
+
int i, j, nsub = s->number_of_minor_intervals;
|
|
564
|
+
double inside=0.0, outside=0.0, length;
|
|
565
|
+
bool did_line = false;
|
|
566
|
+
if (s->log_values && nsub > 9) nsub = 9;
|
|
567
|
+
length = s->minor_tick_length * ((s->vertical)? p->default_text_height_dx : p->default_text_height_dy);
|
|
568
|
+
if (s->ticks_inside) inside = length;
|
|
569
|
+
if (s->ticks_outside) outside = length;
|
|
570
|
+
if (s->top_or_right) { inside = -inside; outside = -outside; }
|
|
571
|
+
if (s->line_width != s->minor_tick_width)
|
|
572
|
+
c_line_width_set(p, s->line_width = s->minor_tick_width);
|
|
573
|
+
if (s->locations_for_minor_ticks != Qnil) {
|
|
574
|
+
long cnt;
|
|
575
|
+
double *locs = Dvector_Data_for_Read(s->locations_for_minor_ticks, &cnt);
|
|
576
|
+
for (i=0; i < cnt; i++) {
|
|
577
|
+
if (s->vertical)
|
|
578
|
+
figure_join(p, s->x0+inside, locs[i], s->x0+outside, locs[i]);
|
|
579
|
+
else
|
|
580
|
+
figure_join(p, locs[i], s->y0+inside, locs[i], s->y0+outside);
|
|
581
|
+
did_line = true;
|
|
582
|
+
}
|
|
583
|
+
} else {
|
|
584
|
+
for (i=0; i <= s->nmajors; i++) {
|
|
585
|
+
double loc = (i==0)? s->majors[0] - s->interval : s->majors[i-1];
|
|
586
|
+
double next_loc = (i==s->nmajors)? loc + s->interval : s->majors[i];
|
|
587
|
+
double subinterval = (next_loc - loc) / nsub;
|
|
588
|
+
if (subinterval <= 0.0) continue;
|
|
589
|
+
for (j = 1; j < nsub; j++) {
|
|
590
|
+
double subloc = loc + ((!s->log_values) ? (j * subinterval) : log_subintervals[j-1]);
|
|
591
|
+
if (subloc >= next_loc) break;
|
|
592
|
+
if (subloc <= s->axis_min || subloc >= s->axis_max) continue;
|
|
593
|
+
if (s->vertical)
|
|
594
|
+
figure_join(p, s->x0+inside, subloc, s->x0+outside, subloc);
|
|
595
|
+
else
|
|
596
|
+
figure_join(p, subloc, s->y0+inside, subloc, s->y0+outside);
|
|
597
|
+
did_line = true;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (did_line) axis_stroke(p);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
static void show_numeric_label(FM *p , VALUE fmkr, PlotAxis *s, char *text, int location, double position, double shift)
|
|
605
|
+
{ // position is in figure coords and must be converted to frame coords
|
|
606
|
+
double pos = ((!s->reversed)? (position - s->axis_min) : (s->axis_max - position)) / s->length;
|
|
607
|
+
c_show_rotated_text(p, text, location, shift, pos,
|
|
608
|
+
s->numeric_label_scale, s->numeric_label_angle, s->numeric_label_justification, s->numeric_label_alignment);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
static void draw_numeric_labels(FM *p , VALUE fmkr, int location, PlotAxis *s)
|
|
612
|
+
{
|
|
613
|
+
int i;
|
|
614
|
+
double shift = (s->ticks_outside) ? s->major_tick_length : 0.5; // default shift
|
|
615
|
+
shift += s->numeric_label_shift;
|
|
616
|
+
s->labels = Get_Labels(p, s);
|
|
617
|
+
for (i=0; i < s->nmajors; i++) {
|
|
618
|
+
if (s->labels[i] != NULL) show_numeric_label(p, fmkr, s, s->labels[i], location, s->majors[i], shift);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
static void c_show_side(VALUE fmkr, FM *p, PlotAxis *s) {
|
|
623
|
+
int i;
|
|
624
|
+
if (s->type == AXIS_HIDDEN) return;
|
|
625
|
+
Start_Axis_Standard_State(p, s->stroke_color, s->line_width * p->default_line_scale);
|
|
626
|
+
// gsave, set line type and stroke color
|
|
627
|
+
draw_axis_line(p, s->location, s);
|
|
628
|
+
if (s->type == AXIS_LINE_ONLY) goto done;
|
|
629
|
+
draw_major_ticks(p, s);
|
|
630
|
+
if (s->type == AXIS_WITH_MAJOR_TICKS_ONLY) goto done;
|
|
631
|
+
if (s->type == AXIS_WITH_MAJOR_TICKS_AND_NUMERIC_LABELS) {
|
|
632
|
+
draw_numeric_labels(p, fmkr, s->location, s);
|
|
633
|
+
goto done;
|
|
634
|
+
}
|
|
635
|
+
draw_minor_ticks(p, s);
|
|
636
|
+
if (s->type == AXIS_WITH_TICKS_ONLY) goto done;
|
|
637
|
+
draw_numeric_labels(p, fmkr, s->location, s);
|
|
638
|
+
done:
|
|
639
|
+
End_Axis_Standard_State(); // grestore
|
|
640
|
+
if (s->free_majors) free(s->majors);
|
|
641
|
+
if (s->labels != NULL) {
|
|
642
|
+
if (s->free_strings_for_labels) {
|
|
643
|
+
for (i = 0; i < s->nmajors; i++)
|
|
644
|
+
if (s->labels[i] != NULL) free(s->labels[i]);
|
|
645
|
+
}
|
|
646
|
+
free(s->labels);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
VALUE FM_show_axis(VALUE fmkr, VALUE loc)
|
|
651
|
+
{
|
|
652
|
+
FM *p = Get_FM(fmkr);
|
|
653
|
+
PlotAxis axis;
|
|
654
|
+
int location;
|
|
655
|
+
Init_PlotAxis_struct(&axis);
|
|
656
|
+
loc = rb_Integer(loc);
|
|
657
|
+
location = NUM2INT(loc);
|
|
658
|
+
if (location == LEFT || location == RIGHT || location == AT_X_ORIGIN) {
|
|
659
|
+
if (!p->yaxis_visible) goto done;
|
|
660
|
+
Get_yaxis_Specs(p, &axis);
|
|
661
|
+
} else if (location == TOP || location == BOTTOM || location == AT_Y_ORIGIN) {
|
|
662
|
+
if (!p->xaxis_visible) goto done;
|
|
663
|
+
Get_xaxis_Specs(p, &axis);
|
|
664
|
+
} else rb_raise(rb_eArgError,
|
|
665
|
+
"Sorry: invalid 'loc' for axis: must be one of LEFT, RIGHT, TOP, BOTTOM, AT_X_ORIGIN, or AT_Y_ORIGIN: is (%i)", location);
|
|
666
|
+
axis.location = location;
|
|
667
|
+
c_show_side(fmkr, p, &axis);
|
|
668
|
+
done:
|
|
669
|
+
return fmkr;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
VALUE FM_show_edge(VALUE fmkr, VALUE loc) {
|
|
673
|
+
FM *p = Get_FM(fmkr);
|
|
674
|
+
PlotAxis axis;
|
|
675
|
+
int location;
|
|
676
|
+
Init_PlotAxis_struct(&axis);
|
|
677
|
+
loc = rb_Integer(loc);
|
|
678
|
+
location = NUM2INT(loc);
|
|
679
|
+
switch (location) {
|
|
680
|
+
case LEFT:
|
|
681
|
+
if (!p->left_edge_visible) goto done;
|
|
682
|
+
Get_yaxis_Specs(p, &axis); axis.type = p->left_edge_type;
|
|
683
|
+
break;
|
|
684
|
+
case RIGHT:
|
|
685
|
+
if (!p->right_edge_visible) goto done;
|
|
686
|
+
Get_yaxis_Specs(p, &axis); axis.type = p->right_edge_type;
|
|
687
|
+
break;
|
|
688
|
+
case BOTTOM:
|
|
689
|
+
if (!p->bottom_edge_visible) goto done;
|
|
690
|
+
Get_xaxis_Specs(p, &axis); axis.type = p->bottom_edge_type;
|
|
691
|
+
break;
|
|
692
|
+
case TOP:
|
|
693
|
+
if (!p->top_edge_visible) goto done;
|
|
694
|
+
Get_xaxis_Specs(p, &axis); axis.type = p->top_edge_type;
|
|
695
|
+
break;
|
|
696
|
+
default: rb_raise(rb_eArgError,
|
|
697
|
+
"Sorry: invalid 'loc' for edge: must be one of LEFT, RIGHT, TOP, or BOTTOM: is (%i)", location);
|
|
698
|
+
}
|
|
699
|
+
axis.location = location;
|
|
700
|
+
c_show_side(fmkr, p, &axis);
|
|
701
|
+
done:
|
|
702
|
+
return fmkr;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
VALUE FM_no_title(VALUE fmkr)
|
|
707
|
+
{
|
|
708
|
+
FM *p = Get_FM(fmkr);
|
|
709
|
+
p->title_visible = false;
|
|
710
|
+
return fmkr;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
VALUE FM_no_xlabel(VALUE fmkr)
|
|
714
|
+
{
|
|
715
|
+
FM *p = Get_FM(fmkr);
|
|
716
|
+
p->xlabel_visible = false;
|
|
717
|
+
return fmkr;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
VALUE FM_no_ylabel(VALUE fmkr)
|
|
722
|
+
{
|
|
723
|
+
FM *p = Get_FM(fmkr);
|
|
724
|
+
p->ylabel_visible = false;
|
|
725
|
+
return fmkr;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
VALUE FM_no_xaxis(VALUE fmkr)
|
|
730
|
+
{
|
|
731
|
+
FM *p = Get_FM(fmkr);
|
|
732
|
+
p->xaxis_visible = false;
|
|
733
|
+
return fmkr;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
VALUE FM_no_yaxis(VALUE fmkr)
|
|
738
|
+
{
|
|
739
|
+
FM *p = Get_FM(fmkr);
|
|
740
|
+
p->yaxis_visible = false;
|
|
741
|
+
return fmkr;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
VALUE FM_no_left_edge(VALUE fmkr)
|
|
746
|
+
{
|
|
747
|
+
FM *p = Get_FM(fmkr);
|
|
748
|
+
p->left_edge_visible = false;
|
|
749
|
+
return fmkr;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
VALUE FM_no_right_edge(VALUE fmkr)
|
|
754
|
+
{
|
|
755
|
+
FM *p = Get_FM(fmkr);
|
|
756
|
+
p->right_edge_visible = false;
|
|
757
|
+
return fmkr;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
VALUE FM_no_top_edge(VALUE fmkr)
|
|
762
|
+
{
|
|
763
|
+
FM *p = Get_FM(fmkr);
|
|
764
|
+
p->top_edge_visible = false;
|
|
765
|
+
return fmkr;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
VALUE FM_no_bottom_edge(VALUE fmkr)
|
|
769
|
+
{
|
|
770
|
+
FM *p = Get_FM(fmkr);
|
|
771
|
+
p->bottom_edge_visible = false;
|
|
772
|
+
return fmkr;
|
|
773
|
+
}
|
|
774
|
+
|