# TikZ: draw only a certain central length of a given path

I have two nodes (A) and (B), and I want to only draw a central segment of the straight line between them, of a certain given length (say 2cm, but will vary). Is there some way I can do this? I am guaranteed that (A) and (B) are at least 2cm apart.

I know about shorten < and shorten >, but the problem is that I don't know the exact amount to shorten by, and I don't want to have to do the calculation myself each time.

-

I didn't read the question very carefully and thought you want to draw the middle part of of any kind of path. So I created a (meta-)decoration to do just that. For straight lines the other solutions given here are of course a lot simpler.

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

% A simple empty decoration, that is used to ignore the last bit of the path
\pgfdeclaredecoration{ignore}{final}
{
\state{final}{}
}

% Declare the actual decoration.
\state{initial}[
next state=middle
]
{\decoration{moveto}}

\state{middle}[
width={\the\pgfdecorationsegmentlength},
next state=final
]
{\decoration{curveto}}

\state{final}
{\decoration{ignore}}
}

% Create a key for easy access to the decoration (as suggested by Jake).
\tikzset{middle segment/.style={decoration={middle},decorate, segment length=#1}}

\begin{document}
\fill (0,0) circle;
\fill (4,0) circle;
\draw[middle segment=2cm,double,red,->] (0,0) to[out=30,in=150] (4,0);
\end{tikzpicture}
\end{document}


-
Excellent! Adding to that: If you define a style \tikzset{middle segment/.style={decoration={middle},decorate, segment length=#1}}, you can easily draw line segments with different lengths using \draw [middle segment=<length>] (a) -- (b); –  Jake May 19 '11 at 18:04
@Jake: Good idea! –  Caramdir May 19 '11 at 18:22
Hi Caramdir. I like your solution, it seems really flexible! I tried modify it so that the line segment would have an arrow at the end, but without any luck. Can someone give me a hand? –  Jamie Vicary May 19 '11 at 19:20
@Jamie: Add \afterdecoration { \pgfsetarrowsend{to} \pgfusepath{stroke} } to the middle state (right after ...curveto}, before the second }). You can replace to by the arrow type you want. See also the example on page 601 of the (v2.10) manual. –  Caramdir May 19 '11 at 19:30
That's great! I actually just found that myself. But now I've also noticed that my [double] option is getting ignored, if I want make the line into two parallel lines ... how can I add that in? –  Jamie Vicary May 19 '11 at 19:32

The calc library eats this sort of thing for breakfast.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}
\node (a) at (0,0) {A};
\node (b) at (3,3) {B};
\draw ($($(a)!.5!(b)$)!1cm!(a)$) --  ($($(a)!.5!(b)$)!1cm!(b)$);
\end{tikzpicture}
\end{document}


The syntax works as follows: $...$ is interpreted as a "coordinate calculation" and it returns a coordinate. We start with $(a)!.5!(b)$ which is halfway between (a) and (b). Then we move 1cm from this point towards (a). That's our starting point. We draw a line from that to the same but with (b) in place of (a).

Result:

-
Thanks Andrew, I don't really know much about the calc package, this is a good advertisement for it. –  Jamie Vicary May 19 '11 at 19:20

Along the same line as the other answers, but also using the intersections library.

\documentclass{minimal}

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{intersections}

\begin{document}

\begin{tikzpicture}
\pgfmathsetmacro{\length}{2}

\coordinate (A) at (0,0) ;
\coordinate (B) at (4,4);

\coordinate (mid) at ($(A)!0.5!(B)$);

\path[name path=line,draw=lightgray] (A) node[left] {$A$} -- (B)  node[right] {$B$};

\draw [red, blue,ultra thick, name intersections={of=line and circle}]
(intersection-1) -- (intersection-2);
\end{tikzpicture}

\end{document}


The output is

The length of the blue segment is determined by the value of the macro \length.

Another option is to clip the path :

\begin{tikzpicture}
\pgfmathsetmacro{\length}{2}

\coordinate[label=left:$A$] (A) at (0,0) ;
\coordinate[label=right:$B$] (B) at (4,4);

\coordinate (mid) at ($(A)!0.5!(B)$);

\begin{scope}
\draw[blue,ultra thick] (A) -- (B);
\end{scope}
\end{tikzpicture}

-
This is a great illustration of named paths. Thanks! –  Matthew Leingang May 19 '11 at 17:47
@Jamie : I just realized that the length of the line segment is the diameter of the circle !! I must divide the radius of the circle by 2. I fixed the code, but not the picture. –  Frédéric May 19 '11 at 17:53
Thanks Frédéric. It's funny that the first three solutions manage to do it in four different ways! –  Jamie Vicary May 19 '11 at 19:21

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}
% def Points
\fill (0,0) coordinate (A) circle (1pt) (5,2) coordinate (B) circle (1pt);
% two nodes A and B
\node [below] at (A) {Node A};
\node [above] at (B) {Node B};
% line between
\draw ($(A)!1cm!(B)$) -- ($(A)!3cm!(B)$);
\end{tikzpicture}
\end{document}


First I define two corrdinates, draw them and add two nodes. The I the ⟨p⟩!⟨factor/dimension⟩!⟨q⟩ syntax to get specified points between A and B.
Unfortunately in my solution you have to use two dimes to get a defined length. In ths case 3cm - 1cm = 2cm segment length.

See PGF manual, section “4.2.1 Using Partway Calculations for the Construction of D” in the Euclid Tutorial

-
Thanks for the solution, Tobi! –  Jamie Vicary May 19 '11 at 19:21