tioga 1.9 → 1.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -55,15 +55,23 @@ DECLARE_SYMBOL(void, Dvector_Push_Double, (VALUE ary, double val));
55
55
 
56
56
 
57
57
  /* functions for interpolation */
58
- DECLARE_SYMBOL(double, c_dvector_spline_interpolate,
59
- (double x, int n_pts_data, double *Xs, double *Ys,
60
- double *Bs, double *Cs, double *Ds));
61
- DECLARE_SYMBOL(double, c_dvector_linear_interpolate,
62
- (int num_pts, double *xs, double *ys, double x));
63
58
  DECLARE_SYMBOL(void, c_dvector_create_spline_interpolant,
64
59
  (int n_pts_data, double *Xs, double *Ys,
65
60
  bool start_clamped, double start_slope,
66
61
  bool end_clamped, double end_slope,
67
62
  double *As, double *Bs, double *Cs));
63
+ DECLARE_SYMBOL(double, c_dvector_spline_interpolate,
64
+ (double x, int n_pts_data, double *Xs, double *Ys,
65
+ double *Bs, double *Cs, double *Ds));
66
+
67
+ DECLARE_SYMBOL(void, c_dvector_create_pm_cubic_interpolant,
68
+ (int n_pts_data, double *Xs, double *Ys,
69
+ double *As, double *Bs, double *Cs));
70
+ DECLARE_SYMBOL(double, c_dvector_pm_cubic_interpolate,
71
+ (double x, int n_pts_data, double *Xs, double *Ys,
72
+ double *Bs, double *Cs, double *Ds));
73
+
74
+ DECLARE_SYMBOL(double, c_dvector_linear_interpolate,
75
+ (int num_pts, double *xs, double *ys, double x));
68
76
  #endif /* __Dvector_H__ */
69
77
 
@@ -49,6 +49,9 @@
49
49
  #ifndef MIN
50
50
  #define MIN(a,b) (((a) < (b)) ? (a) : (b))
51
51
  #endif
52
+ #ifndef SIGN
53
+ #define SIGN(a) (((a) > 0) ? 1 : -1)
54
+ #endif
52
55
 
53
56
 
54
57
 
@@ -1068,7 +1071,8 @@ PRIVATE
1068
1071
  * call-seq:
1069
1072
  * dvector.min_gt(val) -> float or nil
1070
1073
  *
