ctioga2 0.0 → 0.1

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.
Files changed (84) hide show
  1. data/Changelog +25 -1
  2. data/lib/ctioga2/commands/commands.rb +13 -2
  3. data/lib/ctioga2/commands/doc/doc.rb +13 -17
  4. data/lib/ctioga2/commands/doc/documentation-commands.rb +14 -1
  5. data/lib/ctioga2/commands/doc/help.rb +136 -25
  6. data/lib/ctioga2/commands/doc/html.rb +56 -4
  7. data/lib/ctioga2/commands/doc/introspection.rb +45 -9
  8. data/lib/ctioga2/commands/doc/man.rb +7 -5
  9. data/lib/ctioga2/commands/doc/markup.rb +39 -12
  10. data/lib/ctioga2/commands/doc/wordwrap.rb +70 -0
  11. data/lib/ctioga2/commands/general-commands.rb +7 -4
  12. data/lib/ctioga2/commands/general-types.rb +27 -12
  13. data/lib/ctioga2/commands/interpreter.rb +2 -2
  14. data/lib/ctioga2/commands/parsers/command-line.rb +9 -5
  15. data/lib/ctioga2/commands/parsers/file.rb +5 -3
  16. data/lib/ctioga2/commands/type.rb +10 -3
  17. data/lib/ctioga2/commands/variables.rb +2 -2
  18. data/lib/ctioga2/data/backends/backend.rb +17 -15
  19. data/lib/ctioga2/data/backends/backends.rb +2 -2
  20. data/lib/ctioga2/data/backends/backends/gnuplot.rb +20 -5
  21. data/lib/ctioga2/data/backends/backends/math.rb +2 -2
  22. data/lib/ctioga2/data/backends/backends/text.rb +112 -17
  23. data/lib/ctioga2/data/backends/description.rb +10 -11
  24. data/lib/ctioga2/data/datacolumn.rb +73 -14
  25. data/lib/ctioga2/data/dataset.rb +305 -9
  26. data/lib/ctioga2/data/filters.rb +49 -1
  27. data/lib/ctioga2/data/indexed-dtable.rb +137 -0
  28. data/lib/ctioga2/data/point.rb +98 -7
  29. data/lib/ctioga2/data/stack.rb +98 -21
  30. data/lib/ctioga2/graphics/coordinates.rb +19 -2
  31. data/lib/ctioga2/graphics/elements.rb +12 -2
  32. data/lib/ctioga2/graphics/elements/containers.rb +14 -2
  33. data/lib/ctioga2/graphics/elements/contour.rb +67 -0
  34. data/lib/ctioga2/graphics/elements/curve2d.rb +103 -42
  35. data/lib/ctioga2/graphics/elements/element.rb +12 -2
  36. data/lib/ctioga2/graphics/elements/gradient-region.rb +94 -0
  37. data/lib/ctioga2/graphics/elements/parametric2d.rb +172 -0
  38. data/lib/ctioga2/graphics/elements/primitive.rb +37 -21
  39. data/lib/ctioga2/graphics/elements/region.rb +143 -0
  40. data/lib/ctioga2/graphics/elements/subplot.rb +92 -32
  41. data/lib/ctioga2/graphics/elements/tangent.rb +99 -0
  42. data/lib/ctioga2/graphics/elements/xyz-map.rb +126 -0
  43. data/lib/ctioga2/graphics/generator.rb +91 -6
  44. data/lib/ctioga2/graphics/legends.rb +26 -21
  45. data/lib/ctioga2/graphics/legends/area.rb +8 -8
  46. data/lib/ctioga2/graphics/legends/items.rb +5 -5
  47. data/lib/ctioga2/graphics/legends/storage.rb +4 -2
  48. data/lib/ctioga2/graphics/root.rb +24 -2
  49. data/lib/ctioga2/graphics/styles.rb +8 -0
  50. data/lib/ctioga2/graphics/styles/axes.rb +49 -23
  51. data/lib/ctioga2/graphics/styles/base.rb +2 -2
  52. data/lib/ctioga2/graphics/styles/carrays.rb +9 -2
  53. data/lib/ctioga2/graphics/styles/colormap.rb +272 -0
  54. data/lib/ctioga2/graphics/styles/curve.rb +64 -4
  55. data/lib/ctioga2/graphics/styles/drawable.rb +68 -9
  56. data/lib/ctioga2/graphics/styles/errorbar.rb +73 -0
  57. data/lib/ctioga2/graphics/styles/factory.rb +133 -17
  58. data/lib/ctioga2/graphics/styles/gradients.rb +60 -0
  59. data/lib/ctioga2/graphics/styles/location.rb +64 -0
  60. data/lib/ctioga2/graphics/styles/map-axes.rb +164 -0
  61. data/lib/ctioga2/graphics/styles/plot.rb +165 -62
  62. data/lib/ctioga2/graphics/styles/sets.rb +14 -1
  63. data/lib/ctioga2/graphics/styles/texts.rb +44 -34
  64. data/lib/ctioga2/graphics/subplot-commands.rb +94 -6
  65. data/lib/ctioga2/graphics/types.rb +113 -35
  66. data/lib/ctioga2/graphics/types/bijection.rb +3 -3
  67. data/lib/ctioga2/graphics/types/boundaries.rb +120 -1
  68. data/lib/ctioga2/graphics/types/dimensions.rb +8 -1
  69. data/lib/ctioga2/graphics/types/grid.rb +196 -0
  70. data/lib/ctioga2/graphics/types/location.rb +228 -0
  71. data/lib/ctioga2/graphics/types/point.rb +2 -2
  72. data/lib/ctioga2/log.rb +18 -18
  73. data/lib/ctioga2/metabuilder/type.rb +15 -3
  74. data/lib/ctioga2/metabuilder/types.rb +2 -2
  75. data/lib/ctioga2/metabuilder/types/coordinates.rb +13 -1
  76. data/lib/ctioga2/metabuilder/types/data.rb +50 -0
  77. data/lib/ctioga2/metabuilder/types/generic.rb +60 -0
  78. data/lib/ctioga2/metabuilder/types/lists.rb +53 -16
  79. data/lib/ctioga2/metabuilder/types/styles.rb +26 -45
  80. data/lib/ctioga2/plotmaker.rb +91 -20
  81. data/lib/ctioga2/postprocess.rb +8 -8
  82. data/lib/ctioga2/utils.rb +23 -4
  83. metadata +107 -75
  84. data/lib/ctioga2/data/merge.rb +0 -43
