4

This is a two part question that I'd really appreciate any help with, I couldn't find previous posts about this so I apologize if this is a repeat question. It all stems from attempting to create this figure that I drew:

enter image description here

where the two blue lines are imported from a data file created with C++, and the grey pencil marks are what I'd like to draw with Tikz. My first question deals with alignment, I'm having issues placing the lines I'd like to draw next to my imported lines. Whenever I try to draw them, the blue imported lines shift. If anyone has suggestions as to how I could draw on an imported curve that'd be great.

My second question is how do I create the arrows behind the blue lines? I know how to create them one-by-one, but I'm sure there is a better way where they stop at the next line they see.

Here's my code, it is able to compile, but definitely doesn't come close to creating my hand drawn image:

\documentclass{report}

\usepackage[top=1in,left=1in,bottom=1in,right=1in]{geometry}
\usepackage{pgfplots}
\usepackage{subfigure}

\pgfplotsset{compat=1.7}
\usetikzlibrary{backgrounds}
\usetikzlibrary{patterns}

\pgfdeclarepatternformonly{north east lines med}{\pgfqpoint{-1pt}{-1pt}}{\pgfqpoint{7pt}   {7pt}}{\pgfqpoint{6pt}{6pt}}%
{
  \pgfsetlinewidth{0.4pt}
  \pgfpathmoveto{\pgfqpoint{0pt}{0pt}}
  \pgfpathlineto{\pgfqpoint{6.1pt}{6.1pt}}
  \pgfusepath{stroke}
}


\begin{document}

\begin{figure}[!htb]
\centering
    \subfigure{
        \begin{tikzpicture}
            \begin{axis}[
            xtick=\empty,
            ytick=\empty,
            axis lines=none,
            no markers,
            ]
            \addplot + table[x index=50, y index=5000]{velocityprofile1.dat};
            \end{axis}
        \end{tikzpicture}
    }
    \subfigure{
        \begin{tikzpicture}
            \begin{axis}[
            xtick=\empty,
            ytick=\empty,
            axis lines=none,
            no markers,
            ]
            \addplot + table[x index=3644, y index=5000]{velocityprofile1.dat};
            \end{axis}
        \end{tikzpicture}
    }
\begin{tikzpicture}
    \begin{scope}[on background layer]
    \draw[-](-3,0)--(5,0);
    \end{scope}[on background layer]
\end{tikzpicture}
\caption{FTCS I}
\label{fig:please work}
\end{figure}


\end{document}

The velocityprofile.dat file is somewhat large and the question isn't really about importing that data specifically so I haven't attached it, let me know if you need it. Thanks for your help in advance!

EDIT: This is my code. The first column is x index=50 in the code, the second column is x index=3644, and the third is y index=5000.

  • 1
    The data files would be nice so we can see better what you've come up with. – A.Ellett Apr 10 '14 at 23:03
  • @Gonzalo Medina, how would I plot the curves directly with pgfplots? Isn't that what I did, or is there another way? @A.Ellett I tried uploading the data file to pastbin.com but my file size is too big, any other suggestions as to where to post it? – Patamoose Apr 10 '14 at 23:33
  • @Patamoose: Does the example really need your entire data set? Can't you just extrapolate 5-10 points so that the problem can be reproduced. As far as drawing the arrows perhaps Plotting Arrows Programmatically in Pgfplots might help. – Peter Grill Apr 10 '14 at 23:36
  • @Patamoose Ah, yes. Sorry about that; I read your question too quicly. I've deleted my previous comment. – Gonzalo Medina Apr 10 '14 at 23:38
  • You can put those two blue curves in a node and then it becomes similar to Drawing on an image with TikZ – user11232 Apr 10 '14 at 23:59
7

Here's a bit of a start on the image.

I first save the graph of your data in a standalone file (named graph_01.tex):

\documentclass{standalone}
\usepackage{pgfplots}
\pgfdeclarepatternformonly{north east lines med}{\pgfqpoint{-1pt}{-1pt}}{\pgfqpoint{7pt}   {7pt}}{\pgfqpoint{6pt}{6pt}}%
{
  \pgfsetlinewidth{0.4pt}
  \pgfpathmoveto{\pgfqpoint{0pt}{0pt}}
  \pgfpathlineto{\pgfqpoint{6.1pt}{6.1pt}}
  \pgfusepath{stroke}
}
\begin{document}

