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.

Here's the problem:

\documentclass{minimal}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
[scale = 3,
foo/.style={line width = 5pt}]
\draw[foo,red] (0,0) -- (0,1);
\draw[foo,blue] (0,1) -- (1,2);
\end{tikzpicture}
\end{document}

I want a line that changes colour half way along. I could do this with two paths (as above) but as you can see, the picture doesn't look great.

TikZ problem

I can make the first path go up to (1,2) as well, and then just draw over it, but the fundamental problem is that the thick line kind of cuts at the wrong angle. I'd like the transition between the red and blue to be angled nicely.

Is there a way to do this with paths, or am I going to have to create custom shapes to achieve the effect I want? Which looks like this:

TikZ problem 2

share|improve this question
add comment

9 Answers

up vote 16 down vote accepted

Use clipping. Supplying a clip does affect the line endings so if you clip against a path at the correct angle, it will truly clip the path as you want. There may be easier ways to implement this (namely, there may be quicker ways to get at the coordinates involved), but the following seems to work.

\documentclass{minimal}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (2,1);
\coordinate (c) at (0,-1);
\path (a);
\pgfgetlastxy{\ax}{\ay}
\path (b);
\pgfgetlastxy{\bx}{\by}
\path (c);
\pgfgetlastxy{\cx}{\cy}
\pgfmathsetmacro{\bx}{\bx - \ax}
\pgfmathsetmacro{\by}{\by - \ay}
\pgfmathsetmacro{\cx}{\cx - \ax}
\pgfmathsetmacro{\cy}{\cy - \ay}
\pgfmathsetmacro{\blen}{veclen(\bx,\by)}
\pgfmathsetmacro{\clen}{veclen(\cx,\cy)}
\pgfmathsetmacro{\dx}{\bx * \clen/\blen + \cx}
\pgfmathsetmacro{\dy}{\by * \clen/\blen + \cy}

\begin{scope}
\clip (a) -- ++(\dx pt, \dy pt) -- ++(2* \bx pt, 2* \by pt) -- ++(-2* \dx pt, -2 * \dy pt) -- ++(-2 * \bx pt, -2 * \by pt) -- (a);
\draw[line width=1cm,blue,line cap=rect] (a) -- (b);
\end{scope}
\begin{scope}
\clip (a) -- ++(\dx pt, \dy pt) -- ++(2* \cx pt, 2* \cy pt) -- ++(-2* \dx pt, -2 * \dy pt) -- ++(-2 * \cx pt, -2 * \cy pt) -- (a);
\draw[line width=1cm,red,line cap=rect] (a) -- (c);
\end{scope}
\end{tikzpicture}
\end{document}

The horrendous calculations are simply to find a point that bisects the angle between the vectors (a)->(b) and (a)->(c). We do that by finding the point on the line from (a) to (b) which is the same distance as (c) is from (a) and then finding the midpoint between that point and (c). That (or rather, the relative vector from (a) to that point) is our desired vector. We then draw two quadrilaterals whose basic properties are that near (a), they are angled to that they bisect the angle (b)(a)(c) and are large enough to contain the rest of the paths.

split colour paths

This method is robust in that changing the coordinates of the three points works as it should. Where it is not robust is that if the paths are more complicated then the clipping boxes will need to be more complicated to accommodate them. As I said, there might also be cleaner ways of implementing this using more internal stuff.

share|improve this answer
    
That's pretty clever. Does pgf not have a "bisect angle and return a vector" macro? That seems to be the tricky bit... –  Seamus Feb 13 '11 at 18:36
add comment

Forgive me for adding a second answer, but since the idea is quite different I thought that it would be better for organizing.

The following solution is completely automatic and doesn't require any math. It should work for any angle (except 0 and 180), though if it is larger than 180 degrees, you might want to exchange some of the below and above. Also, for very acute angles, you might want to add some clipping (and see the note about pos below).

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{calc,intersections}
\begin{document}

