ctioga2 0.9 → 0.10

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 (41) hide show
  1. data/Changelog +27 -0
  2. data/bin/ct2-make-movie +92 -45
  3. data/lib/ctioga2/commands/doc/html.rb +1 -1
  4. data/lib/ctioga2/commands/doc/introspection.rb +52 -0
  5. data/lib/ctioga2/commands/doc/markup.rb +4 -0
  6. data/lib/ctioga2/commands/general-commands.rb +19 -0
  7. data/lib/ctioga2/commands/general-functions.rb +8 -1
  8. data/lib/ctioga2/commands/general-types.rb +14 -3
  9. data/lib/ctioga2/commands/parsers/file.rb +20 -3
  10. data/lib/ctioga2/data/backends/backends/math.rb +1 -1
  11. data/lib/ctioga2/data/backends/backends/text.rb +3 -3
  12. data/lib/ctioga2/data/point.rb +1 -1
  13. data/lib/ctioga2/graphics/elements.rb +1 -0
  14. data/lib/ctioga2/graphics/elements/curve2d.rb +5 -0
  15. data/lib/ctioga2/graphics/elements/primitive.rb +16 -14
  16. data/lib/ctioga2/graphics/elements/style-lists.rb +353 -0
  17. data/lib/ctioga2/graphics/elements/subplot.rb +17 -2
  18. data/lib/ctioga2/graphics/elements/tangent.rb +16 -17
  19. data/lib/ctioga2/graphics/styles.rb +1 -0
  20. data/lib/ctioga2/graphics/styles/axes.rb +63 -0
  21. data/lib/ctioga2/graphics/styles/base.rb +13 -0
  22. data/lib/ctioga2/graphics/styles/colorbrewer.rb +316 -0
  23. data/lib/ctioga2/graphics/styles/colormap.rb +47 -7
  24. data/lib/ctioga2/graphics/styles/image.rb +83 -0
  25. data/lib/ctioga2/graphics/styles/plot.rb +43 -7
  26. data/lib/ctioga2/graphics/styles/sets.rb +47 -5
  27. data/lib/ctioga2/graphics/styles/sheet.rb +18 -3
  28. data/lib/ctioga2/graphics/styles/texts.rb +49 -8
  29. data/lib/ctioga2/graphics/subplot-commands.rb +13 -13
  30. data/lib/ctioga2/graphics/types.rb +42 -10
  31. data/lib/ctioga2/graphics/types/boundaries.rb +3 -2
  32. data/lib/ctioga2/graphics/types/boxes.rb +13 -0
  33. data/lib/ctioga2/graphics/types/dimensions.rb +4 -1
  34. data/lib/ctioga2/graphics/types/location.rb +13 -2
  35. data/lib/ctioga2/graphics/types/point.rb +86 -0
  36. data/lib/ctioga2/metabuilder/types/styles.rb +2 -2
  37. data/lib/ctioga2/plotmaker.rb +3 -0
  38. data/lib/ctioga2/ruby.rb +49 -0
  39. data/lib/ctioga2/utils.rb +34 -0
  40. data/lib/ctioga2/version.rb +2 -2
  41. metadata +8 -4
@@ -49,17 +49,23 @@ module CTioga2
49
49
  # @todo These are currently not implemented.
50
50
  attr_accessor :below, :above
51
51
 
52
- # Whether the map follows RGB (true) or HLS (false). On by
53
- # default.
52
+ # Whether the map is interpolated in the RGB (true) or HLS
53
+ # (false) color space. On by default.
54
54
  #
55
55
  # It does not change anything with respect to how the colors
56
56
  # are interpreted: whatever happens, the values are RGB.
57
57
  attr_accessor :rgb
58
58
 
59
+ # Whether or not the map should be considered symmetric around
60
+ # a given value.
61
+ attr_accessor :symmetry_center
62
+
59
63
  def initialize(values = [], colors = [])
60
64
  @values = values.dup
61
65
  @colors = colors.dup
62
66
 
67
+ @symmetry_center = nil
68
+
63
69
  @rgb = true
64
70
  end
65
71
 
@@ -77,12 +83,33 @@ module CTioga2
77
83
  def self.from_text(str)
78
84
  str = str.dup
79
85
  hls = false
80
- re = /natural:?/i # Not too bad ?
86
+ re = /(natural|hls|wheel):?/i # Not too bad ?
81
87
  if str =~ re
