2

I was inspired by the OP in this thread: Tikz: Drawing railway tracks to make a tikzstyle that will allow me to draw arbitrarily shaped pairs of silver lines with black borders (which will actually be part of train tracks, but the examples in the linked threads do not meet my requirements). However, as stated in the comment on the linked thread, the double distance makes the area inbetween the lines opaque. Adding double=none only makes them black instead of white... but I need them to be 100% transparent. Is there a way to change my code so it works just like it does now, but the space inbetween the lines is transparent?

This is my minimal code example:

\documentclass[tikz]{standalone}
\usetikzlibrary{decorations.pathmorphing}
\usepackage{pagecolor}


\definecolor{railColor}{RGB}{200,200,200}
\newcommand{\connectionRailThickness}{0.051cm}
\newcommand{\connectionRailLineThickness}{0.013cm}
\newcommand{\connectionRailDistance}{0.367cm}


\tikzstyle{track}=[
postaction={draw=black,decorate,fill=none,double distance=\connectionRailDistance+\connectionRailThickness-\connectionRailLineThickness,line width=\connectionRailLineThickness},
postaction={draw=railColor,decorate,fill=none,double distance=\connectionRailDistance-\connectionRailThickness-\connectionRailLineThickness,line width=\connectionRailThickness},
postaction={draw=black,decorate,fill=none,double distance=\connectionRailDistance-\connectionRailThickness-\connectionRailLineThickness,line width=\connectionRailLineThickness},
]


\begin{document}
\pagecolor{yellow}

\begin{tikzpicture}
\draw[track] (0,0) to (10,0);
\end{tikzpicture}

