5

This is a related (more general) question to the previous post

Tikz: Drawing a line inside of certain shape

The answer given in the above question works perfectly if the given shape can be described by a single path. However, it doesn't work with any shape containing 2x2 block.

Let me illustrate my problem with the following example.

enter image description here

Like the picture above, I have a connected shape which is a union of square blocks. Now, I want to draw red lines so that these red lines form a "shrinked" version of the shape. However, I can not simply scale the shape as the new shape fomed by red lines is not exactly similar to the original shape.

Here is my code:

\documentclass{article}
\usepackage{tikz}
\begin{document}
    \begin{tikzpicture}
        \draw (-3, -3) grid (5, 5);
        \draw[dashed, color=red] (0+0.1, 0-0.1) -- (1+0.1, 0-0.1) -- (1+0.1, 2-0.1)-- (2+0.1, 2-0.1) -- (2+0.1, 4-0.1) -- (3-0.1, 4-0.1) -- (3-0.1, 1+0.1) -- (3-0.1, -1+0.1) -- (-0+0.1, -1+0.1) -- (0+0.1, 0-0.1);
    \end{tikzpicture}   
\end{document}

Although I can manually add or substract a small number to every vertex of the original shape to create red lines, but I am looking for a simpler solution. Thanks in advance.

6

An option using some fake shape, using a line inside other with less thicknes that not allow to draw like dashed style, whatever is posible with manual drawing helped using node names for desired shapes and without style problems.

RESULT: enter image description here

MWE:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{backgrounds,fit}
\begin{document}
    \begin{tikzpicture}[
        Myline/.style={
            draw,
            red,
            line width=0.8cm,
            shorten >=-0.4cm,
            shorten <=-0.4cm,
            postaction={
                -,draw,white, line width=0.75cm, shorten >=-0.375cm,
            shorten <=-0.375cm,
                }
        }
    ]
    \draw (0,0) grid (8, 8);
    \foreach \x in {1,2,...,8}{
        \foreach \y in {1,2,...,8}{
                \draw (\x-0.5,\y-0.5) coordinate (\x-\y);
                \node[rectangle, inner sep=12pt](N-\x-\y) at (\x-0.5,\y-0.5){};
            }
        }
        %Draw as a line % dasheed is not posible
        \begin{scope}[on background layer]
        \draw[Myline] (1-1) |- (2-3) |- (1-5);
        \draw[Myline] (4-3) -| (5-5) -| (6-7);
        \draw[Myline,blue] (4-1) -| (5-2) -| (6-1) -| (8-2) -| (7-3);
        \end{scope}
        %Manual drawing using node coordinates
        \draw[dashed,red,thick,fill=red,fill opacity=0.1](N-1-8.135) 
            -| (N-5-6.-45)
            -| (N-4-7.-135)
            -| (N-3-7.135) 
            -|(N-4-6.45) 
            -| (N-5-8.-135)
            -| cycle;
        \draw[dashed,blue,thick,fill=blue,fill opacity=0.1](N-4-3.-135)
            -| (N-6-7.45)
            -| (N-6-5.135)
            -| (N-5-3.135) 
            -| cycle;
    \end{tikzpicture}   
\end{document}
7

This is really just a fun proposal, which may or may not be useful. It seems to me that you want to draw a boundary around certain points of the grid. We could represent the grid by a matrix and say that the boundary should be drawn around the entries 1, all other entries are 0. Here is a very first version. It can and will be improved if that way turns out to make at least a tiny bit of sense. At the moment, the dimensions are hard coded and the shape cannot extend to the boundary of the grid, two things that can easily be fixed.

\documentclass[border=3.14mm]{standalone}
\usepackage{tikz}
\usepackage{pgfplotstable}
\usepackage{filecontents}