@@ -16,7 +16,7 @@ require 'ctioga2/log'
16
16
 
17
17
  module CTioga2
18
18
 
19
- Version::register_svn_info('$Revision: 67 $', '$Date: 2009-05-30 23:38:00 +0200 (Sat, 30 May 2009) $')
19
+ Version::register_svn_info('$Revision: 155 $', '$Date: 2010-06-21 21:41:32 +0200 (Mon, 21 Jun 2010) $')
20
20
 
21
21
  module Graphics
22
22
 
@@ -61,10 +61,10 @@ module CTioga2
61
61
  # separated by :: -- or only one block in the case of an
62
62
  # involution (very common, actually, all 1/x transforms).
63
63
  #
64
- # TODO: few things around here to change... in particular,
64
+ # \todo few things around here to change... in particular,
65
65
  # I should try to find a way to include Math...
66
66
  #
67
- # TODO: add very common cases ?
67
+ # \todo add very common cases ?
68
68
  def self.from_text(spec)
69
69
  blocks = spec.split(/::/).map do |code|
70
70
  eval("proc do |x|\n#{code}\nend")
@@ -16,7 +16,7 @@ require 'ctioga2/log'
16
16
 
17
17
  module CTioga2
18
18
 
19
- Version::register_svn_info('$Revision: 2 $', '$Date: 2009-04-25 14:03:30 +0200 (Sat, 25 Apr 2009) $')
19
+ Version::register_svn_info('$Revision: 125 $', '$Date: 2010-01-12 00:56:15 +0100 (Tue, 12 Jan 2010) $')
20
20
 
21
21
  # This module contains all graphical elements of CTioga2
