Cleaned up metapost code

This commit is contained in:
Yann Esposito (Yogsototh) 2012-10-20 11:00:56 +02:00
parent 132b19b88e
commit 21b515c5c6
2 changed files with 228 additions and 206 deletions

196
lib/graph.mp Normal file
View file

@ -0,0 +1,196 @@
% solarized color scheme
color baseZeroThree, baseZeroTwo, baseZeroOne, baseZeroZero
, baseZero, baseOne, baseTwo, baseThree, yellow, orange
, red, magenta, violet, blue, cyan, green;
baseZeroThree :=(0.0 ,0.168627450980392,0.211764705882353);
baseZeroTwo :=(0.0274509803921569,0.211764705882353,0.258823529411765);
baseZeroOne :=(0.345098039215686 ,0.431372549019608,0.458823529411765);
baseZeroZero :=(0.396078431372549 ,0.482352941176471,0.513725490196078);
baseZero :=(0.513725490196078 ,0.580392156862745,0.588235294117647);
baseOne :=(0.576470588235294 ,0.631372549019608,0.631372549019608);
baseTwo :=(0.933333333333333 ,0.909803921568627,0.835294117647059);
baseThree :=(0.992156862745098 ,0.964705882352941,0.890196078431372);
yellow :=(0.709803921568627 ,0.537254901960784,0.0);
orange :=(0.796078431372549 ,0.294117647058824,0.0862745098039216);
red :=(0.862745098039216 ,0.196078431372549,0.184313725490196);
magenta :=(0.827450980392157 ,0.211764705882353,0.509803921568627);
violet :=(0.423529411764706 ,0.443137254901961,0.768627450980392);
blue :=(0.149019607843137 ,0.545098039215686,0.823529411764706);
cyan :=(0.164705882352941 ,0.631372549019608,0.596078431372549);
green :=(0.52156862745098 ,0.6 ,0.0);
vardef shorten(expr p,d) =
path q,bcirc,ecirc;
bcirc := fullcircle scaled d shifted point 0 of p;
ecirc := fullcircle scaled d shifted point length(p) of p;
q := p cutbefore bcirc cutafter ecirc;
q
enddef;
%%%%%%%%%%%%%%%%%%%%
% Automata drawing %
%%%%%%%%%%%%%%%%%%%%
u:=.5cm; % unity
gu:=5u; % distance between states
% -- Generic private functions
% return the edge between points A and B.
% out angle from A is inan
% in angle to B is outan
% nodesize is the size of the node
vardef _edgeFullParam(expr posA,posB,inan,outan,nodesize) =
path sub;
if (posA = posB):
pair ba,ea,b;
path circ,p;
b :=posA shifted (0,nodesize);
p:=posA{1,1}..b..{1,-1}cycle;
circ:= fullcircle scaled nodesize shifted posA;
ba = circ intersectionpoint (subpath (0,1) of p);
ea = circ intersectionpoint (subpath (1,2) of p);
sub:= ba{1,1}..b..{1,-1}ea;
else:
path s; s := posA {dir inan} .. {dir outan} posB ;
pair bA;
pair bA; bA = (fullcircle scaled nodesize shifted posA) intersectionpoint s;
pair eB; eB = (fullcircle scaled nodesize shifted posB) intersectionpoint s;
sub := bA {dir inan} .. {dir outan} eB ;
fi
sub
enddef;
% return a picture of the label l for edge e
vardef _edgelabel(expr e,l) =
picture ret;
pair mid;
mid := point 1/2length(e) of e;
numeric an;
an := angle (direction 1/2length(e) of e);
picture lab;
pair height,width;
lab:=thelabel(l,origin);
height:=(0,ypart (ulcorner l - llcorner l));
width:=(ypart (urcorner l - ulcorner l),0);
if (an>-35) and (an<35):
ret:=lab shifted height rotated an shifted mid;
elseif (an>145) or (an<-145):
ret:=thelabel(l,origin) shifted height rotated (an+180) shifted mid;
elseif (an>75) and (an<120):
ret:=lab shifted mid shifted -width;
elseif (an>-120) and (an<-75):
ret:=lab shifted mid shifted width;
else:
ret:=lab shifted mid shifted height;
fi;
ret
enddef;
% draw an edge
def _drawEdgeFullParam(expr posA,posB,l,inan,outan,nodesize) =
path sub;
picture lab;
sub := _edgeFullParam(posA,posB,inan,outan,nodesize);
drawarrow sub;
draw _edgelabel(sub,l);
enddef;
% --- LABELED GRAPHS ---
% return the edge between points A and B.
% out angle from A is inan
vardef edgeAngle(expr posA,posB,an) =
path sub;
sub := _edgeFullParam(posA,posB,an,-an,1.2u);
sub
enddef;
% return the direct edge between A and B
vardef edge(expr posA,posB) =
numeric an;
an := angle(posB-posA);
path sub;
sub := _edgeFullParam(posA,posB,an,an,1.2u);
sub
enddef;
% --- UNLABELED GRAPHS ---
% return the edge between points A and B.
% out angle from A is inan
vardef nl_edgeAngle(expr posA,posB,an) =
path sub;
sub := _edgeFullParam(posA,posB,an,-an,6);
sub
enddef;
% return the direct edge between A and B
vardef nl_edge(expr posA,posB) =
numeric an;
an := angle(posB-posA);
path sub;
sub := _edgeFullParam(posA,posB,an,an,6);
sub
enddef;
def drawloop(expr a,b,l) =
pair ba,ea;
path circ,p,s;
p:=a{1,1}..b..{1,-1}cycle;
circ:= fullcircle scaled 6 shifted a;
ba = circ intersectionpoint (subpath (0,1) of p);
ea = circ intersectionpoint (subpath (1,2) of p);
s:= ba{1,1}..b..{1,-1}ea;
drawarrow s;
label.top(l,b);
enddef;
def drawLoop(expr a,l) =
pair b; b:=a shifted (0,u);
pair ba,ea;
path circ,p,s;
p:=a{1,1}..b..{1,-1}cycle;
circ:= fullcircle scaled 1.2u shifted a;
ba = circ intersectionpoint (subpath (0,1) of p);
ea = circ intersectionpoint (subpath (1,2) of p);
s:= ba{1,1}..b..{1,-1}ea;
drawarrow s;
label.top(l,b);
enddef;
def drawstate(expr pos) =
draw pos withpen pencircle scaled 4bp;
enddef;
def drawedgeWithDoubleAngle(expr posA,posB,l,inan,outan) =
_drawEdgeFullParam(posA,posB,l,inan,outan,6);
enddef;
def drawedgeangle(expr posA,posB,l,an) =
_drawEdgeFullParam(posA,posB,l,an,-an,6);
enddef;
def drawedge(expr posA,posB,l) =
numeric an;
an=angle(posB-posA);
_drawEdgeFullParam(posA,posB,l,an,an,6);
enddef;
def drawState(expr pos,l) =
label(l,pos);
draw fullcircle scaled u shifted pos;
enddef;
def drawEdgeWithDoubleAngle(expr posA,posB,l,inan,outan) =
_drawEdgeFullParam(posA,posB,l,inan,outan,1.2u);
enddef;
def drawEdgeWithAngle(expr posA,posB,l,an) =
drawEdgeWithDoubleAngle(posA,posB,l,an,-an);
enddef;
def drawEdge(expr posA,posB,l) =
numeric an;
if (posA = posB):
an := 0;
else:
an=angle(posB-posA);
fi
drawEdgeWithDoubleAngle(posA,posB,l,an,an);
enddef;
prologues:=3;

