metapost-erb 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.
data/README ADDED
@@ -0,0 +1,15 @@
1
+ = Metapost-erb
2
+
3
+ A simple tool to turn erb templates into metapost files, run the metapost, and open the resulting files in Preview.
4
+
5
+ Also includes some support libraries to help make drawing grids and charts easier.
6
+
7
+ NB: when I say easier, I mean easier given I know ruby much better than I know metapost. There are probably elegant ways of doing this stuff in metapost itself.
8
+
9
+ Usage:
10
+ metapost-erb filenameoferb.erb
11
+
12
+
13
+ This software is (c) 2010 Green on Black Ltd and distributed under the open source MIT [http://www.opensource.org/licenses/mit-license.php] licence. (See LICENCE for the wording).
14
+
15
+
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'erb'
4
+ require_relative '../lib/metapost-erb'
5
+
6
+ metapost_command = 'mpost'
7
+
8
+ puts "Loading template '#{ARGV[0]}'"
9
+ template = IO.readlines(ARGV[0]).join
10
+
11
+ template_directory = File.dirname(File.expand_path(ARGV[0]))
12
+
13
+ support_library = File.basename(ARGV[0],'.*')
14
+ support_module = support_library.split(/[^a-zA-Z0-9]/).map { |w| w.capitalize }.join
15
+ metapost_name = ARGV[1] || (File.basename(ARGV[0],'.*') + '.mp')
16
+ log_file_name = (File.basename(ARGV[1] || ARGV[0],'.*') + '.log')
17
+
18
+ begin
19
+ puts "Trying to load supporting library #{support_library} with module #{support_module} "
20
+ require File.join(template_directory,support_library)
21
+ include eval(support_module)
22
+ rescue LoadError => e
23
+ puts e
24
+ puts "No support library #{support_library} found"
25
+ end
26
+
27
+ puts "Compiling template"
28
+ erb = ERB.new(template)
29
+ metapost = erb.result(binding)
30
+
31
+ puts "Writing metapost to #{metapost_name}"
32
+ File.open(metapost_name,'w') do |f|
33
+ puts metapost
34
+ f.puts metapost
35
+ end
36
+
37
+ puts "Running metapost"
38
+ puts `#{metapost_command} -interaction=nonstopmode #{metapost_name}`
39
+
40
+ puts "Opening files"
41
+ logfile = IO.readlines(log_file_name).join
42
+ logfile[/files? written:(.*)/m,1].split(/.. /).map(&:strip).each do |output|
43
+ `open #{output}`
44
+ end
@@ -0,0 +1,99 @@
1
+ % Estimates of terrestrial carbon stocks from IPCC TAR 3 ("The Carbon Cycle and Atmospheric Carbon Dioxide") Table 3.2
2
+ <%= credits %>
3
+ <%
4
+ x_axis_unit_label = "btex Area $10^9$ ha etex"
5
+ x_axis_range = (0..15)
6
+ x_minor_grid_step = 1
7
+ x_major_grid_step = 5
8
+
9
+ case y_units = ARGV[1] || 'ktCO2e'
10
+ when 'ktCO2e'
11
+ y_axis_unit_label = "btex Carbon density (ktCO$_{2}$e/ha) etex"
12
+ y_axis_range = (0..3)
13
+ y_minor_grid_step = 0.1
14
+ y_major_grid_step = 1
15
+ y_axis_conversion = lambda { |c| c * (44.0/12.0)/1000.0 }
16
+ comparison_label = "100 GtCO$_{2}$e (c. 2 years of man-made emissions)"
17
+ when 'tC'
18
+ y_axis_unit_label = "btex Carbon density (tC/ha) etex"
19
+ y_axis_range = (0..800)
20
+ y_minor_grid_step = 10
21
+ y_major_grid_step = 100
22
+ y_axis_conversion = lambda { |c| c } # No conversion
23
+ comparison_label = "10 GtC (c. 1 year of man-made emissions)"
24
+ end
25
+ %>
26
+
27
+ input boxes
28
+ input TEX
29
+ prologues:=3;
30
+ outputtemplate := "%j-%3c.eps";
31
+ beginfig(1);
32
+
33
+ % Define the scaling and axes
34
+ chart_width := 10 cm;
35
+ chart_height := 10cm;
36
+ xunit := (chart_width / <%= x_axis_range.max %>);
37
+ yunit := (chart_height / <%= y_axis_range.max %> );
38
+
39
+ % Define colours
40
+ % Grid
41
+ color minor_grid_color; minor_grid_color = 0.95 white;
42
+ color major_grid_color; major_grid_color = 0.85 white;
43
+ color grid_label_color; grid_label_color = black;
44
+
45
+ % Stacks
46
+ color outer_box_color; outer_box_color = 0.3 white;
47
+ color soil_color; soil_color = (1,0.5,0.1);
48
+ color plant_color; plant_color = (0,1.0,0);
49
+ color soil_label_color; soil_label_color = soil_color * 0.9;
50
+ color plant_label_color; plant_label_color = plant_color * 0.5;
51
+
52
+ % Comparator
53
+ color comparator_box_color; comparator_box_color = black;
54
+
55
+ % Draw the grid lines
56
+ <%= grid_lines x_axis_range.step(x_minor_grid_step), y_axis_range.step(y_minor_grid_step), 'minor_grid_color' %>
57
+ <%= grid_lines x_axis_range.step(x_major_grid_step), y_axis_range.step(y_major_grid_step), 'major_grid_color' %>
58
+
59
+ % Draw the grid labels
60
+ <%= grid_labels x_axis_range.step(x_major_grid_step), y_axis_range.step(y_major_grid_step), 'grid_label_color' %>
61
+
62
+ % Draw the axes labels
63
+ label.llft( <%= x_axis_unit_label %>, (<%= x_axis_range.max %> xunit,-0.5cm) );
64
+ label.llft( <%= y_axis_unit_label %> rotated 90, (-0.75cm, <%= y_axis_range.max %> yunit) );
65
+
66
+ % Draw the stacks
67
+ <%=
68
+ chart ['soil_color','plant_color'] do
69
+ stack 'Wetlands' ,0.35 ,[ 643,43 ].map(&y_axis_conversion)
70
+ stack 'Boreal forests' ,1.37 ,[ 344,64 ].map(&y_axis_conversion)
71
+ stack 'Tropical forests' ,1.76 ,[ 123,120].map(&y_axis_conversion)
72
+ stack 'Temperate grasslands \& shrublands' ,1.25 ,[ 236,7 ].map(&y_axis_conversion)
73
+ stack 'Temperate forests' ,1.04 ,[ 96 ,57 ].map(&y_axis_conversion)
74
+ stack 'Tropical savannas \& grasslands' ,2.25 ,[ 117,29 ].map(&y_axis_conversion)
75
+ stack 'Tundra' ,0.95 ,[ 127,6 ].map(&y_axis_conversion)
76
+ stack 'Croplands' ,1.60 ,[ 80 ,2 ].map(&y_axis_conversion)
77
+ stack 'Deserts and semi deserts' ,4.55 ,[ 42 ,2 ].map(&y_axis_conversion)
78
+
79
+ stacks.each do |stack_name,boxes|
80
+ box_draw "draw #{boxes.first}.sw--#{boxes.last}.nw--#{boxes.last}.ne--#{boxes.first}.se--cycle withcolor outer_box_color"
81
+ label_box boxes.last, stack_name, :n, 'outer_box_color'
82
+ end
83
+
84
+ label_box stacks['Deserts and semi deserts'].first, "in first 1m of soil", :e, 'soil_label_color'
85
+ label_box stacks['Deserts and semi deserts'].last, "in plants", :e, 'plant_label_color'
86
+ end
87
+ %>
88
+
89
+ % Comparison
90
+ boxit.comparator();
91
+ comparator.sw = (<%= x_axis_range.max-x_minor_grid_step %> xunit, <%= y_axis_range.max-y_minor_grid_step %> yunit);
92
+ comparator.ne = (<%= x_axis_range.max %> xunit, <%= y_axis_range.max %> yunit);
93
+ draw bpath(comparator) withcolor comparator_box_color;
94
+ fill bpath(comparator) withcolor 0.9*white+0.1*comparator_box_color;
95
+ <%= label_box 'comparator', comparison_label, :e %>
96
+
97
+ endfig;
98
+
99
+ end;
@@ -0,0 +1,9 @@
1
+ module TerrestrialCarbonStocks
2
+ include MetaPost
3
+ include Grid
4
+ include Stacks
5
+
6
+ def credits
7
+ "% This image was created by Tom Counsell, with improvements by David MacKay, based on underlying data from the IPCC"
8
+ end
9
+ end
@@ -0,0 +1,156 @@
1
+ module MetaPost
2
+ module Standard
3
+
4
+ def layers
5
+ @layers ||= []
6
+ end
7
+
8
+ def draw_on_layer(layer,*strings)
9
+ layers[layer] ||= []
10
+ layers[layer] << strings.flatten.join
11
+ end
12
+
13
+ def write!
14
+ result = layers.flatten.join(";\n ") + ";\n "
15
+ layers.clear
16
+ result
17
+ end
18
+
19
+ def x(value)
20
+ "#{value} xunit"
21
+ end
22
+
23
+ def y(value)
24
+ "#{value} yunit"
25
+ end
26
+
27
+ def labels
28
+ @labels ||= []
29
+ end
30
+
31
+ def draw_labels
32
+ labels.join(";\n")+";\n"
33
+ end
34
+
35
+ def v(*names)
36
+ name = names.join
37
+ @variables ||= {}
38
+ return @variables[name] if @variables.has_key?(name)
39
+ variable_name = name.gsub(/[^a-zA-Z0-9]/,'')
40
+ variable_name.succ! while @variables.has_value?(variable_name)
41
+ @variables[name] = variable_name
42
+ variable_name
43
+ end
44
+ end
45
+
46
+
47
+ module Grid
48
+ include Standard
49
+
50
+ def grid_lines(x_values,y_values = x_values,colour = 'grid')
51
+ x_values = x_values.to_a
52
+ y_values = y_values.to_a
53
+ x_min, x_max = x_values.min, x_values.max
54
+ y_min, y_max = y_values.min, y_values.max
55
+
56
+ x_values.each do |x_value|
57
+ grid_line "draw (#{x x_value}, #{y y_min})--(#{x x_value}, #{y y_max}) withcolor #{colour}"
58
+ end
59
+
60
+ y_values.each do |y_value|
61
+ grid_line "draw (#{x x_min}, #{y y_value})--(#{x x_max}, #{y y_value}) withcolor #{colour}"
62
+ end
63
+
64
+ write!
65
+ end
66
+
67
+ def grid_labels(x_values,y_values = nil,colour = 'black')
68
+ if x_values
69
+ x_values.each do |x_value|
70
+ grid_label "label.bot(btex #{x_value} etex, (#{x x_value},0)) withcolor #{colour}"
71
+ end
72
+ end
73
+
74
+ if y_values
75
+ y_values.each do |y_value|
76
+ grid_label "label.lft(btex #{y_value} etex, (0,#{y y_value})) withcolor #{colour}"
77
+ end
78
+ end
79
+
80
+ write!
81
+ end
82
+
83
+ def grid_line(string)
84
+ draw_on_layer 0, string
85
+ end
86
+
87
+ def grid_label(string)
88
+ draw_on_layer 1, string
89
+ end
90
+ end
91
+
92
+ module Stacks
93
+ include Standard
94
+ attr_accessor :default_stack_colours
95
+ attr_accessor :stacks
96
+ attr_accessor :stack_sw_x
97
+
98
+ def stack(stack_name, width, heights, pen_color = self.default_stack_colours, fill_color = nil)
99
+ self.stacks ||= {}
100
+ self.stacks[stack_name] = []
101
+ self.stack_sw_x ||= 0
102
+ heights = [heights] unless heights.is_a?(Array)
103
+ pen_color = Array.new(heights.size,pen_color) unless pen_color.is_a?(Array)
104
+ fill_color = pen_color.map { |pen| "0.75*white+0.25*(#{pen})" } unless fill_color
105
+ fill_color = Array.new(heights.size,fill_color) unless fill_color.is_a?(Array)
106
+ result = []
107
+ height = 0
108
+ heights.each.with_index do |box_height,i|
109
+ self.stacks[stack_name] << box_name = "#{v(stack_name)}[#{i}]"
110
+ box_definition "boxit.#{box_name}()"
111
+ box_position "#{box_name}.sw = (#{x @stack_sw_x}, #{y height})"
112
+ box_position "#{box_name}.ne = (#{x(@stack_sw_x + width)}, #{y height + box_height})"
113
+ height = height + box_height
114
+ box_draw "fill bpath(#{box_name}) withcolor #{fill_color[i]}"
115
+ box_draw "draw bpath(#{box_name}) withcolor #{pen_color[i]}"
116
+ end
117
+ self.stack_sw_x = self.stack_sw_x + width
118
+ end
119
+
120
+ def chart(default_stack_colours, &block)
121
+ self.stacks = nil
122
+ self.stack_sw_x = nil
123
+ self.default_stack_colours = default_stack_colours
124
+ block.call
125
+ write!
126
+ end
127
+
128
+ def label_box(box_name,text,corner = :n, colour = "black", rotation = nil, offset = nil, label_position = nil)
129
+ rotation ||= {'ne' => '45', 'n' => '45'}[corner.to_s]
130
+ offset ||= {'ne' => "(0.5 cm, 0.5 cm)", 'n' => "(0.5 cm,0.5 cm)", 'e' => "(0.5 cm, 0 cm)"}[corner.to_s]
131
+ label_position ||= {'ne' => 'urt', 'e' => 'rt', 'n' => 'urt' }[corner.to_s]
132
+
133
+ anchor = "#{box_name}.#{corner}"
134
+ box_label arrow = "draw (#{anchor} shifted #{offset})..(#{anchor} shifted (#{offset}/10)) withcolor #{colour}"
135
+ box_label text = "label.#{label_position}( btex #{text} etex #{rotation && "rotated #{rotation}"}, (#{anchor} shifted #{offset}) ) withcolor #{colour}"
136
+ arrow + ";\n" + text + ";\n"
137
+ end
138
+
139
+ def box_definition(string)
140
+ draw_on_layer 0, string
141
+ end
142
+
143
+ def box_position(string)
144
+ draw_on_layer 1, string
145
+ end
146
+
147
+ def box_draw(string)
148
+ draw_on_layer 2, string
149
+ end
150
+
151
+ def box_label(string)
152
+ draw_on_layer 3, string
153
+ end
154
+
155
+ end
156
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metapost-erb
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Thomas Counsell, Green on Black Ltd
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-08-13 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description:
22
+ email: metapost-erb@greenonblack.com
23
+ executables:
24
+ - metapost-erb
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - README
31
+ - lib/metapost-erb.rb
32
+ - bin/metapost-erb
33
+ - examples/terrestrial-carbon-stocks.erb
34
+ - examples/terrestrial-carbon-stocks.rb
35
+ has_rdoc: true
36
+ homepage: http://github.com/tamc/metapost-erb
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ segments:
49
+ - 1
50
+ - 9
51
+ - 1
52
+ version: 1.9.1
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.6
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Helps to programatically create metapost files, making use of erb templates
67
+ test_files: []
68
+