4

Given an arbitrary path in Latex, e.g. drawn with Tikz, I want to surround this path by a larger path which has a fixed distance to the original path, e.g. 1 cm.

Here is a sketch of it: enter image description here

Note that this is really only a sketch and in the sketch the distance of the outer path to the inner path is not constant, though it should be. I read the term for my problem would be "offset", yet I could not find out, how I can realize that.

I currently do not have Latex code for this sketch. One can also consider a rectangle surrounded by a larger rectangle for an easy example - the important thing is, that the outer path is generated using a generic code, that can be applied to any path.

The intended use case for this is to draw sewing patterns, the outer path then marks the seam allowance.

Update

Here is a minimal working example for the original path:

\pagestyle{empty}
\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}

% I know this could be drawn with a single
% use of \draw, but in reality my figures
% will be more complicated and will also be created
% using multiple \draw calls.
\draw (0,3) -- (2,7) -- (4,3);
\draw (4,3) -- (3,0) -- (1,0) -- (0,3);

\end{tikzpicture}
\end{document}

This code leads to

enter image description here

How would one add a surrounding path as requested without manually drawing the same figure again, just larger (with manually calculated coordinates) ?

I also like to limit my question a little bit: Arbitrary path is too general, I can't describe it in words, but the things I will be drawing won't be too complicated. A generic way for this provided path example should likely work on other paths I will be drawing.

  • Please provide a minimal working example which shows what you've tried or, at least provides the inner bit. – cfr Jan 30 '16 at 0:18
  • For some shapes, you could use copy shadow but it won't work for arbitrary paths. – cfr Jan 30 '16 at 0:34
  • You may spy your path with some scale... – Paul Gaborit Jan 30 '16 at 0:37
  • @PaulGaborit Cunning... But with arbitrary/random paths it might break. – Alenanno Jan 30 '16 at 0:43
  • @Alenanno Do you know a path (or some paths) that breaks the spy library ? (for example, in Can we mirror a part in tikz?) – Paul Gaborit Jan 30 '16 at 0:53
3