22
22
  module Graphics
@@ -25,7 +25,108 @@ module CTioga2
25
25
  # with Tioga
26
26
  module Types
27
27
 
28
+ # A range of coordinates.
29
+ class SimpleRange
30
+
31
+ attr_accessor :first, :last
32
+
33
+ # Create a new SimpleRange object that runs from _first_ to
34
+ # _last_ (_last_ can be less than _first_). A _nil_,
35
+ # _false_ or NaN in one of those means *unspecified*.
36
+ #
37
+ # Alternatively, _first_ can be an object that responds to
38
+ # #first and #last.
39
+ def initialize(first, last = nil)
40
+ if first.respond_to?(:first)
41
+ @first = first.first
42
+ @last = first.last
43
+ else
44
+ @first = first
45
+ @last = last
46
+ end
47
+ end
48
+
49
+ # Minimum value
50
+ def min
51
+ @first < @last ? @first : @last
52
+ end
53
+
54
+ # Maximum value
55
+ def max
56
+ @first > @last ? @first : @last
57
+ end
58
+
59
+ # Algebraic distance
60
+ def distance
61
+ return @last - @first
62
+ end
63
+
64
+ # This function makes sures that the SimpleRange object is big
65
+ # enough to encompass what it currently does and the _range_
66
+ # SimpleRange object.
67
+ #
68
+ # \todo this does not work correctly in the case of reversed
69
+ # boundaries. I don't think it can anyway.
70
+ #
71
+ # Actually, it even works with normal Range elements !
72
+ def extend(range)
73
+ # Left/right
74
+ if (! @first.is_a? Float) or @first.nan? or
75
+ (@first > range.first)
76
+ @first = range.first
77
+ end
78
+
79
+ if (! @last.is_a? Float) or @last.nan? or
80
+ (@last < range.last)
81
+ @last = range.last
82
+ end
83
+
84
+ return self
85
+ end
86
+
87
+
88
+ # Override the Boundaries with the contents of _override_. All
89
+ # elements which are not _nil_ or NaN from _override_
90
+ # precisely override those in _self_.
91
+ def override(override)
92
+ for el in [ :first, :last]
93
+ val = override.send(el)
94
+ if val and (val == val) # Strip NaN on the property that NaN != NaN
95
+ self.send("#{el}=", val)
96
+ end
97
+ end
98
+ end
99
+
100
+ # Apply a fixed margin on the Boundaries.
101
+ def apply_margin!(margin)
102
+ d = self.distance
103
+ @first = @first - margin * d
104
+ @last = @last + margin * d
105
+ end
106
+
107
+ # Returns a SimpleRange object that is large enough to exactly
108
+ # contain all _values_
109
+ def self.bounds(values)
110
+ return SimpleRange.new(values.min, values.max)
111
+ end
112
+
113
+ # Takes an array of Boundaries and returns a Boundaries object
114
+ # that precisely encompasses them all. Invalid floats are simply
115
+ # ignored.
116
+ def self.overall_range(ranges)
117
+ retval = SimpleRange.new(nil, nil)
118
+ for r in ranges
119
+ retval.extend(b)
120
+ end
121
+ return retval
122
+ end
123
+ end
124
+
125
+
28
126
  # An object representing boundaries for a plot.
127
+ #
128
+ # \todo Should be converted to using two SimpleRange
129
+ # objects. Will be more clear anyway.
29
130
  class Boundaries
30
131
 
31
132
  # Boundaries
@@ -65,6 +166,18 @@ module CTioga2
65
166
  @bottom > @top ? @bottom : @top
66
167
  end
67
168
 
169
+ # Returns a SimpleRange object corresponding to the horizontal
170
+ # range
171
+ def horizontal
172
+ return SimpleRange.new(@left, @right)
173
+ end
174
+
175
+ # Returns a SimpleRange object corresponding to the vertical
176
+ # range
177
+ def vertical
178
+ return SimpleRange.new(@bottom, @top)
179
+ end
180
+
68
181
 
69
182
  # Converts to an [xmin, xmax, ymin, ymax] array
70
183
  def extrema
