How to pimp my tube?
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}
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
.
Just for completeness:
Based on percusse's comment about double
, here's a version for a tube like in the picture.
\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}}