10

This question is similar to Is there a TikZ dashed line decorator or some other way to make part of a path dashed?.

What I want to draw: A node with a dashed loop, with a small node on the loop, and the part of the loop from the big node to the small one undashed.

How far I went:

\begin{tikzpicture}[scale=5]
  \draw node (n) [circle,fill] {} edge [dashed,loop above] node
  [fill,circle,minimum size=.4em,inner sep=0pt,pos=0.1] (s) {} ();
  \draw[->] (n) -- (s);
\end{tikzpicture}

The trouble with it being, of course, that the (n)--(s) path does not match the curvy path. The solution of the previous question does not seem to help, as I want to work with a path resulting from a clipping (and I'm not sure to know how).

Michaël
  • 1,384
  • 11
  • 22

1 Answers1

13

This is an incomplete answer or more exactly an answer with some disadvantages. You need to find the length manually of the path between (n) and (s), and if you change the scaling argument, you need to find another length. The main problem is to calculate the length automatically. I think it's possible with the decoration librarybut I don't know enough this library to find a solution. A macro to calculate the length of a path between two nodes would be interesting.

Update of the first code In some simple case, it's possible to calculate the length.

\documentclass{article}
\usepackage{tikz} 
\usetikzlibrary{decorations} 

\makeatletter
\newif\ifpgfextractpointsreseonmoveto

\pgfextractpointsreseonmovetotrue%
\def\calclength#1{{
    \pgf@decorate@parsesoftpath#1\parsedpath
    \xdef\length{\pgf@decorate@totalpathlength}
    \parsedpath
}} 

