metapost-erb 0.0.1

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