tioga 1.7 → 1.8

Sign up to get free protection for your applications and to get access to all the features.
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
+ }