tioga 1.7 → 1.8

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 CHANGED
@@ -1,6 +1,7 @@
1
- This is the README for the Tioga kernel, version 1.6, March 17, 2007.
1
+ This is the README for the Tioga kernel, version 1.8, April 4, 2008.
2
2
 
3
- Copyright (C) 2005, 2006, 2007 Bill Paxton
3
+ Copyright (C) 2005, 2006, 2007, 2008 Bill Paxton
4
+ Copyright (C) 2007, 2008 Vincent Fourmond, Taro Sato
4
5
 
5
6
  This file is part of Tioga.
6
7
 
@@ -14,36 +15,21 @@ This is the README for the Tioga kernel, version 1.6, March 17, 2007.
14
15
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
16
  GNU Library General Public License for more details.
16
17
 
17
- You should have received a copy of the GNU Library General Public LicenseD
18
+ You should have received a copy of the GNU Library General Public License
18
19
  along with Tioga; if not, write to the Free Software
19
20
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21
 
21
22
  << What's new >>
22
23
 
23
- Version 1.7 adds an option in legends for markers without any line;
24
- just call save_legend_info with 'line_type' => 'None' in addition to
25
- the marker information. It is also now possible to give a 'legend' argument
26
- to show_marker. The value of the arg can be either a legend dictionary
27
- or simply the legend text in which case defaults will be supplied for
28
- the rest. There is an example of this in samples/plots.rb
29
- in the Legend_Outside figure.
30
-
31
- It saw a very significant improvement in that you can now query
32
- the exact size of a text typeset by LaTeX, with the function text_size. Please
33
- have a look at its documentation, and at the Text_size and
34
- Text_size_with_rotation samples in samples/figures/figures.rb.
35
-
36
- The code base was quite moved around so as to facilitate work on a
37
- Python version that would share as much code as possible with the Ruby one;
38
- this should not bring user-visible changes (apart, maybe, from compilation
39
- problems, but we hope not).
24
+ Version 1.8 is essentially a cleanup/bug fix release. Tioga now compiles
25
+ with hardly any warnings, thanks to the work by Taro Sato. show_axis can now
26
+ take a hash instead of a simple location, and can draw axes basically
27
+ anywhere. See the axes_fun function in samples/plots/plots.rb and
28
+ show_axis documentation. Few bugs were fixed, in particular the
29
+ position of ticks with ticks_inside/ticks_outside, and the
30
+ installation via Rubygems which was broken for such a long time we are
31
+ ashamed of it.
40
32
 
41
- Some bug fixes, including potential stack overflows (unprotected
42
- snprintfs), and some new methods of Function. Dvector.fancy_read has been
43
- reimplemented in C and benchmarked: it should be around three times faster
44
- than before.
45
-
46
- Code should now compile cleanly with Ruby 1.9.
47
33
 
48
34
  << Quick Installation of Tioga >>
49
35
 
@@ -54,9 +40,10 @@ the whole thing with a 'sudo'. For Linux, you may have to become root.
54
40
  Once you've taken care of that, just run the QUICK_INSTALL script and
55
41
  keep your fingers crossed.
56
42
 
57
- You now have the option to run HOME_INSTALL instead, which will install the files to
58
- your home directory (no root privileges needed). You just need to set your RUBYLIB
59
- environment variable as reminded at the end of the file.
43
+ You now have the option to run HOME_INSTALL instead, which will
44
+ install the files to your home directory (no root privileges
45
+ needed). You just need to set your RUBYLIB environment variable as
46
+ reminded at the end of the file.
60
47
 
61
48
  Please check that there are 0 failures and 0 errors at the end of the test.
62
49
  Then, in your favorite PDF previewer, open the newly created 'tests/Icon_Test.pdf'
@@ -191,6 +178,35 @@ Bill Paxton
191
178
  Here are the old release messages:
192
179
 
193
180
 
