diff options
Diffstat (limited to 'graphics/metapost/contrib/macros/mptrees/mptrees.mp')
-rw-r--r-- | graphics/metapost/contrib/macros/mptrees/mptrees.mp | 844 |
1 files changed, 810 insertions, 34 deletions
diff --git a/graphics/metapost/contrib/macros/mptrees/mptrees.mp b/graphics/metapost/contrib/macros/mptrees/mptrees.mp index b832d0f94a..f31080b61c 100644 --- a/graphics/metapost/contrib/macros/mptrees/mptrees.mp +++ b/graphics/metapost/contrib/macros/mptrees/mptrees.mp @@ -2,10 +2,10 @@ %% mptrees.mp %% %% Probability trees with MetaPost %% %% o.peault@posteo.net %% -%% Version 23.04 (April 2023) %% +%% Version 24.02 (February 2024) %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string mptreesversion; -mptreesversion:="23.04"; +mptreesversion:="24.02"; % % This work may be distributed and/or modified under the conditions of % the LaTeX Project Public License, either version 1.3 of this license @@ -23,7 +23,7 @@ arbres_latexmp:=true; boolean mpt_begtr; % is begintree used ? mpt_begtr:=false; -numeric mpt_passe; +numeric mpt_passe; mpt_passe:=1; @@ -31,7 +31,7 @@ mpt_passe:=1; def begintree= mpt_begtr:=true; - scantokens "def mpt_tree=" + scantokens "def mpt_tree=" enddef; let endtree = enddef; @@ -45,7 +45,7 @@ extra_endfig:="if mpt_begtr: mpt_tree currentpicture:=nullpicture; mpt_passe:=2; numeric posprob; % position de l'étiquette sur la branche -posprob:=0.6; +posprob:=-1; numeric scaleprob; scaleprob:=0.85; % échelle de l'étiquette sur la branche @@ -72,6 +72,9 @@ linewidth:=0.5bp; color linecolor; linecolor:=black; +numeric nodelinewidth; % épaisseur de la ligne autour des noeuds +nodelinewidth:=0.5bp; + pair Orig_arbre[][]; % sommet de l'arbre i,j Orig_arbre[1][1]:=origin; @@ -91,7 +94,7 @@ numeric mptLargeur[][],mptHauteur[][]; % diff largeur au rang i, diff hauteur r numeric countligne[]; % nombre de ligne pour le niveau i for i=0 upto 128: countligne[i]:=0; endfor - + %numeric typedec; % 0 origine dépend de la taille de l'évènement, 1 taille fixée numeric shiftev; % taille du décalage dans le cas où typedec=1 shiftev:=-1; % dans ce cas, typedec =0 @@ -163,6 +166,7 @@ vardef labelarbres(expr s)= save p; picture p; if picture s: p=s elseif path s: p=image(draw s) +% elseif string s: p=scantokens("btex" & s & "etex"); else: p=textext(s) fi; p @@ -170,7 +174,7 @@ enddef; % longueur du segment qui traverse la figure p selon l'angle inc -vardef longdir(expr p,inc)= +vardef longdir(expr p,inc)= if urcorner p = llcorner p: 0 elseif (abs inc <= abs angle (urcorner p -llcorner p)) or (abs inc > 180 - abs angle (urcorner p -llcorner p)): @@ -214,15 +218,23 @@ vardef superellipsebox(expr p)= b=0.5[urcorner l,ulcorner l]; c=0.5[ulcorner l,llcorner l]; d=0.5[llcorner l,lrcorner l]; - l:=superellipse(a,b,c,d,superellipseparam); + if (mpt_isgraph and (not naturalwidth) and (not mpt_isprob)): + l:=superellipse(1/2 right, 1/2 up, 1/2 left, 1/2 down, .8); + l:=l scaled nodewidth + elseif naturalwidth: + l:=superellipse(a,b,c,d,superellipseparam); + l:=l shifted -center l + else: + l:=superellipse(a,b,c,d,superellipseparam) + fi; l enddef; vardef supellformat(expr p,cl,cb,cf)= image(% - fill superellipsebox(p) withcolor cb; - draw superellipsebox(p) withcolor cl; - draw p withcolor cf; + if (cb<>white) or (mpt_bgc): fill superellipsebox(p) withcolor cb mpt_opbg_ fi; + draw superellipsebox(p) withcolor cl withpen pencircle scaled nodelinewidth mpt_po_ ; + if arbrebool or mpt_isprob: draw p withcolor cf mpt_po_ fi; ) enddef; @@ -233,23 +245,60 @@ vardef circlebox(expr p)= a:=urcorner bbox p; b:=llcorner bbox p; c:=0.5[a,b]; - fullcircle scaled (abs(b-a)-2) shifted c + if (mpt_isgraph and (not naturalwidth) and (not mpt_isprob)): + fullcircle scaled nodewidth + elseif naturalwidth: + fullcircle scaled (abs(b-a)-2) + else: + fullcircle scaled (abs(b-a)-2) shifted c + fi enddef; vardef circleformat(expr p,cl,cb,cf)= image(% - fill circlebox(p) withcolor cb; - draw circlebox(p) withcolor cl; - draw p withcolor cf; + if (cb<>white) or (mpt_isprobover) or (mpt_bgc): fill circlebox(p) withcolor cb mpt_opbg_ fi; + draw circlebox(p) withcolor cl withpen pencircle scaled nodelinewidth mpt_po_; + if arbrebool or mpt_isprob: draw p withcolor cf mpt_po_ fi; +) +enddef; + +vardef circleprobformat(expr p,cf)= +image(% + fill circlebox(p) withcolor background; + draw p withcolor cf mpt_po_; +) +enddef; + +% square +vardef squarebox(expr p)= + save H,L; + numeric H,L; + L=abs((urcorner bbox p) - (ulcorner bbox p)); + H=abs((urcorner bbox p) - (lrcorner bbox p)); + if H>L: L:= H fi; + if (mpt_isgraph and (not naturalwidth) and (not mpt_isprob)): + unitsquare shifted (-0.5,-0.5) scaled nodewidth + elseif naturalwidth: + unitsquare shifted (-0.5,-0.5) scaled L + else: + unitsquare shifted (-0.5,-0.5) scaled L shifted center bbox p + fi +enddef; + +vardef squareformat(expr p,cl,cb,cf)= +image(% + if (cb<>white) or (mpt_bgc): fill squarebox(p) withcolor cb mpt_opbg_ fi; + draw squarebox(p) withcolor cl withpen pencircle scaled nodelinewidth mpt_po_; + if arbrebool or mpt_isprob: draw p withcolor cf mpt_po_ fi; ) enddef; % bbox vardef bboxformat(expr p,cl,cb,cf)= image(% - fill bbox p withcolor cb; - draw bbox p withcolor cl; - draw p withcolor cf; + if (cb<>white) or (mpt_bgc): fill bbox p withcolor cb mpt_opbg_ fi; + draw bbox p withcolor cl withpen pencircle scaled nodelinewidth mpt_po_; + if arbrebool or mpt_isprob: draw p withcolor cf mpt_po_ fi; ) enddef; @@ -274,10 +323,14 @@ vardef formatprob(expr p)= supellformat(p,cl,cb,cf) elseif probformat="circle": circleformat(p,cl,cb,cf) + elseif probformat="square": + squareformat(p,cl,cb,cf) elseif probformat="bbox": bboxformat(p,cl,cb,cf) + elseif mpt_isprobover and (probformat=""): + circleprobformat(p,cf) else: - image (draw p withcolor cf) + image (draw p withcolor cf mpt_po_) fi enddef; @@ -291,10 +344,14 @@ vardef formatnodeev(expr p)= supellformat(p,cl,cb,cf) elseif nodeformat="circle": circleformat(p,cl,cb,cf) + elseif (mpt_isgraph) and (nodeformat=""): + circleformat(p,cl,cb,cf) + elseif nodeformat="square": + squareformat(p,cl,cb,cf) elseif nodeformat="bbox": bboxformat(p,cl,cb,cf) else: - image (draw p withcolor cf) + image (draw p withcolor cf mpt_po_) fi enddef; @@ -435,7 +492,9 @@ enddef; %%%%%%%% Dessin de la branche vardef dessinbranche(expr Ori,Fin)= - if branchtype="segment": + if mpt_isgraph: + mpt_tmp_branche + elseif branchtype="segment": Ori--Fin elseif branchtype="curve": curveline(Ori,Fin) @@ -463,7 +522,7 @@ vardef branche_abs(expr Ori,Fin,Eve,Pro)= figtmp=image(% if branchtype<>"none": if edgearrow: - drawarrow + drawarrow else: draw fi @@ -508,6 +567,7 @@ vardef _arbre_(expr Ori)(text t)(text r)= % (pt)(pt1,pt2...)(ev,proba,ev,proba.. picture figtmp,labeltmp[]; numeric counttmp,countlab,tmpcountligne; pair Fintmp[]; + mpt_isgraph:=false; if dirtree<>0: dirlabel:=dirtree fi; if colonne_cour=1: countligne[1]:=1;countligne[0]:=1; @@ -537,7 +597,7 @@ vardef _arbre_(expr Ori)(text t)(text r)= % (pt)(pt1,pt2...)(ev,proba,ev,proba.. labeltmp[1]:=formatnode(labeltmp[1]); labeltmp[2]:=formatprob(labeltmp[2]); draw branche_abs(Ori,mptFinBranche[colonne_cour+1][counttmp],labeltmp[1] scaled scaleev,labeltmp[2]); - Orig_arbre[colonne_cour+1][counttmp]:=mptFinBranche[colonne_cour+1][counttmp] shifted + Orig_arbre[colonne_cour+1][counttmp]:=mptFinBranche[colonne_cour+1][counttmp] shifted if shiftev<0: ((longdir(labeltmp[1] scaled scaleev,dirlabel) + 2labeloffset)*(1,0)) else: (shiftev,0) fi @@ -556,7 +616,7 @@ enddef; -vardef arbre_decv(expr Ori,horiz,Ymax)(text t)(text r)= +vardef arbre_decv(expr Ori,horiz,Ymax)(text t)(text r)= % (pt,dec horiz)(dy1,dy2...)(ev,proba,ev,proba...) save Fin,compt,Ytmp; numeric compt,Ytmp; @@ -643,7 +703,7 @@ vardef reg.arbre[][](text t)(text r)= ligne_cour:=@; compt:=0; for i=t: - if numeric i: + if numeric i: compt:=compt+1; decal[compt]:=i fi; @@ -671,7 +731,7 @@ vardef comp.arbre[][](text t)(text r)= hide(tmp_compt:=tmp_compt+1;) if (tmp_compt>1) and (not string i): ,Orig_arbre[colonne_cour][ligne_cour]+i - elseif not string i: + elseif not string i: Orig_arbre[colonne_cour][ligne_cour]+i fi endfor @@ -680,7 +740,7 @@ vardef comp.arbre[][](text t)(text r)= _arbre_(Orig_arbre[colonne_cour][ligne_cour])(tmp_text)(r) enddef; - + %%%%%%%%%%%%%%%%%%%%%%%%% Modif 10/16 - Décalage par rapport à l'origine vardef dec.arbre[][](text t)(text r)= save decal; @@ -781,15 +841,21 @@ enddef; pair current_tree; +boolean arbrebool; % est-on à l'intérieur d'un arbre ? +arbrebool:=false; + vardef arbre[][](text t)(text r)= + arbrebool:=true; + naturalwidth:=false; init_loc_var; + if posprob=-1: posprob:=0.6 fi; save tmp_type,tmp_compt,tmp_chdb; numeric tmp_type,tmp_compt,tmp_comptii; string tmp_chdb; tmp_compt:=0;tmp_comptii:=0; for i=t: tmp_comptii:=tmp_comptii+1; - if numeric i: + if numeric i: tmp_compt:=tmp_compt+1 elseif string i: tmp_chdb:=singletodoublequote(i); @@ -830,7 +896,7 @@ vardef stree[][](text t)(text r)= numeric cc,ll; cc:=colonne.#@; ll:=@; - def tmptxt= + def tmptxt= for i=r: i,"", endfor @@ -844,7 +910,7 @@ enddef; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% vardef ymean(expr i,j)= - (0 + (0 for k=1 upto mptNbBranches[i][j]: + ypart (mptFinBrancheRel[i][j][k] rotated -dirtree) endfor)/mptNbBranches[i][j] @@ -900,7 +966,7 @@ numeric mpt_decbranche[][][]; -def AdjustNodes= +def AdjustNodes= tmplig:=0; for i=1 upto countligne[colonne_cour]: for j= 1 upto mptNbBranches[colonne_cour][i]: @@ -914,7 +980,7 @@ def AdjustNodes= for i=1 upto countligne[col]: if known mptNbBranches[col][i]: for j= 1 upto mptNbBranches[col][i]: - if known exist.arbre[col][i]: + if known exist.arbre[col][i]: tmplig:=tmplig+1; if known exist.arbre[col+1][tmplig]: mptFinBrancheRel[col][i][j]:= @@ -1016,7 +1082,7 @@ vardef bernoulliprocess(expr n)(text t)(text r)= tmp_ct:=0; for i=r: tmp_ct:=tmp_ct+1; - if string i: + if string i: tmp_ch[tmp_ct]:=i fi; endfor @@ -1045,7 +1111,7 @@ vardef bernoulliprocessL(expr n)(text t)(text r)= tmp_ct:=0; for i=r: tmp_ct:=tmp_ct+1; - if string i: + if string i: tmp_chi[tmp_ct]:=i fi; endfor @@ -1100,4 +1166,714 @@ vardef binomialtreeL(expr n)(expr L,H)= enddef; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% GRAPHES +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Outils +vardef isdigit primary d = + ("0"<=d)and(d<="9") +enddef ; + +% Convertit un suffixe en chaine avec les chiffres en indice +vardef _chaine(suffix s)= + save c,d; + string c,d; + d:= str s; + if length(d)=1: + c:=d + elseif isdigit (substring (1,2) of d): + c:= (substring (0,1) of d) & "_{" & substring (1,infinity) of d & "}" + else: c:=str s + fi; + c +enddef; + +vardef _chainec(expr d)= + save c; + string c; + if length(d)=1: + c:=d + elseif isdigit (substring (1,2) of d): + c:= (substring (0,1) of d) & "_{" & substring (1,infinity) of d & "}" + elseif isdigit (substring (2,3) of d): + c:= (substring (0,2) of d) & "_{" & substring (2,infinity) of d & "}" + else: + c:=d + fi; + c +enddef; + +% longueur d'un paramètre text +vardef long_texte(text t)= + save i; + numeric i; + i:=0; + for n=t: i:=i+1; endfor + i +enddef; + + +% Placement fin des étiquettes +vardef thelabelang@#(expr s,z)= + save tmpang,tmpfig,tmppt,tmppath,tmpstr; + string tmpstr; + numeric tmpang; + pair tmppt; + path tmppath; + save p; picture p; + tmpstr := str @#; + if picture s: p=s + else: p = textext(s) + fi; + tmppath := llcorner p -- lrcorner p -- urcorner p -- ulcorner p -- cycle; + if ASCII tmpstr = 91: + tmpang := scantokens substring(1,length(tmpstr)-1) of tmpstr + else: + tmpang := scantokens tmpstr + fi; + tmppt := tmppath intersectionpoint ((0.5urcorner p+0.5llcorner p)-- (0.5urcorner p +0.5llcorner p+ 100 * (dir (180+tmpang)))); + p shifted (-tmppt + z + labeloffset*(cosd(tmpang),sind(tmpang)) ) +enddef; + +def labelang = draw thelabelang enddef; + + +%%%%%% +%% Paramètres +%%%%% + + +numeric nodewidth,edgelinewidth,edgearrowpos; +nodewidth:=0.6cm; +edgelinewidth:=1; +nodelinewidth:=1; +edgearrowpos:=1; + +boolean naturalwidth; +naturalwidth:=false; + +numeric nodelabeloffset, nodeedgeoffset; % pour la position des étiquettes +nodelabeloffset:=2; +%nodeedgeoffset:=nodelinewidth/2+edgelinewidth/2; +nodeedgeoffset:=-101; + + + +numeric edgeangle,loopangle,loopsize,loopstartangle; +edgeangle:=0; +loopangle:=90; +loopsize:=-1; +loopstartangle:=30; + + +%%% Format du nom des sommets +string defnodename; +defnodename:="A"; +string nodename; +nodename:="array"; +numeric startnodename; +startnodename=1; + + +boolean printnodename; +printnodename:=true; + + + +numeric mpt_numtotal; % nombre total de sommets +mpt_numtotal:=0; + +pair mpt_nodecoord[]; % coordonnées du noeud i +string mpt_nodename[]; % nom du noeud i +path mpt_nodepath[]; % chemin autour du noeud i +string mpt_nodelpart[],mpt_nodenumpart[]; % parties alphanumérique et numérique du nom du noeud + +color gridcolor; +gridcolor:=0.7white; + +numeric gridlinewidth; +gridlinewidth:=0.5; + + + +%%%% Variables privées +boolean mpt_dir; %arête orientée ou non +mpt_dir:=false; + +boolean mpt_isgraph; +mpt_isgraph:=false; + +picture mpt_tmp_fig_cbg; +path mpt_tmp_branche; +string mpt_tmp_prob; + +path mpt_tmp_path; + +boolean mpt_isprob,mpt_isprobover; +mpt_isprob:=false; +mpt_isprobover:=false; + + +boolean mpt_bgc; +mpt_bgc:=false; + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% Noeuds + +vardef mptlpart(expr tt)= + save tmp; + string tmp; + tmp:=""; + for i =1 upto length tt: + if not isdigit substring(i-1,i) of tt: + tmp:=tmp & substring(i-1,i) of tt + fi; + endfor + tmp +enddef; + +vardef mptnumpart(expr tt)= + save tmp; + string tmp; + tmp:=""; + for i =1 upto length tt: + if isdigit substring(i-1,i) of tt: + tmp:=tmp & substring(i-1,i) of tt + fi; + endfor + tmp +enddef; + +% définit le noeud et certains attributs +def defnode(suffix ptA)(expr A)= + save tmpchcomp,tmpchlet,tmpchnum; + string tmpchcomp,tmpchlet,tmpchnum; + mpt_isgraph:=true; + tmpchcomp:= str ptA; + tmpchlet:=mptlpart(str ptA); + tmpchnum:=mptnumpart(str ptA); + if tmpchnum="": + pair ptA; + ptA:=A; + else: + scantokens("if not known " & tmpchlet & ": pair " & tmpchlet & "[] fi;" & tmpchlet & tmpchnum & ":=("& decimal(xpart A)&","& decimal(ypart A) & ");") + fi; + mpt_numtotal:=mpt_numtotal+1; + mpt_nodecoord[mpt_numtotal]:=A; + mpt_nodename[mpt_numtotal]:= tmpchcomp; + mpt_nodelpart[mpt_numtotal]:= tmpchlet; + mpt_nodenumpart[mpt_numtotal]:= tmpchnum; + mpt_nodepath[mpt_numtotal]:= formatnodepath(labelarbres(str ptA) scaled scaleev) shifted A; +enddef; + + +def defnodestr(expr ptA)(expr A)= % Quand le premier paramètre est une chaine simple + save tmpchcomp,tmpchlet,tmpchnum; + string tmpchcomp,tmpchlet,tmpchnum; + mpt_isgraph:=true; + tmpchcomp:= ptA; + tmpchlet:=ptA; + tmpchnum:=""; + scantokens("pair " & tmpchcomp & ";" & tmpchcomp & ":=("& decimal(xpart A)&","& decimal(ypart A) & ");") + mpt_numtotal:=mpt_numtotal+1; + mpt_nodecoord[mpt_numtotal]:=A; + mpt_nodename[mpt_numtotal]:= tmpchcomp; + mpt_nodelpart[mpt_numtotal]:= tmpchlet; + mpt_nodenumpart[mpt_numtotal]:= tmpchnum; + mpt_nodepath[mpt_numtotal]:= formatnodepath(labelarbres(tmpchcomp) scaled scaleev) shifted A; +enddef; + + +def defnodes(text t)= % Pour définir plusieurs noeuds à la fois + if (nodename="array") or (nodename="arabic"): + for i=t: + mpt_numtotal:=mpt_numtotal+1; + if mpt_numtotal=1: + scantokens("pair " & defnodename & "[];") + fi; + scantokens(defnodename & decimal(mpt_numtotal) & ":=("& decimal(xpart i)&","& decimal(ypart i) & ");"); + mpt_nodecoord[mpt_numtotal]:=i; + mpt_nodename[mpt_numtotal]:= defnodename & decimal(mpt_numtotal); + mpt_nodelpart[mpt_numtotal]:= defnodename; + mpt_nodenumpart[mpt_numtotal]:= decimal(mpt_numtotal); + mpt_nodepath[mpt_numtotal]:= formatnodepath(labelarbres(mpt_nodename[mpt_numtotal]) scaled scaleev) shifted mpt_nodecoord[mpt_numtotal]; + endfor + elseif (nodename="Alph") or (nodename="alph"): + save tmp_str,tmp_nn; + string tmp_str; + numeric tmp_nn; + tmp_nn:= if nodename="Alph": 64 else: 96 fi; + for i=t: + tmp_str:=char(mpt_numtotal+startnodename+tmp_nn); + defnodestr(tmp_str)(i); + endfor + fi +enddef; + + +% Renvoie le rang d'un noeud par suffixe +vardef searchnode(suffix ptA)= + save val,st; + numeric val; + string st; + st= str ptA; + for i=1 upto mpt_numtotal: + if mpt_nodename[i]=st: + val=i + fi; + exitif known val; + endfor + val +enddef; + +% Renvoie le rang d'un noeud suivi d'une chaine +vardef searchnodech(suffix s)(expr c)= + searchnode(s) +enddef; + +% Renvoie le path d'un noeud +vardef nodepath(suffix ptA)= + save nn; + numeric nn; + nn:=searchnode(ptA); + mpt_nodepath[nn] +enddef; + +% Forme du chemin autour du noeud +vardef formatnodepath(expr p)= + if nodeformat="superellipse": + superellipsebox(p) + elseif (nodeformat="circle") or (nodeformat=""): + circlebox(p) + elseif nodeformat="square": + squarebox(p) + else: + bbox p shifted -center bbox p + fi +enddef; + + +% Dessin du noeud +vardef thenode@#(text t)= + save tmp_fig,tmpstr; + picture tmp_fig; + string tmp_str; + if long_texte(t)=1: + tmp_fig:=thenodenum@#(searchnode(t)) + else: + for i=t: + if string i: tmp_fig:=thenodenum@#(searchnodech(t),i) fi; + endfor + fi; + tmp_fig +enddef; + +vardef thenodenum@#(text t)= + save tmp_pt,ch,dess,latch,num; + numeric num; + pair tmp_pt; + string ch,latch; + picture dess; + mpt_isgraph:=true; + interim labeloffset:=nodelabeloffset+nodewidth/2; + if ((ASCII str @# < 58) or (ASCII str @# = 91)) and (str @#<>""): + def mylabel = labelang enddef + else: + def mylabel = label enddef + fi; + if long_texte(t)=1: + num:=t; + dess:=image( + ch:="$" & _chainec(mpt_nodename[num]) & "$"; + if nodename="arabic": ch := "$" & decimal(num) & "$" fi; + mpt_nodepath[num]:=formatnodepath(labelarbres(ch) scaled scaleev) shifted mpt_nodecoord[num]; + label(formatnodeev(labelarbres(ch) scaled scaleev),mpt_nodecoord[num]); + if printnodename: + mylabel@#(textext(ch) scaled scaleev,mpt_nodecoord[num]) withcolor nodefgcolor mpt_po_ + fi) + else: + dess:=image(% + for PP=t: + if numeric PP: + num:=PP; + tmp_pt:=mpt_nodecoord[num]; + else: + mpt_nodepath[num]:=formatnodepath(labelarbres(PP) scaled scaleev) shifted mpt_nodecoord[num]; + label(formatnodeev(labelarbres(PP) scaled scaleev),tmp_pt); + if printnodename: + if string PP: + mylabel@#(textext(PP),tmp_pt) withcolor nodefgcolor mpt_po_; + else: + mylabel@#(PP scaled defaultscale,tmp_pt) withcolor nodefgcolor mpt_po_; + fi + fi + fi; + endfor) + fi; + dess +enddef; + +vardef node@#(text s)= + save mpt_boolnum; + boolean mpt_boolnum; + mpt_boolnum:=false; + for i=s: + if numeric i: + mpt_boolnum:=true + fi; + endfor + if mpt_boolnum: + thenodenum@#(s) + else: + thenode@#(s) + fi +enddef; + + +vardef firstnode@#(suffix s)(text t) text r= + drawnode@#(s) r; + def tmp_text= t enddef; +enddef; + + +vardef nodes@#(text t) text s= % Dessin des noeuds à partir de leur rang + save tmp_pt; + pair tmp_pt; + save mpt_boolnum; + boolean mpt_boolnum; + mpt_boolnum:=false; + for i=t: + if numeric i: + mpt_boolnum:=true + fi; + endfor + image( + if long_texte(t)=0: + for i=1 upto mpt_numtotal: + drawnode@#(i) s; + endfor + elseif mpt_boolnum: + for i=t: + drawnode@#(i) s; + endfor + else: + save n;numeric n; + n=long_texte(t); + def tmp_text= t enddef; + for i=1 upto n-1: + firstnode@#(tmp_text) s; + endfor + drawnode@#(tmp_text) s; + fi + ) +enddef; + + + +vardef drawnode@#(text p) text t = + mpt_drop(t); + mpt_tmp_fig_cbg:=image(draw (0,0) mpt_po_); + draw node@#(p); + mpt_bgc:=false; + mpt_drop(); +enddef; + +def drawnodes = draw nodes enddef; + + +%%%%%%%%%%%%% +%% Arêtes +%%%%%%%%%%%%% +% chemin entre les noeuds de rangs n et m, angles en param +vardef theedgeAB(expr m,n)= + save an,ta,pb,pathab,A,B,C,tmpoffset; + numeric an,tmpoffset; + numeric ta,tb; + pair A,B,C; + if nodeedgeoffset=-101: tmpoffset:=0 + else: tmpoffset:=nodeedgeoffset + fi; + tmpoffset:=tmpoffset+nodelinewidth/2+edgelinewidth/2; + A:=mpt_nodecoord[m]; + B:=mpt_nodecoord[n]; + path pathab; + if m<>n: + an:=angle(B-A); + pathab:=A{dir (an+edgeangleaa[0])}..{dir (an-edgeangleaa[1])}B; + ta=xpart(pathab intersectiontimes mpt_nodepath[m]); + tb=xpart(pathab intersectiontimes mpt_nodepath[n]); + pathab:= subpath(ta,tb) of pathab; + ta:= arctime tmpoffset of pathab; + tb:= arctime ((arclength pathab)-tmpoffset) of pathab; + pathab:= subpath (ta, tb) of pathab; + else: + pathab:=theloopA(n) + fi; + pathab +enddef; + + + +% boucle sur le noeud n +vardef theloopA(expr n)= + save pathaa,aapath,A,B,C,tmpoffset,ta,tb; + pair A,B,C; + numeric tmpoffset,ta,tb; + path pathaa,aapath; + if nodeedgeoffset=-101: tmpoffset:=0 + else: tmpoffset:=nodeedgeoffset + fi; + tmpoffset:=tmpoffset+nodelinewidth/2+edgelinewidth/2; + C:=mpt_nodecoord[n]; + pathaa:=C{dir (-tmp_loopangle[1]+tmp_loopangle[0])}.. + (C+((0.5loopsize,0.77loopsize) rotated (tmp_loopangle[0]-90))){dir (tmp_loopangle[0])}.. + (C+((loopsize,0) rotated (tmp_loopangle[0]))){dir (tmp_loopangle[0]+90)}.. + (C+((-0.5loopsize,0.7loopsize) rotated (tmp_loopangle[0]-90))){dir (tmp_loopangle[0]+180)}.. + {dir (tmp_loopangle[1]+tmp_loopangle[0]+180)}C; + aapath:= reverse pathaa; + ta=xpart(subpath(0,0.5*length pathaa) of pathaa intersectiontimes mpt_nodepath[n]); + tb=xpart(subpath(0,0.5*length aapath) of aapath intersectiontimes mpt_nodepath[n]); + pathaa:= subpath (ta,(length pathaa) - tb) of pathaa; + ta:= arctime tmpoffset of pathaa; + tb:= arctime ((arclength pathaa)-tmpoffset) of pathaa; + pathaa:= subpath (ta, tb) of pathaa; + pathaa +enddef; + +% Chemin entre les noeuds A et B, angles dans p +vardef theedge(suffix A,B)(text p)= + save nA,nB,tmp_fig; + numeric nA,nB; + picture tmp_fig; + nA:=searchnode(A); + nB:=searchnode(B); + theedgenum(nA,nB)(p) +enddef; + +% Chemin entre les noeuds nA et nB, angles dans p +vardef theedgenum(expr nA,nB)(text p)= + save tmp_fig; + picture tmp_fig; + numeric edgeangleaa[],tmp_loopangle[]; + edgeangleaa[0]=edgeangleaa[1]=edgeangle; + tmp_loopangle[0]:=loopangle;tmp_loopangle[1]:=loopstartangle; + mpt_isgraph:=true; + nn:=0; + for i=p: + if numeric i: + if nn=0: edgeangleaa[0]:=i;edgeangleaa[1]:=i;tmp_loopangle[0]:=i + else: edgeangleaa[1]:=-i;tmp_loopangle[1]:=i + fi; + nn:=nn+1; + elseif string i: + mpt_tmp_prob:=i; + fi + endfor + theedgeAB(nA,nB) +enddef; + +% Figure représentant le chemin avec (ou non) la flèche +vardef theedgenumfig(expr nA,nB)(text p)= + save tmppath; + path tmppath; + tmppath:=theedgenum(nA,nB)(p); + image(draw tmppath withpen pencircle scaled edgelinewidth mpt_po_; + if mpt_dir: + filldraw arrowhead subpath(0, edgearrowpos*length mpt_tmp_path) of mpt_tmp_path mpt_po_ + fi; + ) +enddef; + +vardef edges@#(text s)(text p) text t= % dessine plusieurs arêtes simultanément + save a,b,isp; + numeric a,b; + boolean isp; + isp:=false; + image( + for i=s: + if pair i: + if isp: drawedge@#(a,b)(p) t; fi; + a:= xpart i;b:= ypart i; + isp:=true; + else: + drawedge@#(a,b)(i,p) t; + isp:=false + fi; + endfor + if isp: drawedge(a,b)(p) t; fi + ) +enddef; + + + + + + +vardef theedgepond@#(suffix A,B)(text p)= + save nA,nB; + numeric nA,nB; + nA:=searchnode(A); + nB:=searchnode(B); + theedgepondnum@#(nA,nB)(p) +enddef; + +vardef theedgepondnum@#(expr nA,nB)(text p)= + save tmpfig,tmppath,tmppt,mpt_isprob,mpt_isprobover; + boolean mpt_isprob,mpt_isprobover; + mpt_isprob:=true; + path tmppath; + picture tmpfig; + pair tmppt; + if str @#="": mpt_isprobover:=true else: mpt_isprobover:=false fi; + if ((ASCII str @# < 58) or (ASCII str @# = 91)) and (str @#<>""): + def mylabel = labelang enddef + else: + def mylabel = label enddef + fi; + tmppath:=theedgenum(nA,nB)(p); + tmppt:=point (arctime posprob*(arclength tmppath) of tmppath) of tmppath; + image(draw theedgenum(nA,nB)(p) withpen pencircle scaled edgelinewidth mpt_po_; + if mpt_dir: + filldraw arrowhead subpath(0, edgearrowpos*length mpt_tmp_path) of mpt_tmp_path mpt_po_ + fi; + mylabel@#(formatprob(labelarbres(mpt_tmp_prob) scaled scaleprob),tmppt)) +enddef; + +vardef edge@#(text s)(text p)= + save mpt_boolprob,mpt_boolnum; + boolean mpt_boolprob,mpt_boolnum; + mpt_boolprob:=false; + mpt_boolnum:=false; + if posprob=-1: posprob:=0.5 fi; + if loopsize=-1: + loopsize:=1.5nodewidth; + if loopsize<0.6cm: loopsize:=0.6cm fi; + fi; + for i=p: + if string i: + mpt_boolprob:=true + fi; + endfor + for i=s: + if numeric i: + mpt_boolnum:=true + fi; + endfor + if mpt_boolnum: + mpt_tmp_path:=theedgenum(s)(p); + if mpt_boolprob: + theedgepondnum@#(s)(p) + else: + theedgenumfig(s)(p) + fi + else: + mpt_tmp_path:=theedge(s)(p); + if mpt_boolprob: + theedgepond@#(s)(p) + else: + theedge(s)(p) + fi + fi +enddef; + +%%%%%%%%%% Drawing edges + +vardef drawedge@#(text s)(text p) text t= + mpt_drop(t); + draw edge@#(s)(p) withpen pencircle scaled edgelinewidth; + mpt_drop(); +enddef; + +vardef drawedges@#(text s)(text p) text t= + draw edges@#(s)(p) t +enddef; + + +vardef drawdiredge@#(text s)(text p) text t= + save mpt_dir; + boolean mpt_dir; + mpt_dir:=true; + drawedge@#(s)(p) t; +enddef; + +vardef drawdiredges@#(text s)(text p) text t= + save mpt_dir; + boolean mpt_dir; + mpt_dir:=true; + drawedges@#(s)(p) t; +enddef; + + +vardef drawgraph@#(text s)(text p) text t= % dessine les noeuds et les arêtes + drawnodes@#() t; + drawedges@#(s)(p) t; +enddef; + +vardef drawdirgraph@#(text s)(text p) text t= % dessine les noeuds et les arêtes + drawnodes@#() t; + drawdiredges@#(s)(p) t; +enddef; + + +%%%%%%%%%%%%%% Managing colors + +def mpt_drop(text t) = + def mpt_po_ = t enddef; +enddef; + +mpt_drop(); +def withbgcolor expr c= + hide(mpt_bgc:=true; def mpt_opbg_ = withcolor c enddef) +enddef; + +def mpt_opbg_ = enddef; + +%%%%%%%%%%%%%% Grids + +vardef thegridcomp(expr xmin,ymin,xmax,ymax,pas,u)= + image( + for i=xmin step pas until xmax: + draw (i*u,ymin*u)--(i*u,ymax*u) withcolor gridcolor withpen pencircle scaled gridlinewidth; + label.bot(textext("$" & decimal(i)& "$") scaled 0.6,(i*u,ymin*u)) withcolor gridcolor; + endfor + for i=ymin step pas until ymax: + draw (xmin*u,i*u)--(xmax*u,i*u) withcolor gridcolor withpen pencircle scaled gridlinewidth; + label.lft(textext("$" & decimal(i)& "$") scaled 0.6,(xmin*u,i*u)) withcolor gridcolor; + endfor + ) +enddef; + + +vardef grid(text t)(text s)= + save minmax,pasun,c; + numeric minmax[],pasun[],c; + c:=0; + pasun[1]:=1cm; + pasun[2]:=1; + for i=s: + c:=c+1; + pasun[c]:=i; + endfor + c:=0; + for i=t: + c:=c+1; + minmax[c]:=i; + endfor + if c=4: + thegridcomp(minmax[1],minmax[2],minmax[3],minmax[4],pasun[2],pasun[1]) + else: + thegridcomp(0,0,minmax[1],minmax[2],pasun[2],pasun[1]) + fi +enddef; + +def drawgrid= draw grid enddef; |