\end{document}
Lukas
  • 23
  • Hi, welcome. Something like https://tex.stackexchange.com/questions/406162/two-problems-with-double-lines-in-tikz/406171#406171 (without the arrow head) could perhaps be an option, but that specific code doesn't work for curved lines, only straight ones. – Torbjørn T. Mar 03 '18 at 20:03
  • 1
    double lines are draw with two lines: first wider, second narrower width which its color cover the first one. with this make illusion, that are drawn two lines on prescribed distance. consequently space between "lines" can not be transparent. or i'm wrong? – Zarko Mar 03 '18 at 20:04
  • @cfr, i don't undertand op question well. Mark Wibrow answer on linked question gives solution (and eiterom too) ... as far i understand how tikz work a cascade of postactions here is wrong (dead end) way. – Zarko Mar 03 '18 at 20:30
  • @cfr, if postaction accumulate? i doubt (don't know). i thing that on power is the last one. – Zarko Mar 03 '18 at 20:32
  • @TorbjørnT. Thanks for your suggestion, it is quite important to me that curved lines work. – Lukas Mar 03 '18 at 21:34
  • @cfr The code by Mark Wibrow gives seems to give nice results at first, but what I wanted to have borders around the rails and sleepers. I tried to do that by editing his code, but I wasn't able to, because the code is way too confusing to me. The code by user61383 seemed easier to edit to my specifications.

    Also, I don't like how the sleepers curve in Mark Wibrow's code, but as I am going to produce then in a different way, that doesn't matter too much. Anyway, if someone could show me how to edit his code to get my wanted results, that would be awesome too (with or without sleepers).

    – Lukas Mar 03 '18 at 21:40
  • @Zarko 'eiterom'? Actually, they do seem to accumulate. However, I agree that's a dead end if you want actual (rather than fake) transparency. – cfr Mar 03 '18 at 22:00
  • 1
    I'm sorry for saying "first answer" when I meant to say OP. I edited my post. True transparency is indeed important to me, because in the final document, the background won't be just a single color. The yellow background in my example was just to illustrate the opacity of the tracks. – Lukas Mar 03 '18 at 22:17
  • @Lukas Thanks for clarifying the question. It makes sense now. – cfr Mar 03 '18 at 23:51
  • @Zarko @ OP Tidied up the comments a bit. Maybe you'd like to do likewise? – cfr Mar 04 '18 at 00:25

1 Answers1

5

This is not exactly what you asked for, but I think it is pretty close. The only downside is that you need to use two, rather than one, \draw lines per path. The first uses outlined track and the second track. Both styles use a slightly modified version of Mark Wibrow's answer.

\begin{tikzpicture}
  \draw[outlined track] (0,0) to (10,0);
  \draw[track] (0,0) to (10,0);
  \begin{scope}[shift=(-45:4)]
    \draw [outlined track] (-2,5) to (0,5) to[out=  0,in=270] (2,8);
    \draw [track] (-2,5) to (0,5) to[out=  0,in=270] (2,8);
    \draw [outlined track]  (6,5) to (4,5) to[out=180,in=270] (2,8) to (2,10);
    \draw [track] (6,5) to (4,5) to[out=180,in=270] (2,8) to (2,10);
  \end{scope}
\end{tikzpicture}  

I think the result is not bad in terms of the output:

outlined tracks

Ideally, a little more would be automated, but the basic idea seems fairly sound. Essentially, we first draw a slightly enlarged version of the tracks in the outlining colour (black by default) and then draw a normally-sized version in the filling colour (gray by default). Done this way, we can also include the sleepers by adjusting the dash pattern definition used in the tracks decoration's code. First, we adjust the on-off pattern to allow for the different sizes of the thicker outlining lines and the thinner filling lines. Then we use dash phase to offset it appropriately in similar fashion.

This is all very trivial. The code is essentially Mark's - I've just added a few more keys, another style and a very small amount of flexibility to the part of the decoration responsible for the sleepers.

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usepackage{pagecolor}

% addaswyd o ateb Mark Wibrow: https://tex.stackexchange.com/a/198114/
\usetikzlibrary{decorations,fit,fadings}

% Layers
\pgfdeclarelayer{sleeper}
\pgfdeclarelayer{rail}
\pgfsetlayers{sleeper,rail,main}

\pgfdeclaredecoration{tracks}{final}{%
  \state{final}{%
    \pgftransformreset% <- I think is possibly vital.% <- cfr: why?
    %
    % Get bounding box of decorated path as a node.
    % Must do it this way using basic layer.
    \pgftransformshift{\pgfpointanchor{current path bounding box}{south west}}%
    \pgfcoordinate{@1}\pgfpointorigin
    \pgftransformshift{\pgfpointanchor{current path bounding box}{north east}}%
    \pgfcoordinate{@2}\pgfpointorigin
    \node [fit=(@1)(@2), inner sep=\railsep+2*\railwidth] (@@) {};
    %
    % Create a fading for the track.
    \pgfinterruptpicture%
    \begin{tikzfadingfrompicture}[name=tracks]
      \path[draw=transparent!0, line width=\railsep+2*\railwidth, postaction={draw=transparent!100, line width=\railsep}] \pgfextra{\pgfsetpath\pgfdecoratedpath};
      \useasboundingbox (@@.south west) (@@.north east);
    \end{tikzfadingfrompicture}%
    \endpgfinterruptpicture
    %
    % Draw sleepers.
    \ifx\sleeperlayer\emptylayer\else\pgfonlayer{\sleeperlayer}\fi
    \draw [draw=\sleepercolor, line width=\sleeperlength, dash pattern=on \sleeperwidth off {\sleepersep-\sleeperwidth+\sleeperowidth}, dash phase={0.5*(\sleeperwidth-\sleeperowidth)}, every sleeper/.try] \pgfextra{\pgfsetpath\pgfdecoratedpath};
    \ifx\sleeperlayer\emptylayer\else\endpgfonlayer\fi
    %
    % Draw the track
    \ifx\raillayer\emptylayer\else\pgfonlayer{\raillayer}\fi
    \fill [path fading=tracks, fit fading=false, fading transform={shift=(@@.center)}, fill=\railcolor] (@@.south west) rectangle (@@.north east);
    \ifx\raillayer\emptylayer\else\endpgfonlayer\fi
  }
}
\def\emptylayer{}
\tikzset{%
  track/.style={
    decoration=tracks, decorate
  },
  outlined track/.style={
    track,
    decorations/.cd,
    rail width=\railowidth,
    rail sep=\railisep,
    rail color=\raildraw,
    sleeper color=\sleeperdraw,
    sleeper width=\sleeperowidth,
  },
  decorations/.cd,
  rail sep/.store in=\railsep,
  rail inner sep/.store in=\railisep,
  rail width/.store in=\railwidth,
  rail inner width/.forward to=/tikz/decorations/rail width,
  rail outer width/.store in=\railowidth,
  rail color/.store in=\railcolor,
  rail draw/.store in=\raildraw,
  rail layer/.store in=\raillayer,
  sleeper sep/.store in=\sleepersep,
  sleeper width/.store in=\sleeperwidth,
  sleeper inner width/.store in=\sleeperiwidth,
  sleeper inner width/.forward to=/tikz/decorations/sleeper width,
  sleeper outer width/.store in=\sleeperowidth,
  sleeper length/.store in=\sleeperlength,
  sleeper color/.store in=\sleepercolor,
  sleeper draw/.store in=\sleeperdraw,
  sleeper layer/.store in=\sleeperlayer,
  rail sep=4pt,
  rail inner sep=3pt,
  rail inner width=1pt,
  rail outer width=2pt,
  rail color=gray,
  rail draw=black,
  rail layer=rail,
  sleeper sep=6pt,
  sleeper inner width=1pt,
  sleeper outer width=2pt,
  sleeper length=10pt,
  sleeper color=gray,
  sleeper draw=black,
  sleeper layer=sleeper,
}

\begin{document}
\pagecolor{yellow}
\begin{tikzpicture}
  \draw[outlined track] (0,0) to (10,0);
  \draw[track] (0,0) to (10,0);
  \begin{scope}[shift=(-45:4)]
    \draw [outlined track] (-2,5) to (0,5) to[out=  0,in=270] (2,8);
    \draw [track] (-2,5) to (0,5) to[out=  0,in=270] (2,8);
    \draw [outlined track]  (6,5) to (4,5) to[out=180,in=270] (2,8) to (2,10);
    \draw [track] (6,5) to (4,5) to[out=180,in=270] (2,8) to (2,10);
  \end{scope}
\end{tikzpicture}  
\end{document}
cfr
  • 198,882
  • bravo, (+1)! i need some time to understand all used tricks :-) – Zarko Mar 03 '18 at 22:07
  • Thank you for your answer, but I am getting error codes when trying to compile your code: – Lukas Mar 03 '18 at 22:08
  • Zeile 90: pgfkeys: I do not know the key '/tikz/decorations/rail inner width/.forward to' and I am going to ignore it. Perhaps you misspelled it. } Zeile 90: pgfkeys: I do not know the key '/tikz/decorations/sleeper inner width/.forward to' and I am going to ignore it. Perhaps you misspelled it. } Zeile 90: pgfkeys: I do not know the key '/tikz/decorations/rail inner width' and I am going to ignore it. Perhaps you misspelled it. } Zeile 96: Undefined control sequence \draw[track] (0,0) to (10,0); Zeile 96: Missing number, treated as zero \draw[track] (0,0) to (10,0); – Lukas Mar 03 '18 at 22:08
  • @Lukas Do you get those errors from exactly the code I posted i.e. you copy-paste the code into a new .tex file and you compile it and you get those errors? If so, what version of PGF/TikZ do you have? – cfr Mar 03 '18 at 23:49
  • @Zarko Thanks, but the tricks are not mine, but Mark's. Does the code work for you? – cfr Mar 03 '18 at 23:50
  • 1
    i tested it . it work nice and smooth. – Zarko Mar 04 '18 at 00:02
  • @Zarko Thanks, Zarko. I'm guessing the OP just needs to update, in that case, though I thought .forward to was not especially new. (But, of course, the OP may have a not-at-all-recent installation.) – cfr Mar 04 '18 at 00:23
  • 1
    @cfr, i have recent miktex installation, but tikz is official one (3.0.1.a, from 2015). pagecolor is recent (2017/05/29). if op has the same version of packages and test your code, that he shouldn't receive errors. – Zarko Mar 04 '18 at 00:40
  • Yes, I get the errors with the exact code you posted. If it works for both of you, it's propably on my end. The log said "Package: tikz 2010/10/13 v2.10 (rcs-revision 1.76)", so I guess my tikz installation is indeed quite outdated. I'm using MikTeX 2.9 with TeXStudio in case that is of any relevance as well. I am going to update all packages and get back to you when it's done. – Lukas Mar 04 '18 at 09:31
  • 1
    Ok, after the updates kept failing and I reinstalled MiKTeX, it finally worked! Getting the code to do exactly what I want will now only be a matter of changing the exact measurements and color, which should be easy for me to do. Thank you very much for your help! – Lukas Mar 04 '18 at 09:59
  • @Lukas I'm not surprised it didn't work for you. 2.10 is really quite ancient. Lots of code posted on TeX SE would have failed - anything using a .pic, for example, which is quite popular. Glad you got it sorted. – cfr Mar 05 '18 at 00:39
  • On a recent tikz, this does not work any more. – GrB Feb 20 '22 at 18:46