\makeatother  
\tikzset{
  solid part/.style={%
  postaction={solid, decorate, draw,ultra thick,
  decoration={
             moveto,
             pre=curveto, 
             post=moveto, 
             pre length=#1,
             post length=#1}}
    }
}    

\begin{document}


\begin{tikzpicture}[scale=2]
   \path[save path=\tmppath] (0,0) -- (6,4); 
    \calclength{\tmppath}   
    \draw[dotted,solid part=.5*\length] (0,0) -- (6,4); 
\end{tikzpicture}   

\begin{tikzpicture}[scale=2]
   \path[save path=\tmppath] (0,0) to[out=0,in=-90] (6,4); 
    \calclength{\tmppath}   
    \draw[dotted,solid part=.5*\length] (0,0) to[out=0,in=-90] (6,4); 
\end{tikzpicture}  
\end{document}    

enter image description here

Update to get the correct arrow with edgeand loop but my code is perhaps not sure in some conditions (I need to test)

\documentclass{article}
\usepackage{tikz} 
\usetikzlibrary{decorations} 

\makeatletter
\newif\ifpgfextractpointsreseonmoveto

\pgfextractpointsreseonmovetotrue%

\def\pgf@extractprocessorsecond#1{%
 \ifx#1\pgfsyssoftpath@movetotoken
   \ifpgfextractpointsreseonmoveto
     \let\pgf@next=\pgf@extractprocessorfirst%
   \else%
     \let\pgf@next=\pgf@@extractprocessorsecond%
   \fi%
 \else%
   \let\pgf@next=\pgf@@extractprocessorsecond%
 \fi%
 \pgf@next#1%
}

\tikzset{
 adjust arrow/.code={%
   \csname if#1\endcsname%
     \pgfextractpointsreseonmovetofalse%
   \else%
     \pgfextractpointsreseonmovetotrue%
   \fi},
 adjust arrow/.default=true,
}

\makeatother  

\begin{document}

\tikzset{
  solid part/.style={%
  postaction={solid, decorate, draw,adjust arrow,
  decoration={
moveto,
             pre=curveto, 
             post=moveto, 
             pre length=#1,
             post length=#1}}
    }
}

\begin{tikzpicture}[scale=20,>=latex]
   \draw[thick] node (n) [circle,fill] {} 
         edge [<-,dotted,solid part=28mm,loop above] ();
\end{tikzpicture}

\end{document}

enter image description here

Update N°3) The best solution for the moment. I try to use \usetikzlibrary{decorations.markings}but I need to work with to and not edge. To avoid the arrow with loop, I redefine \tikzstyle{every loop}= [shorten >=1pt]

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations} 
\usetikzlibrary{decorations.markings}
\begin{document}

\pgfkeys{
/pgf/decoration/.cd,
pre fraction/.style={pre length=#1*\pgfmetadecoratedpathlength},
post fraction/.style={post length=#1*\pgfmetadecoratedpathlength}
}

\begin{tikzpicture}
\coordinate (A) at (0,0);
\coordinate (B) at (4,2);

\draw [  
decoration={ 
curveto,
pre=moveto, pre fraction=0,
post=moveto, post fraction=0.3}, decorate, red, ultra thick] (A) to[out=0,in=-90](B);

\draw [decoration={curveto,
                   pre=moveto, pre fraction=0.7,
                   post=moveto, post fraction=0},%
       decorate, blue, ultra thick,dotted] (A) to[out=0,in=-90](B); 

\path [  
decoration={ 
     markings, mark=at position .7  with {\arrow[red,line width=2pt]{>}}},  
     decorate  ] (A) to[out=0,in=-90](B);         
\end{tikzpicture} 

\begin{tikzpicture}[scale=20,>=latex]  
 \tikzstyle{every loop}= [shorten >=1pt]  
 \node[draw,circle,minimum size=2pt,fill](s){};  
\draw[decoration={curveto,
                  pre=moveto, 
                  pre fraction=0,
                  post=moveto, 
                  post fraction=0.7}, 
      decorate,red, ultra thick] (s)  to[loop above] ();

\draw[decoration={ 
curveto,
pre=moveto, pre fraction=0.33,post=moveto, post fraction=0},
 decorate, blue,dotted, ultra thick] node[]{}  to[loop above] (); 

\path [decoration={markings,
       mark=at position .32  with {\arrow[red,line width=2pt]{>}}},
       decorate  ]  (s)  to [loop above] ();                    
\end{tikzpicture}       
\end{document}

enter image description here

Update final With edge we need to add decorate in the option of `edge``

% remove the arrow from the style of every loop
\tikzset{every loop/.style={looseness=10}}
\begin{tikzpicture}[scale=5] 
% draw the loop
 \draw node (n) [circle,draw] {A} edge [dashed,loop above]   ();  
% first decoration : solid line
\path [ decoration={ curveto,
                     pre=moveto, 
                     pre fraction=0,
                     post=moveto, 
                     post fraction=0.9},red,thick]%
                      (n) edge[decorate,loop above]();  
% second decoration the arrow 
 \path[>=latex,decoration={  markings, 
                     mark=at position .12  with {\arrow[red,thick]{>}}}]%
                      (n) edge[decorate,loop above]  ();

\end{tikzpicture}

enter image description here

Alain Matthes
  • 95,075
  • Great! I've been tweaking with that solution for some time now, and, trying to find a shorter solution, I felt back at yours :-) There's still two glitches: how can I get an arrow tip at the end of the solid line, and what is the clean way to avoid the weird double arrow tip at the end of the dotted path? Thanks! – Michaël Dec 01 '11 at 19:52
  • I need to correct my code. The problem comes from edge. I use this code only with --and tobut you need edge to creta a loop. The code is complicated to avoid the weird double arrow tip at the end of the dotted path and I don't know how to get an arrow at the end of the solid line :( – Alain Matthes Dec 01 '11 at 22:08
  • @Michaël Be careful with this code because it's not perfect and I need to hack some intern macros and it's not easy – Alain Matthes Dec 01 '11 at 22:54
  • Still, a quite nice approach. – percusse Dec 01 '11 at 23:14
  • Thanks @Altermundus ! I'll play with that later on today. Still, I'm being quite frustrated with TikZ. Every time I try to make a simple (IMO) drawing, I end up hacking for hours on :-( – Michaël Dec 02 '11 at 15:10
  • @Altermundus: I think I've found a way to get the arrow tip at the end of the solid line, and maybe simplify the whole process. Define the following decoration: \pgfdeclaredecoration{remove}{final}{\state{final}[width=\pgfdecoratedpathlength]{}}, then update solid part to have remove as post and use arrows=-> as style. It seems to do what I want: actually construct a path which is PART of the original path. Would you care updating your solution with that option? – Michaël Dec 02 '11 at 18:33
  • Yes no problem. I found myself another simpler solution but I need time to write the code – Alain Matthes Dec 02 '11 at 19:35
  • @Michaël Perhaps you can update my solution because I've a problem with the last part of your code : then update solid part to have remove as post and use arrows=-> as style.. You can also post your answer ! – Alain Matthes Dec 02 '11 at 20:11