# arrowhead ,,in the middle'' of the line (arc) in psmatrix

Denis Girou Denis.Girou at idris.fr
Sun Dec 3 23:38:50 CET 2000

-----------------------------------------------------------------------------
This is the PSTricks mailing list, devoted to discussions about computational
graphics in (La)TeX using the PSTricks package from Timothy van Zandt.
For help using this mailing list, see instructions at the end of message.
-----------------------------------------------------------------------------

>>>>> "Jan.Krupa" == Jan Krupa <krupa at alpha.sggw.waw.pl> writes:

Jan.Krupa> Q1:
Jan.Krupa> I would like to draw in diagram a line (or curve or arc)
Jan.Krupa> which connects two nodes and  the line (or curve) is to be with
Jan.Krupa> arrowhead not at the end (or beginning) of the line (or curve)
Jan.Krupa> but in the middle of the line, more precisely somewhere between
Jan.Krupa> the beginning and the end of the line (arc).
Jan.Krupa> I use %\psmatrix  and %\ncline and %\ncarc
Jan.Krupa> e.g. node1 ---->---- node2

Jan.Krupa> It is easy to draw such line or arc with arrowhead in the middle
Jan.Krupa> outside psmatrix but I need them in diagram so I need to use
Jan.Krupa> e.g. psmatrix.

In December 97 (see the mailing list archives), I give a general solution
for some cases (\psline, \pspolygon, \psbezier). We can adapt it for the case
of \ncline and \nccurve, redefining the NCLine and NCCurve PostScript macros.

The case of lines is rather easy to handle. Obviously, the case of curves is
not. The code is really more complex, and it is not possible to compute
accurately the length of the curve to position the arrow exactly. So, you must
visually check the result and adapt the value of the ArrowInsidePos parameter
for these cases.

Jan.Krupa> Q2: How to set different rowsep and colsep for different
Jan.Krupa> part of psmatrix? E.g.
Jan.Krupa> rowsep between 1st and 2nd row is 2cm but between 2nd and 3rd is 3cm.
Jan.Krupa> Similar for column.

For rows, this is easy. Use the standard syntax \\[Dim] to add a vertical
space between two rows (betadoc2.ps page 29).

