% Copyright 2022 by Qrrbrbirlbel
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Free Documentation License.
%

\unless\ifcsname tikzextset\endcsname
  \input tikzext-util.tex
\fi

%% For the operators r-lr, r-rl, r-ud and r-du we need to check after TikZ found r
\let\tikzextorig@tikz@rect\tikz@rect
\def\tikz@rect{\pgfutil@ifnextchar e\tikzextorig@tikz@rect\tikzext@tikz@r}
\def\tikzext@tikz@r -{%
  \pgfutil@ifnextchar l\tikzext@ortho@lr{%
    \pgfutil@ifnextchar r\tikzext@ortho@rl{%
      \pgfutil@ifnextchar u\tikzext@ortho@ud{%
        \pgfutil@ifnextchar d\tikzext@ortho@du\tikz@expand
      }%
    }%
  }%
}
%% For the operator |-| we need to check after TikZ found |-
\let\tikzextorig@tikz@vh@lineto@next\tikz@vh@lineto@next
\def\tikz@vh@lineto@next{%
  \pgfutil@ifnextchar|{\expandafter\tikzext@ortho@vhv\pgfutil@gobble}%
    {\pgfutil@ifnextchar\tikz@activebar{\expandafter\tikzext@ortho@vhv\pgfutil@gobble}%
      {\tikzextorig@tikz@vh@lineto@next}}}
%% For the operator -|- we need to check after TikZ found -|
\let\tikzextorig@tikz@hv@lineto\tikz@hv@lineto
\def\tikz@hv@lineto{%
  \pgfutil@ifnextchar-{\expandafter\tikzext@ortho@hvh\pgfutil@gobble}%
    {\tikzextorig@tikz@hv@lineto}}