181
+ --------------------------
182
+
183
+ Version 1.7 adds an option in legends for markers without any line;
184
+ just call save_legend_info with 'line_type' => 'None' in addition to
185
+ the marker information. It is also now possible to give a 'legend' argument
186
+ to show_marker. The value of the arg can be either a legend dictionary
187
+ or simply the legend text in which case defaults will be supplied for
188
+ the rest. There is an example of this in samples/plots.rb
189
+ in the Legend_Outside figure.
190
+
191
+ It saw a very significant improvement in that you can now query
192
+ the exact size of a text typeset by LaTeX, with the function text_size. Please
193
+ have a look at its documentation, and at the Text_size and
194
+ Text_size_with_rotation samples in samples/figures/figures.rb.
195
+
196
+ The code base was quite moved around so as to facilitate work on a
197
+ Python version that would share as much code as possible with the Ruby one;
198
+ this should not bring user-visible changes (apart, maybe, from compilation
199
+ problems, but we hope not).
200
+
201
+ Some bug fixes, including potential stack overflows (unprotected
202
+ snprintfs), and some new methods of Function. Dvector.fancy_read has been
203
+ reimplemented in C and benchmarked: it should be around three times faster
204
+ than before.
205
+
206
+ Code should now compile cleanly with Ruby 1.9.
207
+
208
+
209
+
194
210
 
195
211
  --------------------------
196
212
 
