Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.
\path[->] (A) edge [out=180, in=0] (B);

This path is written quite often in my document. Sometimes I find myself changing it to:

\path[->] (B) edge [out=0, in=180] (A);

I do not want to touch the -> property for consistance sake. But I would love to write something like:

\path[->] (B) edge [inout = horizontal] (A);

How can I achieve the implied effect?


EDIT:

Clarification: I want those two paths to be the same path without manually changing the input output angles.

\path[-] (B) edge [inout = horizontal] (A);
\path[-] (A) edge [inout = horizontal] (B);

Here is a miniexample that illustrates the question better:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
    \node (A) at (0,0) {A};
    \node (B) at (3,2) {B};

    \node (C) at (3,0) {C};
    \node (D) at (6,2) {D};

    \path[-] (B) edge [out=0, in=180] (A); %not desired - longer path
    \path[-] (A) edge [out=0, in=180] (B); %desired path - shorter path

    %\path[-] (C) edge [inout = automagic] (D); %desired path - shorter path
    %\path[-] (D) edge [inout = automagic] (C); %desired path - shorter path 
    \path[-, ultra thick, red] (C) edge [out=0, in=180] (D); %desired result of [inout = automagic]
\end{tikzpicture}
\end{document}

enter image description here

share|improve this question
add comment

2 Answers

up vote 10 down vote accepted

I provide three styles:

  • the curve - style that produces a “horizontal” curve (the in and out direction are 0 and 180),
  • the curve | style that produces a “vertical” curve (the in and out direction are 90 and 270),
  • the underlying curve + style that, if used directly, decides on its own whether a “vertical” or “horizontal” curve shall be used.

Code

\documentclass[tikz]{standalone}
\makeatletter
\tikzset{
  curve +/.default=2,
  curve +/.style={
    to path={
      \pgfextra
        \tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
        \pgf@xa\pgf@x
        \pgf@ya\pgf@y
        \tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
        \ifnum#1=2
          \pgfmathifthenelse{abs(\pgf@xa-\pgf@x)<abs(\pgf@ya-\pgf@y)}{0}{1}% 0 = ver
                                                                           % 1 = hor
        \else
          \def\pgfmathresult{#1}%
        \fi
        \ifnum\pgfmathresult=0
          \ifdim\pgf@ya<\pgf@y
            \def\tikz@to@out{90}\def\tikz@to@in{270}%
          \else
            \def\tikz@to@out{270}\def\tikz@to@in{90}%
          \fi
        \else
          \ifdim\pgf@xa<\pgf@x
            \def\tikz@to@out{0}\def\tikz@to@in{180}%
          \else
            \def\tikz@to@out{180}\def\tikz@to@in{0}%
          \fi
        \fi
      \endpgfextra
      \tikz@to@curve@path
    }
  },
  curve -/.style={curve +=1},
  curve |/.style={curve +=0},
}
\makeatother

\begin{document}
\foreach \a in {0,2,...,359}{% Warning: Will typeset 180 pages!
\begin{tikzpicture}
\useasboundingbox (-2.2,-2.2) rectangle (2.2,2.2);
\node (A) at (0,0) {A};
\node (B) at (\a:2cm) {B};
\path[->] (A) edge [black!50, curve |] (B)
              edge [black!50, curve -] (B)
              edge [black,    curve +] (B);
\end{tikzpicture}
}
\end{document}

Output

enter image description here

share|improve this answer
    
+1 That's very clever! –  JLDiaz Feb 26 '13 at 14:03
add comment

You can create your custom .is choice family. It will also complain if you mistype, or use an undesignated option that doesn't belong to the choice family which is helpful to debug.

\documentclass[tikz]{standalone}

\tikzset{inout/.is choice,
inout/horizo/.style={in=180,out=0},
inout/horizorev/.style={out=180,in=0}
}

\begin{document}
\begin{tikzpicture}
\node (A) at (0,0) {A};
\node (B) at (3,2) {B};
\node (C) at (3,-2) {C};
\path[->] (A) edge [inout=horizo] (B);
\path[->] (A) edge [inout=horizorev] (C);
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
1  
I like the answer, however i would like tikz to make that choice for me. It should always prefere the nearest connection over the further away connextion. –  Johannes Feb 26 '13 at 12:27
    
@Johannes So you don't want to write [inout = horizontal] at all but only inout since the option would be redundant if things are automated. Am I right? –  percusse Feb 26 '13 at 12:44
    
i am ok with writing [inout = horizontal]. if that causes the \path[->] (A) edge [in=180,out=0] (B); and \path[->] (B) edge [in=0,out=180] (A);. i want TikZ to pick the shorter path for me regardless of my input. The above option is a shorthand for the numbers but does not save me creating errors during my refactorings. –  Johannes Feb 26 '13 at 13:19
    
@Johannes Should the choice whether the connection is made horizontal (0/180) or vertical (90/270) be made by TikZ, too? –  Qrrbrbirlbel Feb 26 '13 at 13:25
    
@Qrrbrbirlbel no, thats why i suggested using the key horizontal. The idea is to use math to determine what is "best", where best would be case 1 if leftside.X smaller rigthside.X and case 2 otherwise. My usecase does not feature points that are so close that tex would be required to create a vertical connetion. –  Johannes Feb 26 '13 at 13:36
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.