\begin{filecontents*}{grid.csv}
0,0,0,0,0,0,0,0
0,0,0,0,0,1,0,0
0,0,0,0,0,1,0,0
0,0,0,0,1,1,0,0
0,0,0,0,1,1,0,0
0,0,0,1,1,1,0,0
0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0
\end{filecontents*}
\newcommand*{\ReadOutElement}[4]{%
    \pgfplotstablegetelem{#2}{[index]#3}\of{#1}%
    \let#4\pgfplotsretval
}
\begin{document}
\pgfplotstableread[header=false,col sep=comma]{grid.csv}\datatable
\tikzset{mystyle/.style={red,dashed}}
\begin{tikzpicture}
\foreach \Y [evaluate=\Y as \PrevY using {int(\Y-1)},
evaluate=\Y as \NextY using {int(\Y+1)}] in {1,...,6}
{\foreach \X [evaluate=\X as \PrevX using {int(\X-1)},
evaluate=\X as \NextX using {int(\X+1)}] in {1,...,6}
{
\ReadOutElement{\datatable}{\Y}{\X}{\Current}
\ReadOutElement{\datatable}{\PrevY}{\X}{\Above}
\ReadOutElement{\datatable}{\NextY}{\X}{\Below}
\ReadOutElement{\datatable}{\Y}{\PrevX}{\Left}
\ReadOutElement{\datatable}{\Y}{\NextX}{\Right}
\ifnum\Current=1
\typeout{\Y,\X,\Above}
  \ifnum\Left=0
   \draw[mystyle] (1+\X-0.95,8-\Y-0.95) -- (1+\X-0.95,8-\Y-0.05);   
  \fi
  \ifnum\Right=0
   \draw[mystyle] (1+\X-0.05,8-\Y-0.95) -- (1+\X-0.05,8-\Y-0.05);   
  \fi
  \ifnum\Above=0
   \draw[mystyle] (1+\X-0.95,8-\Y-0.05) -- (1+\X-0.05,8-\Y-0.05);   
  \fi
  \ifnum\Below=0
   \draw[mystyle] (1+\X-0.95,8-\Y-0.95) -- (1+\X-0.05,8-\Y-0.95);   
  \fi
\fi
}
}
\draw (0,0) grid (8,8);
\end{tikzpicture}
\end{document}

enter image description here

2

I don't know if this answer will fit the problem, but it shows another way for referencig cells and filling areas.

logicpuzzle is package which can be used to prepare what it's name means, logic puzzles loke sudokus, kakuros, ... But it also provides an easy way of drawing grids and some commands to frame and fill areas in these grids.

Environment \begin{logicpuzzle}[rows=8,columns=8]...\end{logicpuzzle} will draw a 8x8 grid.

Commands for drawing/filling areas inside the grid are \framearea{color}{tikzpath}, \fillarea{color}{tikzpath}, \colorarea{color}{tikzpath}. In this commands the tikzpath is path where coordinates identifiy the lower left corner of each cell and where (1,1) is the lower left cell. Linear (--) or perpendicular (-|, |-) paths are allowed.

Another syntax is provided by xtikzpath which can be used inside tikzpath argument in previous commands.

\fillarea{red!20}{\xtikzpath{6}{1}{6/1,8/1,4/1,2/1}}

fills cell (6,1). First ,two arguments represent the bottom left corner of starting position. Following pairs like 6/1 mean move right (6=right) 1 cell. The first number of the pair represents a direction according its position in numeric keyboard, while the second is the distance to move.

A complete code with some examples looks like:

\documentclass{article} 
\usepackage{logicpuzzle}
\begin{document}
\begin{logicpuzzle}[rows=8,columns=8]
\framearea{red}{(4,3)-|(6,5)-|(7,8)-|(6,6)-|(5,4)-|cycle}
\fillarea{brown!40}{(1,1)-|(3,6)-|(2,4)-|cycle}
\colorarea{blue!50}{(1,9)--(3,9)--(3,8)--(5,8)--(5,6)--(2,6)--(2,8)--(1,8)--cycle}
\fillarea{red!20}{\xtikzpath{6}{1}{6/2,8/2,6/1,8/3,4/1,2/2,4/1,2/2,4/1,2/1}}
\end{logicpuzzle}
\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.