1071
- * Returns the minimum entry in _dvector_ which is greater than _val_, or <code>nil</code> if no such entry if found.
1074
+ * Returns the minimum entry in _dvector_ which is greater than _val_,
1075
+ * or <code>nil</code> if no such entry if found.
1072
1076
  */ VALUE dvector_min_gt(VALUE ary, VALUE val) {
1073
1077
  Dvector *d = Get_Dvector(ary);
1074
1078
  val = rb_Float(val);
@@ -1092,7 +1096,8 @@ PRIVATE
1092
1096
  * call-seq:
1093
1097
  * dvector.max_lt(val) -> float or nil
1094
1098
  *
1095
- * Returns the maximum entry in _dvector_ which is less than _val_, or <code>nil</code> if no such entry if found.
1099
+ * Returns the maximum entry in _dvector_ which is less than _val_,
1100
+ * or <code>nil</code> if no such entry if found.
1096
1101
  */ VALUE dvector_max_lt(VALUE ary, VALUE val) {
1097
1102
  Dvector *d = Get_Dvector(ary);
1098
1103
  val = rb_Float(val);
@@ -1390,7 +1395,8 @@ PRIVATE
1390
1395
  Dvector *d2 = Get_Dvector(ary2);
1391
1396
  long len = d->len;
1392
1397
  if (len != d2->len) {
1393
- rb_raise(rb_eArgError, "vectors with different lengths (%d vs %d) for reverse_each2_with_index", len, d2->len);
1398
+ rb_raise(rb_eArgError, "vectors with different lengths (%d vs %d) for reverse_each2_with_index",
1399
+ len, d2->len);
1394
1400
  }
1395
1401
  while (len--) {
1396
1402
  rb_yield_values(3, rb_float_new(d->ptr[len]), rb_float_new(d2->ptr[len]), LONG2NUM(len));
@@ -1687,8 +1693,10 @@ PRIVATE
1687
1693
  * call-seq:
1688
1694
  * dvector.dup -> a_dvector
1689
1695
  *
1690
- * Returns a copy of _dvector_. For performance sensitive situations involving a series of vector operations,
1691
- * first make a copy using dup and then do "bang" operations to modify the result without further copying.
1696
+ * Returns a copy of _dvector_.
1697
+ * For performance sensitive situations involving a series of vector operations,
1698
+ * first make a copy using dup and then do "bang" operations to modify the result
1699
+ * without further copying.
1692
1700
  */ VALUE dvector_dup(VALUE ary) {
1693
1701
  Dvector *d = Get_Dvector(ary);
1694
1702
  return dvector_new4_dbl(d->len, d->ptr);
@@ -1700,7 +1708,8 @@ PRIVATE
1700
1708
  * dvector.collect {|x| block } -> a_dvector
1701
1709
  * dvector.map {|x| block } -> a_dvector
1702
1710
  *
1703
- * Invokes <i>block</i> once for each element of _dvector_. Returns a new vector holding the values returned by _block_.
1711
+ * Invokes <i>block</i> once for each element of _dvector_.
1712
+ * Returns a new vector holding the values returned by _block_.
1704
1713
  * Note that for numeric operations on long vectors, it is more efficient to
1705
1714
  * apply the operator directly to the vector rather than using map or collect.
1706
1715
  *
@@ -4896,7 +4905,8 @@ PRIVATE
4896
4905
  * Replaces contents of _dvector_ by control points for Bezier curve.
4897
4906
  * The cubic, y(x), is defined from x0 to x0+delta_x.
4898
4907
  * At location x = x0 + dx, with dx between 0 and delta_x, define y = a*dx^3 + b*dx^2 + c*dx + y0.
4899
- * This routine replaces the contents of _dest_ by [x1, y1, x2, y2, x3, y3], the Bezier control points to match this cubic.
4908
+ * This routine replaces the contents of _dest_ by [x1, y1, x2, y2, x3, y3],
4909
+ * the Bezier control points to match this cubic.
4900
4910
  *
4901
4911
  */
4902
4912
  VALUE dvector_make_bezier_control_points_for_cubic_in_x(VALUE dest, VALUE x0, VALUE y0, VALUE delta_x, VALUE a, VALUE b, VALUE c)
@@ -4911,6 +4921,162 @@ VALUE dvector_make_bezier_control_points_for_cubic_in_x(VALUE dest, VALUE x0, VA
4911
4921
  NUM2DBL(x0), NUM2DBL(y0), NUM2DBL(delta_x), NUM2DBL(a), NUM2DBL(b), NUM2DBL(c));
4912
4922
  }
4913
4923
 
4924
+
4925
+
4926
+
4927
+
4928
+ void c_dvector_create_pm_cubic_interpolant(int nx, double *x, double *f,
4929
+ double *As, double *Bs, double *Cs)
4930
+ {
4931
+ double *h = (double *)ALLOC_N(double, nx);
4932
+ double *s = (double *)ALLOC_N(double, nx);
4933
+ double *p = (double *)ALLOC_N(double, nx);
4934
+ double as00, asm1, ap00, sm1, s00;
4935
+ int n = nx-1, i;
4936
+
4937
+
4938
+ for (i=0; i < n; i++) {
4939
+ h[i] = x[i+1] - x[i];
4940
+ s[i] = (f[i+1] - f[i])/h[i];
4941
+ }
4942
+
4943
+ /* slope at i of parabola through i-1, i, and i+1 */
4944
+ for (i=1; i < n; i++) {
4945
+ p[i] = (s[i-1]*h[i] + s[i]*h[i-1])/(h[i]+h[i-1]);
4946
+ }
4947
+
4948
+ /* "safe" slope at i to ensure monotonic -- see Steffen paper for explanation. */
4949
+ for (i=1; i < n; i++) {
4950
+ asm1 = fabs(s[i-1]);
4951
+ as00 = fabs(s[i]);
4952
+ ap00 = fabs(p[i]);
4953
+ sm1 = (s[i-1] > 0)? 1.0 : -1.0;
4954
+ s00 = (s[i] > 0)? 1.0 : -1.0;
4955
+ Cs[i] = (sm1+s00)*MIN(asm1, MIN(as00, 0.5*ap00));
4956
+ }
4957
+
4958
+ /* slope at 1st point of parabola through 1st 3 points */
4959
+ p[0] = s[0]*(1 + h[0] / (h[0] + h[1])) - s[1] * h[0] / (h[0] + h[1]);
4960
+
4961
+ /* safe slope at 1st point */
4962
+ if (p[0]*s[0] <= 0) {
4963
+ Cs[0] = 0;
4964
+ } else if (fabs(p[0]) > 2.0*fabs(s[0])) {
4965
+ Cs[0] = 2.0*s[0];
4966
+ } else {
4967
+ Cs[0] = p[0];
4968
+ }
4969
+
4970
+ /* slope at last point of parabola through last 3 points */
4971
+ p[n] = s[n-1]*(1 + h[n-1] / (h[n-1] + h[n-2])) - s[n-2]*h[n-1] / (h[n-1] + h[n-2]);
4972
+
4973
+ /* safe slope at last point */
4974
+ if (p[n]*s[n-1] <= 0) {
4975
+ Cs[n] = 0;
4976
+ } else if (fabs(p[n]) > 2.0*fabs(s[n-1])) {
4977
+ Cs[n] = 2.0*s[n-1];
4978
+ } else {
4979
+ Cs[n] = p[n];
4980
+ }
4981
+
4982
+ for (i=0; i < n; i++) {
4983
+ Bs[i] = (3.0*s[i] - 2.0*Cs[i] - Cs[i+1]) / h[i];
4984
+ }
4985
+ Bs[n] = 0;
4986
+
4987
+ for (i=1; i < n; i++) {
4988
+ As[i] = (Cs[i] + Cs[i+1] - 2.0*s[i]) / (h[i]*h[i]);
4989
+ }
4990
+ As[n] = 0;
4991
+
4992
+ free(p); free(s); free(h);
4993
+ }
4994
+
4995
+ PRIVATE
4996
+ /*
4997
+ * call-seq:
4998
+ * Dvector.create_pm_cubic_interpolant(xs, ys) -> interpolant
4999
+ *
5000
+ * Uses Dvectors _xs_ and _ys_ to create a cubic pm_cubic interpolant. The _xs_ must be given in ascending order.
5001
+ * The interpolant is an array of Dvectors: [Xs, Ys, As, Bs, Cs].
5002
+ * For x between Xs[j] and Xs[j+1], let dx = x - Xs[j], and find interpolated y for x by
5003
+ * y = As[j]*dx^3 + Bs[j]*dx^2 + Cs[j]*dx + Ys[j].
5004
+ * pm_cubic algorithms derived from Steffen, M., "A simple method for monotonic interpolation in one dimension",
5005
+ * Astron. Astrophys., (239) 1990, 443-450.
5006
+ *
5007
+ */
5008
+ VALUE dvector_create_pm_cubic_interpolant(int argc, VALUE *argv, VALUE klass) {
5009
+ if (argc != 2)
5010
+ rb_raise(rb_eArgError, "wrong # of arguments(%d) for create_pm_cubic_interpolant", argc);
5011
+ klass = Qnil;
5012
+ VALUE Xs = argv[0], Ys = argv[1];
5013
+ long xdlen, ydlen;
5014
+ double start = 0.0, end = 0.0;
5015
+ double *X_data = Dvector_Data_for_Read(Xs, &xdlen);
5016
+ double *Y_data = Dvector_Data_for_Read(Ys, &ydlen);
5017
+ if (X_data == NULL || Y_data == NULL || xdlen != ydlen)
5018
+ rb_raise(rb_eArgError, "Data for create_pm_cubic_interpolant must be equal length Dvectors");
5019
+ int nx = xdlen;
5020
+ VALUE As = Dvector_Create(), Bs = Dvector_Create(), Cs = Dvector_Create();
5021
+ double *As_data = Dvector_Data_Resize(As, nx);
5022
+ double *Bs_data = Dvector_Data_Resize(Bs, nx);
5023
+ double *Cs_data = Dvector_Data_Resize(Cs, nx);
5024
+ c_dvector_create_pm_cubic_interpolant(nx, X_data, Y_data, As_data, Bs_data, Cs_data);
5025
+ VALUE result = rb_ary_new2(5);
5026
+ rb_ary_store(result, 0, Xs);
5027
+ rb_ary_store(result, 1, Ys);
5028
+ rb_ary_store(result, 2, As);
5029
+ rb_ary_store(result, 3, Bs);
5030
+ rb_ary_store(result, 4, Cs);
5031
+ return result;
5032
+ }
5033
+
5034
+ double c_dvector_pm_cubic_interpolate(double x, int nx,
5035
+ double *Xs, double *Ys, double *As, double *Bs, double *Cs)
5036
+ {
5037
+ int j;
5038
+ for (j = 0; j < nx && x >= Xs[j]; j++);
5039
+ if (j == nx) return Ys[j-1];
5040
+ if (j == 0) return Ys[0];
5041
+ j--;
5042
+ double dx = x - Xs[j];
5043
+ return Ys[j] + dx*(Cs[j] + dx*(Bs[j] + dx*As[j]));
5044
+ }
5045
+
5046
+ PRIVATE
5047
+ /*
5048
+ * call-seq:
5049
+ * Dvector.pm_cubic_interpolate(x, interpolant) -> y
5050
+ *
5051
+ * Returns the _y_ corresponding to _x_ by pm_cubic interpolation using the _interpolant_
5052
+ * which was previously created by calling _create_pm_cubic_interpolant_.
5053
+ *
5054
+ */
5055
+ VALUE dvector_pm_cubic_interpolate(int argc, VALUE *argv, VALUE klass) {
5056
+ if (argc != 2)
5057
+ rb_raise(rb_eArgError, "wrong # of arguments(%d) for pm_cubic_interpolate", argc);
5058
+ klass = Qnil;
5059
+ VALUE x = argv[0];
5060
+ VALUE interpolant = argv[1];
5061
+ x = rb_Float(x);
5062
+ interpolant = rb_Array(interpolant);
5063
+ if (RARRAY(interpolant)->len != 5)
5064
+ rb_raise(rb_eArgError, "interpolant must be array of length 5 from create_pm_cubic_interpolant");
5065
+ Dvector *Xs = Get_Dvector(rb_ary_entry(interpolant,0));
5066
+ Dvector *Ys = Get_Dvector(rb_ary_entry(interpolant,1));
5067
+ Dvector *As = Get_Dvector(rb_ary_entry(interpolant,2));
5068
+ Dvector *Bs = Get_Dvector(rb_ary_entry(interpolant,3));
5069
+ Dvector *Cs = Get_Dvector(rb_ary_entry(interpolant,4));
5070
+ if (Xs->len <= 0 || Xs->len != Ys->len || Xs->len != Bs->len || Xs->len != Cs->len || Xs->len != As->len)
5071
+ rb_raise(rb_eArgError, "interpolant must be from create_pm_cubic_interpolant");
5072
+ double y = c_dvector_pm_cubic_interpolate(NUM2DBL(x), Xs->len, Xs->ptr, Ys->ptr, As->ptr, Bs->ptr, Cs->ptr);
5073
+ return rb_float_new(y);
5074
+ }
5075
+
5076
+
5077
+
5078
+
5079
+
4914
5080
  void c_dvector_create_spline_interpolant(int n_pts_data, double *Xs, double *Ys,
4915
5081
  bool start_clamped, double start_slope, bool end_clamped, double end_slope,
4916
5082
  double *As, double *Bs, double *Cs)
@@ -5319,7 +5485,8 @@ static VALUE dvector_convolve(VALUE self, VALUE kernel, VALUE middle)
5319
5485
  :call-seq:
5320
5486
  Dvector.fast_fancy_read(stream, options) => Array_of_Dvectors
5321
5487
 
5322
- Reads data from an IO stream and separate it into columns of data
5488
+ Reads data from an IO stream (or anything that supports a gets method)
5489
+ and separate it into columns of data
5323
5490
  according to the _options_, a hash holding the following elements
5324
5491
  (compulsory, but you can use FANCY_READ_DEFAULTS):
5325
5492
  * 'sep': a regular expression that separate the entries
@@ -5333,8 +5500,6 @@ static VALUE dvector_convolve(VALUE self, VALUE kernel, VALUE middle)
5333
5500
 
5334
5501
  As a side note, the read time is highly non-linear, which suggests that
5335
5502
  the read is memory-allocation/copying-limited, at least for big files.
5336
- Well, the read time is non-linear for
5337
-
5338
5503
 
5339
5504
  An internal memory allocation with aggressive policy should solve that,
5340
5505
  that is, not using directly Dvectors (and it would be way faster to store
@@ -5534,6 +5699,10 @@ void Init_Dvector() {
5534
5699
  rb_define_singleton_method(cDvector, "read_row", dvector_read_row, -1);
5535
5700
  rb_define_singleton_method(cDvector, "create_spline_interpolant", dvector_create_spline_interpolant, -1);
5536
5701
  rb_define_singleton_method(cDvector, "spline_interpolate", dvector_spline_interpolate, -1);
5702
+
5703
+ rb_define_singleton_method(cDvector, "create_pm_cubic_interpolant", dvector_create_pm_cubic_interpolant, -1);
5704
+ rb_define_singleton_method(cDvector, "pm_cubic_interpolate", dvector_pm_cubic_interpolate, -1);
5705
+
5537
5706
  rb_define_singleton_method(cDvector, "linear_interpolate", dvector_linear_interpolate, -1);
5538
5707
  rb_define_singleton_method(cDvector, "min_of_many", dvector_min_of_many, 1);
5539
5708
  rb_define_singleton_method(cDvector, "max_of_many", dvector_max_of_many, 1);
@@ -135,6 +135,18 @@ PRIVATE double c_dvector_spline_interpolate(double x, int n_pts_data,
135
135
  double *Xs, double *Ys, double *Bs, double *Cs, double *Ds);
136
136
  PRIVATE VALUE dvector_spline_interpolate(int argc, VALUE *argv, VALUE klass);
137
137
 
138
+
139
+
140
+ PRIVATE void c_dvector_create_pm_cubic_interpolant(int n_pts_data, double *Xs, double *Ys,
141
+ double *Bs, double *Cs, double *Ds);
142
+ PRIVATE VALUE dvector_create_pm_cubic_interpolant(int argc, VALUE *argv, VALUE klass);
143
+
144
+ PRIVATE double c_dvector_pm_cubic_interpolate(double x, int n_pts_data,
145
+ double *Xs, double *Ys, double *Bs, double *Cs, double *Ds);
146
+ PRIVATE VALUE dvector_pm_cubic_interpolate(int argc, VALUE *argv, VALUE klass);
147
+
148
+
149
+
138
150
  PRIVATE double c_dvector_linear_interpolate(int num_pts, double *xs, double *ys, double x);
139
151
  PRIVATE VALUE dvector_linear_interpolate(int argc, VALUE *argv, VALUE klass);
140
152
 
@@ -55,15 +55,23 @@ DECLARE_SYMBOL(void, Dvector_Push_Double, (VALUE ary, double val));
55
55
 
56
56
 
57
57
  /* functions for interpolation */
58
- DECLARE_SYMBOL(double, c_dvector_spline_interpolate,
59
- (double x, int n_pts_data, double *Xs, double *Ys,
60
- double *Bs, double *Cs, double *Ds));
61
- DECLARE_SYMBOL(double, c_dvector_linear_interpolate,
62
- (int num_pts, double *xs, double *ys, double x));
63
58
  DECLARE_SYMBOL(void, c_dvector_create_spline_interpolant,
64
59
  (int n_pts_data, double *Xs, double *Ys,
65
60
  bool start_clamped, double start_slope,
66
61
  bool end_clamped, double end_slope,
67
62
  double *As, double *Bs, double *Cs));
63
+ DECLARE_SYMBOL(double, c_dvector_spline_interpolate,
64
+ (double x, int n_pts_data, double *Xs, double *Ys,
65
+ double *Bs, double *Cs, double *Ds));
66
+
67
+ DECLARE_SYMBOL(void, c_dvector_create_pm_cubic_interpolant,
68
+ (int n_pts_data, double *Xs, double *Ys,
69
+ double *As, double *Bs, double *Cs));
70
+ DECLARE_SYMBOL(double, c_dvector_pm_cubic_interpolate,
71
+ (double x, int n_pts_data, double *Xs, double *Ys,
72
+ double *Bs, double *Cs, double *Ds));
73
+
74
+ DECLARE_SYMBOL(double, c_dvector_linear_interpolate,
75
+ (int num_pts, double *xs, double *ys, double x));
68
76
  #endif /* __Dvector_H__ */
69
77
 
@@ -33,9 +33,28 @@ module Dobjects
33
33
  #
34
34
  # e = MathEvaluator.new("x*y", "x,y")
35
35
  # e.compute(1,2) -> 2
36
+ #
37
+ # If an exception arises, NaN is returned. Note that compilation
38
+ # problems will be caught before ;-)...
36
39
  def compute(*args)
40
+ begin
41
+ return compute_unsafe(*args)
42
+ rescue
43
+ return 0.0/0.0
44
+ end
45
+ end
46
+
47
+ # This function does the actual evaluation with the blocks
48
+ # given.
49
+ #
50
+ # e = MathEvaluator.new("x*y", "x,y")
51
+ # e.compute(1,2) -> 2
52
+ #
53
+ # No care is taken to intercept exceptions.
54
+ def compute_unsafe(*args)
37
55
  return @block.call(*args)
38
56
  end
57
+
39
58
  end
40
59
 
41
60
  class Dvector
@@ -55,15 +55,23 @@ DECLARE_SYMBOL(void, Dvector_Push_Double, (VALUE ary, double val));
55
55
 
56
56
 
57
57
  /* functions for interpolation */
58
- DECLARE_SYMBOL(double, c_dvector_spline_interpolate,
59
- (double x, int n_pts_data, double *Xs, double *Ys,
60
- double *Bs, double *Cs, double *Ds));
61
- DECLARE_SYMBOL(double, c_dvector_linear_interpolate,
62
- (int num_pts, double *xs, double *ys, double x));
63
58
  DECLARE_SYMBOL(void, c_dvector_create_spline_interpolant,
64
59
  (int n_pts_data, double *Xs, double *Ys,
65
60
  bool start_clamped, double start_slope,
66
61
  bool end_clamped, double end_slope,
67
62
  double *As, double *Bs, double *Cs));
63
+ DECLARE_SYMBOL(double, c_dvector_spline_interpolate,
64
+ (double x, int n_pts_data, double *Xs, double *Ys,
65
+ double *Bs, double *Cs, double *Ds));
66
+
67
+ DECLARE_SYMBOL(void, c_dvector_create_pm_cubic_interpolant,
68
+ (int n_pts_data, double *Xs, double *Ys,
69
+ double *As, double *Bs, double *Cs));
70
+ DECLARE_SYMBOL(double, c_dvector_pm_cubic_interpolate,
71
+ (double x, int n_pts_data, double *Xs, double *Ys,
72
+ double *Bs, double *Cs, double *Ds));
73
+
74
+ DECLARE_SYMBOL(double, c_dvector_linear_interpolate,
75
+ (int num_pts, double *xs, double *ys, double x));
68
76
  #endif /* __Dvector_H__ */
69
77
 
data/split/Tioga/axes.c CHANGED
@@ -20,19 +20,15 @@
20
20
  along with Tioga; if not, write to the Free Software
21
21
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
22
  */
23
+ #include <math.h>
24
+
23
25
  #include "figures.h"
24
26
  #include "pdfs.h"
25
27
 
28
+
29
+
26
30
  /*
27
31
  Here is my (Vincent) big TODO-list for the axes stuff:
28
- * provide a way to reliably get the location from major/minor
29
- ticks for a given axis, so users can build lines/grids that build on
30
- top of that (or rather under it ;-)...)
31
- -> this is partly done, as you can now get the major ticks position.
32
- * let the users choose between the current way to pick up ticks position
33
- and another, such as the one I'm using in SciYAG, which seems to give
34
- results that are more according to my expectations.
35
-
36
32
  * BUG fix: apparently, two calls to the axes stuff do no return the
37
33
  same thing, so I'll need to have a careful look at that
38
34
  */
@@ -41,9 +37,17 @@ typedef struct {
41
37
  int type;
42
38
  int other_axis_type;
43
39
  double line_width;
40
+
41
+ /* Stroke color... */
44
42
  double stroke_color_R;
45
43
  double stroke_color_G;
46
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
+
47
51
  double major_tick_width; // same units as line_width
48
52
  double minor_tick_width; // same units as line_width
49
53
  double major_tick_length; // in units of numeric label char heights
@@ -127,6 +131,11 @@ static void Get_xaxis_Specs(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
127
131
  s->stroke_color_R = p->xaxis_stroke_color_R; // for axis line and tick marks
128
132
  s->stroke_color_G = p->xaxis_stroke_color_G;
129
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
+
130
139
  s->major_tick_width = p->xaxis_major_tick_width; // same units as line_width
131
140
  s->minor_tick_width = p->xaxis_minor_tick_width; // same units as line_width
132
141
  s->major_tick_length = p->xaxis_major_tick_length; // in units of numeric label char heights
@@ -163,9 +172,15 @@ static void Get_yaxis_Specs(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
163
172
  s->type = p->yaxis_type;
164
173
  s->other_axis_type = p->xaxis_type;
165
174
  s->line_width = p->yaxis_line_width; // for axis line
175
+
166
176
  s->stroke_color_R = p->yaxis_stroke_color_R; // for axis line and tick marks
167
177
  s->stroke_color_G = p->yaxis_stroke_color_G;
168
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
+
169
184
  s->major_tick_width = p->yaxis_major_tick_width; // same units as line_width
170
185
  s->minor_tick_width = p->yaxis_minor_tick_width; // same units as line_width
171
186
  s->major_tick_length = p->yaxis_major_tick_length; // in units of numeric label char heights
@@ -635,16 +650,21 @@ static double * pick_major_ticks_positions_Vincent(OBJ_PTR fmkr, FM *p,
635
650
  double norm_tick_min = tick_min/factor;
636
651
  int i;
637
652
 
653
+ /* printf("axis_min: %g\taxis_max: %g\n", axis_min, axis_max); */
638
654
  /* We get the one just above tick_min */
639
655
  for(i = 0; i < nb_natural_distances; i++)
640
656
  if(natural_distances[i] >= norm_tick_min)
641
657
  break;
642
658
 
659
+
643
660
  *tick = natural_distances[i] * factor;
661
+ /* printf("norm_tick_min: %g\ttick: %g\ttick_min:%g\n", */
662
+ /* norm_tick_min, *tick, tick_min); */
644
663
  double first_tick = ceil(axis_min /(*tick)) * (*tick);
645
664
  double last_tick = floor(axis_max /(*tick)) * (*tick);
646
665
 
647
- *num_locations = (int)((last_tick - first_tick)/(*tick) + 1);
666
+ *num_locations = (int)round((last_tick - first_tick)/(*tick));
667
+ *num_locations += 1;
648
668
 
649
669
  double *majors = ALLOC_N_double(*num_locations);
650
670
  for (i = 0; i < *num_locations; i++)
@@ -831,6 +851,13 @@ static void draw_minor_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
831
851
  static void show_numeric_label(OBJ_PTR fmkr, FM *p, PlotAxis *s,
832
852
  char *text, int location, double position, double shift, int *ierr)
833
853
  {
854
+ /* We need a buffer to implement the color */
855
+ long len = strlen(text) + 100; /* Should be enough overhead ! */
856
+ char * buffer = ALLOC_N_char(len);
857
+ snprintf(buffer, len, "\\textcolor[rgb]{%0.2f,%0.2f,%0.2f}{%s}",
858
+ s->labels_color_R, s->labels_color_G, s->labels_color_B,
859
+ text);
860
+
834
861
  if(location == AXIS_FREE_LOCATION) {
835
862
  /* We convert the tick position into frame position */
836
863
  double x,y, ft_ht = p->default_text_scale *
@@ -852,7 +879,7 @@ static void show_numeric_label(OBJ_PTR fmkr, FM *p, PlotAxis *s,
852
879
  ft_ht * ENLARGE * shift);
853
880
  }
854
881
 
855
- c_show_rotated_label(fmkr, p, text, x, y,
882
+ c_show_rotated_label(fmkr, p, buffer, x, y,
856
883
  s->numeric_label_scale,
857
884
  s->numeric_label_angle + angle,
858
885
  s->numeric_label_justification,
@@ -862,9 +889,10 @@ static void show_numeric_label(OBJ_PTR fmkr, FM *p, PlotAxis *s,
862
889
  else {
863
890
  // position is in figure coords and must be converted to frame coords
864
891
  double pos = ((!s->reversed)? (position - s->axis_min) : (s->axis_max - position)) / s->length;
865
- c_show_rotated_text(fmkr, p, text, location, shift, pos,
892
+ c_show_rotated_text(fmkr, p, buffer, location, shift, pos,
866
893
  s->numeric_label_scale, s->numeric_label_angle, s->numeric_label_justification, s->numeric_label_alignment, OBJ_NIL, ierr);
867
894
  }
895
+ free(buffer);
868
896
  }
869
897
 
870
898
  static void draw_numeric_labels(OBJ_PTR fmkr, FM *p, int location, PlotAxis *s, int *ierr)
@@ -1168,6 +1196,40 @@ static int prepare_dict_PlotAxis(OBJ_PTR fmkr, FM *p,
1168
1196
  if(Hash_Has_Key(axis_spec, "minor_tick_length"))
1169
1197
  axis->minor_tick_length = Hash_Get_Double(axis_spec, "minor_tick_length");
1170
1198
 
1199
+ /* Stroke color */
1200
+ if(Hash_Has_Key(axis_spec, "stroke_color") ||
1201
+ Hash_Has_Key(axis_spec, "color")) {
1202
+ OBJ_PTR color = (Hash_Has_Key(axis_spec, "stroke_color") ?
1203
+ Hash_Get_Obj(axis_spec, "stroke_color") :
1204
+ Hash_Get_Obj(axis_spec, "color") );
1205
+ int err;
1206
+ axis->stroke_color_R = Array_Entry_double(color, 0, &err);
1207
+ axis->stroke_color_G = Array_Entry_double(color, 1, &err);
1208
+ axis->stroke_color_B = Array_Entry_double(color, 2, &err);
1209
+ }
1210
+
1211
+ /* Labels color */
1212
+ if(Hash_Has_Key(axis_spec, "labels_color") ||
1213
+ Hash_Has_Key(axis_spec, "color")) {
1214
+ OBJ_PTR color = (Hash_Has_Key(axis_spec, "labels_color") ?
1215
+ Hash_Get_Obj(axis_spec, "labels_color") :
1216
+ Hash_Get_Obj(axis_spec, "color") );
1217
+ int err;
1218
+ axis->labels_color_R = Array_Entry_double(color, 0, &err);
1219
+ axis->labels_color_G = Array_Entry_double(color, 1, &err);
1220
+ axis->labels_color_B = Array_Entry_double(color, 2, &err);
1221
+ }
1222
+
1223
+ /* Log scale: */
1224
+ if(Hash_Has_Key(axis_spec, "log")) {
1225
+ OBJ_PTR val = Hash_Get_Obj(axis_spec, "log");
1226
+ if(val == OBJ_NIL || val == OBJ_FALSE)
1227
+ axis->log_vals = 0;
1228
+ else
1229
+ axis->log_vals = 1;
1230
+ }
1231
+
1232
+
1171
1233
  return 1;
1172
1234
  }
1173
1235
 
@@ -1193,7 +1255,8 @@ void c_show_axis_generic(OBJ_PTR fmkr, FM *p, OBJ_PTR axis_spec, int *ierr)
1193
1255
  /*
1194
1256
  This function takes an axis specification (either integer or
1195
1257
  hash) and returns a hash containing the following keys:
1196
- * 'major' : position of all major ticks
1258
+ * 'major_ticks' : position of all major ticks
1259
+ * 'minor_ticks' : position of all major ticks
1197
1260
  * 'labels' : the names of all labels
1198
1261
  * 'vertical' : if the axis is vertical or horizontal
1199
1262
  * 'line_width' : the line width
@@ -1202,8 +1265,9 @@ void c_show_axis_generic(OBJ_PTR fmkr, FM *p, OBJ_PTR axis_spec, int *ierr)
1202
1265
  * 'scale', 'shift' and 'angle': the scale, shift and angle of numeric
1203
1266
  labels
1204
1267
  * 'x0', 'y0', 'x1', 'y1': the position of the axis in figure coordinates
1205
-
1206
- */
1268
+ * 'stroke_color': the color to use for drawing lines.
1269
+ * 'labels_color': the color to use for drawing tick labels.
1270
+ */
1207
1271
  OBJ_PTR c_axis_get_information(OBJ_PTR fmkr, FM *p, OBJ_PTR axis_spec,
1208
1272
  int *ierr)
1209
1273
  {
@@ -1219,14 +1283,15 @@ OBJ_PTR c_axis_get_information(OBJ_PTR fmkr, FM *p, OBJ_PTR axis_spec,
1219
1283
  /* First, major ticks positions */
1220
1284
  prepare_axis_coordinates(fmkr, p, axis.location, &axis, ierr);
1221
1285
  compute_major_ticks(fmkr, p, &axis, ierr);
1222
- Hash_Set_Obj(hash, "major", Vector_New(axis.nmajors, axis.majors));
1286
+ Hash_Set_Obj(hash, "major_ticks", Vector_New(axis.nmajors, axis.majors));
1223
1287
 
1224
1288
  /* Then, minor ticks positions */
1225
1289
  double * minor;
1226
1290
  long count;
1291
+ OBJ_PTR color;
1227
1292
  minor = get_minor_ticks_location(fmkr, p, &axis, &count);
1228
1293
  if(minor) {
1229
- Hash_Set_Obj(hash, "minor", Vector_New(count, minor));
1294
+ Hash_Set_Obj(hash, "minor_ticks", Vector_New(count, minor));
1230
1295
  free(minor);
1231
1296
  }
1232
1297
 
@@ -1259,6 +1324,25 @@ OBJ_PTR c_axis_get_information(OBJ_PTR fmkr, FM *p, OBJ_PTR axis_spec,
1259
1324
  Hash_Set_Double(hash, "y0", axis.y0);
1260
1325
  Hash_Set_Double(hash, "y1", axis.y1);
1261
1326
 
1327
+ /* Log values */
1328
+ Hash_Set_Obj(hash, "log", axis.log_vals ? OBJ_TRUE : OBJ_FALSE);
1329
+
1330
+ /* Stroke color */
1331
+ color = Array_New(3);
1332
+ Array_Store(color, 0, Float_New(axis.stroke_color_R),ierr);
1333
+ Array_Store(color, 1, Float_New(axis.stroke_color_G),ierr);
1334
+ Array_Store(color, 2, Float_New(axis.stroke_color_B),ierr);
1335
+ Hash_Set_Obj(hash, "stroke_color", color);
1336
+
1337
+ /* Tick labels color */
1338
+ color = Array_New(3);
1339
+ Array_Store(color, 0, Float_New(axis.labels_color_R),ierr);
1340
+ Array_Store(color, 1, Float_New(axis.labels_color_G),ierr);
1341
+ Array_Store(color, 2, Float_New(axis.labels_color_B),ierr);
1342
+ Hash_Set_Obj(hash, "labels_color", color);
1343
+
1344
+
1345
+
1262
1346
  free_allocated_memory(&axis);
1263
1347
  return hash;
1264
1348
  }