@@ -161,6 +274,12 @@ module CTioga2
161
274
  return retval
162
275
  end
163
276
 
277
+ # Creates a Boundaries object from two SimpleRange objects.
278
+ def self.from_ranges(horiz, vert)
279
+ return Boundaries.new(horiz.first, horiz.last,
280
+ vert.last, vert.first)
281
+ end
282
+
164
283
  end
165
284
 
166
285
  end
@@ -16,7 +16,7 @@ require 'ctioga2/log'
16
16
 
17
17
  module CTioga2
18
18
 
19
- Version::register_svn_info('$Revision: 92 $', '$Date: 2009-06-24 01:17:46 +0200 (Wed, 24 Jun 2009) $')
19
+ Version::register_svn_info('$Revision: 198 $', '$Date: 2010-11-30 00:48:23 +0100 (Tue, 30 Nov 2010) $')
20
20
 
21
21
  module Graphics
22
22
 
@@ -85,6 +85,13 @@ module CTioga2
85
85
  to_figure(t, orientation))
86
86
  end
87
87
 
88
+ # Express the Dimension in units of text height (dy)
89
+ def to_text_height(t, orientation = nil)
90
+ orientation ||= @orientation
91
+ return self.to_figure(t, orientation)/
92
+ t.send("default_text_height_d#{orientation}")
93
+ end
94
+
88
95
  # Replace this Dimension by _dimension_ if the latter is
89
96
  # bigger. Conserves the current orientation.
90
97
  def replace_if_bigger(t, dimension)