%% |-|[<opts>] and -|-[<opts>] are allowed
\def\tikzext@ortho@vhv{\pgfutil@ifnextchar[{\tikzext@ortho@opts\tikzext@ortho@vhv@next}{\tikzext@ortho@opts\tikzext@ortho@vhv@next[]}}
\def\tikzext@ortho@hvh{\pgfutil@ifnextchar[{\tikzext@ortho@opts\tikzext@ortho@hvh@next}{\tikzext@ortho@opts\tikzext@ortho@hvh@next[]}}

%% r-rl[<opts>], r-lr[<opts>], etc.
\def\tikzext@ortho@rl rl{\pgfutil@ifnextchar[{\tikzext@ortho@opts\tikzext@ortho@rl@next}{\tikzext@ortho@opts\tikzext@ortho@rl@next[]}}
\def\tikzext@ortho@lr lr{\pgfutil@ifnextchar[{\tikzext@ortho@opts\tikzext@ortho@lr@next}{\tikzext@ortho@opts\tikzext@ortho@lr@next[]}}
\def\tikzext@ortho@du du{\pgfutil@ifnextchar[{\tikzext@ortho@opts\tikzext@ortho@du@next}{\tikzext@ortho@opts\tikzext@ortho@du@next[]}}
\def\tikzext@ortho@ud ud{\pgfutil@ifnextchar[{\tikzext@ortho@opts\tikzext@ortho@ud@next}{\tikzext@ortho@opts\tikzext@ortho@ud@next[]}}

%% TikZ interjects are done, the rest is independent:
\newif\iftikzext@ortho@fromcenter
\newif\iftikzext@ortho@preflush
\tikzext@ortho@preflushtrue

%%% HVVH/UDLR
\tikzextset{%
  ortho/.code=\pgfqkeys{/tikz/ext/ortho}{#1},
  hvvh/.code=\pgfqkeys{/tikz/ext/ortho}{#1},%
  udlr/.code=\pgfqkeys{/tikz/ext/ortho}{#1},%
  ortho/.search also=/tikz,
  ortho/middle 0 to 1/.style={/tikz/ext/ortho/spacing=0},%
  ortho/from center/.is if=tikzext@ortho@fromcenter,%
  ortho/spacing/.code=% spacing = 0 or 1 means that the middle part are the pos-itions 0 to 1,
  %                                          the first part is -1 to 0, the last part is to 2
    \pgfmathint{#1}\let\tikzext@ortho@timing@parts\pgfmathresult% in case they are calculations to be done
    \ifnum\tikzext@ortho@timing@parts<2
      \def\tikzext@ortho@timing@parts{1}%
      \def\tikzext@ortho@timing@first{0}%
      \def\tikzext@ortho@timing@last{1}%
      \def\tikzext@ortho@timing@subtr{0}%
      \def\tikzext@ortho@timing@factor{1}%
    \else            % in all other cases n > 1 the kinks are at pos = 1/n and (n - 1)/n
      \pgfmathreciprocal{\tikzext@ortho@timing@parts}%
      \let\tikzext@ortho@timing@first\pgfmathresult
      \pgfmathsetmacro\tikzext@ortho@timing@last{1-\pgfmathresult}%
      \pgfmathreciprocal{\tikzext@ortho@timing@parts-2}%
      \let\tikzext@ortho@timing@subtr\pgfmathresult
      \pgfmathsetmacro\tikzext@ortho@timing@factor{1+2*\pgfmathresult}%
    \fi,%
  ortho/hvh ratio/.code=%
    \pgfkeyssetvalue{/tikz/ext/ortho/hvh distance}{}%
    \pgfkeyssetvalue{/tikz/ext/ortho/hvh ratio}{#1},
  ortho/vhv ratio/.code=%
    \pgfkeyssetvalue{/tikz/ext/ortho/vhv distance}{}%
    \pgfkeyssetvalue{/tikz/ext/ortho/vhv ratio}{#1},
  ortho/hvh distance/.code=%
    \pgfkeyssetvalue{/tikz/ext/ortho/hvh distance}{#1}%
    \pgfkeyssetvalue{/tikz/ext/ortho/hvh ratio}{},
  ortho/vhv distance/.code=%
    \pgfkeyssetvalue{/tikz/ext/ortho/vhv distance}{#1}%
    \pgfkeyssetvalue{/tikz/ext/ortho/vhv ratio}{},
  ortho/hvvh distance/.style={
    /tikz/ext/ortho/hvh distance={#1},
    /tikz/ext/ortho/vhv distance={#1}},
  ortho/hvvh ratio/.style={
    /tikz/ext/ortho/hvh ratio={#1},
    /tikz/ext/ortho/vhv ratio={#1}},
  ortho/ratio/.style={% there's no udlr ratio so we make ratio an alias to hvvh ratio
    /tikz/ext/ortho/hvh ratio={#1},
    /tikz/ext/ortho/vhv ratio={#1}},
  % with it's always a distance (or a unit in the xy cs)
  ortho/ud distance/.initial=+.5cm,
  ortho/du distance/.initial=+.5cm,
  ortho/lr distance/.initial=+.5cm,
  ortho/rl distance/.initial=+.5cm,
  ortho/udlr distance/.style={
    /tikz/ext/ortho/ud distance={#1},
    /tikz/ext/ortho/du distance={#1},
    /tikz/ext/ortho/lr distance={#1},
    /tikz/ext/ortho/rl distance={#1}},
  ortho/distance/.style={
    /tikz/ext/ortho/hvh distance={#1},
    /tikz/ext/ortho/vhv distance={#1},
    /tikz/ext/ortho/ud  distance={#1},
    /tikz/ext/ortho/du  distance={#1},
    /tikz/ext/ortho/lr  distance={#1},
    /tikz/ext/ortho/rl  distance={#1}},
  ortho/ratio=.5,% default value
  ortho/spacing=4,% default value
}%

%% collect options and nodes, coordinates and pics onpath
\let\tikzext@ortho@options\pgfutil@empty
\def\tikzext@ortho@opts#1[#2]{\def\tikzext@ortho@options{#2}#1}
\def\tikzext@ortho@hvh@next{%
  \pgfutil@ifnextchar n{\tikz@collect@label@onpath\tikzext@ortho@hvh@next}
    {\pgfutil@ifnextchar c{\tikz@collect@coordinate@onpath\tikzext@ortho@hvh@next}%
      {\pgfutil@ifnextchar p{\tikz@collect@pic@onpath\tikzext@ortho@hvh@next}{\tikz@scan@one@point\tikzext@ortho@hvh@do}}}}%
\def\tikzext@ortho@vhv@next{%
  \pgfutil@ifnextchar n{\tikz@collect@label@onpath\tikzext@ortho@vhv@next}
    {\pgfutil@ifnextchar c{\tikz@collect@coordinate@onpath\tikzext@ortho@vhv@next}%
      {\pgfutil@ifnextchar p{\tikz@collect@pic@onpath\tikzext@ortho@vhv@next}{\tikz@scan@one@point\tikzext@ortho@vhv@do}}}}%
\def\tikzext@ortho@ud@next{%
  \pgfutil@ifnextchar n{\tikz@collect@label@onpath\tikzext@ortho@ud@next}
    {\pgfutil@ifnextchar c{\tikz@collect@coordinate@onpath\tikzext@ortho@ud@next}
      {\pgfutil@ifnextchar p{\tikz@collect@pic@onpath\tikzext@ortho@ud@next}{\tikz@scan@one@point\tikzext@ortho@ud@do}}}}%
\def\tikzext@ortho@du@next{%
  \pgfutil@ifnextchar n{\tikz@collect@label@onpath\tikzext@ortho@du@next}
    {\pgfutil@ifnextchar c{\tikz@collect@coordinate@onpath\tikzext@ortho@du@next}
      {\pgfutil@ifnextchar p{\tikz@collect@pic@onpath\tikzext@ortho@du@next}{\tikz@scan@one@point\tikzext@ortho@du@do}}}}%
\def\tikzext@ortho@lr@next{%
  \pgfutil@ifnextchar n{\tikz@collect@label@onpath\tikzext@ortho@lr@next}
    {\pgfutil@ifnextchar c{\tikz@collect@coordinate@onpath\tikzext@ortho@lr@next}
      {\pgfutil@ifnextchar p{\tikz@collect@pic@onpath\tikzext@ortho@lr@next}{\tikz@scan@one@point\tikzext@ortho@lr@do}}}}%
\def\tikzext@ortho@rl@next{%
  \pgfutil@ifnextchar n{\tikz@collect@label@onpath\tikzext@ortho@rl@next}
    {\pgfutil@ifnextchar c{\tikz@collect@coordinate@onpath\tikzext@ortho@rl@next}
      {\pgfutil@ifnextchar p{\tikz@collect@pic@onpath\tikzext@ortho@rl@next}{\tikz@scan@one@point\tikzext@ortho@rl@do}}}}%

\def\tikzext@ortho@do#1#2#3#4{%
  % #1 = first kink
  % #2 = second kink
  % #3 = end
  % #4 = tikz@shapeborder@name
  \pgfpathlineto{#1}%
  \pgfpathlineto{#2}%
  \pgfpathlineto{#3}%
  \def\tikzext@ortho@timer@kinkA{#1}%
  \def\tikzext@ortho@timer@kinkB{#2}%
  \def\tikz@timer@end{#3}%
  \let\tikz@timer\tikzext@ortho@timer
  \def\tikzext@temp{#4}%
  \ifx\tikzext@temp\pgfutil@empty
    \let\tikz@moveto@waiting\relax
  \else
    \let\tikz@moveto@waiting\tikzext@temp
  \fi
  \tikz@scan@next@command}%

\def\tikzext@ortho@timer{%
  \pgfutil@tempdima=\tikz@time pt
  \ifdim\pgfutil@tempdima<\tikzext@ortho@timer@first pt % first quarter
    \ifnum\tikzext@ortho@timer@parts=1
      \advance\pgfutil@tempdima1pt
    \else
      \pgfutil@tempdima\tikzext@ortho@timer@parts\pgfutil@tempdima
    \fi
    \pgftransformlineattime{\pgf@sys@tonumber\pgfutil@tempdima}{\tikz@timer@start}{\tikzext@ortho@timer@kinkA}%
  \else
    \ifdim\pgfutil@tempdima>\tikzext@ortho@timer@last pt %last quarter
      \ifnum\tikzext@ortho@timer@parts=1
        \advance\pgfutil@tempdima-1pt%
      \else
        \pgfutil@tempdima\tikzext@ortho@timer@parts\pgfutil@tempdima
      \fi
      \advance\pgfutil@tempdima-\tikzext@ortho@timer@parts pt
      \advance\pgfutil@tempdima1pt
      \pgftransformlineattime{\pgf@sys@tonumber\pgfutil@tempdima}{\tikzext@ortho@timer@kinkB}{\tikz@timer@end}%
    \else % middle bit
      \pgfutil@tempdima=\tikzext@ortho@timer@factor\pgfutil@tempdima
      \advance\pgfutil@tempdima-\tikzext@ortho@timer@subtr pt
      \pgftransformlineattime{\pgf@sys@tonumber\pgfutil@tempdima}{\tikzext@ortho@timer@kinkA}{\tikzext@ortho@timer@kinkB}%
    \fi
  \fi
}

\def\tikzext@ortho@savetimer{%
  \def\noexpand\tikzext@ortho@timer@parts{\tikzext@ortho@timing@parts}%
  \def\noexpand\tikzext@ortho@timer@first{\tikzext@ortho@timing@first}%
  \def\noexpand\tikzext@ortho@timer@last{\tikzext@ortho@timing@last}%
  \def\noexpand\tikzext@ortho@timer@subtr{\tikzext@ortho@timing@subtr}%
  \def\noexpand\tikzext@ortho@timer@factor{\tikzext@ortho@timing@factor}%
}
%% -|- operator
\def\tikzext@ortho@hvh@do#1{%
  \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
  \pgf@xb=\tikz@lastx
  \pgf@xc=\tikz@lastx
  \pgf@yc=\tikz@lasty
  \tikz@make@last@position{#1}%
  \tikz@flush@moveto@toward{\pgfqpoint{\tikz@lastx}{\pgf@yc}}\pgf@xc\pgf@yc
  \begingroup
    \def\tikzext@temp{\pgfqkeys{/tikz/ext/ortho}}%
    \expandafter\tikzext@temp\expandafter{\tikzext@ortho@options}%
    \edef\tikzext@ortho@ratio{\pgfkeysvalueof{/tikz/ext/ortho/hvh ratio}}%
    \ifx\tikzext@ortho@ratio\pgfutil@empty
      \pgfmathparse{\pgfkeysvalueof{/tikz/ext/ortho/hvh distance}}%
      \ifpgfmathunitsdeclared
        \pgfutil@tempdima=\pgfmathresult pt
      \else
        \pgf@process{\pgfqpointxy{\pgfmathresult}{0}}%
        \ifdim\pgf@x<0pt
          \pgf@x=-\pgf@x
        \fi
        \ifdim\pgfmathresult pt<0pt
          \pgf@x=-\pgf@x 
        \fi
        \pgfutil@tempdima=\pgf@x
      \fi
    \else
      \pgfmathsetmacro\tikzext@ortho@ratio{\tikzext@ortho@ratio}%
    \fi
    \iftikz@shapeborder
      \pgf@process{\pgfpointshapeborder{\tikz@shapeborder@name}{\pgfqpoint{\pgf@xb}{\tikz@lasty}}}%
      \iftikzext@ortho@fromcenter
        \pgf@xc\pgf@xb
      \fi
      \ifx\tikzext@ortho@ratio\pgfutil@empty
        \ifdim\pgfutil@tempdima<0pt\relax
          \iftikzext@ortho@fromcenter
            \pgf@xc\tikz@lastx
          \else
            \pgf@xc\pgf@x
          \fi
        \fi
        \ifdim\pgf@xb>\tikz@lastx
          \pgfutil@tempdima-\pgfutil@tempdima
        \fi
      \else
        \iftikzext@ortho@fromcenter
          \pgfutil@tempdima\tikz@lastx
        \else
          \pgfutil@tempdima\pgf@x
        \fi
        \advance\pgfutil@tempdima-\pgf@xc
        \pgfutil@tempdima\tikzext@ortho@ratio\pgfutil@tempdima
      \fi
      \advance\pgf@xc\pgfutil@tempdima
      \edef\pgf@tempa{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
      \edef\pgf@tempb{\noexpand\pgfqpoint{\the\pgf@xc}{\the\tikz@lasty}}%
      \edef\pgf@temp{\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
    \else
      \let\tikz@shapeborder@name\pgfutil@empty
      \iftikzext@ortho@fromcenter
        \pgf@xc\pgf@xb
      \fi
      \ifx\tikzext@ortho@ratio\pgfutil@empty
        \ifdim\pgfutil@tempdima<0pt\relax
          \pgf@xc\tikz@lastx
        \fi
        \ifdim\pgf@xb>\tikz@lastx
          \pgfutil@tempdima-\pgfutil@tempdima
        \fi
      \else
        \pgfutil@tempdima\tikz@lastx
        \advance\pgfutil@tempdima-\pgf@xc
        \pgfutil@tempdima\tikzext@ortho@ratio\pgfutil@tempdima
      \fi
      \advance\pgf@xc\pgfutil@tempdima
      \edef\pgf@tempa{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
      \edef\pgf@tempb{\noexpand\pgfqpoint{\the\pgf@xc}{\the\tikz@lasty}}%
      \edef\pgf@temp{\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
    \fi%
    \edef\tikzext@temp{%
  \endgroup
      \tikzext@ortho@savetimer
      \noexpand\tikzext@ortho@do
        {\expandafter\noexpand\pgf@tempa}%
        {\expandafter\noexpand\pgf@tempb}%
        {\expandafter\noexpand\pgf@temp}%
        {\tikz@shapeborder@name}}%
  \tikzext@temp
}%

%% |-| operator
\def\tikzext@ortho@vhv@do#1{%
  \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
  \pgf@xc=\tikz@lastx
  \pgf@yb=\tikz@lasty
  \pgf@yc=\tikz@lasty
  \tikz@make@last@position{#1}%
  \tikz@flush@moveto@toward{\pgfqpoint{\pgf@xc}{\tikz@lasty}}\pgf@xc\pgf@yc
  \begingroup
    \def\tikzext@temp{\pgfqkeys{/tikz/ext/ortho}}%
    \expandafter\tikzext@temp\expandafter{\tikzext@ortho@options}%
    \edef\tikzext@ortho@ratio{\pgfkeysvalueof{/tikz/ext/ortho/vhv ratio}}%
    \ifx\tikzext@ortho@ratio\pgfutil@empty
      \pgfmathparse{\pgfkeysvalueof{/tikz/ext/ortho/vhv distance}}%
      \ifpgfmathunitsdeclared
        \pgfutil@tempdima=\pgfmathresult pt
      \else
        \typeout{\pgfmathresult\space before}%
        \pgf@process{\pgfqpointxy{0}{\pgfmathresult}}%
        \ifdim\pgf@y<0pt
          \pgf@y=-\pgf@y
        \fi
        \ifdim\pgfmathresult pt<0pt
          \pgf@y=-\pgf@y
        \fi
        \typeout{\pgfmathresult\space after, \the\pgf@y}%
        \pgfutil@tempdima=\pgf@y
      \fi
    \else
      \pgfmathsetmacro\tikzext@ortho@ratio{\tikzext@ortho@ratio}%
    \fi
    \iftikz@shapeborder
      \pgf@process{\pgfpointshapeborder{\tikz@shapeborder@name}{\pgfqpoint{\tikz@lastx}{\pgf@yb}}}%
      \iftikzext@ortho@fromcenter
        \pgf@yc\pgf@yb
      \fi
      \ifx\tikzext@ortho@ratio\pgfutil@empty
        \ifdim\pgfutil@tempdima<0pt\relax
          \iftikzext@ortho@fromcenter
            \pgf@yc\tikz@lasty
          \else
            \pgf@yc\pgf@y
          \fi
        \fi
        \ifdim\pgf@yb>\tikz@lasty
          \pgfutil@tempdima-\pgfutil@tempdima
        \fi
      \else
        \iftikzext@ortho@fromcenter
          \pgfutil@tempdima\tikz@lasty
        \else
          \pgfutil@tempdima\pgf@y
        \fi
        \advance\pgfutil@tempdima-\pgf@yc
        \pgfutil@tempdima\tikzext@ortho@ratio\pgfutil@tempdima
      \fi
      \advance\pgf@yc\pgfutil@tempdima
      \edef\pgf@tempa{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
      \edef\pgf@tempb{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\pgf@yc}}%
      \edef\pgf@temp{\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
    \else
      \let\tikz@shapeborder@name\pgfutil@empty
      \iftikzext@ortho@fromcenter
        \pgf@yc\pgf@yb
      \fi
      \ifx\tikzext@ortho@ratio\pgfutil@empty
        \ifdim\pgfutil@tempdima<0pt\relax
          \pgf@yc\tikz@lasty
        \fi
        \ifdim\pgf@yb>\tikz@lasty
          \pgfutil@tempdima-\pgfutil@tempdima
        \fi
      \else
        \pgfutil@tempdima\tikz@lasty
        \advance\pgfutil@tempdima-\pgf@yc
        \pgfutil@tempdima\tikzext@ortho@ratio\pgfutil@tempdima
      \fi
      \advance\pgf@yc\pgfutil@tempdima
      \edef\pgf@tempa{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
      \edef\pgf@tempb{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\pgf@yc}}%
      \edef\pgf@temp{\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
    \fi%
    \edef\tikzext@temp{%
  \endgroup
      \tikzext@ortho@savetimer
      \noexpand\tikzext@ortho@do
        {\expandafter\noexpand\pgf@tempa}%
        {\expandafter\noexpand\pgf@tempb}%
        {\expandafter\noexpand\pgf@temp}%
        {\tikz@shapeborder@name}}%
    \tikzext@temp
}

%% r-ud operator
\def\tikzext@ortho@ud@do#1{\tikzext@ortho@uddu@do{#1}{}{ud}{<}}

%% r-du operator
\def\tikzext@ortho@du@do#1{\tikzext@ortho@uddu@do{#1}{-}{du}{>}}

%% r-lr operator
\def\tikzext@ortho@lr@do#1{\tikzext@ortho@lrrl@do{#1}{-}{lr}{>}}

%% r-rl operator
\def\tikzext@ortho@rl@do#1{\tikzext@ortho@lrrl@do{#1}{}{rl}{<}}

% ud/du
\def\tikzext@ortho@uddu@do#1#2#3#4{%
 \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
  \pgf@xc\tikz@lastx
  \pgf@yb\tikz@lasty
  \advance\tikz@lasty#21pt%
  \let\pgf@temp\tikz@moveto@waiting
  \tikz@flush@moveto@toward{\pgfqpoint{\tikz@lastx}{\tikz@lasty}}\pgf@xc\pgf@yc
  \tikz@make@last@position{#1}%
  \begingroup
    \def\tikzext@temp{\pgfqkeys{/tikz/ext/ortho}}%
    \expandafter\tikzext@temp\expandafter{\tikzext@ortho@options}%
    \pgfmathparse{\pgfkeysvalueof{/tikz/ext/ortho/#3 distance}}%
    \ifpgfmathunitsdeclared
      \pgfutil@tempdima=\pgfmathresult pt
    \else
      \pgf@process{\pgfqpointxy{0}{\pgfmathresult}}%
      \pgfutil@tempdima=\pgf@y
      \ifdim\pgfutil@tempdima<0pt
        \pgfutil@tempdima=-\pgfutil@tempdima
      \fi
    \fi
    \iftikz@shapeborder
      \advance\pgf@y#21pt%
      \pgf@process{\pgfpointshapeborder{\tikz@shapeborder@name}{\pgfqpoint{\pgf@x}{\pgf@y}}}%
      \iftikzext@ortho@fromcenter
        \pgf@yc\pgf@yb
      \else\ifx\pgf@temp\relax
          \pgf@yc\pgf@yb
        \fi
      \fi
      \ifdim\pgf@yc#4\pgf@y
        \iftikzext@ortho@fromcenter
          \pgf@yc=\tikz@lasty
        \else
          \pgf@yc=\pgf@y
        \fi
      \fi
      \advance\pgf@yc#2\pgfutil@tempdima
      \edef\pgf@temp{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
    \else
      \let\tikz@shapeborder@name\pgfutil@empty
      \ifx\pgf@temp\relax\else
        \iftikzext@ortho@fromcenter\else
          \pgf@yb\pgf@yc
        \fi
      \fi
      \ifdim\pgf@yb#4\tikz@lasty\pgf@yb\tikz@lasty\fi
      \advance\pgf@yb#2\pgfutil@tempdima
      \pgf@yc\pgf@yb
      \edef\pgf@temp{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
    \fi
    \edef\tikzext@temp{%
  \endgroup
      \tikzext@ortho@savetimer
      \noexpand\tikzext@ortho@do
        {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
        {\noexpand\pgfqpoint{\the\tikz@lastx}{\the\pgf@yc}}%
        {\expandafter\noexpand\pgf@temp}%
        {\tikz@shapeborder@name}}%
  \tikzext@temp
}

%% lr/rl
\def\tikzext@ortho@lrrl@do#1#2#3#4{%
  \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
  \pgf@xb\tikz@lastx
  \pgf@yc\tikz@lasty
  \advance\tikz@lastx#21pt%
  \let\pgf@temp\tikz@moveto@waiting
  \tikz@flush@moveto@toward{\pgfqpoint{\tikz@lastx}{\tikz@lasty}}\pgf@xc\pgf@yc
  \tikz@make@last@position{#1}%
  \begingroup
    \def\tikzext@temp{\pgfqkeys{/tikz/ext/ortho}}%
    \expandafter\tikzext@temp\expandafter{\tikzext@ortho@options}%
    \pgfmathparse{\pgfkeysvalueof{/tikz/ext/ortho/#3 distance}}%
    \ifpgfmathunitsdeclared
      \pgfutil@tempdima=\pgfmathresult pt
    \else
      \pgf@process{\pgfqpointxy{\pgfmathresult}{0}}%
      \pgfutil@tempdima=\pgf@x
      \ifdim\pgfutil@tempdima<0pt
        \pgfutil@tempdima=-\pgfutil@tempdima
      \fi
    \fi
    \iftikz@shapeborder
      \advance\pgf@x#21pt%
      \pgf@process{\pgfpointshapeborder{\tikz@shapeborder@name}{\pgfqpoint{\pgf@x}{\pgf@y}}}%
      \iftikzext@ortho@fromcenter
        \pgf@xc\pgf@xb
      \else\ifx\pgf@temp\relax
          \pgf@xc\pgf@xb
        \fi
      \fi
      \ifdim\pgf@xc#4\pgf@x
        \iftikzext@ortho@fromcenter
          \pgf@xc=\tikz@lastx
        \else
          \pgf@xc=\pgf@x
        \fi
      \fi
      \advance\pgf@xc#2\pgfutil@tempdima
      \edef\pgf@temp{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
    \else
      \let\tikz@shapeborder@name\pgfutil@empty
      \ifx\pgf@temp\relax\else
        \iftikzext@ortho@fromcenter\else
          \pgf@xb\pgf@xc
        \fi
      \fi
      \ifdim\pgf@xb#4\tikz@lastx\pgf@xb\tikz@lastx\fi
      \advance\pgf@xb#2\pgfutil@tempdima
      \pgf@xc\pgf@xb
      \edef\pgf@temp{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
    \fi
    \edef\tikzext@temp{%
  \endgroup
      \tikzext@ortho@savetimer
      \noexpand\tikzext@ortho@do
        {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
        {\noexpand\pgfqpoint{\the\pgf@xc}{\the\tikz@lasty}}%
        {\expandafter\noexpand\pgf@temp}%
        {\tikz@shapeborder@name}}%
  \tikzext@temp
}

%% a few nice to haves, use with to or edge operator
\tikzextset{
  node as new start/.is if=tikzext@ortho@preflush,
  node as new start,
  ortho/install shortcuts/.style={
    *|/.style={/tikz/ext/only vertical   second={##1}}, *|/.default=,
    |*/.style={/tikz/ext/only vertical   first={##1}},  |*/.default=,
    *-/.style={/tikz/ext/only horizontal second={##1}}, *-/.default=,
    -*/.style={/tikz/ext/only horizontal first={##1}},  -*/.default=,
    |-/.style={/tikz/to path={|-(\tikztotarget)\tikztonodes}},
    -|/.style={/tikz/to path={-|(\tikztotarget)\tikztonodes}},
    -|-/.style={/tikz/ext/horizontal vertical horizontal={##1}}, -|-/.default=,
    |-|/.style={/tikz/ext/vertical   horizontal vertical={##1}}, |-|/.default=,
    r-du/.style={/tikz/ext/down horizontal up={##1}}, r-du/.default=,
    r-ud/.style={/tikz/ext/up horizontal down={##1}}, r-ud/.default=,
    r-rl/.style={/tikz/ext/right vertical left={##1}}, r-rl/.default=,
    r-lr/.style={/tikz/ext/left vertical right={##1}}, r-lr/.default=%
  },
  horizontal vertical/.style={/tikz/to path={-|(\tikztotarget)\tikztonodes}},
  vertical horizontal/.style={/tikz/to path={|-(\tikztotarget)\tikztonodes}},
  horizontal vertical horizontal/.default=,
  horizontal vertical horizontal/.style={/tikz/to path={-|-[{#1}](\tikztotarget)\tikztonodes}},
  vertical horizontal vertical/.default=,
  vertical horizontal vertical/.style={/tikz/to path={|-|[{#1}](\tikztotarget)\tikztonodes}},
  right vertical left/.default=,
  right vertical left/.style={/tikz/to path={r-rl[{#1}](\tikztotarget)\tikztonodes]}},
  left vertical right/.default=,
  left vertical right/.style={/tikz/to path={r-lr[{#1}](\tikztotarget)\tikztonodes]}},
  up horizontal down/.default=,
  up horizontal down/.style={/tikz/to path={r-ud[{#1}](\tikztotarget)\tikztonodes]}},
  down horizontal up/.default=,
  down horizontal up/.style={/tikz/to path={r-du[{#1}](\tikztotarget)\tikztonodes]}},
  only vertical second/.style={/tikz/to path={
    \pgfextra
      \let\tikzext@ortho@anchor\pgfutil@empty
      \let\tikzext@origtotarget\pgfutil@empty
      \tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
      \iftikz@shapeborder
        \tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
        \ifdim\pgf@y>\tikz@lasty\relax
          \edef\tikztostart{\tikztostart.north}%
          \iftikz@shapeborder\def\tikzext@ortho@anchor{.south}\fi
        \else
          \edef\tikztostart{\tikztostart.south}%
          \iftikz@shapeborder\def\tikzext@ortho@anchor{.north}\fi
        \fi
      \fi
      \def\tikz@tempa{#1}%
      \ifx\tikz@tempa\pgfutil@empty\else
        \let\tikzext@origtotarget\tikztotarget
        \edef\tikztotarget{[xshift={#1}]\tikztotarget\tikzext@ortho@anchor}%
      \fi
    \endpgfextra
    \pgfkeys@expanded{%
      (perpendicular cs: horizontal line through={(\tikztostart)},
                         vertical line through={(\tikztotarget)}) -- (\tikztotarget)}\tikztonodes
      \pgfextra
        \ifx\tikzext@origtotarget\pgfutil@empty\else
          \iftikzext@ortho@preflush(\tikzext@origtotarget)\fi\fi\endpgfextra}},
  only vertical second/.default=,
  only horizontal second/.style={/tikz/to path={
    \pgfextra
      \let\tikzext@ortho@anchor\pgfutil@empty
      \let\tikzext@origtotarget\pgfutil@empty
      \tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
      \iftikz@shapeborder
        \tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
        \ifdim\pgf@x>\tikz@lastx\relax
          \edef\tikztostart{\tikztostart.east}%
          \iftikz@shapeborder\def\tikzext@ortho@anchor{.west}\fi
        \else
          \edef\tikztostart{\tikztostart.west}%
          \iftikz@shapeborder\def\tikzext@ortho@anchor{.east}\fi
        \fi
      \fi
      \def\tikz@tempa{#1}%
      \ifx\tikz@tempa\pgfutil@empty\else
        \let\tikzext@origtotarget\tikztotarget
        \edef\tikztotarget{[yshift={#1}]\tikztotarget\tikzext@ortho@anchor}%
      \fi
    \endpgfextra
    \pgfkeys@expanded{%
      (perpendicular cs: vertical line through={(\tikztostart)},
                         horizontal line through={(\tikztotarget)}) -- (\tikztotarget)}\tikztonodes
    \pgfextra
      \ifx\tikzext@origtotarget\pgfutil@empty\else
        \iftikzext@ortho@preflush(\tikzext@origtotarget)\fi\fi\endpgfextra}},
  only horizontal second/.default=,
  only vertical first/.style={/tikz/to path={
    \pgfextra
      \let\tikzext@ortho@anchor\pgfutil@empty
      \let\tikzext@origtotarget\pgfutil@empty
      \tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
      \pgf@ya=\pgf@y
      \iftikz@shapeborder
        \let\tikzext@origtotarget\tikztotarget
        \tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
        \ifdim\pgf@ya>\tikz@lasty\relax
          \edef\tikztotarget{\tikztotarget.south}%
          \iftikz@shapeborder\def\tikzext@ortho@anchor{.north}\fi
        \else
          \edef\tikztotarget{\tikztotarget.north}%
          \iftikz@shapeborder\def\tikzext@ortho@anchor{.south}\fi
        \fi
      \fi
      \def\tikz@tempa{#1}%
      \ifx\tikz@tempa\pgfutil@empty\else
        \edef\tikztostart{[xshift={#1}]\tikztostart\tikzext@ortho@anchor}%
      \fi
    \endpgfextra
    \expandafter(\tikztostart)
    -- (perpendicular cs: vertical line through/.expanded={(\tikztostart)},
                        horizontal line through={(\tikztotarget)})
    \tikztonodes
    \pgfextra
      \ifx\tikzext@origtotarget\pgfutil@empty\else
        \iftikzext@ortho@preflush(\tikzext@origtotarget)\fi\fi\endpgfextra}},
  only vertical first/.default=,
  only horizontal first/.style={/tikz/to path={
    \pgfextra
      \let\tikzext@ortho@anchor\pgfutil@empty
      \let\tikzext@origtotarget\pgfutil@empty
      \tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
      \pgf@xa=\pgf@x
      \iftikz@shapeborder
        \let\tikzext@origtotarget\tikztotarget
        \tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
        \ifdim\pgf@xa>\tikz@lastx\relax
          \edef\tikztotarget{\tikztotarget.west}%
          \iftikz@shapeborder\def\tikzext@ortho@anchor{.east}\fi
        \else
          \edef\tikztotarget{\tikztotarget.east}%
          \iftikz@shapeborder\def\tikzext@ortho@anchor{.west}\fi
        \fi
      \fi
      \def\tikz@tempa{#1}%
      \ifx\tikz@tempa\pgfutil@empty\else
        \edef\tikztostart{[yshift={#1}]\tikztostart\tikzext@ortho@anchor}%
      \fi
    \endpgfextra
    \expandafter(\tikztostart)
      -- (perpendicular cs: horizontal line through/.expanded={(\tikztostart)},
                              vertical line through={(\tikztotarget)})
    \tikztonodes \pgfextra
      \ifx\tikzext@origtotarget\pgfutil@empty\else
        \iftikzext@ortho@preflush(\tikzext@origtotarget)\fi\fi\endpgfextra}},
  only horizontal first/.default=,
  only vertical first to center/.style={/tikz/to path={
    \pgfextra
      \let\tikzext@origtotarget\tikztotarget
    \endpgfextra
    (\tikztostart) -- (perpendicular cs: vertical line through={(\tikztostart)},
                                         horizontal line through={(\tikztotarget)})
    \tikztonodes \ifx\tikzext@origtotarget\pgfutil@empty\else\iftikzext@ortho@preflush(\tikzext@origtotarget)\fi\fi}},
  only horizontal first to center/.style={/tikz/to path={
    \pgfextra
      \let\tikzext@origtotarget\tikztotarget
    \endpgfextra
    (\tikztostart) -- (perpendicular cs: horizontal line through={(\tikztostart)},
                                         vertical line through={(\tikztotarget)})
    \tikztonodes \ifx\tikzext@origtotarget\pgfutil@empty\else\iftikzext@ortho@preflush(\tikzext@origtotarget)\fi\fi}}%
}

%%% Compatibility
\tikzextset{
  /tikz-ext/compat/add library={paths.ortho}{pre 0.6},
  compat/paths.ortho/warn/.append code={%
    \pgfutil@for\tikzext@temp:=ortho/ratio,ortho/distance,ortho/from center,ortho/spacing,ortho/middle 0 to 1,%
      ortho/ud distance,ortho/du distance,ortho/lr distance,ortho/rl distance,ortho/udlr distance,%
      horizontal vertical,vertical horizontal,horizontal vertical horizontal,%
      vertical horizontal vertical,up horizontal down,down horizontal up,%
      left vertical right,right vertical left,only vertical second,%
      only horizontal second,only vertical first,only horizontal first,%
      ortho/install shortcuts\do{%
      \pgfkeys@expanded{\noexpand\tikzextutil@compatwarning@key
        {paths.ortho}{pre 0.6}{/tikz/\tikzext@temp}{/tikz/ext/\tikzext@temp}%
      }%
    }%
  },
  compat/paths.ortho/pre 0.6/.append code={%
    \pgfutil@for\tikzext@temp:=ortho/ratio,ortho/distance,ortho/from center,ortho/spacing,ortho/middle 0 to 1,%
        ortho/ud distance,ortho/du distance,ortho/lr distance,ortho/rl distance,ortho/udlr distance,%
        horizontal vertical,vertical horizontal,horizontal vertical horizontal,%
        vertical horizontal vertical,up horizontal down,down horizontal up,%
        left vertical right,right vertical left,only vertical second,%
        only horizontal second,only vertical first,only horizontal first,%
        ortho/install shortcuts\do{%
      \pgfkeysedef{/tikz/\tikzext@temp}{%
        \noexpand\pgfkeysvalueof{/tikz/ext/\tikzext@temp/.@cmd}##1\noexpand\pgfeov
      }%
    }%
  },
  compat/paths.ortho/\pgfkeysvalueof{/tikz/ext/compat/paths.ortho}%
}
\endinput