\begin{tikzpicture}%%[x=#1,y=#1]
      \begin{axis}[
        clip bounding box=upper bound,
        hide axis,
        no markers,
      ]
      \addplot + table[x index=0, y index=2]{vp1.dat};
      \end{axis}
\end{tikzpicture}

\end{document}

The choice of key words here is important. clip bounding box=upper bound in conjunction with hide axis allows you to get a copy of just the graph with no extraneous white space buffering it. This is important because you want the imported graphic to fit snugly in the structures of the primary document. For an alternative approach see my answer to my own question here.

I then import this standalone file in the primary document:

\documentclass{report}

\usepackage{graphicx}

\usepackage[margin=0.5in]{geometry}

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{arrows.meta}

\begin{document}

\begin{tikzpicture}[broad arrow/.tip={>[length=0.5em,width=0.75em]},
                    narrow arrow/.tip={Latex[length=0.75em,width=0.5em]},
                    flat arrow/.tip={Tee Barb[length=0pt,width=0.75em]},
                    flushed arrow/.tip={broad arrow[] . flat arrow[]}
                   ]

  %% general frame for picture
  %% bottom line
  \coordinate (bot/l) at (0,0);
  \coordinate (bot/r) at (5.5in,0);
  \draw (bot/l) -- (bot/r);

  %% top line
  \coordinate (top/l) at ($(bot/l)+(0,1.75in)$);
  \coordinate (top/r) at (top/l-|bot/r);
  \draw (top/l) -- (top/r);

  %% hash marks along top
  \foreach \myn in {1,2,...,30}
  {
    \coordinate (top/\myn) at ($(top/l)!\myn/30!(top/r)$);
    \draw (top/\myn) -- ($(top/\myn)+(130:0.5cm)$);
  }

  %% center dashed line
  \coordinate (bot/m) at ($(bot/l)!0.5!(bot/r)$);
  \coordinate (top/m) at (top/l-|bot/m);
  \coordinate (mid/c) at ($(bot/m)!0.65!(top/m)$);
  \coordinate (mid/b) at ($(bot/m)!0.50!(top/m)$);
  \coordinate (mid/a) at ($(bot/m)!0.35!(top/m)$);

  \draw[dashed] ($(top/m)+(0,1cm)$) 
                -- 
                           (mid/c)         
                        -- ($(mid/b)-(10pt,0)$)
                        -- ($(mid/b)+(3pt,0)$)
                        -- ($(mid/a)-(10pt,0)$)
                        -- (mid/a) 
                --
                ($(bot/m)-(0,1cm)$);

  %% left side notation
  \path[draw,
        arrows={flushed arrow-flushed arrow}]
    ($(bot/l)-(0.5cm,0)$) -- ($(top/l)-(0.5cm,0)$) node [midway,xshift=-0.5cm] {4cm};
  %% top notation
  \path (top/l) -- (top/m) node[yshift=0.5cm,midway,above] {0.1 seconds};
  \path (top/m) -- (top/r) node[yshift=0.5cm,midway,above] {steady state};

  %% left side graph
  \path let \p1=($(top/m)-(bot/m)$),
            \n1={veclen(\x1,\y1)}
        in
       node[inner sep=0pt] 
                           (left image) 
                           at ($(top/m)!0.5!(bot/l)$) 
                           {\includegraphics[height=\n1]{graph_01}};
  \coordinate (top/left/l) at (left image.west|-top/l);  
  \coordinate (bot/left/l) at (left image.west|-bot/l);  

   %% arrows pointing to graph
   \draw[dashed] ($(bot/left/l)!0.50!(top/left/l)$) -- (bot/left/l);
   \draw[arrows={-narrow arrow}] ($(bot/left/l)!0.20!(top/left/l)$) -- ++ (1.23cm,0);
   \draw[arrows={-narrow arrow}] ($(bot/left/l)!0.10!(top/left/l)$) -- ++ (2.75cm,0);

  \coordinate (bot/left/arrow/l) at ($(bot/left/l)-(0,0.5cm)$);
  \coordinate (bot/left/arrow/r) at (bot/left/arrow/l-|left image.east);

   %% arrow along horizontal axis below graph
   \draw  (bot/left/arrow/l)                             edge[arrows={flat arrow - flat arrow}] 
          ($(bot/left/arrow/l)!0.80!(bot/left/arrow/r)$) edge[arrows={-broad arrow}]
          (bot/left/arrow/r);

\end{tikzpicture}

\end{document}

which results in

enter image description here

I am still a bit of a novice at tikz, which means I'm sure there are better ways to do some of the things I'm doing here. So I hope others do chime in.

There are couple things I'm doing that might be of interest:

  • The graph to be imported is placed in a node between the upper and lower lines.
  • I measure the distance between those two lines to scale the contents of the node. I use \includegraphics key height to set the correct height via the \path let .... directives of tikz.
  • I set the inner sep for this node to 0pt. Then I use the east and west ends of the node to determine the length and positioning of the arrow placed under this image.
  • I also use the west side of the node to determine where to draw the vertical broken line on the left side of the image (I assumed that was added separately from the imported image.... perhaps I'm wrong).
  • Then I add arrows from the west side and guess approximately where the arrow head should end.
  • I use edge directive for the more complex arrow underlying the whole graph.
  • That's a really interesting way to solve it. It's sort of like the link @Harish Kumar gave. Anyway, it ends up working out if you put it in a node like that, thanks for the help! – Patamoose Apr 11 '14 at 1:01
  • @Patamoose I've updated my answer. Not too many changes, but I show a method of better importing your image and getting it to fit snugly. – A.Ellett Apr 11 '14 at 4:12

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.