82
88
  str.sub!(re,'')
83
89
  hls = true
84
90
  end
85
91
 
92
+ sym = nil
93
+
94
+ re = /:(?:sym|around):(.*)$/i
95
+ if str =~ re
96
+ sym = $1.to_f
97
+ str.sub!(re,'')
98
+ end
99
+
100
+ # We first try to see if it could be a color set ?
101
+ colorsettype = Commands::CommandType.get_type('color-set')
102
+
103
+ begin
104
+ set = colorsettype.string_to_type(str)
105
+ cm = ColorMap.new([nil] * set.size, set)
106
+ cm.rgb = ! hls
107
+ cm.symmetry_center = sym
108
+ return cm
109
+ rescue Exception => e
110
+ # This is not a color set
111
+ end
112
+
86
113
  l = str.split(/::/)
87
114
 
88
115
 
@@ -141,6 +168,7 @@ module CTioga2
141
168
  cm.above = above
142
169
  cm.below = below
143
170
  cm.rgb = ! hls
171
+ cm.symmetry_center = sym
144
172
  return cm
145
173
  end
146
174
 
@@ -241,6 +269,19 @@ module CTioga2
241
269
  def z_values(zmin, zmax)
242
270
  # Real Z values.
243
271
  z_values = @values.dup
272
+
273
+ # We tweak the zmin and zmax to be symmetric around the
274
+ # symmetry_center should that be needed.
275
+ if @symmetry_center
276
+ dmin = (zmin - @symmetry_center).abs
277
+ dmax = (zmax - @symmetry_center).abs
278
+
279
+ dfin = [dmin, dmax].max
280
+ zmin = @symmetry_center - dfin
281
+ zmax = @symmetry_center + dfin
282
+
283
+ end
284
+
244
285
  z_values[0] ||= zmin
245
286
  z_values[-1] ||= zmax
246
287
 
@@ -252,10 +293,9 @@ module CTioga2
252
293
  if z_values[i]
253
294
  if last_value + 1 < i
254
295
  (last_value+1).upto(i - 1) do |j|
255
- frac = (j - last_value)/(i - last_value + 1.0)
256
- # p [last_value, j, i, frac]
257
- z_values[j] = z_values[last_value] * frac +
258
- z_values[i] * (1 - frac)
296
+ frac = (j - last_value )/(i - last_value*1.0)
297
+ z_values[j] = z_values[last_value] * (1 - frac) +
298
+ z_values[i] * frac
259
299
  end
260
300
  end
261
301
  last_value = i
@@ -0,0 +1,83 @@
1
+ # image.rb: style of images
2
+ # copyright (c) 2014 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
+ # This module contains all the classes used by ctioga
18
+ module CTioga2
19
+
20
+ module Graphics
21
+
22
+ # All the styles
23
+ module Styles
24
+
25
+ AspectRatioRE = {
26
+ /ignore/i => :ignore,
27
+ /expand/i => :expand,
28
+ /contract/i => :contract,
29
+ }
30
+
31
+ AspectRatioType =
32
+ CmdType.new('aspect-ratio',
33
+ {:type => :re_list,
34
+ :list => AspectRatioRE}, <<EOD)
35
+ How the {command: draw-image} command respects the original image
36
+ aspect ratio:
37
+ * @ignore@ (the default) ignores the original aspect ratio
38
+ * @expand@ expand the original box to respect aspect ratio
39
+ * @contract@ contract the original box to respect aspect ratio
40
+ EOD
41
+
42
+
43
+
44
+ # This class represents the style for an image
45
+ class ImageStyle < BasicStyle
46
+ # The line style
47
+ typed_attribute :aspect_ratio, 'aspect-ratio'
48
+
49
+ # The line width
50
+ typed_attribute :transparency, 'float'
51
+
52
+ # Automatically rotate
53
+ typed_attribute :auto_rotate, 'boolean'
54
+
55
+ # Draws an image according to this
56
+ def draw_image(t, file, tl, br)
57
+ info = t.jpg_info(file)
58
+ if ! info
59
+ info = t.load_png(file)
60
+ end
61
+
62
+ r = Types::Rect.new(tl, br)
63
+ ul, ll, lr = r.make_corners(t, (@auto_rotate == nil ? true : @auto_rotate), @aspect_ratio || :ignore,
64
+ info['width']*1.0/info['height'])
65
+
66
+ dict = info.dup
67
+ dict.merge!('ul' => ul,
68
+ 'll' => ll,
69
+ 'lr' => lr,)
70
+
71
+ # @todo provide a way to reuse images ?
72
+ t.context do
73
+ if @transparency
74
+ t.fill_opacity = 1 - @transparency
75
+ end
76
+ t.show_image(dict)
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
@@ -79,6 +79,11 @@ module CTioga2
79
79
  # Mode for auto-adjust
