33

How can I pimp my tube?

enter image description here

\documentclass{scrartcl}
% needs logicpuzzle bundle v1.8
% http://mirrors.ctan.org/graphics/pgf/contrib/logicpuzzle/logicpuzzle.sty
% or replace logicpuzzle -> battleship
\usepackage{logicpuzzle}
\makeatletter
\definecolor{LPlgrey}{rgb}{.8,.8,.8}
\definecolor{LPtgrey}{rgb}{.7,.7,.7}
\definecolor{LPgrey}{rgb}{.5,.5,.5}
\def\myscale{.7}
\newcommand*\LPtunnel%
{%
  \begin{tikzpicture}[scale=\myscale]
    \fill[color=black] (0,0) -- (0,1) -- (.4,.5) -- (.4,0) -- cycle;
    \fill[color=LPgrey] (0,1) -- (1,1) -- (1,.5) -- (.4,.5) -- cycle;
    \fill[color=LPlgrey] (.40,0) rectangle (1,.5);
  \end{tikzpicture}
}%
\newcommand*\tunnel[2]{\LP@setcellcontent{#1}{#2}{\LPtunnel}}
\newcommand*\tube[3]%
{%
  \def\tubepath{%
  (#1.5,#2.5)
  \foreach \dir in {#3}%
  {%
    \ifnum\dir=2%
    --++(0,-1)%
    \fi%
    \ifnum\dir=4%
    --++(-1,0)%
    \fi%
    \ifnum\dir=6%
    --++(1,0)%
    \fi%
    \ifnum\dir=8%
    --++(0,1)%
    \fi%
  };}%
  \begin{puzzlebackground}
    \pgfsetcornersarced{\pgfpoint{3mm}{3mm}}
    \draw[color=LPtgrey, line width=.4cm*\myscale] \tubepath;%
  \end{puzzlebackground}
}%
\makeatother
\begin{document}
  \begin{logicpuzzle}[scale=\myscale]
    \tunnel{1}{1}
    \tunnel{5}{5}
    \tube{1}{1}{6,6,6,6,8,8,8,4,2,4,4,4,8,8,6,6,6,6}
  \end{logicpuzzle}
\end{document}

Can I add a decoration like in this picture?

I know I can add a shading (kind of 3D effect) to a rectangle. But it is also possible for such a complex path with a shading based on the angle?

Another important point: It must survive scaling.

  • That looks like a line with double option. I don't see where the shadows come into play here. – percusse Apr 18 '13 at 14:25
  • @percusse Not in the picture tube. The shading 3D-effect is just another idea. – Josef Apr 18 '13 at 14:32
36

Something like that ?

\documentclass{standalone}
% needs logicpuzzle bundle v1.8
% http://mirrors.ctan.org/graphics/pgf/contrib/logicpuzzle/logicpuzzle.sty
% or replace logicpuzzle -> battleship
\usepackage{logicpuzzle}
\makeatletter
\definecolor{LPlgrey}{rgb}{.8,.8,.8}
\definecolor{LPtgrey}{rgb}{.7,.7,.7}
\definecolor{LPgrey}{rgb}{.5,.5,.5}
\def\myscale{.7}
\newcommand*\LPtunnel%
{%
  \begin{tikzpicture}[scale=\myscale]
    \fill[color=black] (0,0) -- (0,1) -- (.4,.5) -- (.4,0) -- cycle;
    \fill[color=LPgrey] (0,1) -- (1,1) -- (1,.5) -- (.4,.5) -- cycle;
    \fill[color=LPlgrey] (.40,0) rectangle (1,.5);
  \end{tikzpicture}
}%
\newcommand*\tunnel[2]{\LP@setcellcontent{#1}{#2}{\LPtunnel}}
\newcommand*\tube[3]%
{%
  \def\tubepath{%
  (#1.5,#2.5)
  \foreach \dir in {#3}%
  {%
    \ifnum\dir=2%
    --++(0,-1)%
    \fi%
    \ifnum\dir=4%
    --++(-1,0)%
    \fi%
    \ifnum\dir=6%
    --++(1,0)%
    \fi%
    \ifnum\dir=8%
    --++(0,1)%
    \fi%
  };}%
  \begin{puzzlebackground}
    \pgfsetcornersarced{\pgfpoint{3mm}{3mm}}
    \draw[color=LPtgrey!80!black, line width=.4cm*\myscale] \tubepath;%
    \draw[color=LPtgrey, line width=.38cm*\myscale] \tubepath;%
    \draw[color=LPtgrey!85, line width=.35cm*\myscale] \tubepath;%
    \draw[color=LPtgrey!70, line width=.32cm*\myscale] \tubepath;%
    \draw[color=LPtgrey!55, line width=.29cm*\myscale] \tubepath;%
    \draw[color=LPtgrey!45, line width=.25cm*\myscale] \tubepath;%
    \draw[color=LPtgrey!35, line width=.2cm*\myscale] \tubepath;%
  \end{puzzlebackground}
}%
\makeatother
\begin{document}
  \begin{tikzpicture}[scale=\myscale]
    \path[draw] (1,1) grid (6,6);
    \tunnel{1}{1}
    \tunnel{5}{5}
    \tube{1}{1}{6,6,6,6,8,8,8,4,2,4,4,4,8,8,6,6,6,6}
  \end{tikzpicture}
\end{document}

enter image description here

  • looks fine, indeed! ;-) – Josef Apr 18 '13 at 14:37
  • 1
    This solution shall be part of tunnel.sty in the next version of the logicpuzzle bundle. May i kindly ask you for a waiver (based on cc-wiki) to include your code and license it under LPPL? I will of course attribute you. Even with your real name, if you contact me. ;-) – Josef Apr 19 '13 at 10:47
  • you can use this code as you want ! I'm happy that it's useful for you. – Xoff Apr 19 '13 at 13:47
17

enter image description here

Solution below uses the Asymptote module tubepuzzle.asy to set up the puzzle and to draw it. The puzzle is defined by dimensions and a pipe path, numbers are counted automatically. File tpuzzle.tex:

\begin{filecontents*}{tubepuzzle.asy}
struct TubePuzzle{
  int m,n;
  pair start;
  pair fin;
  guide pipe;
  pen inPen,outPen;
  pen txtPen,gridPen;
  pen botPen,topPen;
  pen leftPen;

  int[] rowCount;
  int[] colCount;
  int[][] M;

  picture picBoard;

  void iniPens(){ 
    inPen= rgb(236/255,234/255,238/255)+5;
    outPen=rgb(132/255,174/255,204/255)+7;
    txtPen=rgb(52/255,50/255,52/255);
    gridPen=txtPen+0.8pt;
    botPen=rgb(228/255,238/255,236/255);
    topPen=rgb(132/255,134/255,132/255);
    leftPen=rgb(28/255,30/255,36/255);
  }
  transform sh,pipesh;


  void hole(picture pict,pair t, transform tr){
    pair a=(0,0);
    fill(pict,tr*shift(t)*((a.x,-0.5)--(0.5,-0.5)--(0.5,a.y)--a--cycle),botPen);
    fill(pict,tr*shift(t)*(a--(-0.5,0.5)--(-0.5,-0.5)--(a.x,-0.5)--cycle),leftPen);
    fill(pict,tr*shift(t)*(a--(0.5,a.y)--(0.5,0.5)--(-0.5,0.5)--cycle),topPen);
  }

  void countCells(){
    rowCount=array(m,0);    
    colCount=array(n,0);
    M=array(m,array(n,0));
    pair a,b,c,d;
    a=point(pipe,0);
    for(int k=1;k<size(pipe);++k){
      b=point(pipe,k);
      c=(min(a.x,b.x),min(a.y,b.y));
      d=(max(a.x,b.x),max(a.y,b.y));
      for(int i=(int)c.y;i<=(int)d.y;++i)M[i-1][(int)d.x-1]=max(M[i-1][(int)d.x-1],1);
      for(int j=(int)c.x;j<=(int)d.x;++j)M[(int)d.y-1][j-1]=max(M[(int)d.y-1][j-1],1);
      a=b;
    }
    for(int i=0;i<M.length;++i){
      for(int j=0;j<M[0].length;++j){
        colCount[j]+=M[i][j];
        rowCount[i]+=M[i][j];
      }
    }
  }

  picture draw(transform sc=identity(), bool showPipe=false){
    picture temp;
    erase(picBoard);
    temp.add(new void(picture pict,transform tr){
      for(int i=1;i<m;++i){
        draw(pict,tr*sh*((0,i)--(n,i)),gridPen);
      }
      for(int j=1;j<n;++j){
        draw(pict,tr*sh*((j,0)--(j,m)),gridPen);      
      }
      draw(pict,tr*sh*((0,0)--(n,0)--(n,m)--(0,m)--cycle),gridPen+2pt);

      real  xxyy=max(tr.xx,tr.xy,tr.yx,tr.yy);
      inPen= rgb(236/255,234/255,238/255)+xxyy*0.5;
      outPen=rgb(132/255,174/255,204/255)+xxyy*0.8;

      if(showPipe){// drawTube(pict,tr);

        draw(pict,tr*pipesh*pipe,outPen);
        draw(pict,tr*pipesh*pipe,inPen);
      }
      hole(pict,start,tr);
      hole(pict,fin,tr);    
      for(int i=0;i<rowCount.length;++i){
        label(pict,tr*shift(-1,i)*scale(2pt/10mm)*Label(string(rowCount[i])));
      }
      for(int j=0;j<colCount.length;++j){
        label(pict,tr*shift(j,m)*scale(2pt/10mm)*Label(string(colCount[j])));
      }
    });
    picBoard.add(sc*temp);
    return picBoard;
  }

  void operator init(int m=9, int n=m 
    , guide pipe=(1,1)--(n,1)--(n,m)
    ){
    this.sh=shift(-0.5,-0.5);
    this.pipesh=shift(-1,-1);
    this.m     = m    ;
    this.n     = n    ;
    this.pipe  = pipe ;
    this.start = pipesh*point(this.pipe,0);
    this.fin   = pipesh*point(this.pipe,length(this.pipe));
    iniPens();
    countCells();
  }
}
\end{filecontents*}
%
%
\documentclass[10pt,a4paper]{article}
\usepackage{lmodern}
\usepackage{caption}
\usepackage{asymptote}
\begin{document}

\section*{Tube puzzles with the Asymptote}
\begin{minipage}{5cm}
\center
\begin{asy}
import tubepuzzle; 
unitsize(5mm);
texpreamble("\usepackage{lmodern}");
TubePuzzle tp=TubePuzzle();
add(tp.draw());
\end{asy}
\captionof{figure}{Default puzzle board}
\end{minipage}
%
\begin{minipage}{5cm}
\begin{asy}
import tubepuzzle; 
unitsize(5mm);
//size(300,300,IgnoreAspect);
texpreamble("\usepackage{lmodern}");
TubePuzzle tp=TubePuzzle();
//add(tp.draw());
add(shift(12,0)*tp.draw(true));
\end{asy}

\captionof{figure}{Default puzzle solution}
\end{minipage}

\center
\begin{asy}
import tubepuzzle; 
unitsize(5mm);
//size(300,300,IgnoreAspect);
texpreamble("\usepackage{lmodern}");
guide g=(4,2)--(4,1)--(2,1)--(2,2)--(1,2)--(1,4)--(5,4)--(5,6)--(1,6)
--(1,8)--(2,8)--(2,9)--(5,9)--(5,8)--(9,8)--(9,4)--(8,4)--(8,3)--(7,3)--(7,2);

TubePuzzle tp=TubePuzzle(9,9,pipe=g);
add(scale(0.8)*rotate(60)*tp.draw());
add(shift(6,0)*scale(1.5)*tp.draw(true));
\end{asy}

\captionof{figure}{Custom puzzle/solution}

\end{document}

To process it with latexmk, create file latexmkrc:

sub asy {return system("asy '$_[0]'");}
add_cus_dep("asy","eps",0,"asy");
add_cus_dep("asy","pdf",0,"asy");
add_cus_dep("asy","tex",0,"asy");

and run latexmk -pdf tpuzzle.tex.

  • 3
    Each and every one of your answers using Asymptote convinces me more and more that it's a really powerful tool. Fantastic job! – Gonzalo Medina Apr 18 '13 at 23:36
  • Thanks a lot for your perspective, it inspires everyone. – texenthusiast Apr 19 '13 at 5:56
  • @Gonzalo Medina: It is really powerful indeed. Just touching the tip of the iceberg, actually. – g.kov Apr 19 '13 at 9:36
  • Interesting answer, but i'm focused on TikZ – Josef Apr 19 '13 at 10:41
9

Just for completeness:

Based on percusse's comment about double, here's a version for a tube like in the picture.

enter image description here

\newcommand*\tube[3]%
{%
  \def\tubepath{%
  (#1.5,#2.5)
  \foreach \dir in {#3}%
  {%
    \ifnum\dir=2%
    --++(0,-1)%
    \fi%
    \ifnum\dir=4%
    --++(-1,0)%
    \fi%
    \ifnum\dir=6%
    --++(1,0)%
    \fi%
    \ifnum\dir=8%
    --++(0,1)%
    \fi%
  };}%
  \begin{puzzlebackground}
    \pgfsetcornersarced{\pgfpoint{3mm}{3mm}}
    \draw[color=blue!40, double=LPtgrey!40, line width=1pt*\myscale, double distance between line centers=.4cm*\myscale] \tubepath;%
  \end{puzzlebackground}
}%

For a version with corners, just delete \pgfsetcornersarced{\pgfpoint{3mm}{3mm}}

1

Just for fun. The pipe is drawn with a double line, the tunnel is defined with a pic which allows to repeate it very easily. And pipe's path is defined using perpendicular segments or following turtle route.

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{turtle}

\definecolor{LPlgrey}{rgb}{.8,.8,.8}
\definecolor{LPtgrey}{rgb}{.7,.7,.7}
\definecolor{LPgrey}{rgb}{.5,.5,.5}
\tikzset{
    pipe/.style={double=gray!30, draw, double distance=3mm, rounded corners=3mm},
    tunnel/.pic={%
        \fill[color=black] (0,0) -- (0,1) -- (.4,.5) -- (.4,0) -- cycle;
        \fill[color=LPgrey] (0,1) -- (1,1) -- (1,.5) -- (.4,.5) -- cycle;
        \fill[color=LPlgrey] (.40,0) rectangle (1,.5);}
}

\begin{document}
\begin{tikzpicture}
    \draw (0,0) grid (5,5);
    \path (0,0) pic{tunnel};
    \path (4,4) pic{tunnel};
    \draw[pipe] (1,.5)-|(4.5,3.5)-|(3.5,2.5)-|(0.5,4.5)--(4,4.5);
\end{tikzpicture}

\begin{tikzpicture}
    \draw (0,0) grid (5,5);
    \path (0,0) pic{tunnel};
    \path (4,4) pic{tunnel};
    \draw[pipe] (1,.5) 
        [turtle={right, fd=3.5, lt, fd=3, lt, fd, lt, fd, rt, fd=3, rt, fd=2, rt, fd=3.5}];
\end{tikzpicture}
\end{document}

enter image description here

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.