3

I'd like to draw a piece of "ground line" (picture below), but I don't know, how to make a line style and how to ensure proper localizations of the picture boundary. The solution of achieving an expected line style I found in the following discussion: laser beam drawing - the line having a gradient of colours which is perpendicular in each point to the line axis.

Is there any way of creating a customized line style, that will be executed by the command like \ground (0,0) -- (0.5,1) -- (1,0.25); or by option (for instance with the name ground) in the optional argument of \draw command?

According to @Loop Space answer (tikz: double lines are shifted) the bounding box covers all paths and is extra enlarged with the half of the line width. So by default any line might be placed within the bounding box while line join=round option is chosen (I prefer miter style). How to find the line boundaries to avoid unwanted cutting of the line?

Line of the "earth surface"

In MWE below I applied an extension of lines with the use of point symmetry to solve the problem of vertical line endings (the best other solution given by @Loop Space in vertical line endings leads to not smooth line boundaries - as he demonstrated it).

MWE:

\documentclass{standalone}
\usepackage{amsmath}
\usepackage{pgfplots}
\usetikzlibrary{calc}

\newcommand\groundthick{12} % ground thickness
\newcommand\linesamount{30} % number of coaxial gray lines having various hue

\newcommand\groundpath[1]{
    \begin{scope}
        % start and end point
        \path #1 coordinate (rend) -- cycle
              -- (current subpath start) coordinate (lend);
        \begin{scope}
            \clip #1 |- (current bounding box.south) -| cycle;
            \foreach \lineno [evaluate=\lineno as \shader using \lineno*100/\linesamount] in {0,...,\linesamount}{
                \def\thicker{\groundthick*2-\lineno*\groundthick*2/\linesamount}
                % ground line member
                \draw [line width=\thicker,color=gray!\shader,
                       line join=miter] #1;
                % left ground line extension
                \draw [line width=\thicker,color=gray!\shader,
                       line join=miter,scale around={-1:(lend)}] #1;
                % right ground line extension
                \draw [line width=\thicker,color=gray!\shader,
                       line join=miter,scale around={-1:(rend)}] #1;
            }
        \end{scope}
        \draw #1;   % pavement
    \end{scope}
}

\begin{document}
    \begin{tikzpicture}
    \groundpath{
        (0,0) -- +(0.5,0.15) -- +(1.0,0.65) -- +(1.5,-0.12)
        -- +(2.0,0.56) -- +(2.5,0.58) -- +(3.0,0.65) -- +(3.5,0.6)
        -- +(4.0,0.98) -- +(4.5,0.55) -- +(5.0,0.95)
    }
    \end{tikzpicture}
\end{document}

EDIT:

After @cfr comment and answer I decided to try correct my question. The problem is connected with automatic finding of coordinates of the most external parts of lines. What I am doing in the code is depicted below:

MWE explanation

After adding only the line in which the line is drawing with opacity=0, as proposed by @cfr below, the problem follows from the addition of unwanted margins, as well as from the removing of one line tip (generally of more tips):

enter image description here

And I also would like to ask, if the line:

\groundpath{(A) -- (B) -- (C)}

could be replaced by something like that:

\groundpath (A) -- (B) -- (C);

or like that:

\draw [groundpath] (A) -- (B) -- (C);

  • I don't really understand what you want. Why clip the path at all if you don't want it to be cut off? And do you really mean 'to narrow picture boundaries'? If so, I have no idea what you mean. My best guess is that you really meant too narrow picture boundaries which is rather a different thing.... – cfr Nov 1 '15 at 19:42
  • I'd like to achieve a picture with automatically adjusted boundaries. I used clip command to remove upper part of coaxial lines, and I don't know how to chose the proper position of the clip path below my "ground line" (to not cut it, but also not producing an empty space below the line). If clip command is not applied, the "ground line" is still cut because the bounding box is to small (I used the word "narrow"). – forrest Nov 1 '15 at 19:53
  • You mean too small? Or too narrow? Correcting that would help clarify things, if so. – cfr Nov 1 '15 at 20:04