80
80
  attr_accessor :text_auto_adjust
81
81
 
82
+ # If not nil, then the boundaries are computed from the real
83
+ # dimensions of the plot frame, using the given number as a
84
+ # conversion factor from the output dimensions.
85
+ attr_accessor :frame_real_size
86
+
82
87
 
83
88
  @@current_index = 0
84
89
 
@@ -108,7 +113,6 @@ module CTioga2
108
113
  StyleSheet.style_for(TextLabel, 'title',
109
114
  nil,
110
115
  Types::PlotLocation.new(:top))
111
-
112
116
  @plot_margin = nil
113
117
 
114
118
  @transforms = CoordinateTransforms.new
@@ -307,7 +311,7 @@ module CTioga2
307
311
  exts << @title.label_extension(t, 'title', @title.loc) *
308
312
  (@text_scale || 1)
309
313
  end
310
- Types::Dimension.new(:dy, exts.max)
314
+ Types::Dimension.new(:dy, exts.max || 0)
311
315
  end
312
316
 
313
317
  box = Types::MarginsBox.new(*margins)
@@ -319,6 +323,15 @@ module CTioga2
319
323
  return box
320
324
  end
321
325
 
326
+ # Clear all axes
327
+ def clear_axes()
328
+ [:left, :right, :top, :bottom].each do |loc|
329
+ style = get_axis_style(loc)
330
+ style.decoration = Tioga::FigureConstants::AXIS_HIDDEN
331
+ style.axis_label.text = false
332
+ end
333
+ end
334
+
322
335
  # Computes the margins based on the text information.
323
336
  #
324
337
  # This is very different from the one above, since this one
@@ -433,11 +446,7 @@ EOH
433
446
  ClearAxesCommand =
434
447
  Cmd.new("clear-axes",nil,"--clear-axes"
435
448
  ) do |plotmaker, opts|
436
- [:left, :right, :top, :bottom].each do |loc|
437
- style = AxisStyle.current_axis_style(plotmaker, loc)
438
- style.decoration = Tioga::FigureConstants::AXIS_HIDDEN
439
- style.axis_label.text = false
440
- end
449
+ PlotStyle.current_plot_style(plotmaker).clear_axes
441
450
  end
442
451
  ClearAxesCommand.
