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 +15 -0
- data/bin/metapost-erb +44 -0
- data/examples/terrestrial-carbon-stocks.erb +99 -0
- data/examples/terrestrial-carbon-stocks.rb +9 -0
- data/lib/metapost-erb.rb +156 -0
- metadata +68 -0
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
|
+
|
data/bin/metapost-erb
ADDED
@@ -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;
|
data/lib/metapost-erb.rb
ADDED
@@ -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
|
+
|