\begin{tikzpicture}[scale = 3]
    \def\linewidth{5pt}
    \def\pointa{(0,0)}
    \def\pointb{(0,1)}
    \def\pointc{(1,2)}
    \path \pointa -- 
        node[pos=0,coordinate,sloped,above=\linewidth/2] (tmp1-1) {} 
        node[pos=2,coordinate,sloped,above=\linewidth/2] (tmp1-2) {}
        node[pos=0,coordinate,sloped,below=\linewidth/2] (tmp1-3) {}
        node[pos=2,coordinate,sloped,below=\linewidth/2] (tmp1-4) {}
        \pointb;
    \path \pointb -- 
        node[pos=-1,coordinate,sloped,above=\linewidth/2] (tmp2-1) {} 
        node[pos=1,coordinate,sloped,above=\linewidth/2] (tmp2-2) {}
        node[pos=-1,coordinate,sloped,below=\linewidth/2] (tmp2-3) {}
        node[pos=1,coordinate,sloped,below=\linewidth/2] (tmp2-4) {}
        \pointc;

    \path[name path=line11] (tmp1-1) -- (tmp1-2);
    \path[name path=line12] (tmp1-3) -- (tmp1-4);
    \path[name path=line21] (tmp2-1) -- (tmp2-2);
    \path[name path=line22] (tmp2-3) -- (tmp2-4);

    \path[name intersections={of=line11 and line21}] node[coordinate] (i1) at (intersection-1) {};
    \path[name intersections={of=line12 and line22}] node[coordinate] (i2) at (intersection-1) {};

    \fill[red] (tmp1-1) -- (i1) -- (i2) -- (tmp1-3) -- cycle;
    \fill[blue] (tmp2-2) -- (i1) -- (i2) -- (tmp2-4) -- cycle;
\end{tikzpicture}
\end{document}

First we create some nodes at the sides of the line, half the line width away from the center. The end nodes should be exactly at the height very the path ends, but the middle nodes need to be extended a bit further. For very short paths and big line widths or very acute angles you probably need to make the values in pos=2 and pos=-1 larger. On the other hand, for “decent proportions” you might want to make them smaller, so that the nodes don't enlarge your bounding box. (Or just reset the bounding box afterwards.)

We use these nodes to specify some paths at the sides of the lines we want to draw and then intersect those to get the point where the colors should meet.

Finally, instead of drawing the lines, we fill two shapes using all the points we made TikZ calculate for us.

result

share|improve this answer
add comment

Here's yet another answer for you. I was thinking how to implement the clip solution for the TeX-SX package and how to deal with the problem about ensuring that the clip path only clips the right part, and thought of a different solution entirely. This solution defines a new family of arrow heads which make the line pointy according to some set angle.

Here's the code:

\documentclass{standalone}

\usepackage{tikz}

\makeatletter