443
452
  describe("Clear all axes",
@@ -445,6 +454,33 @@ EOH
445
454
  Removes all the axes and their associated labels
446
455
  EOH
447
456
 
457
+ DrawingFrameCommand =
458
+ Cmd.new("drawing-frame",nil,"--drawing-frame", [],
459
+ { 'units' => CmdArg.new('text')
460
+ }) do |plotmaker, opts|
461
+ style = PlotStyle.current_plot_style(plotmaker)
462
+ style.clear_axes
463
+ style.padding = nil
464
+ u = opts['units'] || 'cm'
465
+ if u =~ /([\d.]+)?\s*(cm|in|bp|pt|mm)/
466
+ nb = $1 ? $1.to_f : 1.0
467
+ un = $2
468
+ style.frame_real_size = 10 * nb *
469
+ Types::Dimension::DimensionConversion.fetch(un)
470
+ else
471
+ raise 'Invalid unit'
472
+ end
473
+ end
474
+ DrawingFrameCommand.
475
+ describe("Setup a drawing frame",
476
+ <<"EOH", AxisGroup)
477
+ Setup a drawing frame, ie a frame in which the top-left point is at
478
+ 0,0, with X and Y values positive over the whole frame, and counted in
479
+ centimeters (or with the unit given using the @/units@ option, ie
480
+ @/units=mm@ expressed in millimeters or @/units=12pt@ expressed in
481
+ multiple of 12 TeX points).
482
+ EOH
483
+
448
484
 
449
485
  TicksCommand =
450
486
  Cmd.new("ticks",nil,"--ticks",
@@ -1,5 +1,5 @@
1
- # carrays.rb: 'circular arrays'
2
- # copyright (c) 2009 by Vincent Fourmond
1
+ # sets.rb: sets
2
+ # copyright (c) 2009, 2014 by Vincent Fourmond
3
3
 
4
4
  # This program is free software; you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -14,6 +14,8 @@
14
14
  require 'ctioga2/utils'
15
15
  require 'ctioga2/log'
16
16
 
17
+ require 'ctioga2/graphics/styles/colorbrewer'
18
+
17
19
  # This module contains all the classes used by ctioga
18
20
  module CTioga2
19
21
 
@@ -39,16 +41,56 @@ module CTioga2
39
41
  [LightPlum, PaleGreen, Gold, RedBrown, SkyBlue ],
40
42
  "gnuplot" =>
41
43
  [Red, [0,1.0,0], Blue, Magenta, Cyan, Yellow, Black, Coral, Gray],
42
-
43
44
  }
45
+
46
+ begin
47
+ t = Tioga::FigureMaker.new
48
+ lst = []
49
+ 10.times do |i|
50
+ lst << t.hls_to_rgb([36*i, 0.5, 1.0])
51
+ end
52
+ ColorSets['wheel10'] = lst
53
+
54
+ lst = []
55
+ 20.times do |i|
56
+ lst << t.hls_to_rgb([18*i, 0.5, 1.0])
57
+ end
58
+ ColorSets['wheel20'] = lst
59
+
60
+ colortype = Commands::CommandType.get_type('color')
61
+ for k,v in ColorBrewerSets
62
+ for n, a in v
63
+ if n > 4
64
+ ColorSets["cb-#{k.downcase}-#{n}"] = a.map do |c|
65
+ colortype.string_to_type(c)
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ end
44
72
 
45
73
  MarkerSets = {
46
74
  "default" =>
47
- [Bullet, TriangleUp, Square, Plus, Times],
75
+ [Bullet, TriangleUp, Square, Plus, Times, Diamond, TriangleDown],
48
76
  "open" =>
49
- [BulletOpen, TriangleUpOpen, SquareOpen, PlusOpen, TimesOpen],
77
+ [BulletOpen, TriangleUpOpen, SquareOpen, PlusOpen, TimesOpen,
78
+ DiamondOpen, TriangleDownOpen],
50
79
  }
51
80
 
81
+ for k, b in {
82
+ 'number1' => 171,
83
+ 'number2' => 181,
84
+ 'number3' => 191,
85
+ 'number4' => 201
86
+ }
87
+ lst = []
88
+ 1.upto(10) do |i|
89
+ lst << [14, b + i]
90
+ end
91
+ MarkerSets[k] = lst
92
+ end
93
+
52
94
  LineWidthSets = {
53
95
  'default' => [1.0]
54
96
  }
@@ -152,6 +152,15 @@ module CTioga2
152
152
  def self.current_sheet()
153
153
  return @sheet
154
154
  end
155
+
156
+
157
+ # Updates the style sheet concerning the _what_ of class _cls_
158
+ # with the given values
159
+ def self.update_style(cls, what, values)
160
+ StyleSheet.current_sheet.own_styles[cls] ||= {}
161
+ StyleSheet.current_sheet.own_styles[cls][what] ||= {}
162
+ StyleSheet.current_sheet.own_styles[cls][what].merge!(values)
163
+ end
155
164
 
156
165
  end
157
166
 
@@ -183,6 +192,7 @@ EOD
183
192
  ['marker', MarkerStringStyle, 'marker'],
184
193
  ['box', BoxStyle, 'boxes'],
185
194
  ['arrow', ArrowStyle, 'arrows'],
195
+ ['image', ImageStyle, 'image'],
186
196
  ['line', StrokeStyle, 'lines']
187
197
  ]
188
198
 
@@ -200,9 +210,7 @@ EOD
200
210
  ],
201
211
  cls.options_hash
202
212
  ) do |plotmaker, what, opts|
203
- StyleSheet.current_sheet.own_styles[cls] ||= {}
204
- StyleSheet.current_sheet.own_styles[cls][what] ||= {}
205
- StyleSheet.current_sheet.own_styles[cls][what].merge!(opts)
213
+ StyleSheet.update_style(cls, what, opts)
206
214
  end
207
215
  StyleSheetCommands[name].