View file

@ -20,221 +20,47 @@ class MPost < Nanoc3::Filter
title=$2
str=$3
filename=title.gsub(/[^a-zA-Z0-9_]/,"_")
code=%{
% solarized color scheme
color baseZeroThree, baseZeroTwo, baseZeroOne, baseZeroZero
, baseZero, baseOne, baseTwo, baseThree, yellow, orange
, red, magenta, violet, blue, cyan, green;
baseZeroThree :=(0.0 ,0.168627450980392,0.211764705882353);
baseZeroTwo :=(0.0274509803921569,0.211764705882353,0.258823529411765);
baseZeroOne :=(0.345098039215686 ,0.431372549019608,0.458823529411765);
baseZeroZero :=(0.396078431372549 ,0.482352941176471,0.513725490196078);
baseZero :=(0.513725490196078 ,0.580392156862745,0.588235294117647);
baseOne :=(0.576470588235294 ,0.631372549019608,0.631372549019608);
baseTwo :=(0.933333333333333 ,0.909803921568627,0.835294117647059);
baseThree :=(0.992156862745098 ,0.964705882352941,0.890196078431372);
yellow :=(0.709803921568627 ,0.537254901960784,0.0);
orange :=(0.796078431372549 ,0.294117647058824,0.0862745098039216);
red :=(0.862745098039216 ,0.196078431372549,0.184313725490196);
magenta :=(0.827450980392157 ,0.211764705882353,0.509803921568627);
violet :=(0.423529411764706 ,0.443137254901961,0.768627450980392);
blue :=(0.149019607843137 ,0.545098039215686,0.823529411764706);
cyan :=(0.164705882352941 ,0.631372549019608,0.596078431372549);
green :=(0.52156862745098 ,0.6 ,0.0);
# write the mp file using the code
code=File.read('lib/graph.mp')
code<<=%{beginfig(1)
drawoptions (withcolor base01);}
code <<= str
code <<= %{\nendfig;\nbye;\n}
vardef shorten(expr p,d) =
path q,bcirc,ecirc;
bcirc := fullcircle scaled d shifted point 0 of p;
ecirc := fullcircle scaled d shifted point length(p) of p;
q := p cutbefore bcirc cutafter ecirc;
q
enddef;
%%%%%%%%%%%%%%%%%%%%
% Automata drawing %
%%%%%%%%%%%%%%%%%%%%
u:=.5cm; % unity
gu:=5u; % distance between states
% -- Generic private functions
% return the edge between points A and B.
% out angle from A is inan
% in angle to B is outan
% nodesize is the size of the node
vardef _edgeFullParam(expr posA,posB,inan,outan,nodesize) =
path sub;
if (posA = posB):
pair ba,ea,b;
path circ,p;
b :=posA shifted (0,nodesize);
p:=posA{1,1}..b..{1,-1}cycle;
circ:= fullcircle scaled nodesize shifted posA;
ba = circ intersectionpoint (subpath (0,1) of p);
ea = circ intersectionpoint (subpath (1,2) of p);
sub:= ba{1,1}..b..{1,-1}ea;
else:
path s; s := posA {dir inan} .. {dir outan} posB ;
pair bA;
pair bA; bA = (fullcircle scaled nodesize shifted posA) intersectionpoint s;
pair eB; eB = (fullcircle scaled nodesize shifted posB) intersectionpoint s;
sub := bA {dir inan} .. {dir outan} eB ;
fi
sub
enddef;
% return a picture of the label l for edge e
vardef _edgelabel(expr e,l) =
picture ret;
pair mid;
mid := point 1/2length(e) of e;
numeric an;
an := angle (direction 1/2length(e) of e);
picture lab;
pair height,width;
lab:=thelabel(l,origin);
height:=(0,ypart (ulcorner l - llcorner l));
width:=(ypart (urcorner l - ulcorner l),0);
if (an>-35) and (an<35):
ret:=lab shifted height rotated an shifted mid;
elseif (an>145) or (an<-145):
ret:=thelabel(l,origin) shifted height rotated (an+180) shifted mid;
elseif (an>75) and (an<120):
ret:=lab shifted mid shifted -width;
elseif (an>-120) and (an<-75):
ret:=lab shifted mid shifted width;
else:
ret:=lab shifted mid shifted height;
fi;
ret
enddef;
% draw an edge
def _drawEdgeFullParam(expr posA,posB,l,inan,outan,nodesize) =
path sub;
picture lab;
sub := _edgeFullParam(posA,posB,inan,outan,nodesize);
drawarrow sub;
draw _edgelabel(sub,l);
enddef;
% --- LABELED GRAPHS ---
% return the edge between points A and B.
% out angle from A is inan
vardef edgeAngle(expr posA,posB,an) =
path sub;
sub := _edgeFullParam(posA,posB,an,-an,1.2u);
sub
enddef;
% return the direct edge between A and B
vardef edge(expr posA,posB) =
numeric an;
an := angle(posB-posA);
path sub;
sub := _edgeFullParam(posA,posB,an,an,1.2u);
sub
enddef;
% --- UNLABELED GRAPHS ---
% return the edge between points A and B.
% out angle from A is inan
vardef nl_edgeAngle(expr posA,posB,an) =
path sub;
sub := _edgeFullParam(posA,posB,an,-an,6);
sub
enddef;
% return the direct edge between A and B
vardef nl_edge(expr posA,posB) =
numeric an;
an := angle(posB-posA);
path sub;
sub := _edgeFullParam(posA,posB,an,an,6);
sub
enddef;
def drawloop(expr a,b,l) =
pair ba,ea;
path circ,p,s;
p:=a{1,1}..b..{1,-1}cycle;
circ:= fullcircle scaled 6 shifted a;
ba = circ intersectionpoint (subpath (0,1) of p);
ea = circ intersectionpoint (subpath (1,2) of p);
s:= ba{1,1}..b..{1,-1}ea;
drawarrow s;
label.top(l,b);
enddef;
def drawLoop(expr a,l) =
pair b; b:=a shifted (0,u);
pair ba,ea;
path circ,p,s;
p:=a{1,1}..b..{1,-1}cycle;
circ:= fullcircle scaled 1.2u shifted a;
ba = circ intersectionpoint (subpath (0,1) of p);
ea = circ intersectionpoint (subpath (1,2) of p);
s:= ba{1,1}..b..{1,-1}ea;
drawarrow s;
label.top(l,b);
enddef;
def drawstate(expr pos) =
draw pos withpen pencircle scaled 4bp;
enddef;
def drawedgeWithDoubleAngle(expr posA,posB,l,inan,outan) =
_drawEdgeFullParam(posA,posB,l,inan,outan,6);
enddef;
def drawedgeangle(expr posA,posB,l,an) =
_drawEdgeFullParam(posA,posB,l,an,-an,6);
enddef;
def drawedge(expr posA,posB,l) =
numeric an;
an=angle(posB-posA);
_drawEdgeFullParam(posA,posB,l,an,an,6);
enddef;
def drawState(expr pos,l) =
label(l,pos);
draw fullcircle scaled u shifted pos;
enddef;
def drawEdgeWithDoubleAngle(expr posA,posB,l,inan,outan) =
_drawEdgeFullParam(posA,posB,l,inan,outan,1.2u);
enddef;
def drawEdgeWithAngle(expr posA,posB,l,an) =
drawEdgeWithDoubleAngle(posA,posB,l,an,-an);
enddef;
def drawEdge(expr posA,posB,l) =
numeric an;
if (posA = posB):
an := 0;
else:
an=angle(posB-posA);
fi
drawEdgeWithDoubleAngle(posA,posB,l,an,an);
enddef;
prologues:=3;
beginfig(1)
drawoptions (withcolor base01);\n}
code <<= str
code <<= %{\nendfig;\nbye;\n}
# create the directory to compile metapost files
FileUtils.mkdir_p(@@tmp)
# write the code into a temporary file
File.open(@@tmp+filename+'.mp','w') do |f|
f.write solarized(code)
end
webpath=@item.path + 'mpost/' + filename + '.png'
if not (File.exists?(@@tmp+filename+'.old') and FileUtils.compare_file(@@tmp+filename+'.mp',@@tmp+filename+'.old'))
# write the URL of the image
imgurl=@item.path + 'mpost/' + filename + '.png'
# We compile only if the source changed
if not (File.exists?(@@tmp+filename+'.old') and
FileUtils.cmp(@@tmp+filename+'.mp', @@tmp+filename+'.old'))
then
FileUtils.mkdir_p('output'+@item.path+'mpost')
path='output'+webpath
cmd="cd #{@@tmp} && mpost #{filename}.mp >/dev/null 2>&1 && convert -density 180 #{filename}.1 $OLDPWD/#{path} >/dev/null"
print %{\t[mpost] updating: #{filename}}
fspath=FileUtils.pwd+'/output'+imgurl
# create the directory for the output file
FileUtils.mkdir_p(File.dirname(fspath))
# Launch the metapost compilation and update
# the cache in case of success
cmd="cd #{@@tmp} && mpost #{filename}.mp >/dev/null 2>&1 && convert -density 180 #{filename}.1 #{fspath} >/dev/null"
if system(cmd)
FileUtils.copy(@@tmp+filename+'.mp',@@tmp+filename+'.old')
if FileUtils.copy(@@tmp+filename+'.mp',@@tmp+filename+'.old')
puts " [SUCCESS]"
else
puts " [ERROR: couldn't copy]"
end
else
puts " [ERROR: compilation error; check #{@@tmp}#{filename}.log ]"
end
end
%{<figure><img alt="#{title}" src="#{webpath}"/><figcaption>#{title}</figcaption></figure>}
# replace the code by the image
%{<figure><img alt="#{title}" src="#{imgurl}"/><figcaption>#{title}</figcaption></figure>}
end
end
end