%% DC-PiCTeX %% Copyright (c) 1990-2013 Pedro Quaresma, University of Coimbra, Portugal %% 11/1990 (version 1.0); %% 10/1991 (version 1.1); %% 9/1993 (version 1.2); %% 3/1995 (version 1.3); %% 7/1996 (version 2.1); %% 5/2001 (version 3.0); %% 11/2001 (version 3.1); %% 1/2002 (version 3.2) %% 5/2002 (version 4.0); %% 3/2003 (version 4.1); %% 12/2004 (version 4.1.1) %% 3/2007 (version 4.2) %% 5/2008 (version 4.2.1) %% 8/2008 (version 4.3) %% 12/2008 (version 4.3.1) %% 12/2009 (version 4.3.2) %% 4/2013 (version 4.4.0) %% 5/2013 (version 5.0) \immediate\write10{Package DCpic 2013/05/01 v5.0} \ProvidesPackage{dcpic}[2013/05/01 v5.0] %% Version X.Y.Z %% X - major versions %% Y - minor versions %% Z - bug corrections %% %% Copyright (c) 1990-2013 Pedro Quaresma %% % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Pedro Quaresma (pedro@mat.uc.pt). % % This work consists of the files dcpic.sty. %% %% Coimbra, 1st of May, 2013 (2013/05/01) %% Pedro Quaresma %% %% DCpic is a package of \TeX\ macros for graph modelling in a %% (La)\TeX\ or Con\TeX t document. Its distinguishing features are: %% the use of \PiCTeX\ a powerful graphical engine, and a simple %% specification syntax. A graph is described in terms of its objects %% and its edges. The objects are textual elements and the edges can %% have various straight or curved forms. %% %% %% A graph in DCpic is a "picture" in \PiCTeX, in which we place our %% {\em objects} and {\em morphisms} (edges). The user's commands in %% DCpic are: {\tt begindc} and {\tt enddc} which establishe the %% coordinate system where the objects will by placed; {\tt obj}, the %% command which defines the place and the contents of each object; %% {\tt mor}, and {\tt cmor}, the commands which define the %% morphisms, linear and curved edges, and its labels. %% %% Example: %% \begindc{\commdiag}[30] %% \obj(10,15){$A$} %% \obj(25,15){$B$} %% \obj(40,15){$C$} %% \mor{$A$}{$B$}{$f$} %% \mor{$B$}{$C$}{$g$} %% \cmor((10,11)(11,7)(15,6)(25,6)(35,6)(39,7)(40,11)) %% \pup(25,3){$g\circ f$} %% \enddc %% %% NOTES: %% all the numeric values should be integer values. %% %% Available commands: %% %% The environment: %% \begindc{#1}[#2] %% #1 - Graph type %% 0 = "commdiag" (commutative diagram) %% 1 = "digraph" (direct graph) %% 2 = "undigraph" (undirect graph) %% 3 = "cdigraph" with incircled objects %% 4 = "cundigraph" with incircled objects %% (optional) #2 - magnification factor (default value, 300) %% %% \enddc %% %% Objects: %% \obj(#1,#2)[#3]{#4}[#5] %% #1 and #2 - coordenates %% (optional) #3 - Label, to be used in the morphims command, if not %% present the #4 will be used to that purpose %% #4 - Object contents %% (optional) #5 - placement of the object (default value \north) %% 0="\pcent", center %% 1="\north", north %% 2="\northeast", northeast %% 3="\east", east %% 4="\southeast", southeast %% 5="\south", south %% 6="\southwest", southwest %% 7="\west", west %% 8="\northwest", northwest %% !!! Note !!! %% if you omit the #3 argument (label) and the #4 argument is a %% complex LaTeX command this can cause this command to crash. In %% this case you must specify a label (the empty label [], if you do %% needed it it for nothing). %% %% Morphims (linear edges). This commando has to two major variants %% i) Starting and Ending objects specification %% \mor{#1}{#2}[#5,#6]{#7}[#8,#9] %% %% As you can see this first form is (intencionaly) badly formed, the %% arguments #3 and #4 are missing (the actual command is correctly %% formed). %% %% #1 - The starting object reference %% #2 - The ending object reference %% %% from this two we will obtain the objects coordinates, and also the %% dimensions of the enclosing box. %% %% The objects box dimensions are used to do an automatic adjustment of %% the edge width. %% %% from #1 we obtain (x,y), (#1,#2) in the second form %% from #2 we obtain (x',y'), (#3,#4) in the second form %% %% this values will be passed to the command second form %% %%ii) Two points coordinates specification %% \mor(#1,#2)(#3,#4)[#5,#6]{#7}[#8,#9] %% %% Now we can describe all the arguments %% %% #1 and #2 - coordinates (beginning) %% #3 and #4 - coordinates (ending) %%(optional)#5,#6 - correction factors (defaul values, 100 and 100 (10pt)) %% #5 - actual beginning of the edge %% #6 - actual ending of the edge %% #7 - text (morphism label) %%(optional)#8,#9 %% #8 - label placement %% 1 = "\atright", at right, default value %% -1 = "\atleft", at left %% #9 - edge type %% 0 = "\solidarrow", default edge %% 1 = "\dashArrow" %% 2 = "\dotArrow (thanks to Xingliang Liang ) %% 3 = "\solidline" %% 4 = "\dashline" %% 5 = "\dotline" %% 6 = "\injectionarrow" %% 7 = "\aplicationarrow" %% 8 = "\surjectivearrow" %% 9 = "\equalline" (thanks to Ruben Debeerst ) %% 10 = "\doublearrow" %% 11 = "\doubleopposite" %% 12 = "\nullarrow" (to allow adding labels to existing arrows) %% %% Notes: the equalline "arrow" does not provide a second label. %% %% Curved Morphisms (quadratic edges): %% \cmor(#1) #2(#3,#4){#5}[#6] %% #1 - list of points (odd number) %% #2 - tip direction %% 0 = "\pup", pointing up %% 1 = "\pdown", pointing down %% 2 = "\pright", pointing right %% 3 = "\pleft", pointing left %% #3 and #4 - coordenates of the label %% #5 - morphism label %%(optional)#6 - edge type %% 0 ="\solidarrow", default value %% 1 = "\dashArrow" %% 2 = "\solidline" %% %% Notes: insert a space after the command. %% the space after the list of points is mandatory %% %% Examples: %% \documentclass[a4paper,11pt]{article} %% \usepackage{dcpic,pictexwd} %% %% \begin{document} %% \begindc[3] %% \obj(14,11){$A$} %% \obj(39,11){$B$} %% \mor(14,12)(39,12){$f$}%[\atright,\solidarrow] %% \mor(39,10)(14,10){$g$}%[\atright,\solidarrow] %% \cmor((10,10)(6,11)(5,15)(6,19)(10,20)(14,19)(15,15)) %% \pdown(2,20){$id_A$} %% \cmor((40,7)(41,3)(45,2)(49,3)(50,7)(49,11)(45,12)) %% \pleft(54,3){$id_B$} %% \enddc %% %% \begindc{\commdiag}[3] %% \obj(10,15)[A]{$A$} %% \obj(40,15)[Aa]{$A$} %% \obj(25,15)[B]{$B$} %% \mor{A}{B}{$f$}%[\atright,\solidarrow] %% \mor{B}{Aa}{$g$}%[\atright,\solidarrow] %% \cmor((10,11)(11,7)(15,6)(25,6)(35,6)(39,7)(40,11)) %% \pup(25,3){$id_A$} %% \enddc %% %% \newcommand{\barraA}{\vrule height2em width0em depth0em} %% \newcommand{\barraB}{\vrule height1.6em width0em depth0em} %% \begindc{\commdiag}[35] %% \obj(1,1)[Gr]{$G$} %% \obj(3,1)[Grstar]{$G_{r^*}$} %% \obj(5,1)[H]{$H$} %% \obj(2,2)[SigmaG]{$\Sigma^G$} %% \obj(6,2)[SigmaH]{$\Sigma^H$} %% \obj(1,3)[Lm]{$L_m$} %% \obj(3,3)[Krm]{$K_{r,m}$} %% \obj(5,3)[Rmstar]{$R_{m^*}$} %% \obj(1,5)[L]{$L$} %% \obj(3,5)[Lr]{$L_r$} %% \obj(5,5)[R]{$R$} %% \obj(2,6)[SigmaL]{$\Sigma^L$} %% \obj(6,6)[SigmaR]{$\Sigma^R$} %% \mor{Gr}{SigmaG}{$\lambda^G$} %% \mor{Grstar}{Gr}{$i_5$}[\atleft,\aplicationarrow] %% \mor{Grstar}{H}{$r^*$}[\atright,\solidarrow] %% \mor{H}{SigmaH}{$\lambda^H$}[\atright,\dashArrow] %% \mor{SigmaG}{SigmaH}{$\varphi^{r^*}$}[\atright,\solidarrow] %% \mor{Lm}{Gr}{$m$}[\atright,\solidarrow] %% \mor{Lm}{L}{$i_2$}[\atleft,\aplicationarrow] %% \mor{Krm}{Lm}{$i_3\quad$}[\atright,\aplicationarrow] %% \mor{Krm}{Rmstar}{$r$} %% \mor{Krm}{Lr}{$i_4$}[\atright,\aplicationarrow] %% \mor{Krm}{Grstar}{$m$} %% \mor{Rmstar}{R}{$i_6$}[\atright,\aplicationarrow] %% \mor{Rmstar}{H}{$m^*$} %% \mor{L}{SigmaL}{$\lambda^L$} %% \mor{Lr}{L}{$i_1\quad$}[\atright,\aplicationarrow] %% \mor{Lr}{R}{$r$} %% \mor{R}{SigmaR}{$\lambda^R$}[\atright,\solidarrow] %% \mor{SigmaL}{SigmaG}{$\varphi^m$}[\atright,\solidarrow] %% \mor{SigmaL}{SigmaR}{$\varphi^r$} %% \mor{SigmaR}{SigmaH}{$\varphi^{m^*}$} %% \enddc %% %% \end{document} %%-----------------//------------- %% Modifications (9/1993) %% argument "distance" between de tip of the arrow and the objects %% became optional; a new option for the "arrows" (option 3) %% %% 2/3/1995 (version 1.3) %% adds "the aplication arrow" (option 4); the distance between %% the label and the "arrow" is now a fixed value (100 units). %% 15/7/1996 (version 2.1) %% The comand "\mor" has a new sintax. The 5th and 6th %% parameters are now the distance between the two objects and %% the arrow tips. The 7th parameter is the label. The 8th e 9th %% parameters (label position and type of arrow) are now optional %% %% 5/2001 (version 3.0) %% Implementation of the comand "\cmor" based on the quadratic %% curver comand of PiCTeX %% %% 11/2001 (version 3.1) %% Changes on the tips of the arrow to became more LaTeX style %% (after a conversation on EuroTeX 2001). %% %% 1/2002 (version 3.2) %% Modification of the commands "obj" and "mor" in such a way %% that allows the logical specification of the morphisms, that %% is, it is now possible to specify the starting object and the %% ending object instead of specify the coordinates. %% %% The length of the arrows is automatically trimmed to the %% objects' size. %% %% 5/2002 (version 4.0) %% New syntax for the commands "begindc" e "obj" %% !!! New syntax !!! %% The command "begindc" now have an obligatory argument, this %% argument allows the specification of the graph type %% "commdiag" (0), commutative diagrams %% "digraph" (1), directed graphs %% "undigraph" (2), undirected graphs %% The command "obj" has a new syntax: after the coordinates %% specification, an optional argument specifying a label, an %% obligatory argument given the "value" of the object and the %% final optional argument used in the graphs to set the %% relative position of the "value" to the "dot" defining the %% objects position, the default value is "north". %% %% 3/2003 (version 4.1) %% Responding to a request of Jon Barker I %% create a new type of arrow, the surjective arrow. %% For now only horizontal and vertical versions, other angles %% are poorly rendered. %% 12/2004 (version 4.1.1) %% New version for the surjective arrows, solve the problems %% with the first implementation of this option. %% 3/2007 (version 4.2) %% Adds the "providespackage" directive that was missing. %% Adds dashed lines, and dotted lines. %% 5/2008 (version 4.2.1) %% Deleting some counters, trying to avoid the problem "running %% out of counters", that occurs because of the use of PiCTeX %% and DCpic (only two...) %% 8/2008 (version 4.3) %% Thanks to Ruben Debeerst (debeerst@mathematik.uni-kassel.de), %% he added a new arrow "equalline". After that I %% decided to add: the doublearrow; the doublearrow with %% opposite directions; the null arrow. This last can be used as %% a simple form of adding new labels. %%12/2008 (version 4.3.1) %% The comand \id is internalised (\!id), it should be that way %% from the begining because it is not to be used from the %% outside. %% The comand \dasharrow was changed to \dashArrow to avoid a %% clash with the AMS command with the same name. %%12/2009 (version 4.3.2) %% There is a conflict between dcpic.sty and hyperref in current %% texlive-2009 due to the one letter macro \d (thanks Thorsten %% S ). %% The \d changed to \deuc (Euclidian Distance). The \x and \y %% changed to \xO \yO %% 4/2013 (version 4.4.0) %% Thanks to Xingliang Liang . He added a new %% arrow "dotarrow". %% 5/2013 (version 5.0) %% The base scale of the graph has changed from 1pt to .1pt to %% solve a problem with the implementation of the oblique %% equalline (Thanks to Antonio de Nicola). %% The LaTeX circle and oval commands where replaced by the %% PiCTeX circulararc and ellipticalarc commands to avoid %% differences in scales. %%-----------------//------------- \catcode`!=11 % ***** THIS MUST NEVER BE OMITTED (See PiCTeX) \newcount\aux% \newcount\auxa% \newcount\auxb% \newcount\xO% \newcount\yO% \newcount\xl% \newcount\yl% \newcount\deuc% \newcount\dnm% \newcount\xa% \newcount\xb% \newcount\xmed% \newcount\xc% \newcount\xd% \newcount\xe \newcount\xf \newcount\ya% \newcount\yb% \newcount\ymed% \newcount\yc% \newcount\yd \newcount\ye \newcount\yf %% "global variables" \newcount\expansao% \newcount\tipografo% version 4.0 \newcount\distanciaobjmor% version 4.0 \newcount\tipoarco% version 4.0 \newif\ifpara% %% version 3.2 \newbox\caixa% \newbox\caixaaux% \newif\ifnvazia% \newif\ifvazia% \newif\ifcompara% \newif\ifdiferentes% \newcount\xaux% \newcount\yaux% \newcount\guardaauxa% \newcount\alt% \newcount\larg% \newcount\prof% %% for the triming \newcount\auxqx \newcount\auxqy \newif\ifajusta% \newif\ifajustadist \def\objPartida{}% \def\objChegada{}% \def\objNulo{}% %% %% Stack specification %% %% %% Emtpy stack %% \def\!vazia{:} %% %% Is Empty? : Stack -> Bool %% %% nvazia - True if Not Empy %% vazia - True if Empty \def\!pilhanvazia#1{\let\arg=#1% \if:\arg\ \nvaziafalse\vaziatrue \else \nvaziatrue\vaziafalse\fi} %% %% Push : Elems x Stack -> Stack %% \def\!coloca#1#2{\edef\pilha{#1.#2}} %% %% Top : Stack -> Elems %% %% the empty stack is not taken care %% the element is "kept" ("guardado") \def\!guarda(#1)(#2,#3)(#4,#5,#6){\def\!id{#1}% \xaux=#2% \yaux=#3% \alt=#4% \larg=#5% \prof=#6% } \def\!topaux#1.#2:{\!guarda#1} \def\!topo#1{\expandafter\!topaux#1} %% %% Pop : Stack -> Stack %% %% the empty stack is not taken care \def\!popaux#1.#2:{\def\pilha{#2:}} \def\!retira#1{\expandafter\!popaux#1} %% %% Compares words : Word x Word -> Bool %% %% compara - True if equal %% diferentes - True if not equal \def\!comparaaux#1#2{\let\argA=#1\let\argB=#2% \ifx\argA\argB\comparatrue\diferentesfalse\else\comparafalse\diferentestrue\fi} \def\!compara#1#2{\!comparaaux{#1}{#2}} %% Private Macro %% Absolute Value) %% \absoluto{n}{absn} %% input %% n - integer %% output %% absn - |n| \def\!absoluto#1#2{\aux=#1% \ifnum \aux > 0 #2=\aux \else \multiply \aux by -1 #2=\aux \fi} %% Name definitions for edge types and directions \def\solidarrow{0} \def\dashArrow{1} \def\dotArrow{2} \def\solidline{3} \def\dashline{4} \def\dotline{5} \def\injectionarrow{6} \def\aplicationarrow{7} \def\surjectivearrow{8} \def\equalline{9} \def\doublearrow{10} \def\doubleopposite{11} \def\nullarrow{12} %% Name definitions for edge label placement \def\atright{-1} \def\atleft{1} %% Tip direction for curved edges \def\pup{0} \def\pdown{1} \def\pright{2} \def\pleft{3} %% Type of graph \def\commdiag{0} \def\digraph{1} \def\undigraph{2} \def\cdigraph{3} \def\cundigraph{4} %% Positioning of labels in graphs \def\pcent{0} \def\north{1} \def\northeast{2} \def\east{3} \def\southeast{4} \def\south{5} \def\southwest{6} \def\west{7} \def\northwest{8} %%Private Macro %% Adjust the distance between the arrows and the objects regarding %% the dimensions of the objects. %% %% \ajusta{x}{xl}{y}{yl}{d}{Object} (ajusta = adjust) %% %% Input %% (x,y) e (xl,yl) - start, end coordinates of arrow %% d - distance specified by the user (default value, 100) %% Objecto - reference of the object pointed by the arrow %% Output %% d - adjusted distance %% %% The adjusted distance is the greatest value between 100 and the %% object's box dimensions. If the user specify a value this is not %% altered. %% %% If the arrow is horizontal the length is used. %% If the arrow is vertical the height is used for arrows in the 1st %% or 2nd quadrante, or the depth if the arrow is in the 3rd or 4th %% quadrante. If the arrow is oblique the value is chosen accordingly: %% from 315 to 45 degrees length is used %% from 45 to 135 degrees height is used %% from 135 to 225 degrees length is used %% from 225 to 315 degrees depth is used \def\!ajusta#1#2#3#4#5#6{\aux=#5% \let\auxobj=#6% \ifcase \tipografo % commutative diagrams \ifnum\number\aux=100 \ajustadisttrue % if needed, adjust \else \ajustadistfalse % if not, keeps unchanged \fi \else % graphs (directed, undirected, with frames) \ajustadistfalse \fi \ifajustadist \let\pilhaaux=\pilha% \loop% \!topo{\pilha}% \!retira{\pilha}% \!compara{\!id}{\auxobj}% \ifcompara\nvaziafalse \else\!pilhanvazia\pilha \fi% \ifnvazia% \repeat% %% push the values into the stack \let\pilha=\pilhaaux% \ifvazia% \ifdiferentes% %% %% It is not possible to make de adjustment given the fact that the %% user did not provide a label for the object in question. We set a %% value equal to the default value (100) %% \larg=131072% these values are for unit of .1pt \prof=65536% \alt=65536% \fi% \fi% \divide\larg by 13107% these values are for unit of .1pt \divide\prof by 6553% \divide\alt by 6553% \ifnum\number\yO=\number\yl %% Case 1 -- horizontal arrow %% %% with the division by 13107 we get half the size of the box, for a %% centered text, the adding of 30 is an empirical adjustment. \advance\larg by 30 \ifnum\number\larg>\aux #5=\larg \fi \else \ifnum\number\xO=\number\xl \ifnum\number\yl>\number\yO %% Case 2.1 -- vertical arrow, down direction %% \ifnum\number\alt>\aux #5=\alt \fi \else %% Case 2.2 -- vertical arrow, up direction %% %% with the division by 6553 we get the box height. The adjustment %% of 50 is an empirical adjustment. \advance\prof by 50 \ifnum\number\prof>\aux #5=\prof \fi \fi \else %% Case 3 -- oblique arrow %% Case 3.1 --- from 315o to 45o; |x-xl|>|y-yl| %% Case 3.3 --- from 135o to 225o; |x-xl|>|y-yl|; Length \auxqx=\xO \advance\auxqx by -\xl \!absoluto{\auxqx}{\auxqx}% \auxqy=\yO \advance\auxqy by -\yl \!absoluto{\auxqy}{\auxqy}% \ifnum\auxqx>\auxqy \ifnum\larg<100 \larg=100 \fi \advance\larg by 30 #5=\larg \else %% Case 3.2 --- from 45o to 135o; |x-xl|<|y-yl| e y>0; Length \ifnum\yl>\yO \ifnum\larg<100 \larg=100 \fi \advance\alt by 60 #5=\alt \else %% Case 3.4 -- from 225o to 315o; |x-xl|<|y-yl| e y<0; Depth \advance\prof by 110 #5=\prof \fi \fi \fi \fi \fi} % the branch else is missing %%Private Macro %% Square root %% raiz{n}{m} (raiz = root) %% -> %% n - natural number %% <- %% n - natural number %% m - greatest natural number less then the square root of n \def\!raiz#1#2{\auxa=#1% \auxb=1% \loop \aux=\auxb% \advance \aux by 1% \multiply \aux by \aux% \ifnum \aux < \auxa% \advance \auxb by 1% \paratrue% \else\ifnum \aux=\auxa% \advance \auxb by 1% \paratrue% \else\parafalse% \fi \fi \ifpara% \repeat #2=\auxb} %%Private Macro %% Find the starting and ending points of the "arrow" and also the %% label position (one coordinate at a time) %% %% ucoord{x1}{x2}{x3}{x4}{x5}{x6}{+|- 1} %% Input %% x1,x2,x3,x4,x5 %% Output %% x6 %% %% x2 - x1 %% x6 = x3 +|- ------- x4 %% x5 \def\!ucoord#1#2#3#4#5#6#7{\aux=#2% \advance \aux by -#1% \multiply \aux by #4% \divide \aux by #5% \ifnum #7 = -1 \multiply \aux by -1 \fi% \advance \aux by #3% #6=\aux} %%Private Macro %% Euclidean distance between two points %% %% quadrado = square %% %% quadrado{n}{m}{l} %% Input %% n - natural number %% m - natural number %% Output %% l = (n-m)*(n-m) \def\!quadrado#1#2#3{\aux=#1% \advance \aux by -#2% \multiply \aux by \aux% #3=\aux} %%Private Macro %% Euclidean distance between arrows and its tags %% %% Input %% (x,y), (x',y') morphism's name (tag) %% Output %% dnm - distance between an arrow and its tags %% (with a trim given by the tag's size %% Observations %% The trimming is for horizontal and vertical arrows %% only. Oblique arrows are dealt in a different way %% %% Algorithm %% caixa0 <- morfism name %% if x-xl = 0 then {vertical arrow} %% aux <- caixa0 width %% dnm <- converstion-sp-pt(aux)/2+3 %% else {non-vertical arrow} %% if y-yl = 0 then {horizontal arrow} %% aux <- caixa0 height+depth %% dnm <- converstion-sp-pt(aux)/2+3 %% else {oblique arrow} %% dnm <- 3 %% endif %% endif %% endalgorithm \def\!distnomemor#1#2#3#4#5#6{\setbox0=\hbox{#5}% \aux=#1 \advance \aux by -#3 \ifnum \aux=0 \aux=\wd0 \divide \aux by 13107%2 \advance \aux by 30 #6=\aux \else \aux=#2 \advance \aux by -#4 \ifnum \aux=0 \aux=\ht0 \advance \aux by \dp0 \divide \aux by 13107%2 \advance \aux by 30 #6=\aux% \else #6=30 \fi \fi } %% %% The environment "begindc...enddc" %% \def\begindc#1{\!ifnextchar[{\!begindc{#1}}{\!begindc{#1}[30]}} \def\!begindc#1[#2]{\beginpicture \let\pilha=\!vazia \setcoordinatesystem units <.1pt,.1pt> \expansao=#2 \ifcase #1 \distanciaobjmor=100 \tipoarco=0 % arrow \tipografo=0 % commutative diagram \or \distanciaobjmor=20 \tipoarco=0 % arrow \tipografo=1 % directed graph \or \distanciaobjmor=10 \tipoarco=3 % line \tipografo=2 % undirected graph \or \distanciaobjmor=80 \tipoarco=0 % arrow \tipografo=3 % directed graph \or \distanciaobjmor=80 \tipoarco=3 % line \tipografo=4 % undirected graph \fi} \def\enddc{\endpicture} \def\drawarrowhead <#1> [#2,#3]{% \!ifnextchar<{\!drawarrowhead{#1}{#2}{#3}}{\!drawarrowhead{#1}{#2}{#3}<\!zpt,\!zpt> }} % Xingliang Liang % ** \!ljoin (XCOORD,YCOORD) % ** Draws a straight line starting at the last point specified % ** by the most recent \!start, \!ljoin, or \!qjoin, and % ** ending at (XCOORD,YCOORD). \def\!ljoindummy (#1,#2){% \advance\!intervalno by 1 \!xE=\!M{#1}\!xunit \!yE=\!M{#2}\!yunit \!rotateaboutpivot\!xE\!yE \!xdiff=\!xE \advance \!xdiff by -\!xS%** xdiff = xE - xS \!ydiff=\!yE \advance \!ydiff by -\!yS%** ydiff = yE - yS \!Pythag\!xdiff\!ydiff\!arclength% ** arclength = sqrt(xdiff**2+ydiff**2) \global\advance \totalarclength by \!arclength% %\!drawlinearsegment% ** set by dashpat to \!linearsolid or \!lineardashed \!xS=\!xE \!yS=\!yE% ** shift ending points to starting points \ignorespaces} %% %% \!drawarrowhead{4pt}{DimC}{DimD} from {\xa} {\ya} to {\xb} {\yb} %% \def\!drawarrowhead#1#2#3<#4,#5> from #6 #7 to #8 #9 {% % % ** convert to dimensions \!xloc=\!M{#8}\!xunit \!yloc=\!M{#9}\!yunit \!dxpos=\!xloc \!dimenA=\!M{#6}\!xunit \advance \!dxpos -\!dimenA \!dypos=\!yloc \!dimenA=\!M{#7}\!yunit \advance \!dypos -\!dimenA \let\!MAH=\!M% ** save current c/d mode \!setdimenmode% ** go into dimension mode % \!xshift=#4\relax \!yshift=#5\relax% ** pick up shift \!reverserotateonly\!xshift\!yshift% ** back rotate shift \advance\!xshift\!xloc \advance\!yshift\!yloc % % ** draw shaft of arrow \!xS=-\!dxpos \advance\!xS\!xshift \!yS=-\!dypos \advance\!yS\!yshift \!start (\!xS,\!yS) \!ljoindummy (\!xshift,\!yshift) % % ** find 32*cosine and 32*sine of angle of rotation \!Pythag\!dxpos\!dypos\!arclength \!divide\!dxpos\!arclength\!dxpos \!dxpos=32\!dxpos \!removept\!dxpos\!!cos \!divide\!dypos\!arclength\!dypos \!dypos=32\!dypos \!removept\!dypos\!!sin % % ** construct arrowhead \!halfhead{#1}{#2}{#3}% ** draw half of arrow head \!halfhead{#1}{-#2}{-#3}% ** draw other half % \let\!M=\!MAH% ** restore old c/d mode \ignorespaces} %% Public macro: "mor" %% %% Funtion to built the "arrow" between two points %% %% The points that are uses to built all the elements of the "arrows" %% are: %% %% (xc,yc) %% o %% | %% o------o---------o---------o------o %%(x,y) (xa,ya) (xm,ym) (xb,yb)(xl,yl) %% %% auxa - distance between (x,y) and (xa,ya), 10pt by default %% auxb - distance between (xl,yl) and (xb,yb), 10pt by default %% \def\mor{% \!ifnextchar({\!morxy}{\!morObjA}} \def\!morxy(#1,#2){% \!ifnextchar({\!morxyl{#1}{#2}}{\!morObjB{#1}{#2}}} \def\!morxyl#1#2(#3,#4){% \!ifnextchar[{\!mora{#1}{#2}{#3}{#4}}{\!mora{#1}{#2}{#3}{#4}[\number\distanciaobjmor,\number\distanciaobjmor]}}% \def\!morObjA#1{% \let\pilhaaux=\pilha% \def\objPartida{#1}% \loop% \!topo\pilha% \!retira\pilha% \!compara{\!id}{\objPartida}% \ifcompara \nvaziafalse \else \!pilhanvazia\pilha \fi% \ifnvazia% \repeat% \ifvazia% \ifdiferentes% %% %% error message and ficticious parameters %% Error: Incorrect label specification% \xaux=1% \yaux=1% \fi% \fi% \let\pilha=\pilhaaux% \!ifnextchar({\!morxyl{\number\xaux}{\number\yaux}}{\!morObjB{\number\xaux}{\number\yaux}}} \def\!morObjB#1#2#3{% \xO=#1 \yO=#2 \def\objChegada{#3}% \let\pilhaaux=\pilha% \loop \!topo\pilha % \!retira\pilha% \!compara{\!id}{\objChegada}% \ifcompara \nvaziafalse \else \!pilhanvazia\pilha \fi \ifnvazia \repeat \ifvazia \ifdiferentes% %% %% error message and ficticious parameters %% Error: Incorrect label specification \xaux=\xO% \advance\xaux by \xO% \yaux=\yO% \advance\yaux by \yO% \fi \fi \let\pilha=\pilhaaux \!ifnextchar[{\!mora{\number\xO}{\number\yO}{\number\xaux}{\number\yaux}}{\!mora{\number\xO}{\number\yO}{\number\xaux}{\number\yaux}[\number\distanciaobjmor,\number\distanciaobjmor]}} \def\!mora#1#2#3#4[#5,#6]#7{% \!ifnextchar[{\!morb{#1}{#2}{#3}{#4}{#5}{#6}{#7}}{\!morb{#1}{#2}{#3}{#4}{#5}{#6}{#7}[1,\number\tipoarco] }} \def\!morb#1#2#3#4#5#6#7[#8,#9]{\xO=#1% \yO=#2% \xl=#3% \yl=#4% \multiply \xO by \expansao% \multiply \yO by \expansao% \multiply \xl by \expansao% \multiply \yl by \expansao% %% %% Euclidean distance between two points %% d = \sqrt((x-xl)^2+(y-yl)^2) %% \!quadrado{\number\xO}{\number\xl}{\auxa}% \!quadrado{\number\yO}{\number\yl}{\auxb}% \deuc=\auxa% \advance \deuc by \auxb% \!raiz{\deuc}{\deuc}% %% %% the point (xa,ya) is at a distance #5 (default value 100) from the %% point (x,y) %% %% given the fact that we have two points (start,end) we need to %% recover their value searching the stack \auxa=#5 \!compara{\objNulo}{\objPartida}% \ifdiferentes% adjusting only when needed \!ajusta{\xO}{\xl}{\yO}{\yl}{\auxa}{\objPartida}% \ajustatrue \def\objPartida{}% reset the value of the starting object \fi %% save the value of aux (after adjustment) to be used in the case of %% an injective morphism \guardaauxa=\auxa %% \!ucoord{\number\xO}{\number\xl}{\number\xO}{\auxa}{\number\deuc}{\xa}{1}% \!ucoord{\number\yO}{\number\yl}{\number\yO}{\auxa}{\number\deuc}{\ya}{1}% %% auxa has the value of the distance between the objects minus the %% distance between the arrow and the objects (100 default value) \auxa=\deuc% %% %% the point (xb,yb) is at a distance #6 (default value 100) from the %% point (xl,yl) %% \auxb=#6 \!compara{\objNulo}{\objChegada}% \ifdiferentes% adjusting only when needed % adjustment \!ajusta{\xO}{\xl}{\yO}{\yl}{\auxb}{\objChegada}% \def\objChegada{}% reset the value of the end object \fi \advance \auxa by -\auxb% \!ucoord{\number\xO}{\number\xl}{\number\xO}{\number\auxa}{\number\deuc}{\xb}{1}% \!ucoord{\number\yO}{\number\yl}{\number\yO}{\number\auxa}{\number\deuc}{\yb}{1}% \xmed=\xa% \advance \xmed by \xb% \divide \xmed by 2 \ymed=\ya% \advance \ymed by \yb% \divide \ymed by 2 %% %% find the coordinates of the label position: (xc,yc) %% %% after this the values of xmed and ymed are no longer important %% \!distnomemor{\number\xO}{\number\yO}{\number\xl}{\number\yl}{#7}{\dnm}% \!ucoord{\number\yO}{\number\yl}{\number\xmed}{\number\dnm}{\number\deuc}{\xc}{-#8}% \!ucoord{\number\xO}{\number\xl}{\number\ymed}{\number\dnm}{\number\deuc}{\yc}{#8}% %% %% draw the "arrow" %% \ifcase #9 % 0=solid arrow \arrow <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb} \or % 1=dashed arrow \setdashes <2pt> \plot {\xa} {\ya} {\xb} {\yb} / \setsolid% \drawarrowhead <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb} \or % 2=dotted arrow (Xingliang Liang - 4.4.0) \setdots <2pt> \plot {\xa} {\ya} {\xb} {\yb} / \setsolid% \drawarrowhead <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb} \or % 3=solid line \setlinear \plot {\xa} {\ya} {\xb} {\yb} / \or % 4=dashed line \setdashes <2pt> \setlinear \plot {\xa} {\ya} {\xb} {\yb} / \setsolid \or % 5=dotted line \setdots <2pt> \setlinear \plot {\xa} {\ya} {\xb} {\yb} / \setsolid \or % 6=injective arrow %% %% 30 units, the radius for the tail of the arrow %% %% recover the value of auxa \auxa=\guardaauxa %% makes an adjustment to cope with the tail of the arrow, giving %% space to the semi-circle \advance \auxa by 30% %% %% Note: the values of (xa,ya) will be modified, they will be %% "pushed" further away from (x,y) in order to acomodate the tail %% of the "arrow" %% %% find the point (xd,yd), the center of a 2pt (20*0.1) circle %% \!ucoord{\number\xO}{\number\xl}{\number\xO}{\number\auxa}{\number\deuc}{\xa}{1}% \!ucoord{\number\yO}{\number\yl}{\number\yO}{\number\auxa}{\number\deuc}{\ya}{1}% \!ucoord{\number\yO}{\number\yl}{\number\xa}{20}{\number\deuc}{\xd}{-1}% \!ucoord{\number\xO}{\number\xl}{\number\ya}{20}{\number\deuc}{\yd}{1}% %% building the "arrow" \arrow <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb} %% and its "tail" \circulararc -180 degrees from {\xa} {\ya} center at {\xd} {\yd} \or % 7=maps "arrow" ("|-->") \auxa=20 % %% %% Note: the values of xmed and ymed will be modified %% %% find the two points that defines the tail of the arrow (segment %% (xmed,ymed)(xd,yd)) \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xmed}{-1}% \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\ymed}{1}% \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xd}{1}% \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\yd}{-1}% %% building the "arrow" \arrow <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb} %% and its "tail" \setlinear \plot {\xmed} {\ymed} {\xd} {\yd} / \or % 8=surjective arrow ("-->>") %% building arrow with the first tip \arrow <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb} %% and the second tip \setlinear \arrow <6pt> [0,.72] from {\xa} {\ya} to {\xb} {\yb} \or % 9=equalline %% by Ruben Debeerst: equal-line %% %% sets the separation (distance) between the two parallel lines, if %% horizontal or vertical 1pt (10*0.1) is enough, if not 1.1pt (11*0.1) \auxa=11 \ifnum\number\yO=\number\yl \auxa=10 \fi \ifnum\number\xO=\number\xl \auxa=10 \fi %% the two parallel lines will be given by (xmed,ymed)(xd,yd), and %% (xe,ye)(xf,yf) \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xmed}{-1}% \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\ymed}{1}% \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xd}{1}% \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\yd}{-1}% \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xe}{-1}% \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\ye}{1}% \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xf}{1}% \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\yf}{-1}% \setlinear \plot {\xmed} {\ymed} {\xe} {\ye} / \plot {\xd} {\yd} {\xf} {\yf} / \or % 10=double arrow %% %% sets the separation (distance) between the two parallel lines, if %% horizontal or vertical 2pt is enough, if not 2.5pt. The extra space %% is needed because of the arrow tip. \auxa=25 \ifnum\number\yO=\number\yl \auxa=20 \fi \ifnum\number\xO=\number\xl \auxa=20 \fi %% the two parallel lines will be given by (xmed,ymed)(xd,yd), and %% (xe,ye)(xf,yf) \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xmed}{-1}% \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\ymed}{1}% \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xd}{1}% \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\yd}{-1}% \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xe}{-1}% \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\ye}{1}% \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xf}{1}% \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\yf}{-1}% \arrow <4pt> [.2,1.1] from {\xmed} {\ymed} to {\xe} {\ye} \arrow <4pt> [.2,1.1] from {\xd} {\yd} to {\xf} {\yf} \or % 10=double arrow, opposite directions %% %% sets the separation (distance) between the two parallel lines, if %% horizontal or vertical 2pt is enough, if not 2.5pt. The extra space %% is needed because of the arrow tip. \auxa=22 \ifnum\number\yO=\number\yl \auxa=20 \fi \ifnum\number\xO=\number\xl \auxa=20 \fi %% the two parallel lines will be given by (xmed,ymed)(xd,yd), and %% (xe,ye)(xf,yf) \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xmed}{-1}% \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\ymed}{1}% \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xd}{1}% \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\yd}{-1}% \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xe}{-1}% \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\ye}{1}% \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xf}{1}% \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\yf}{-1}% \arrow <4pt> [.2,1.1] from {\xmed} {\ymed} to {\xe} {\ye} \arrow <4pt> [.2,1.1] from {\xf} {\yf} to {\xd} {\yd} \or % 11=null arrow (no arrow, only a label) %% %% does not draw the arrow, it allows to put two labels in one "arrow" %% \fi %% The label positioning. %% If the arrows are horizontal or verticals the box is built centered %% in the object center. If the arrows are oblique the box is built in %% such a way to avoid the arrow label, having in account the %% quadrante and the relative position of the arrow and the %% corresponding label \auxa=\xl \advance \auxa by -\xO% \ifnum \auxa=0 \put {#7} at {\xc} {\yc} \else \auxb=\yl \advance \auxb by -\yO% \ifnum \auxb=0 \put {#7} at {\xc} {\yc} \else \ifnum \auxa > 0 \ifnum \auxb > 0 \ifnum #8=1 \put {#7} [rb] at {\xc} {\yc} \else \put {#7} [lt] at {\xc} {\yc} \fi \else \ifnum #8=1 \put {#7} [lb] at {\xc} {\yc} \else \put {#7} [rt] at {\xc} {\yc} \fi \fi \else \ifnum \auxb > 0 \ifnum #8=1 \put {#7} [rt] at {\xc} {\yc} \else \put {#7} [lb] at {\xc} {\yc} \fi \else \ifnum #8=1 \put {#7} [lt] at {\xc} {\yc} \else \put {#7} [rb] at {\xc} {\yc} \fi \fi \fi \fi \fi } %% %% Curved arrow command %% %% \cmor(){