@@ -0,0 +1,196 @@
1
+ # grib.rb: setup and use of a "graph grid"
2
+ # copyright (c) 2009,2010 by Vincent Fourmond
3
+
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program 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 General Public License for more details (in the COPYING file).
13
+
14
+ require 'ctioga2/utils'
15
+ require 'ctioga2/log'
16
+
17
+ require 'ctioga2/graphics/types/dimensions'
18
+ require 'ctioga2/graphics/types/boxes'
19
+
20
+ module CTioga2
21
+
22
+ Version::register_svn_info('$Revision: 147 $', '$Date: 2010-04-06 21:13:28 +0200 (Tue, 06 Apr 2010) $')
23
+
24
+ module Graphics
25
+
26
+ module Types
27
+
28
+ # The position of a single element in a GridLayout
29
+ #
30
+ # \todo add the possibility to override one element of the
31
+ # final positions.
32
+ class GridBox < Box
33
+
34
+ OptionHashRE = /([\w-]+)\s*=\s*([^,]+),?\s*/
35
+
36
+ GridBoxRE = /^\s*grid:(\d+)\s*,\s*(\d+)(?:,(#{OptionHashRE}+))?\s*$/
37
+
38
+ # This hash helps to convert from a hash-based representation
39
+ # of frame coordinates to the array-based one.
40
+ #
41
+ # \todo I should either use existing code or refactor into
42
+ # something globally useful.
43
+ FrameCoordsOverride = { 'xl' => 0,
44
+ 'yt' => 1,
45
+ 'xr' => 2,
46
+ 'yb' => 3
47
+ }
48
+
49
+ def self.from_text(txt)
50
+ if txt =~ GridBoxRE
51
+ return GridBox.new(GridLayout.current_grid, $1.to_i, $2.to_i,
52
+ $3) # The latter being to remove
53
+ # the initial comma
54
+ else
55
+ raise "#{txt} is not a grid box."
56
+ end
57
+ end
58
+
59
+ def initialize(grid, x, y, options = {})
60
+ if options.is_a? String
61
+ str = options
62
+ options = {}
63
+ str.split(/\s*,\s*/).map { |s|
64
+ s =~ OptionHashRE
65
+ options[$1] =
66
+ BaseCoordinate.from_text($2,if FrameCoordsOverride[$1] % 2 == 0
67
+ :x
68
+ else
69
+ :y
70
+ end, :frame)
71
+ }
72
+ end
73
+ @x = x.to_i
74
+ @grid = grid
75
+ @y = y.to_i
76
+ @overrides = options || {}
77
+ end
78
+
79
+ def to_frame_coordinates(t)
80
+ a = @grid.frame_coordinates(t, @x, @y)
81
+ ## \todo write a framework for manipulating this !
82
+ for k,v in @overrides
83
+ next unless FrameCoordsOverride.key?(k)
84
+ a[FrameCoordsOverride[k]] = v.to_frame(t)
85
+ end
86
+ return a
87
+ end
88
+ end
89
+
90
+ # This class provides a grid-like layout through the use of a grid
91
+ # setup command and a grid box specification.
92
+ class GridLayout
93
+
94
+ # The margins (left, right, top, bottom) around the whole grid
95
+ attr_accessor :outer_margins
96
+
97
+ # The X offset to go from the right-hand side of one element to
98
+ # the left-hand-side of the next
99
+ attr_accessor :delta_x
100
+
101
+ # The Y offset to go from the bottom of one element to
102
+ # the top of the next.
103
+ attr_accessor :delta_y
104
+
105
+ # The nup: an array nb horizontal, nb vertical
106
+ attr_accessor :nup
107
+
108
+ # Horizontal scales
109
+ attr_accessor :hscales
110
+
111
+ # Vertical scales
112
+ attr_accessor :vscales
113
+
114
+ def initialize(nup = "2x2")
115
+ if nup.respond_to?(:split)
116
+ if nup =~ /,/
117
+ @hscales, @vscales = nup.split(/\s*x\s*/).map { |x|
118
+ x.split(/\s*,\s*/).map { |y| y.to_f }
119
+ }
120
+ @nup = [@hscales.size, @vscales.size]
121
+ else
122
+ @nup = nup.split(/\s*x\s*/).map { |s| s.to_i }
123
+ end
124
+ else
125
+ @nup = nup.dup
126
+ end
127
+
128
+ # Initialize with the given
129
+ @outer_margins = {
130
+ 'left' => Dimension.new(:dy, 2.5, :x),
131
+ 'right' => Dimension.new(:bp, 6, :x),
132
+ 'bottom' => Dimension.new(:dy, 2.5, :y),
133
+ 'top' => Dimension.new(:dy, 2.5, :y)
134
+ }
135
+ @delta_x = Dimension.new(:dy, 2.5, :x)
136
+ @delta_y = Dimension.new(:dy, 2.5, :y)
137
+
138
+ @hscales ||= [1] * @nup[0]
139
+ @vscales ||= [1] * @nup[1]
140
+ end
141
+
142
+ # The grid currently in use.
143
+ @current_grid = nil
144
+
145
+ def self.current_grid=(grid)
146
+ @current_grid = grid
147
+ end
148
+
149
+ def self.current_grid
150
+ return @current_grid
151
+ end
152
+
153
+ # Compute the frame coordinates fo the x,y element of the
154
+ # grid. They are numbered from the top,left element.
155
+ def frame_coordinates(t, x, y)
156
+ compute_lengths(t)
157
+ xo = if x > 0
158
+ @hscales[0..(x-1)].inject(0,:+) * @wbase
159
+ else
160
+ 0
161
+ end
162
+ xl = @outer_margins['left'].to_frame(t, :x) + xo +
163
+ x * @delta_x.to_frame(t, :x)
164
+ yo = if y > 0
165
+ @vscales[0..(y-1)].inject(0,:+) * @hbase
166
+ else
167
+ 0
168
+ end
169
+ yt = 1 - (@outer_margins['top'].to_frame(t, :y) + yo +
170
+ y * @delta_y.to_frame(t, :y))
171
+ return [xl, yt,
172
+ xl + @wbase * @hscales[x],
173
+ yt - @hbase * @vscales[y]]
174
+ end
175
+
176
+ protected
177
+
178
+ # Compute the necessary variables in frame coordinates
179
+ def compute_lengths(t)
180
+ return if (@wbase && @hbase)
181
+ @wbase = (1 -
182
+ (@outer_margins['left'].to_frame(t, :x) +
183
+ @outer_margins['right'].to_frame(t, :x) +
184
+ @delta_x.to_frame(t, :x) * (@nup[0]-1)))/@hscales.inject(0,:+)
185
+ @hbase = (1 -
186
+ (@outer_margins['top'].to_frame(t, :y) +
187
+ @outer_margins['bottom'].to_frame(t, :y) +
188
+ @delta_y.to_frame(t, :y) * (@nup[1]-1)))/@vscales.inject(0,:+)
189
+ end
190
+
191
+ end
192
+
193
+ end
194
+ end
195
+
196
+ end
@@ -0,0 +1,228 @@
1
+ # location.rb: handling the concept of "location" (for an axis especially)
2
+ # copyright (c) 2009 by Vincent Fourmond
3
+
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful, but
10
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # General Public License for more details (in the COPYING file).
13
+
14
+ require 'ctioga2/utils'
15
+ require 'ctioga2/log'
16
+
17
+ module CTioga2
18
+
19
+ Version::register_svn_info('$Revision: 223 $', '$Date: 2011-01-11 01:07:48 +0100 (Tue, 11 Jan 2011) $')
20
+
21
+ module Graphics
22
+
23
+ module Types
24
+
25
+
26
+ # Location of an object (especially axes) in a plot, in terms of
27
+ # the side of the plot or the X and Y axis.
28
+ class PlotLocation
29
+
30
+ # Conversion between the #base_location attribute and the real
31
+ # constant used for Tioga
32
+ LocationToTiogaLocation = {
33
+ :left => Tioga::FigureConstants::LEFT,
34
+ :right => Tioga::FigureConstants::RIGHT,
35
+ :bottom => Tioga::FigureConstants::BOTTOM,
36
+ :top => Tioga::FigureConstants::TOP,
37
+ :at_x_origin => Tioga::FigureConstants::AT_X_ORIGIN,
38
+ :at_y_origin => Tioga::FigureConstants::AT_Y_ORIGIN
39
+ }
40
+
41
+ # Horizontal or vertical
42
+ LocationVertical = {
43
+ :left => true,
44
+ :right => true,
45
+ :bottom => false,
46
+ :top => false,
47
+ :at_x_origin => true,
48
+ :at_y_origin => false
49
+ }
50
+
51
+ # A few helper hashes to convert from sides to margins
52
+ # @todo won't work for origins.
53
+ LocationBaseMargins = {
54
+ :left => [0,1,0,0],
55
+ :right => [1,0,0,0],
56
+ :bottom => [0,0,1,0],
57
+ :top => [0,0,0,1]
58
+ }
59
+
60
+ # Multiply this by the frame dimension in the correct
61
+ # direction to get the frame margins.
62
+ LocationMarginMultiplier = {
63
+ :left => [-1,0,0,0],
64
+ :right => [0,-1,0,0],
65
+ :bottom => [0,0,0,-1],
66
+ :top => [0,0,-1,0]
67
+ }
68
+
69
+ LocationsReorientMargins = {
70
+ :left => [1,0,3,2],
71
+ :right => [0,1,2,3],
72
+ :top => [2,3,1,0],
73
+ :bottom => [3,2,0,1]
74
+ }
75
+
76
+ # The position of the object, one of :left, :right, :top,
77
+ # :bottom, :at_y_origin or :at_x_origin.
78
+ #
79
+ # @todo This will have to be extended to allow possibly
80
+ # arbitrary frame/figure placement.
81
+ attr_accessor :base_location
82
+
83
+ # The shift away from the position given by #base_location.
84
+ #
85
+ # This will be a Dimension object.
86
+ #
87
+ # @todo This is not currently implemented
88
+ attr_accessor :shift
89
+
90
+
91
+ # Creates a new PlotLocation object, either copying the one
92
+ # given as argument or from scratch specifying at least the
93
+ # base location.
94
+ def initialize(location, shift = nil)
95
+ if location.respond_to? :shift
96
+ @base_location = location.base_location
97
+ @shift = shift || location.shift
98
+ else
99
+ @base_location = location
100
+ @shift = shift
101
+ end
102
+ end
103
+
104
+ # Returns the tioga location (ie that suitable for sending to
105
+ # show_axis for instance)
106
+ def tioga_location
107
+ return LocationToTiogaLocation[@base_location]
108
+ end
109
+
110
+ # Whether the given location is vertical or horizontal
111
+ def vertical?
112
+ return LocationVertical[@base_location]
113
+ end
114
+
115
+ # Returns the orientation away from the graph
116
+ def orientation
117
+ if vertical?
118
+ return :x
119
+ else
120
+ return :y
121
+ end
122
+ end
123
+
124
+ # Extra extension that should be reserved for a label on the
125
+ # given side based on simple heuristics. Value is returned in
126
+ # text height units.
127
+ def label_extra_space(t)
128
+ case @base_location
129
+ when :bottom, :right
130
+ extra = 0.5 # To account for baseline ?
131
+ when :top, :left
132
+ extra = 1
133
+ else # We take the safe side !
134
+ extra = 1
135
+ end
136
+ if @shift
137
+ ## @todo Here add the shift
138
+ end
139
+ return extra
140
+ end
141
+
142
+ # Returns whether the location is on the given side.
143
+ def is_side?(which)
144
+ return @base_location == which
145
+ end
146
+
147
+ # Takes a set of margins, expressed in relative terms, ie
148
+ # * _close_ (the margins on the side next to the graph),
149
+ # * _away_ (on the other side),
150
+ # * _aleft_ (on the left going away from the graph) and
151
+ # * _aright_ (on the right going away from the graph)
152
+ # into a left,right,top,bottom suitable for standards margins calls.
153
+ def reorient_margins(close, away, aleft, aright)
154
+ a = [close, away, aleft, aright]
155
+ return LocationsReorientMargins[@base_location].map do |i|
156
+ a[i]
157
+ end
158
+ end
159
+
160
+ # Returns the margins argument suitable for sending to
161
+ # set_subframe to paint within the region defined by the given
162
+ # size at the given position.
163
+ #
164
+ # _size_ is a Dimension object.
165
+ def frame_margins_for_size(t, size)
166
+ margins = Dobjects::Dvector[*LocationBaseMargins[@base_location]]
167
+ ## @todo handle the case of at Y and at X
168
+ dim = size.to_frame(t, orientation)
169
+
170
+ add = Dobjects::Dvector[*LocationMarginMultiplier[@base_location]]
171
+ add.mul!(dim)
172
+ margins += add
173
+ return margins
174
+ end
175
+
176
+ def do_sub_frame(t, size)
177
+ margins = frame_margins_for_size(t, size)
178
+
179
+ ## @todo This is should integrate some common class.
180
+ left = t.convert_frame_to_page_x(margins[0])
181
+ right = t.convert_frame_to_page_x(1 - margins[1])
182
+ top = t.convert_frame_to_page_y(1 - margins[2])
183
+ bottom = t.convert_frame_to_page_y(margins[3])
184
+
185
+ # Ensure that we don't have coords outside of the page range
186
+ # because of rounding problems:
187
+ left = 0.0 if left < 0
188
+ bottom = 0.0 if bottom < 0
189
+ right = 1.0 if right > 1
190
+ top = 1.0 if top > 1
191
+
192
+ t.context do
193
+ t.set_frame_sides(left, right, top, bottom)
194
+ yield
195
+ end
196
+ end
197
+
198
+ # Creates a location from the given text
199
+ #
200
+ # So far, no real parsing
201
+ def self.from_text(str)
202
+ str.gsub!(/-/,"_")
203
+ return PlotLocation.new(str.to_sym)
204
+ end
205
+
206
+
207
+ end
208
+
209
+ # Something meant to be fed to PlotStyle#get_axis_style
210
+ LocationType = CmdType.new('location', { :type => :function_based,
211
+ :class => Graphics::Types::PlotLocation
212
+ }, <<EOD)
213
+ A position on the plot, referenced with respect to the sides. Can be:
214
+ * @left@
215
+ * @right@
216
+ * @top@
217
+ * @bottom@
218
+
219
+ In addition, there will one day be the possibility to specify an
220
+ offset from these locations. But that is still something to do.
221
+ EOD
222
+
223
+
224
+
225
+ end
226
+ end
227
+ end
228
+