summaryrefslogtreecommitdiff
path: root/graphics/metapost
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2024-02-24 03:01:46 +0000
committerNorbert Preining <norbert@preining.info>2024-02-24 03:01:46 +0000
commitf325bd88d1d4db13f51277bc59c8ff8814e937bc (patch)
treee39af6619c91d812dd93cb57d25149da5a84d801 /graphics/metapost
parente7a321bba289c40f39563c19bbeac355f7c0eeeb (diff)
CTAN sync 202402240301
Diffstat (limited to 'graphics/metapost')
-rw-r--r--graphics/metapost/contrib/macros/mptrees/README.md5
-rw-r--r--graphics/metapost/contrib/macros/mptrees/mptrees-doc.pdfbin146573 -> 203314 bytes
-rw-r--r--graphics/metapost/contrib/macros/mptrees/mptrees-doc.tex461
-rw-r--r--graphics/metapost/contrib/macros/mptrees/mptrees.mp844
4 files changed, 1261 insertions, 49 deletions
diff --git a/graphics/metapost/contrib/macros/mptrees/README.md b/graphics/metapost/contrib/macros/mptrees/README.md
index b982e778ca..f74fa1c30c 100644
--- a/graphics/metapost/contrib/macros/mptrees/README.md
+++ b/graphics/metapost/contrib/macros/mptrees/README.md
@@ -1,9 +1,8 @@
-Package mptrees - Version 23.04 - April 27, 2023
+Package mptrees - Version 24.02 - February 22, 2024
---
-This package provides MetaPost tools for drawing simple probability trees.
-One main command, some variants and several parameters to control the output are provided.
+This package provides MetaPost tools for drawing simple probability trees and graphs (in discrete geometry).
---
diff --git a/graphics/metapost/contrib/macros/mptrees/mptrees-doc.pdf b/graphics/metapost/contrib/macros/mptrees/mptrees-doc.pdf
index 300937fc61..5a62a3b517 100644
--- a/graphics/metapost/contrib/macros/mptrees/mptrees-doc.pdf
+++ b/graphics/metapost/contrib/macros/mptrees/mptrees-doc.pdf
Binary files differ
diff --git a/graphics/metapost/contrib/macros/mptrees/mptrees-doc.tex b/graphics/metapost/contrib/macros/mptrees/mptrees-doc.tex
index 907e2eca9f..1cc7339d01 100644
--- a/graphics/metapost/contrib/macros/mptrees/mptrees-doc.tex
+++ b/graphics/metapost/contrib/macros/mptrees/mptrees-doc.tex
@@ -17,7 +17,7 @@
\usepackage[bottom]{footmisc}
\usepackage{mflogo}
-
+
\usepackage[output-decimal-marker={,}]{siunitx}
\usepackage{esvect}
\usepackage{nicefrac}
@@ -25,12 +25,11 @@
\usepackage{multicol}
\setlength{\multicolsep}{3pt}
\setlength{\columnsep}{0pt}
-
+
\usepackage[toc]{multitoc}
-
+
\usepackage{enumitem}
-% \setlist[description]{font=\ttfamily\bfseries\color{blue}}
-
+
\usepackage[svgnames]{xcolor}
\usepackage{graphicx}
@@ -38,7 +37,7 @@
\usepackage{url}
\usepackage{verbatim}
\usepackage{fancyvrb}
-
+
\usepackage{array}
\usepackage{colortbl}
\usepackage{tabularx}
@@ -53,7 +52,7 @@
beginfig(1);}
\everyendmplib{endfig;}
\mplibnumbersystem{decimal}
-
+
\usepackage{tcolorbox}
\tcbuselibrary{listings,skins}%,documentation}
@@ -263,15 +262,14 @@ colback=red!10!white,colframe=red!50!black]
-
+\part{Trees}
\section{Overview}
-This package is intended to simplify the drawing of probability trees with \MP. It provides one main command and several parameters to control the output.
+The first aim of this package is to simplify the drawing of probability trees (or other kind of "tree") with \MP. It provides one main command and several parameters to control the output.
It can be used in standalone files with two compilations (\verb|latexmp| package is loaded) but also with Lua\LaTeX{} and \verb|luamplib| package.
-%Some of the following constructions need to be enclosed between \verb|begintree| and \verb|endtree|.
\begin{rpobjet}{tree[<i>][<j>](<dim1>,<dim2>,...)(<ev1>,<prob1>,<ev2>,<prob2>,...)}{picture}
Probability tree located in column \verb|i| and row \verb|j| (see figure below). \verb|dim1|, \verb|dim2|,... can be numerics or pairs and control the dimension of the tree. \verb|ev1|, \verb|prob1|... can be strings or pictures and will be printed (using \verb|latexmp| if strings) at the end of the edge (the event) and above the edge (the probability).
@@ -514,7 +512,7 @@ draw tree[2][1](3cm,2cm)(...);
In the fisrt case, \verb|scaleev| is changed globally while in the second case, the change only applies to the first tree.
-
+
\subsection{Event}
\begin{mptparam}{scaleev}{numeric}{1}
@@ -789,7 +787,7 @@ Note that double quotes have to be replaced by single quotes when this parameter
\begin{mptparam}{brokenlineratio}{numeric}{0.2}
If string \verb|branchtype| is set to \verb|broken|, \verb|brokenlineratio| indicates the ratio between the length of the first segment of the broken line and the total length of the horizontal space.
\end{mptparam}
-
+
\begin{exemple}[lefthand ratio=0.6]
branchtype:="broken";
draw stree[1][1](3cm,3cm)("$A$","$B$");
@@ -1049,6 +1047,445 @@ draw stree[5][9]()("'u'|1","'o'|1");
endtree;
\end{exemple}
+\part{Graphs}
+\section{Overview}
+This package can also be used to draw graphs. In this case, you need to define the nodes by their coordinates and indicate the edges to be drawn. Various commands allow you to draw graphs quickly, but it is also possible to finely control the drawing of each node and edge.
+
+\section{Nodes}
+\subsection{Definition}
+
+\begin{rpdeclaration}{defnodes(<pair1>,<pair2>,...)}
+The easiest way to define the nodes : just put a list of pairs. This command does not draw anything, it just defines an array of pairs corresponding to the coordinates. By default the array name is \verb|A[]|.
+\end{rpdeclaration}
+
+\begin{mptparam}{defnodename}{string}{"A"}
+Default node array name.
+\end{mptparam}
+
+\begin{mptparam}{nodename}{string}{"array"}
+String indicating how the nodes are stored and labels are drawns:
+\begin{itemize}[nosep]
+\item with \verb|nodename="array"|, nodes are stored in \verb|A[]| and labelled \verb|A1|, \verb|A2|,...
+\item with \verb|nodename="Alph"|, nodes are stored and labelled \verb|A|, \verb|B|,...
+\item with \verb|nodename="alph"|, nodes are stored and labelled \verb|a|, \verb|b|,...
+\item with \verb|nodename="arabic"|, nodes are stored in \verb|A[]|,... but are labelled $1$, $2$,...
+\end{itemize}
+\end{mptparam}
+
+\begin{rpdeclaration}{defnode(<token>,<pair>)}
+Nodes can be defined one by one. \verb|<token>| is the node's name and \verb|<pair>| its coordinates.
+\end{rpdeclaration}
+
+\subsection{Drawing}
+
+\begin{rplabel}{drawnodes.<pos>(<nodei>,<nodej>,...)}
+Draw all the indicated nodes. These nodes can be designated either by name or by rank. If the list is empty, all the nodes are drawn. \verb|pos| can be empty or \verb|lft|, \verb|rt|, etc. or an angle.
+\end{rplabel}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes(1,3);
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes(A1,A3);
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes();
+\end{exemple}
+
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodename:="N";
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes();
+\end{exemple}
+
+
+\begin{exemple}[lefthand ratio = 0.6]
+nodename:="Alph";
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+nodename:="alph";
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+nodename:="arabic";
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes();
+\end{exemple}
+
+\begin{mptparam}{printnodename}{boolean}{true}
+When set to false, node names are not printed.
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+printnodename:=false;
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes();
+\end{exemple}
+
+
+\begin{mptparam}{nodeformat}{string}{""}
+String that indicates how the nodes are printed (the shape of path around the node). Possible values are (for now) \verb|"bbox"|, \verb|"circle"|, \verb|"superellipse"| and \verb|"square"|.
+\end{mptparam}
+
+
+\begin{mptparam}{nodewidth}{numeric}{0.6cm}
+Node width...
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+nodeformat:="square";
+nodewidth:=1cm;
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+nodewidth:=0.2cm;
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes.bot();
+\end{exemple}
+
+\begin{mptparam}{naturalwidth}{boolean}{false}
+When set to true, the width of the node adapts to the content.
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodename:="AA";
+naturalwidth:=true;
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes();
+\end{exemple}
+
+\begin{mptparam}{nodelinewidth}{numeric}{1}
+Line width of the path around the node.
+\end{mptparam}
+
+\begin{mptparam}{nodelinecolor}{color}{black}
+Color of the path around the node.
+\end{mptparam}
+
+\begin{mptparam}{nodebgcolor}{color}{white}
+Color of the background of the region delimited by the previous path.
+\end{mptparam}
+
+\begin{mptparam}{nodefgcolor}{color}{black}
+Color of the text.
+\end{mptparam}
+
+
+\begin{exemple}[lefthand ratio = 0.6]
+nodelinecolor:=(0.8,0,0);
+nodebgcolor:=(1,0.5,0.5);
+nodefgcolor:=white;
+nodeformat:="superellipse";
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes();
+\end{exemple}
+
+
+\begin{rpdeclaration}{drawnodes(<nodes>) withbgcolor <color>}
+While \verb|withcolor| applies to lines and labels, \verb|withbgcolor| applies to the filling of nodes.
+\end{rpdeclaration}
+
+\begin{exemple}[lefthand ratio = 0.63]
+nodelinecolor:=(0.8,0,0);
+nodebgcolor:=(1,0.5,0.5);
+nodefgcolor:=white;
+nodeformat:="superellipse";
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnodes() withcolor black withbgcolor (0.6,0.6,1);
+\end{exemple}
+
+
+\begin{rplabel}{drawnode.<pos>(<node>,<label>)}
+The nodes can be drawn one by one, specifying the text to be displayed if necessary.
+\end{rplabel}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,0),(4cm,0));
+drawnode[60](1);
+drawnode(2,"$\sqrt{2}$") withbgcolor 0.7white;
+drawnode.bot(A3,"Node");
+\end{exemple}
+
+\section{Edges}
+\subsection{Undirected edges}
+
+\begin{rplabel}{drawedges.<pos>(<(Na,Nb)>,<string1>,<(Nc,Nd)>,<string2>,...)(<angle1>,<angle2>)}
+Draw undirected edges between Node Na and node Nb, between node Nc and node Nd,... Na, Nb, Nc, Nd... must be integers. You can't refer to the nodes with their name.
+
+If present, the string is printed at the position indicated in relation to the middle of the edge (by default).
+
+By default, the edge is a segment. If an angle is specified, it is added to the angle at the start of the edge and subtracted from the angle at the end of the edge. If two angles are specified, they are added to the start and end angles respectively.
+\end{rplabel}
+
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedges((1,2),(3,1))();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedges((1,2),(3,1),"$p$")();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedges.bot((1,2),(3,1),"$p$")();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedges((1,2),(3,1))(30);
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedges((1,2),(3,1))(40,10);
+\end{exemple}
+
+
+
+\begin{rplabel}{drawedge.<pos>(<Na>,<Nb>)(<angle1>,<angle2>,<string>)}
+The edges can be drawn one by one.In this case, Na, Nb can be the node name. The label or weight must be indicated in the second set of parameters.
+\end{rplabel}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedge(1,2)();
+drawedge.bot(1,3)("$p$");
+drawedge(2,3)(30,"2");
+\end{exemple}
+
+\subsection{Directed edges}
+
+\begin{rplabel}{drawdiredges.<pos>(<(Na,Nb)>,<string1>,<(Nc,Nd)>,<string2>,...)(<angle1>,<angle2>)}
+Draw directed edges from Node Na to node Nb, from node Nc to node Nd,... Na, Nb, Nc, Nd... must be integers. You can't refer to the nodes with their name.
+
+If present, the string is printed at the position indicated in relation to the middle of the edge (by default).
+
+By default, the edge is a segment. If an angle is specified, it is added to the angle at the start of the edge and subtracted from the angle at the end of the edge. If two angles are specified, they are added to the start and end angles respectively.
+\end{rplabel}
+
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawdiredges((1,2),"35",(3,1),"$p$")();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawdiredges.bot((1,2),(3,1),"$p$")(30);
+\end{exemple}
+
+\begin{rplabel}{drawdiredge.<pos>(<Na>,<Nb>)(<angle1>,<angle2>,<string>)}
+The directed edges can be drawn one by one. In this case, Na, Nb can be the node name. The label or weight must be indicated in the second set of parameters.
+\end{rplabel}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawdiredge(1,2)();
+drawdiredge.bot(1,3)("$p$");
+drawdiredge(2,3)(30,"2");
+\end{exemple}
+
+\subsection{Loops}
+\begin{rplabel}{draw(dir)edge.<pos>(<Na>,<Na>)(<angle1>,<angle2>,<string>)}
+Previous commands can be used to draw loops. If present, \verb|angle1| indicates the angle of the loop with horizontal direction. Default value is 90.
+\end{rplabel}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawdiredge(1,1)();
+drawedge(3,3)(-150);
+drawdiredge.bot(2,2)(-90,"a");
+\end{exemple}
+
+
+\subsection{Parameters}
+\begin{mptparam}{edgelinewidth}{numeric}{1}
+Width of the edge.
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+edgelinewidth:=2;
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedges((1,2),(3,1),"$p$")();
+\end{exemple}
+
+\begin{mptparam}{nodeedgeoffset}{numeric}{0}
+Space between the node and the edge.
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+nodeedgeoffset:=0.3cm;
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedges((1,2),(3,1),"$p$")();
+\end{exemple}
+
+
+\begin{mptparam}{probformat}{string}{""}
+String that indicates how the weights are printed (the shape of the path). Possible values are (for now) \verb|"bbox"|, \verb|"circle"|, \verb|"superellipse"| and \verb|"square"|.
+
+\end{mptparam}
+
+
+\begin{mptparam}{problinecolor}{color}{black}
+Color of the path around the weight.
+\end{mptparam}
+
+\begin{mptparam}{probgcolor}{color}{white}
+Color of the background of the region delimited by the previous path.
+\end{mptparam}
+
+\begin{mptparam}{probfgcolor}{color}{black}
+Color of the text.
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+problinecolor:=(0.8,0,0);
+probbgcolor:=(1,0.5,0.5);
+probfgcolor:=white;
+probformat:="square";
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedges((1,2),"35",(3,1),"$p$")();
+\end{exemple}
+
+\begin{mptparam}{posprob}{numeric}{0.5}
+Position of the weight on the edge.
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+posprob:=0.75;
+drawnodes();
+drawedges((1,2),"35",(3,1),"$p$")();
+\end{exemple}
+
+\begin{mptparam}{edgearrowpos}{numeric}{1}
+Position of arrowhead on the edge.
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+edgearrowpos:=0.5;
+drawnodes();
+drawdiredges.bot((1,2),(3,1),"$p$")();
+\end{exemple}
+
+\begin{mptparam}{loopangle}{numeric}{90}
+Loop direction. It can be specified in the command parameters.
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+loopangle:=-90;
+drawnodes();
+drawdiredges((1,1),(2,2),(3,3))();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawdiredges((1,1),(2,2),(3,3))(-90);
+\end{exemple}
+
+\begin{mptparam}{loopstartangle}{numeric}{30}
+Angle between the path direction at node center and loop direction.
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+loopstartangle:=90;
+drawnodes();
+drawdiredges((1,1),(2,2),(3,3))(-90);
+\end{exemple}
+
+
+\begin{mptparam}{loopsize}{numeric}{1.5nodesize}
+Loop size.
+\end{mptparam}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,0cm),(4cm,0));
+loopsize:=1.5cm;
+drawnodes();
+drawdiredges((1,1),(2,2),(3,3))();
+\end{exemple}
+
+\section{Complete graphs}
+
+\begin{rplabel}{draw(dir)graph.<pos>(<(Na,Nb)>,<string1>,<(Nc,Nd)>,<string2>,...)(<angle1>,<angle2>)}
+These commands are shortcuts for drawing both nodes and edges.
+\end{rplabel}
+
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawgraph((1,2),"35",(3,1),"$p$")();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+nodewidth:=0.2cm;
+drawdirgraph.bot((1,2),(3,1),(2,2))(30);
+\end{exemple}
+
+
+\section{Grids}
+To facilitate node placement, use the following command to draw a grid.
+
+\begin{rplabel}{drawgrid(<xmin>,<ymin>,<xmax>,<ymax>)(<unit>,<step>)}
+Command for drawing a grid. Minimum values are optional and equal to 0 by default. The unit and step values are also optional and default to 1 cm and 1 respectively.
+\end{rplabel}
+
+\begin{exemple}[lefthand ratio = 0.6]
+drawgrid(4,4)();
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedges((1,2),(3,1))();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+drawgrid(-1,-1,5,3)(1cm,0.5);
+defnodes((0cm,0cm),(2cm,2cm),(4cm,0));
+drawnodes();
+drawedges((1,2),(3,1))();
+\end{exemple}
+
+\begin{exemple}[lefthand ratio = 0.6]
+u:=0.75cm;
+drawgrid(-1,-1,5,3)(u);
+defnodes((0,0),(2u,2u),(4u,0));
+drawnodes();
+drawedges((1,2),(3,1))();
+\end{exemple}
+
\end{document}
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;