\pgfkeys{
  /tikz/sharp arrow angle/.code={%
    \pgfsetarrowoptions{sharp left}{#1}
    \pgfsetarrowoptions{sharp right}{#1}
  },
  /tikz/sharp left arrow angle/.code={%
    \pgfsetarrowoptions{sharp left}{#1}
  },
  /tikz/sharp right arrow angle/.code={%
    \pgfsetarrowoptions{sharp right}{#1}
  }
}

\tikzset{sharp arrow angle=30}

\pgfarrowsdeclare{sharp left}{sharp left}{%
  \pgfmathsetlength{\pgf@xa}{.5*\pgflinewidth * tan(\pgfgetarrowoptions{sharp left})}
  \pgfarrowsleftextend{\pgf@xa}
  \pgfarrowsrightextend{\pgf@xa}
}{%
  \pgfmathsetlength{\pgf@xa}{\pgflinewidth * tan(\pgfgetarrowoptions{sharp left})}
  \pgfpathmoveto{\pgfqpoint{-.1\pgflinewidth}{-.5\pgflinewidth}}
  \pgfpathlineto{\pgfqpoint{0pt}{-.5\pgflinewidth}}
  \pgfpathlineto{\pgfqpoint{\pgf@xa}{.5\pgflinewidth}}
  \pgfpathlineto{\pgfqpoint{-.1\pgflinewidth}{.5\pgflinewidth}}
  \pgfusepathqfill
}
\pgfarrowsdeclare{sharp right}{sharp right}{%
  \pgfmathsetlength{\pgf@xa}{.5*\pgflinewidth * tan(\pgfgetarrowoptions{sharp right})}
  \pgfarrowsleftextend{\pgf@xa}
  \pgfarrowsrightextend{\pgf@xa}
}{%
  \pgfmathsetlength{\pgf@xa}{\pgflinewidth * tan(\pgfgetarrowoptions{sharp right})}
  \pgfpathmoveto{\pgfqpoint{-.1\pgflinewidth}{.5\pgflinewidth}}
  \pgfpathlineto{\pgfqpoint{0pt}{.5\pgflinewidth}}
  \pgfpathlineto{\pgfqpoint{\pgf@xa}{-.5\pgflinewidth}}
  \pgfpathlineto{\pgfqpoint{-.1\pgflinewidth}{-.5\pgflinewidth}}
  \pgfusepathqfill
}

\makeatother

\begin{document}
\begin{tikzpicture}
\path (0,2) rectangle (9,-6);
\draw[line width=3cm,red,sharp arrow angle=60,-sharp left] (0,0) -- (6,0);
\draw[line width=3cm,blue,sharp arrow angle=60,sharp right-] (6,0) -- +(-120:6);
\draw[thick,blue] (0,0) -- (6,0);
\draw[thick,red] (6,0) -- +(-120:6);
\end{tikzpicture}
\end{document}

and here's the result:

path colour changing using arrow heads

The rectangle is just to ensure that the bounding box is large enough (arrow tips seem to get ignored for that). The other two lines are to show that the pointy lines meet at the right place.

share|improve this answer
    
Of my three solutions, I think I like this one the best. It is the simplest, the cleanest, and the most robust. –  Andrew Stacey Jun 4 '11 at 21:16
    
Good idea! Now it only remains to calculate the angle automatically... –  Caramdir Jun 4 '11 at 21:37
    
@Caramdir: I'm not sure how best to do that because the first line doesn't know anything about the second line. So the macro that figured it out would have to take in both paths as its arguments, figure out the angle, and then draw the lines appropriately. –  Andrew Stacey Jun 4 '11 at 21:53
add comment

I don't have any easy solution, but with some calculations, you can achieve the following (note that line width is not scaled, so everything is divided by three). With some further thought, one should be able to stuff that into a macro that automatically does the right calculations.

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
    [scale = 3,
    foo/.style={line width = 5pt}]
    \draw[foo,red] (0,0) -- (0,1);
    \draw[foo,blue] (0,1) -- (1,2);

    \fill[red] 
        ($(0,1) + (-2.5pt/3,{(2.5pt*(-1+sqrt(2)))/3})$) --
        ($(0,1) + ( 2.5pt/3,{(2.5pt*( 1-sqrt(2)))/3})$) --
        ($(0,1) + ( 2.5pt/3,-2.5pt/3)$) --
        ($(0,1) + (-2.5pt/3,-2.5pt/3)$) --
        cycle;
    \fill[blue] 
        ($(0,1) + (-2.5pt/3,{(2.5pt*(-1+sqrt(2)))/3})$) --
        ($(0,1) + ( 2.5pt/3,{(2.5pt*( 1-sqrt(2)))/3})$) --
        ($(0.1,1.1) + ( 2.5pt/3,{(2.5pt*( 1-sqrt(2)))/3})$) --
        ($(0.1,1.1) + (-2.5pt/3,{(2.5pt*(-1+sqrt(2)))/3})$) --
        cycle;
\end{tikzpicture}
\end{document}

result

share|improve this answer
    
Calculating and filling is used at last... It seems easier to do such things in Asymptote, if we make a complex module for this. In TikZ, it is hard to use in practice. Anyway, it is exactly what is required. –  Leo Liu Feb 13 '11 at 17:38
    
I just completed a similar solution. It is a brute force solution, but I haven't yet figured out anything better. –  Throwback1986 Feb 13 '11 at 17:52
    
I had a feeling I would end up doing this sort of thing... –  Seamus Feb 13 '11 at 17:52
    
@Seamus: I have a idea to use rounedpath. I think I can do it in Asymptote, if you want. –  Leo Liu Feb 13 '11 at 18:06
1  
@Seamus: But it seems there's no trivial solution. I think the underlying PostScript/PDF has some restriction. –  Leo Liu Feb 13 '11 at 18:54
show 1 more comment

This is a proof-of-concept. It has a lot of implementation issues that would need sorting out to make it automatic, but Ulrike's answer to Bad intersection of lines in TikZ gave me an idea on how to do this by a very sneaky trick. Basically, you draw the paths up to the join point and then each turns towards the bisector path. That turn makes a nice sharp point. If the part of the turned path is the right length, this is a cheap way of making the path end at an angle. As you can see from the picture, it's not 100% perfect as there's a little extra filled in (try shortening the extensions to see why I put that in). And the numbers in the code were obtained by trial and error (though I believe they could be automated).

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}

\begin{tikzpicture}[line width=7]
\draw[red] (0,0) -- ($(1,1)+(-.5\pgflinewidth,-.5\pgflinewidth)$) -- +(180:.35\pgflinewidth);
\draw[green] (0,2) -- ($(1,1)+(-.5\pgflinewidth,.5\pgflinewidth)$) -- +(180:.35\pgflinewidth);
\end{tikzpicture}
\end{document}

Result:

changing colour at line bend

share|improve this answer
add comment

Coming from pgfplots: problem with "non-smooth" intersection of two lines' ends I thought of custom arrow tips, though Andrew Stacey has been one step ahead of me with his answer.
This answer extends this so that an asymmetric arrow tip can be produced.

In a comment, he states truthfully that

[…] the first line doesn't know anything about the second line. So the macro that figured it out would have to take in both paths as its arguments, figure out the angle, and then draw the lines appropriately.

To circumvent this one could possible do this in one path, an extra key (possible to path with a list of coordinate to go through) and a few edge path operators.
A starting path is shown in the code below.

The sharp protrude switch makes the arrow tips slightly overlap the actual line to hide rendering issues (don’t use with transparency or use a transparency group).

Code

\documentclass[tikz,convert=false]{standalone}
\usetikzlibrary{backgrounds}
\makeatletter

\pgfkeys{
  /tikz/sharp angle/.code={%
    \pgfsetarrowoptions{sharp >}{#1}%
    \pgfsetarrowoptions{sharp <}{-#1}%
  },
  /tikz/sharp > angle/.code={%
    \pgfsetarrowoptions{sharp >}{#1}%
  },
  /tikz/sharp < angle/.code={%
    \pgfsetarrowoptions{sharp <}{#1}%
  },
  /tikz/sharp protrude/.code=\csname if#1\endcsname\qrr@tikz@sharp@z@-0.05\p@\else\qrr@tikz@sharp@z@\z@\fi,
  /tikz/sharp protrude/.default=true
}

\newdimen\qrr@tikz@sharp@z@
\qrr@tikz@sharp@z@\z@
\pgfarrowsdeclare{sharp >}{sharp >}{%
  \edef\pgf@marshal{\noexpand\pgfutil@in@{and}{\pgfgetarrowoptions{sharp >}}}%
  \pgf@marshal
  \ifpgfutil@in@
    \edef\pgf@tempa{\pgfgetarrowoptions{sharp >}}
    \expandafter\qrr@tikz@sharp@parse\pgf@tempa\@qrr@tikz@sharp@parse
  \else
    \qrr@tikz@sharp@parse\pgfgetarrowoptions{sharp >}and-\pgfgetarrowoptions{sharp >}\@qrr@tikz@sharp@parse
  \fi
% 
  \pgfmathparse{max(\pgf@tempa,\pgf@tempb,0)}%
  \let\qrr@tikz@sharp@max\pgfmathresult
  \pgfmathsetlength\pgf@xa{.5*\pgflinewidth * tan(\qrr@tikz@sharp@max)}%
  \pgfarrowsleftextend{+\pgf@xa}%
  \pgfarrowsrightextend{+\pgf@xa}%
}{%
  \edef\pgf@marshal{\noexpand\pgfutil@in@{and}{\pgfgetarrowoptions{sharp >}}}%
  \pgf@marshal
  \ifpgfutil@in@
    \edef\pgf@tempa{\pgfgetarrowoptions{sharp >}}
    \expandafter\qrr@tikz@sharp@parse\pgf@tempa\@qrr@tikz@sharp@parse
  \else
    \qrr@tikz@sharp@parse\pgfgetarrowoptions{sharp >}and-\pgfgetarrowoptions{sharp >}\@qrr@tikz@sharp@parse
  \fi
% 
  \pgfmathsetlength\pgf@ya{.5*\pgflinewidth * tan(max(\pgf@tempa,\pgf@tempb,0))}%
  \pgfmathsetlength\pgf@xa{-.5*\pgflinewidth * tan(\pgf@tempa)}%
  \pgfmathsetlength\pgf@xb{-.5*\pgflinewidth * tan(\pgf@tempb)}%
  \advance\pgf@xa\pgf@ya
  \advance\pgf@xb\pgf@ya
  \ifdim\pgf@xa>\pgf@xb
    \pgftransformyscale{-1}%
    \pgf@xc\pgf@xb
    \pgf@xb\pgf@xa
    \pgf@xa\pgf@xc
  \fi
  \pgfpathmoveto{\pgfqpoint{\qrr@tikz@sharp@z@}{.5\pgflinewidth}}%
  \pgfpathlineto{\pgfqpoint{\pgf@xa}{.5\pgflinewidth}}%
  \pgfpathlineto{\pgfqpoint{\pgf@ya}{+0pt}}%
  \pgfpathlineto{\pgfqpoint{\pgf@xb}{-.5\pgflinewidth}}%
  \pgfpathlineto{\pgfqpoint{\qrr@tikz@sharp@z@}{-.5\pgflinewidth}}%
  \pgfusepathqfill
}
\pgfarrowsdeclare{sharp <}{sharp <}{%
  \edef\pgf@marshal{\noexpand\pgfutil@in@{and}{\pgfgetarrowoptions{sharp <}}}%
  \pgf@marshal
  \ifpgfutil@in@
    \edef\pgf@tempa{\pgfgetarrowoptions{sharp <}}
    \expandafter\qrr@tikz@sharp@parse\pgf@tempa\@qrr@tikz@sharp@parse
  \else
    \expandafter\qrr@tikz@sharp@parse\pgfgetarrowoptions{sharp <}and-\pgfgetarrowoptions{sharp <}\@qrr@tikz@sharp@parse
  \fi
% 
  \pgfmathparse{max(\pgf@tempa,\pgf@tempb,0)}%
  \let\qrr@tikz@sharp@max\pgfmathresult
  \pgfmathsetlength\pgf@xa{.5*\pgflinewidth * tan(\qrr@tikz@sharp@max)}%
  \pgfarrowsleftextend{+\pgf@xa}%
  \pgfarrowsrightextend{+\pgf@xa}%
}{%
  \edef\pgf@marshal{\noexpand\pgfutil@in@{and}{\pgfgetarrowoptions{sharp <}}}%
  \pgf@marshal
  \ifpgfutil@in@
    \edef\pgf@tempa{\pgfgetarrowoptions{sharp <}}
    \expandafter\qrr@tikz@sharp@parse\pgf@tempa\@qrr@tikz@sharp@parse
  \else
    \expandafter\qrr@tikz@sharp@parse\pgfgetarrowoptions{sharp <}and-\pgfgetarrowoptions{sharp <}\@qrr@tikz@sharp@parse
  \fi
% 
  \pgfmathsetlength\pgf@ya{.5*\pgflinewidth * tan(max(\pgf@tempa,\pgf@tempb,0))}%
% 
  \pgfmathsetlength\pgf@xa{-.5*\pgflinewidth * tan(\pgf@tempa)}%
  \pgfmathsetlength\pgf@xb{-.5*\pgflinewidth * tan(\pgf@tempb)}%
  \advance\pgf@xa\pgf@ya
  \advance\pgf@xb\pgf@ya
  \ifdim\pgf@xa>\pgf@xb
    \pgftransformyscale{-1}%
    \pgf@xc\pgf@xb
    \pgf@xb\pgf@xa
    \pgf@xa\pgf@xc
  \fi
  \pgfpathmoveto{\pgfqpoint{\qrr@tikz@sharp@z@}{.5\pgflinewidth}}%
  \pgfpathlineto{\pgfqpoint{\pgf@xa}{.5\pgflinewidth}}%
  \pgfpathlineto{\pgfqpoint{\pgf@ya}{+0pt}}%
  \pgfpathlineto{\pgfqpoint{\pgf@xb}{-.5\pgflinewidth}}%
  \pgfpathlineto{\pgfqpoint{\qrr@tikz@sharp@z@}{-.5\pgflinewidth}}%
  \pgfusepathqfill
}
\def\qrr@tikz@sharp@parse#1and#2\@qrr@tikz@sharp@parse{\def\pgf@tempa{#1}\def\pgf@tempb{#2}}
\makeatother
\begin{document}
\begin{tikzpicture}[gridded, sharp protrude]
\path[line width=1cm, sharp angle=45,sharp <-sharp >] (0,0) edge[yellow]                          (4,0)
                                                      (4,0) edge[blue]                            (4,4)
                                                      (4,4) edge[red, sharp > angle=60 and -45]   (0,4)
                                                      (0,4) edge[green, sharp < angle=-45 and 60] (0,0)
                                                      (0,4) edge[line width=.3cm,
                                                                 sharp < angle=75 and 75,
                                                                 sharp > angle=-60 and -30,
                                                                 sharp <-sharp >]               (2,2)
                                                      ;
\end{tikzpicture}
\end{document}

Output

enter image description here

share|improve this answer
add comment

You really want to draw this as a single path - the joins never look correctly otherwise (in my experience, anyway). Take a look at this answer or try the discussion in section 12.4.2 (page 114) of the manual.

Your question doesn't mention smoothly shading between colors, so the first link may be easiest (although both methods can be used to render joined lines similar to your illustration.)

share|improve this answer
    
Fading needs path to be smooth, like line cap=round or rounded corners. No help for zig lines with line cap=butt, I think. –  Leo Liu Feb 13 '11 at 15:26
    
That solution doesn't seem to be drawing the line as a single path, but lots of little paths... –  Seamus Feb 13 '11 at 16:40
    
At which version of the manual are you pointing? In v2.10, 12.4.2 is Using Styles to Manage How Pictures Look (on page 121) and in version v2.00, it is The Syntax of Factors. For both I don't see any connection to the question. –  Caramdir Feb 13 '11 at 17:56
    
Linked version is 1.18 –  Throwback1986 Feb 13 '11 at 18:33
add comment

You can use the line cap=round option to produce round line endings:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
[scale = 3,
foo/.style={line width = 5pt, line cap=round}]
\draw[foo,red] (0,0) -- (0,1);
\draw[foo,blue] (0,1) -- (1,2);
\end{tikzpicture}
\end{document}

Result

An alternative is to define custom "arrow" heads (see PGF manual) which simply extend the blue line by the correct amount. However this amount will most likely depend on the angle between the lines.

share|improve this answer
    
@Martin That's neat, but it's not really what I want: I want the red and blue to be "balanced": in this solution, it's still clear that the blue is drawn on top... –  Seamus Feb 13 '11 at 13:55
    
@Seasmus: I see. This is difficult to get right anyway as long both lines have the same width. You could try to (mis-)use arrow heads for this (see my updated answer). –  Martin Scharrer Feb 13 '11 at 14:09
    
@Martin: It would be helpful if you fill out the "Edit Summary" after an edit. I just wanted to see what your recent edit was. It just said "edited body" (inserted by the software), and it took me some time to find out that you just enlarged your image. Thanks! –  Hendrik Vogt Feb 13 '11 at 15:48
    
@Hendrik: Sorry for that. I actually shrunk the image size to reduce the size of the answer. Before it wasn't looking pleasant. However due to the constant DPI in my PDF->PNG script the lines are enlarged. –  Martin Scharrer Feb 13 '11 at 15:55
1  
btw, line extension can simply be done by shorten <=-amount. –  Caramdir Feb 13 '11 at 18:14
show 1 more comment

I think you can draw the whole zig-line first, and then draw half.

\begin{tikzpicture}[scale = 3,foo/.style={line width = 5pt}]
\draw[foo,red] (0,0) -- (0,1) -- (1,2);
\draw[foo,blue] (0,1) -- (1,2);
\end{tikzpicture}

enter image description here

It is not perfect, even bad for right angle. I think it is difficult if you simply use \draw to get proper connection.


A solution of Asymptote. It seems there's some bug of PostScript's algorithm. :-(

import roundedpath;
defaultpen(squarecap+miterjoin);

void drawzig(path p, pen[] pens)
{
    real r = linewidth(pens[0]) / 5;
    path q = roundedpath(p, r);
    pens.cyclic=true;
    for (int i = 0; i < length(q); ++i) {
        draw(subpath(q, 2*i-0.52, 2*i+1.52), pens[i]);
    }
}

path p1 = (0,0) -- (0,1cm) -- (1cm,2cm);
path p2 = (0,0) -- (0,1cm) -- (1cm,1cm); p2 = shift(1.5cm,0) * p2;
path p3 = (0,0) -- (0,1cm) -- (1cm,0); p3 = shift(3cm,0) * p3;
pen[] pens = {blue+5pt, red+5pt};

drawzig(p1, pens);
drawzig(p2, pens);
drawzig(p3, pens);

// compare
draw(p1 ^^ p2 ^^ p3);

enter image description here

share|improve this answer
    
I mention doing this in my question, but the problem is that the angle of how the blue line starts is wrong. –  Seamus Feb 13 '11 at 16:40
    
I have no good idea. In fact, that's not wrong, but only (really) bad. Obtuse angles seem Okey. If you use line join=bevel, it looks much better for acute angles. –  Leo Liu Feb 13 '11 at 17:41
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.