For columns, this is not so straigthforward, as this is not among the
functionalities offered. We can do it using the hook facilities, modifying
the value of the internal register (due to the grouping mechanism used
internally, this can't be done using the normal user level function).
And you must restore the old value for the next column.

\documentclass{article}

\usepackage{pst-node}

\pagestyle{empty}

\makeatletter

% DG addition begin - Dec. 18/19, 1997

% Adapted from \psset at arrows
\def\psset at ArrowInside#1{%
\begingroup
\pst at activearrows
\xdef\pst at tempg{<#1}%
\endgroup
\expandafter\psset@@ArrowInside\pst at tempg\@empty-\@empty\@nil
\if at pst\else
\fi}

\def\psset@@ArrowInside#1-#2\@empty#3\@nil{%
\@psttrue
\def\next##1,#1-##2,##3\@nil{\def\pst at tempg{##2}}%
\expandafter\next\pst at arrowtable,#1-#1,\@nil
\@ifundefined{psas@#2}%
{\@pstfalse\def\psk at ArrowInside{}}%
{\def\psk at ArrowInside{#2}}}

% Default value empty
\def\psk at ArrowInside{}

% Modified version of \pst at addarrowdef
/ArrowA {
\ifx\psk at arrowA\@empty
\pst at oplineto
\else
\pst at arrowdef{A}
moveto
\fi
} def
/ArrowB {
\ifx\psk at arrowB\@empty \else \pst at arrowdef{B} \fi
} def
/ArrowInside {
\ifx\psk at ArrowInside\@empty \else \pst at arrowdefA{Inside} \fi
} def
}}

% Adapted from \pst at arrowdef
\def\pst at arrowdefA#1{%
\ifnum\pst at repeatarrowsflag>\z@
/Arrow#1c [ 6 2 roll ] cvx def Arrow#1c
\fi
\tx at BeginArrow
\psk at arrowscale
\@nameuse{psas@\@nameuse{psk at Arrow#1}}
\tx at EndArrow}

% ArrowInsidePos parameter (default value 0.5)
\def\psset at ArrowInsidePos#1{\pst at checknum{#1}\psk at ArrowInsidePos}%
\psset at ArrowInsidePos{0.5}

% DG modification begin - Dec. 3, 2000

\pst at def{NCLine}<{%
NCCoor
tx at Dict begin
ArrowA
CP
% D.G. addition begin - Dec.  3, 2000
4 copy
/y1 ED
/x1 ED
/y2 ED
/x2 ED
x1
y1
x2 x1 sub \psk at ArrowInsidePos mul x1 add
y2 y1 sub \psk at ArrowInsidePos mul y1 add
ArrowInside
pop pop pop pop
4 2 roll
ArrowB
lineto
pop pop
end}>

% Warning: ArrowInsidePos could be inaccurately positioned
\pst at def{NCCurve}<{%
GetEdgeA
GetEdgeB
xA1 xB1 sub
yA1 yB1 sub
Pyth
2 div
dup
3 -1 roll mul
/ArmA ED
mul
/ArmB ED
/ArmTypeA 0 def
/ArmTypeB 0 def
GetArmA
GetArmB
xA2 yA2 xA1 yA1
% D.G. addition begin - Dec.  3, 2000
2 copy
/y0 ED
/x0 ED
tx at Dict begin
ArrowA
end
xB2 yB2 xB1 yB1
tx at Dict begin
ArrowB
end
% D.G. addition begin - Dec.  3, 2000
/y3 ED
/x3 ED
/y2 ED
/x2 ED
/y1 ED
/x1 ED
/t \psk at ArrowInsidePos def
/t0 t 0.99 mul def
/cx x1 x0 sub 3 mul def
/cy y1 y0 sub 3 mul def
/bx x2 x1 sub 3 mul cx sub def
/by y2 y1 sub 3 mul cy sub def
/ax x3 x0 sub cx sub bx sub def
/ay y3 y0 sub cy sub by sub def
ax t0 3 exp mul bx t0 t0 mul mul add cx t0 mul add x0 add
ay t0 3 exp mul by t0 t0 mul mul add cy t0 mul add y0 add
ax t 3 exp mul bx t t mul mul add cx t mul add x0 add
ay t 3 exp mul by t t mul mul add cy t mul add y0 add
ArrowInside pop pop pop pop
x1 y1 x2 y2 x3 y3
curveto
/LPutVar [ xA1 yA1 xA2 yA2 xB2 yB2 xB1 yB1 ] cvx def
/LPutPos { t LPutVar BezierMidpoint } def
/HPutPos { { HPutLines } HPutCurve } def
/VPutPos { { VPutLines } HPutCurve } def
}>

% DG modification end

\makeatother

\begin{document}

\psset{arrowscale=2}

\def\pscolhookiii{\global\pscolsep=0.5cm}
\def\pscolhookiv{\global\pscolsep=2cm}

\begin{psmatrix}[colsep=2,rowsep=2,mnode=circle]
[name=N11] N11 & [name=N12] N12 & [name=N13] N13 & [name=N14] N14 \\[0pt]
[name=N21] N21 & [name=N22] N22 & [name=N23] N23 & [name=N24] N24 \\[2cm]
[name=N31] N31 & [name=N32] N32 & [name=N33] N33 & [name=N34] N34
\end{psmatrix}
%
% Node connections
\ncline[ArrowInside=->,ArrowInsidePos=0.25]{N11}{N33}
\ncline[ArrowInside=-|,ArrowInsidePos=0.75]{<->}{N23}{N34}
\nccurve[angleB=90,ArrowInside={-]},ArrowInsidePos=0.6666]{N13}{N14}
\nccurve[angle=-90,ArrowInside=->,ArrowInsidePos=0.5]{N31}{N33}
\nccurve[angleA=90,angleB=180,ArrowInside=->,ArrowInsidePos=0.4]{N31}{N24}

\end{document}

D.G.

-----------------------------------------------------------------------------