@@ -4601,7 +4601,7 @@ VALUE Read_Rows_of_Dvectors(char *filename, VALUE destinations, int first_row_of
4601
4601
  if (!is_okay_number(v)) {
4602
4602
  fclose(file);
4603
4603
  free(buff);
4604
- rb_raise(rb_eArgError, "ERROR: bad value %g in line i% of file %s", v, i, filename);
4604
+ rb_raise(rb_eArgError, "ERROR: bad value %g in line %i of file %s", v, i, filename);
4605
4605
  }
4606
4606
  if (col < d->capa) { row_data[col] = v; d->len = col+1; }
4607
4607
  else {
@@ -1,6 +1,8 @@
1
+ /* -*- c-basic-offset: 3; -*- */
1
2
  /* axes.c */
2
3
  /*
3
4
  Copyright (C) 2005 Bill Paxton
5
+ Copyright (C) 2008 Vincent Fourmond
4
6
 
5
7
  This file is part of Tioga.
6
8
 
@@ -21,6 +23,20 @@
21
23
  #include "figures.h"
22
24
  #include "pdfs.h"
23
25
 
26
+ /*
27
+ 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
+ * BUG fix: apparently, two calls to the axes stuff do no return the
37
+ same thing, so I'll need to have a careful look at that
38
+ */
39
+
24
40
  typedef struct {
25
41
  int type;
26
42
  int other_axis_type;
@@ -172,7 +188,14 @@ static void Get_yaxis_Specs(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
172
188
 
173
189
  /*======================================================================*/
174
190
 
175
- static void draw_axis_line(OBJ_PTR fmkr, FM *p, int location, PlotAxis *s, int *ierr)
191
+ /*
192
+ Internal values for axis locations.
193
+ */
194
+ #define AXIS_FREE_LOCATION 1000
195
+
196
+ /* Prepares the various coordinates according to the axis location */
197
+ static void prepare_axis_coordinates(OBJ_PTR fmkr, FM *p,
198
+ int location, PlotAxis *s, int *ierr)
176
199
  {
177
200
  switch (location) {
178
201
  case LEFT:
@@ -253,7 +276,16 @@ static void draw_axis_line(OBJ_PTR fmkr, FM *p, int location, PlotAxis *s, int *
253
276
  s->other_axis_reversed = p->yaxis_reversed;
254
277
  s->top_or_right = false;
255
278
  break;
256
- }
279
+ case AXIS_FREE_LOCATION:
280
+ /* Nothing to be done here. */
281
+ break;
282
+ }
283
+ }
284
+
285
+ static void draw_axis_line(OBJ_PTR fmkr, FM *p, int location,
286
+ PlotAxis *s, int *ierr)
287
+ {
288
+ prepare_axis_coordinates(fmkr, p, location, s, ierr);
257
289
  c_line_width_set(fmkr, p, s->line_width, ierr);
258
290
  figure_join_and_stroke(fmkr, p, s->x0, s->y0, s->x1, s->y1, ierr);
259
291
  }
@@ -302,6 +334,7 @@ static char *Create_Label(double val, int scale, int prec,
302
334
  return string;
303
335
  }
304
336
 
337
+ /* vincent: I wonder what this function is doing here ;-)... */
305
338
  char *Get_String(OBJ_PTR ary, int index, int *ierr) {
306
339
  OBJ_PTR s = Array_Entry(ary,index,ierr);
307
340
  if (*ierr != 0) return NULL;
@@ -536,9 +569,11 @@ static void Pick_Major_Tick_Interval(OBJ_PTR fmkr, FM *p,
536
569
  }
537
570
  }
538
571
 
539
- static void draw_major_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
572
+ /* This functions fills the majors attribute of the PlotAxis object
573
+ with the position of major ticks
574
+ */
575
+ static void compute_major_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
540
576
  {
541
- s->num_minors = s->number_of_minor_intervals;
542
577
  if (s->locations_for_major_ticks != OBJ_NIL) {
543
578
  long len;
544
579
  s->majors = Vector_Data_for_Read(s->locations_for_major_ticks, &len, ierr);
@@ -559,12 +594,22 @@ static void draw_major_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
559
594
  if (*ierr != 0) return;
560
595
  s->free_majors = true;
561
596
  }
597
+ }
598
+
599
+ static void draw_major_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
600
+ {
601
+ s->num_minors = s->number_of_minor_intervals;
602
+
603
+ /* Get the major ticks position in s->majors */
604
+ compute_major_ticks(fmkr, p, s, ierr);
605
+ if(*ierr != 0) return;
606
+
562
607
  int i;
563
608
  double inside=0.0, outside=0.0, length;
564
609
  bool did_line = false;
565
610
  length = s->major_tick_length * ((s->vertical)? p->default_text_height_dx : p->default_text_height_dy);
566
611
  if (s->ticks_inside) inside = length;
567
- if (s->ticks_outside) outside = length;
612
+ if (s->ticks_outside) outside = -length;
568
613
  if (s->top_or_right) { inside = -inside; outside = -outside; }
569
614
  if (s->line_width != s->major_tick_width) {
570
615
  c_line_width_set(fmkr, p, s->line_width = s->major_tick_width, ierr);
@@ -607,7 +652,7 @@ static void draw_minor_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
607
652
  if (s->log_vals && nsub > 9) nsub = 9;
608
653
  length = s->minor_tick_length * ((s->vertical)? p->default_text_height_dx : p->default_text_height_dy);
609
654
  if (s->ticks_inside) inside = length;
610
- if (s->ticks_outside) outside = length;
655
+ if (s->ticks_outside) outside = -length;
611
656
  if (s->top_or_right) { inside = -inside; outside = -outside; }
612
657
  if (s->line_width != s->minor_tick_width) {
613
658
  c_line_width_set(fmkr, p, s->line_width = s->minor_tick_width, ierr);
@@ -635,10 +680,12 @@ static void draw_minor_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
635
680
  double subloc = loc + ((!s->log_vals) ? (j * subinterval) : log_subintervals[j-1]);
636
681
  if (subloc >= next_loc) break;
637
682
  if (subloc <= s->axis_min || subloc >= s->axis_max) continue;
638
- if (s->vertical)
683
+ if (s->vertical) {
639
684
  figure_join(fmkr, p, s->x0+inside, subloc, s->x0+outside, subloc, ierr);
640
- else
685
+ }
686
+ else {
641
687
  figure_join(fmkr, p, subloc, s->y0+inside, subloc, s->y0+outside, ierr);
688
+ }
642
689
  did_line = true;
643
690
  if (*ierr != 0) return;
644
691
  }
@@ -649,10 +696,41 @@ static void draw_minor_ticks(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr)
649
696
 
650
697
  static void show_numeric_label(OBJ_PTR fmkr, FM *p, PlotAxis *s,
651
698
  char *text, int location, double position, double shift, int *ierr)
652
- { // position is in figure coords and must be converted to frame coords
653
- double pos = ((!s->reversed)? (position - s->axis_min) : (s->axis_max - position)) / s->length;
654
- c_show_rotated_text(fmkr, p, text, location, shift, pos,
655
- s->numeric_label_scale, s->numeric_label_angle, s->numeric_label_justification, s->numeric_label_alignment, OBJ_NIL, ierr);
699
+ {
700
+ if(location == AXIS_FREE_LOCATION) {
701
+ /* We convert the tick position into frame position */
702
+ double x,y, ft_ht = p->default_text_scale *
703
+ s->numeric_label_scale * p->default_font_size;
704
+ double angle;
705
+ /* Defaults to angle = +90, left side of the axis */
706
+ if(s->vertical) {
707
+ y = position;
708
+ x = s->x0 + convert_output_to_figure_dx(p,(s->reversed ? 1.0 : -1.0) *
709
+ ft_ht * ENLARGE * shift);
710
+
711
+
712
+ angle = 90;
713
+ }
714
+ else {
715
+ angle = 0;
716
+ x = position;
717
+ y = s->y0 + convert_output_to_figure_dy(p,(s->reversed ? 1.0 : -1.0) *
718
+ ft_ht * ENLARGE * shift);
719
+ }
720
+
721
+ c_show_rotated_label(fmkr, p, text, x, y,
722
+ s->numeric_label_scale,
723
+ s->numeric_label_angle + angle,
724
+ s->numeric_label_justification,
725
+ s->numeric_label_alignment, OBJ_NIL, ierr);
726
+
727
+ }
728
+ else {
729
+ // position is in figure coords and must be converted to frame coords
730
+ double pos = ((!s->reversed)? (position - s->axis_min) : (s->axis_max - position)) / s->length;
731
+ c_show_rotated_text(fmkr, p, text, location, shift, pos,
732
+ s->numeric_label_scale, s->numeric_label_angle, s->numeric_label_justification, s->numeric_label_alignment, OBJ_NIL, ierr);
733
+ }
656
734
  }
657
735
 
658
736
  static void draw_numeric_labels(OBJ_PTR fmkr, FM *p, int location, PlotAxis *s, int *ierr)
@@ -669,6 +747,20 @@ static void draw_numeric_labels(OBJ_PTR fmkr, FM *p, int location, PlotAxis *s,
669
747
  }
670
748
  }
671
749
 
750
+ /* Frees all temporarily allocated memory */
751
+ static void free_allocated_memory(PlotAxis *s)
752
+ {
753
+ int i;
754
+ if (s->free_majors) free(s->majors);
755
+ if (s->labels != NULL) {
756
+ if (s->free_strings_for_labels) {
757
+ for (i = 0; i < s->nmajors; i++)
758
+ if (s->labels[i] != NULL) free(s->labels[i]);
759
+ }
760
+ free(s->labels);
761
+ }
762
+ }
763
+
672
764
  static void c_show_side(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr) {
673
765
  int i;
674
766
  if (s->type == AXIS_HIDDEN) return;
@@ -694,32 +786,9 @@ static void c_show_side(OBJ_PTR fmkr, FM *p, PlotAxis *s, int *ierr) {
694
786
  if (*ierr != 0) return;
695
787
  done:
696
788
  End_Axis_Standard_State(); // grestore
697
- if (s->free_majors) free(s->majors);
698
- if (s->labels != NULL) {
699
- if (s->free_strings_for_labels) {
700
- for (i = 0; i < s->nmajors; i++)
701
- if (s->labels[i] != NULL) free(s->labels[i]);
702
- }
703
- free(s->labels);
704
- }
789
+ free_allocated_memory(s);
705
790
  }
706
791
 
707
-
708
- void c_show_axis(OBJ_PTR fmkr, FM *p, int location, int *ierr)
709
- {
710
- PlotAxis axis;
711
- if (location == LEFT || location == RIGHT || location == AT_X_ORIGIN) {
712
- if (!p->yaxis_visible) return;
713
- Get_yaxis_Specs(fmkr, p, &axis, ierr);
714
- } else if (location == TOP || location == BOTTOM || location == AT_Y_ORIGIN) {
715
- if (!p->xaxis_visible) return;
716
- Get_xaxis_Specs(fmkr, p, &axis, ierr);
717
- } else RAISE_ERROR_i(
718
- "Sorry: invalid 'loc' for axis: must be one of LEFT, RIGHT, TOP, BOTTOM, AT_X_ORIGIN, or AT_Y_ORIGIN: is (%i)", location, ierr);
719
- if (*ierr != 0) return;
720
- axis.location = location;
721
- c_show_side(fmkr, p, &axis, ierr);
722
- }
723
792
 
724
793
  void c_show_edge(OBJ_PTR fmkr, FM *p, int location, int *ierr)
725
794
  {
@@ -796,3 +865,258 @@ void c_no_bottom_edge(OBJ_PTR fmkr, FM *p, int *ierr)
796
865
  p->bottom_edge_visible = false;
797
866
  }
798
867
 
868
+
869
+ /* Prepares the PlotAxis object for a standard use.
870
+ Returns 1 if the corresponding axis is marked as
871
+ visible and 0 if not.
872
+
873
+ This function will be used later to get the exact same PlotAxis
874
+ object so as to get information about the ticks, for instance.
875
+ */
876
+ static int prepare_standard_PlotAxis(OBJ_PTR fmkr, FM *p,
877
+ int location, PlotAxis * axis,
878
+ int *ierr)
879
+ {
880
+ axis->location = location;
881
+ if (location == LEFT || location == RIGHT || location == AT_X_ORIGIN) {
882
+ Get_yaxis_Specs(fmkr, p, axis, ierr);
883
+ if (!p->yaxis_visible) return 0;
884
+ }
885
+ else if (location == TOP || location == BOTTOM || location == AT_Y_ORIGIN) {
886
+ Get_xaxis_Specs(fmkr, p, axis, ierr);
887
+ if (!p->xaxis_visible) return 0;
888
+ }
889
+ else
890
+ RAISE_ERROR_i("Sorry: invalid 'loc' for axis: must be one of LEFT,"
891
+ "RIGHT, TOP, BOTTOM, AT_X_ORIGIN, or AT_Y_ORIGIN: is (%i)",
892
+ location, ierr);
893
+ if (*ierr != 0)
894
+ return 0;
895
+ return 1;
896
+ }
897
+
898
+
899
+ void c_show_axis(OBJ_PTR fmkr, FM *p, int location, int *ierr)
900
+ {
901
+ PlotAxis axis;
902
+ if(prepare_standard_PlotAxis(fmkr, p, location, &axis, ierr)) {
903
+ c_show_side(fmkr, p, &axis, ierr);
904
+ }
905
+ }
906
+
907
+ /* This function prepares a PlotAxis object based on the information
908
+ given in the dict argument.
909
+ */
910
+ static int prepare_dict_PlotAxis(OBJ_PTR fmkr, FM *p,
911
+ OBJ_PTR axis_spec, PlotAxis * axis,
912
+ int *ierr)
913
+ {
914
+ /* First, we get default from the location or from style.
915
+ Too many things need to be checked if we don't get default values
916
+ from a given point
917
+ */
918
+ if(Hash_Has_Key(axis_spec, "location")) {
919
+ int location = Number_to_int(Hash_Get_Obj(axis_spec, "location"), ierr);
920
+ if (location == LEFT || location == RIGHT || location == AT_X_ORIGIN) {
921
+ Get_yaxis_Specs(fmkr, p, axis, ierr);
922
+ }
923
+ else if (location == TOP || location == BOTTOM ||
924
+ location == AT_Y_ORIGIN) {
925
+ Get_xaxis_Specs(fmkr, p, axis, ierr);
926
+ }
927
+ axis->location = location;
928
+ }
929
+ else {
930
+ if(Hash_Has_Key(axis_spec, "from") && Hash_Has_Key(axis_spec, "to")) {
931
+ long dummy;
932
+ double *from = Vector_Data_for_Read(Hash_Get_Obj(axis_spec, "from"),
933
+ &dummy, ierr);
934
+ double *to = Vector_Data_for_Read(Hash_Get_Obj(axis_spec, "to"),
935
+ &dummy, ierr);
936
+ axis->x0 = from[0];
937
+ axis->x1 = to[0];
938
+ axis->y0 = from[1];
939
+ axis->y1 = to[1];
940
+
941
+ /* We now determine various parameters attached to the axis:
942
+ * its length
943
+ * its min/max boundaries
944
+ * whether it is reversed
945
+ */
946
+ if(axis->y0 != axis->y1) {
947
+ Get_yaxis_Specs(fmkr, p, axis, ierr);
948
+ if(axis->x0 != axis->x1) {
949
+ RAISE_ERROR("show_axis: sorry, axes must be horizontal or "
950
+ "vertical", ierr);
951
+ }
952
+ else {
953
+ if(axis->y0 > axis->y1) {
954
+ axis->reversed = true;
955
+ axis->axis_min = axis->y1;
956
+ axis->axis_max = axis->y0;
957
+ axis->length = axis->y0 - axis->y1;
958
+ }
959
+ else {
960
+ axis->reversed = false;
961
+ axis->axis_min = axis->y0;
962
+ axis->axis_max = axis->y1;
963
+ axis->length = axis->y1 - axis->y0;
964
+ }
965
+ axis->vertical = true;
966
+ axis->location = AXIS_FREE_LOCATION;
967
+ }
968
+ }
969
+ else {
970
+ Get_xaxis_Specs(fmkr, p, axis, ierr);
971
+ if(axis->x0 > axis->x1) {
972
+ axis->reversed = true;
973
+ axis->axis_min = axis->x1;
974
+ axis->axis_max = axis->x0;
975
+ axis->length = axis->x0 - axis->x1;
976
+ }
977
+ else {
978
+ axis->reversed = false;
979
+ axis->axis_min = axis->x0;
980
+ axis->axis_max = axis->x1;
981
+ axis->length = axis->x1 - axis->x0;
982
+ }
983
+ axis->vertical = false;
984
+ axis->location = AXIS_FREE_LOCATION;
985
+ }
986
+ }
987
+ else {
988
+ RAISE_ERROR("show_axis: there must be 'location' or 'to' and 'from'", ierr);
989
+ }
990
+ }
991
+
992
+ /* Some generic overrides */
993
+ if(Hash_Has_Key(axis_spec, "type"))
994
+ axis->type = Number_to_int(Hash_Get_Obj(axis_spec, "type"), ierr);
995
+
996
+ if(Hash_Has_Key(axis_spec, "ticks_inside")) {
997
+ OBJ_PTR val = Hash_Get_Obj(axis_spec, "ticks_inside");
998
+ if(val == OBJ_NIL || val == OBJ_FALSE)
999
+ axis->ticks_inside = false;
1000
+ else
1001
+ axis->ticks_inside = true;
1002
+ }
1003
+
1004
+ if(Hash_Has_Key(axis_spec, "ticks_outside")) {
1005
+ OBJ_PTR val = Hash_Get_Obj(axis_spec, "ticks_outside");
1006
+ if(val == OBJ_NIL || val == OBJ_FALSE)
1007
+ axis->ticks_outside = false;
1008
+ else
1009
+ axis->ticks_outside = true;
1010
+ }
1011
+
1012
+ if(Hash_Has_Key(axis_spec, "major_ticks"))
1013
+ axis->locations_for_major_ticks = Hash_Get_Obj(axis_spec, "major_ticks");
1014
+ if(Hash_Has_Key(axis_spec, "minor_ticks"))
1015
+ axis->locations_for_minor_ticks = Hash_Get_Obj(axis_spec, "minor_ticks");
1016
+ if(Hash_Has_Key(axis_spec, "labels"))
1017
+ axis->tick_labels = Hash_Get_Obj(axis_spec, "labels");
1018
+
1019
+
1020
+ /* Various tick label attributes */
1021
+ if(Hash_Has_Key(axis_spec, "shift"))
1022
+ axis->numeric_label_shift = Hash_Get_Double(axis_spec, "shift");
1023
+ if(Hash_Has_Key(axis_spec, "scale"))
1024
+ axis->numeric_label_scale = Hash_Get_Double(axis_spec, "scale");
1025
+ if(Hash_Has_Key(axis_spec, "angle"))
1026
+ axis->numeric_label_angle = Hash_Get_Double(axis_spec, "angle");
1027
+
1028
+ /* Ticks attributes */
1029
+ if(Hash_Has_Key(axis_spec, "major_tick_width"))
1030
+ axis->major_tick_width = Hash_Get_Double(axis_spec, "major_tick_width");
1031
+ if(Hash_Has_Key(axis_spec, "minor_tick_width"))
1032
+ axis->minor_tick_width = Hash_Get_Double(axis_spec, "minor_tick_width");
1033
+ if(Hash_Has_Key(axis_spec, "major_tick_length"))
1034
+ axis->major_tick_length = Hash_Get_Double(axis_spec, "major_tick_length");
1035
+ if(Hash_Has_Key(axis_spec, "minor_tick_length"))
1036
+ axis->minor_tick_length = Hash_Get_Double(axis_spec, "minor_tick_length");
1037
+
1038
+ return 1;
1039
+ }
1040
+
1041
+
1042
+ /* This function does nearly the same job as c_show_axis, but takes
1043
+ a full hash instead of getting information from the FigureMaker object,
1044
+ it retrieves them from the axis_spec hash. Following keys are
1045
+ understood:
1046
+ - location: position, as in show_axis. Can be omitted, if you
1047
+ provide the position yourself
1048
+
1049
+ This function bypasses the axis_visible checks. Use with caution !
1050
+ */
1051
+ void c_show_axis_generic(OBJ_PTR fmkr, FM *p, OBJ_PTR axis_spec, int *ierr)
1052
+ {
1053
+ PlotAxis axis;
1054
+ if(prepare_dict_PlotAxis(fmkr, p, axis_spec, &axis, ierr)) {
1055
+ c_show_side(fmkr, p, &axis, ierr);
1056
+ }
1057
+ }
1058
+
1059
+
1060
+ /*
1061
+ This function takes an axis specification (either integer or
1062
+ hash) and returns a hash containing the following keys:
1063
+ * 'major' : position of all major ticks
1064
+ * 'labels' : the names of all labels
1065
+ * 'vertical' : if the axis is vertical or horizontal
1066
+ * 'line_width' : the line width
1067
+ * 'major_tick_width', 'major_tick_length' : the major tick width and length
1068
+ * 'minor_tick_width', 'minor_tick_length' : the minor tick width and length
1069
+ * 'scale', 'shift' and 'angle': the scale, shift and angle of numeric
1070
+ labels
1071
+ * 'x0', 'y0', 'x1', 'y1': the position of the axis in figure coordinates
1072
+
1073
+ */
1074
+ OBJ_PTR c_axis_get_information(OBJ_PTR fmkr, FM *p, OBJ_PTR axis_spec,
1075
+ int *ierr)
1076
+ {
1077
+ PlotAxis axis;
1078
+ OBJ_PTR hash = Hash_New(), ar;
1079
+ int i;
1080
+ if(Is_Kind_of_Integer(axis_spec))
1081
+ prepare_standard_PlotAxis(fmkr, p, Number_to_int(axis_spec, ierr),
1082
+ &axis, ierr);
1083
+ else
1084
+ prepare_dict_PlotAxis(fmkr, p, axis_spec, &axis, ierr);
1085
+
1086
+ /* First, major ticks positions */
1087
+ prepare_axis_coordinates(fmkr, p, axis.location, &axis, ierr);
1088
+ compute_major_ticks(fmkr, p, &axis, ierr);
1089
+ Hash_Set_Obj(hash, "major", Vector_New(axis.nmajors, axis.majors));
1090
+
1091
+ /* Then, labels */
1092
+ ar = Array_New(axis.nmajors);
1093
+ axis.labels = Get_Labels(fmkr, p, &axis, ierr);
1094
+ for (i=0; i < axis.nmajors; i++) {
1095
+ if (axis.labels[i])
1096
+ Array_Store(ar, i, String_From_Cstring(axis.labels[i]), ierr);
1097
+ else
1098
+ Array_Store(ar, i, OBJ_NIL, ierr);
1099
+ }
1100
+
1101
+ Hash_Set_Obj(hash, "labels", ar);
1102
+
1103
+ Hash_Set_Obj(hash, "vertical", axis.vertical ? OBJ_TRUE : OBJ_FALSE);
1104
+
1105
+ Hash_Set_Double(hash, "line_width", axis.line_width);
1106
+ Hash_Set_Double(hash, "major_tick_width", axis.major_tick_width);
1107
+ Hash_Set_Double(hash, "minor_tick_width", axis.major_tick_width);
1108
+ Hash_Set_Double(hash, "major_tick_length", axis.major_tick_length);
1109
+ Hash_Set_Double(hash, "minor_tick_length", axis.major_tick_length);
1110
+ Hash_Set_Double(hash, "shift", axis.numeric_label_shift);
1111
+ Hash_Set_Double(hash, "scale", axis.numeric_label_scale);
1112
+ Hash_Set_Double(hash, "angle", axis.numeric_label_angle);
1113
+
1114
+ /* Positions of the axis */
1115
+ Hash_Set_Double(hash, "x0", axis.x0);
1116
+ Hash_Set_Double(hash, "x1", axis.x1);
1117
+ Hash_Set_Double(hash, "y0", axis.y0);
1118
+ Hash_Set_Double(hash, "y1", axis.y1);
1119
+
1120
+ free_allocated_memory(&axis);
1121
+ return hash;
1122
+ }