Here is a solution with clip and double distance (inspired by the comments below cfr's answer):

  • Original distances of path are respected (black curve).
  • Path with angles and curves are usable.
  • May use a list of distances/colors to draw several seam allowances.

The invclip operation comes from How can I invert a 'clip' selection within TikZ?.

Note about line width: Original path is inner clipped so its width is twice narrower than expected. To get all curves with the same width, you must choose a width for seam allowance (line width=1mm in my example) and the double for the original path (line width=2mm in my example).

\documentclass[tikz,border=3cm]{standalone}
\tikzset{%
  draw seam allowance/.style 2 args={
    preaction={line width=1mm,line join=round,double distance=#1*2,draw=#2},
  },
  seam allowances/.style={%
    preaction={clip},
    preaction={draw seam allowance/.list={#1}},
    draw,%fill=white,
  },
  seam allowances/.default={{{2cm}{blue}}},
  invclip/.style={
    clip,
    insert path={
      {[reset cm] (-16000pt,-16000pt)  -| (16000pt,16000pt) -| cycle}
    },
  },
}
\begin{document}
\begin{tikzpicture}
  \def\mypath{
    (0,30) -- (20,50) -- (40,30) to[out=-180,in=130] (30,0)
    -- (10,0) arc(-90:-180:5cm) to[out=90,in=-45] (3,27) -- cycle
  }
  \begin{scope}
    \begin{pgfinterruptboundingbox}
      \path [invclip] \mypath;
    \end{pgfinterruptboundingbox}
    \draw [seam allowances={{4cm}{red},{3cm}{red},{2cm}{blue},{1cm}{blue}},line width=2mm]
    \mypath ;
  \end{scope}
\end{tikzpicture}
\begin{tikzpicture}
  \def\mypath{
    (0,0) -- (-10,10) -- (0,20) -- (10,10) -- cycle
    (0,0) -- (10,-10) -- (0,-20) -- (-10,-10) -- cycle
  }
  \begin{scope}
    \begin{pgfinterruptboundingbox}
      \path [invclip] \mypath;
    \end{pgfinterruptboundingbox}
    \draw [line width=2mm,seam allowances={{4cm}{red},{3cm}{orange},{2cm}{blue},{1cm}{green}}]
    \mypath ;
  \end{scope}
\end{tikzpicture}
\end{document}

enter image description here

enter image description here

  • That looks great and like I perfect solution. I just need some time to check and understand the latex code in more detail. I already understood I could simply leave out line join=round to get really the same shape around the black path :-) Or is there any reason/fault that I yet didn't notice when leaving this out? – stefan.at.wpf Feb 1 '16 at 22:07
  • You may try line join=round, line join=bevel or line join=miter... – Paul Gaborit Feb 2 '16 at 1:27
  • ... or try to play with miter limit (pgfmanual, p.167). – Paul Gaborit Feb 2 '16 at 1:28
  • Leaving it out (=miter) seems the best for me :-) I have one problem with the line widths though - I can't get them equal. I added a reduced sample with only a black and a blue line to your post. Should be available soon (still in peer review). Would be glad if you can help me once again :-) – stefan.at.wpf Feb 2 '16 at 15:54
  • @stefan.at.wpf I modified my answer... – Paul Gaborit Feb 2 '16 at 16:33
2

Here's an ultra simple solution which just uses double to draw the paths. We define a style seam which really just uses double to draw the line, but with a semantic name. The seam allowance can be set as desired. By default it is set here to 2.5pt.

\tikzset{%
  seam/.style={%
    double distance=\seamallowance,
    draw,
  },
  seam allowance/.store in=\seamallowance,
  seam allowance=2.5pt,
}

Applying this to the example, the result looks like this:

seamed shape

Note that there are gaps where the paths join. Really, you will find it difficult to get neat joins if the paths are not drawn continuously. In this case, you'd want to use cycle.

closed seams

EDIT

You can't use cycle if you are combining things with plots but it probably won't matter in most cases. Here's an example which begins in the same way as the other cases, but then uses a plot and, finally, it ends at the starting point. The first coordinate plotted is the last given before the plot and the last plotted is the first given at all.

seamed plot

There are tiny gaps here, but does it really matter? I would guess not given the context. Hence, fixing it probably isn't worth the additional hassle and overhead. If the pieces were not to be cut out and pinned to cloth, it would be different and worth the trouble. For this kind of use, however, I'd go with the simpler solution. (The gap is only ever going to be very small, after all.)

While there might be some corner cases in which you might get something odd happening, I think this is probably going to be pretty exceptional given the use case. Generally, clothing is constructed from pieces which are reasonably regular in shape. (People don't want singularities in their bust darts.)

But I don't guarantee any of this, of course. If you end up dressed in rags as a result of my code, you'll just have to take up patchwork.

\documentclass[tikz,border=10pt,multi]{standalone}
\begin{document}
\tikzset{%
  seam/.style={%
    double distance=\seamallowance,
    draw,
  },
  seam allowance/.store in=\seamallowance,
  seam allowance=2.5pt,
}
\begin{tikzpicture}
  \draw [seam] (0,3) -- (2,7) -- (4,3);
  \draw [seam] (4,3) -- (3,0) -- (1,0) -- (0,3);
\end{tikzpicture}
\begin{tikzpicture}
  \draw [seam] (0,3) -- (2,7) -- (4,3) -- (4,3) -- (3,0) -- (1,0) -- cycle;
\end{tikzpicture}
\begin{tikzpicture}
  \draw [seam] (0,3) -- (2,7) -- (4,3) plot [smooth] coordinates { (4,3) (3,-2) (-2,0) (0,3) };
\end{tikzpicture}
\end{document}
  • Thanks, your ultra simple solution already looks quite good! Until now I did not even notice the not matching lines when using two \draw calls. Unfortunately I have other paths where one \draw call is for lines as in this example and the other one is \draw [black] plot [smooth] coordinates { (x1,y1) (x2,y2) and so on } - do you know how to get this all in one \draw call? Or is there any way to tell Tikz to cycle multiple \draw calls? Thanks :-) – stefan.at.wpf Jan 30 '16 at 22:55
  • I think you can just put it all in one \draw command. As long as you don't need, say, black for one bit and red for the other or something. You only want cycle when the path should be closed i.e. define an enclosed space of the kind it would make sense to fill. But you can do all kinds of things on the way to the cycle and TikZ will process it quite happily. – cfr Jan 30 '16 at 23:29
  • OK. Maybe don't use cycle in that case. But I think it will still work. – cfr Jan 30 '16 at 23:32
  • 1
    Remark: Neither of the two lines respects the original distances. One is inside and the other is outside... – Paul Gaborit Jan 31 '16 at 2:18
  • 1
    @cfr: About gaps mattering: Yes and no ;-) When cutting it myself based on paper, it is not a problem. But think of maybe laser-cut acrylic (that's a long-term thing for me). Then you need a perfect template. But I appreciate your provided solution, probably also influencing Paul's answer, which I still have to check in detail. – stefan.at.wpf Feb 1 '16 at 22:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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