5

Updated version

This is more of a faff but it does clip the path correctly on at least 3 sides (north, west and east). It is a little harder to tell in the case of south because the path fades to white in this direction anyway. (So maybe this is less important - not sure.)

clipped path with drawn bounding box

Faffy code:

\documentclass[tikz,border=5pt]{standalone}

\newcommand\groundthick{12}% ground thickness
\newcommand\linesamount{30}% number of coaxial gray lines having various hue
\begin{document}
  \begin{tikzpicture}
    [
      ground/.pic={
        \path #1 coordinate (rend) -- cycle -- (current subpath start) coordinate (lend);
        \foreach \lineno
        [
          evaluate=\lineno as \shader using \lineno*100/\linesamount,
          evaluate=\lineno as \thicker using (1-\lineno/\linesamount)*2*\groundthick
        ] in {0,...,\linesamount}{%
          \path [line width=\thicker pt, draw=gray!\shader, opacity=0] #1;
          \path [line width=\thicker pt, draw=gray!\shader, scale around={-1:(lend)}, opacity=0] #1;
          \path [line width=\thicker pt, draw=gray!\shader, scale around={-1:(rend)}, opacity=0] #1;
        }
        \coordinate (c) at (current bounding box.south);
        \pgfresetboundingbox
        \begin{scope}
          \clip #1 |- (c) -| cycle;
          \foreach \lineno
          [
          evaluate=\lineno as \shader using \lineno*100/\linesamount,
          evaluate=\lineno as \thicker using (1-\lineno/\linesamount)*2*\groundthick
          ] in {0,...,\linesamount}{%
            \draw [line width=\thicker pt, color=gray!\shader] #1;
            \draw [line width=\thicker pt, color=gray!\shader, scale around={-1:(lend)}] #1;
            \draw [line width=\thicker pt, color=gray!\shader, scale around={-1:(rend)}] #1;
          }
        \end{scope}
      }
    ]
    \pic {ground={(0,0) -- +(0.5,0.15) -- +(1.0,0.65) -- +(1.5,-0.12) -- +(2.0,0.56) -- +(2.5,0.58) -- +(3.0,0.65) -- +(3.5,0.6) -- +(4.0,0.98) -- +(4.5,0.55) -- +(5.0,0.95)}};
    \draw (current bounding box.north west) rectangle (current bounding box.south east);
  \end{tikzpicture}
\end{document}
  • Thanks. The opacity=0 option gives smart solution of the problem of enlarging of the bounding box by the half of the line thickness - it is very useful prompt for me. But the fixed yshift distance doesn't follow the line tip position. Gives LaTeX no solution of this problem till now? Is it an easy way of making a command, that could be executed by \groundpath (A) -- (B) -- (C);, not by \groundpath{(A) -- (B) -- (C)} – forrest Nov 1 '15 at 20:57
  • The yshift is just an accident, I think. I meant to delete it and forgot to do so. I'll get rid of it when I edit the question. It did not seem to have any effect, so I abandoned that idea. If you draw the clipping path, you'll see why it doesn't work ;). – cfr Nov 2 '15 at 2:47
  • But drawing of the invisible line to set bottom coordinate of clipping line give the additional margin on every side of the picture. It has the width of half line width, so it is not sufficient to draw every corner of the miter line (the round one will be drawn correctly). Only \clip command preceding the commands of wide line drawing prevents addiction of unwanted margins above the picture and on left and right side. So the solution with yshift I found better, but still the corner is cut by clipping line. – forrest Nov 2 '15 at 19:07
  • I couldn't get the yshift version to work. That's why I meant to delete it. – cfr Nov 2 '15 at 23:29
  • @forrest You can reset the bounding box, I guess, but it it rather a faff. – cfr Nov 3 '15 at 23:08

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.