208
216
  describe("Sets the default style for the given #{desc}.",
@@ -340,7 +348,14 @@ Axis styles have lots of parameters:
340
348
  * @background-lines-@ parameters define the style of background lines,
341
349
  as in {command: define-line-style}
342
350
  EOD
351
+
352
+
353
+ # Here, a few defaults styles
343
354
 
355
+ StyleSheet.update_style(TextLabel, 'title', {
356
+ 'text_width' =>
357
+ Types::Dimension.new(:frame, 1.0, :x)
358
+ })
344
359
  end
345
360
  end
346
361
  end
@@ -44,15 +44,23 @@ module CTioga2
44
44
  # The vertical alignment
45
45
  typed_attribute :alignment, 'alignment'
46
46
 
47
+ alias_for :valign, :alignment
48
+
47
49
  # The horizontal alignment
48
50
  typed_attribute :justification, 'justification'
49
51
 
52
+ alias_for :halign, :justification
53
+
50
54
  # A text width
51
- typed_attribute :text_width, "text"
55
+ typed_attribute :text_width, "dimension-or-no"
56
+
57
+ # A text alignment within the box, only useful if text_width
58
+ # is specified.
59
+ typed_attribute :text_align, 'text-align'
52
60
 
53
61
  # Draw the _text_ at the given location with the given style.
54
- # If _y_ is _nil_, then _x_or_loc_ is taken to be a location
55
- # (see FigureMaker#show_text).
62
+ # If _y_ is _nil_, or [:pos, _value_] then _x_or_loc_ is taken
63
+ # to be a location (see FigureMaker#show_text).
56
64
  def draw_text(t, text, x_or_loc, y = nil, measure = nil)
57
65
  t.context do
58
66
  dict = prepare_show_text_dict(t, text, x_or_loc, y, measure)
@@ -88,18 +96,24 @@ module CTioga2
88
96
  return dict
89
97
  end
90
98
 
99
+ def vertical?(loc)
100
+ if loc
101
+ return Types::PlotLocation.new(loc).vertical?
102
+ else
103
+ ang = angle || 0
104
+ return Math.sin(ang*3.14/180)**2 > 0.5
105
+ end
106
+ end
107
+
91
108
  protected
92
109
 
93
110
  # Prepares the dictionnary for use with show_text
94
111
  def prepare_show_text_dict(t, text, x_or_loc, y = nil, measure = nil)
95
112
  dict = self.hash_for_tioga(t)
96
- if @text_width
97
- text = "\\parbox{#{@text_width}}{#{text}}"
98
- end
99
113
 
100
- dict['text'] = text
114
+ loc = nil
101
115
 
102
- if y
116
+ if y && (! y.is_a?(Array))
103
117
  dict['at'] = [x_or_loc, y]
104
118
  else
105
119
  # Perform automatic conversion on the location
@@ -107,13 +121,40 @@ module CTioga2
107
121
  when Symbol, Types::PlotLocation
108
122
  ## @todo It won't be easy to implement shifts for this,
109
123
  ## though it may be useful eventually.
124
+ loc = x_or_loc
110
125
  x_or_loc = Types::PlotLocation.new(x_or_loc).tioga_location
111
126
  end
112
127
  dict['loc'] = x_or_loc
128
+ if y
129
+ dict['position'] = y[1]
130
+ end
113
131
  end
114
132
  if measure
115
133
  dict['measure'] = measure
116
134
  end
135
+
136
+ if @text_width
137
+ dir = (vertical?(loc) ? :y : :x)
138
+ dim = @text_width.to_bp(t, dir)
139
+ dim /= t.default_text_scale
140
+
141
+ aln = @text_align || @justification || Tioga::FigureConstants::CENTERED
142
+ cmd =
143
+ case aln
144
+ when Tioga::FigureConstants::CENTERED
145
+ '\centering{}'
146
+ when Tioga::FigureConstants::LEFT_JUSTIFIED
147
+ '\raggedright{}'
148
+ when Tioga::FigureConstants::RIGHT_JUSTIFIED
149
+ '\raggedleft{}'
150
+ else
151
+ ''
152
+ end
153
+ text = "\\parbox{#{dim}bp}{#{cmd}#{text}}"
154
+ end
155
+
156
+ dict['text'] = text
157
+
117
158
  return dict
118
159
  end
119
160
  end