10

why can not some lines(red ones) be drawn?

enter image description here

the following is my codes

\documentclass[tikz,border=5pt]{standalone}
\begin{document}
\begin{tikzpicture}
\clip  (0,0) rectangle (10.8,7.2);
\draw  (0,0) rectangle (10.8,7.2);
 \foreach \x in {-0.8,1,...,10.9}
 \foreach \y in {0.2,2,...,7.4}
  \draw  (\x ,\y)  --(\x+0.9 ,\y);
\foreach \l in {0.6,2.4,...,9.6}
   \foreach \m in {-0.2,1.6,...,8.8}
    \draw (\l,\m) -- (\l,\m+0.9);
     \foreach \x in {0.1,1.9,...,9.1}
 \foreach \y in {1.1,2.9,...,6.5}
  \draw  (\x ,\y)  --(\x+0.9 ,\y);
\foreach \l in {1.5,3.3,...,10.5}
   \foreach \m in {0.7,2.5,...,6.1}
    \draw(\l,\m) -- (\l,\m+0.9);
\end{tikzpicture}
\end{document} 

Another question: are there any simpler\better methods drawing these lines?

dozer
  • 841

3 Answers3

13

You should take into account rounding errors. So enlarge the last value a bit, e.g. to 10.51.

Beside this I would use integers for the steps and then calculate the values. E.g. for your last one:

\foreach \l in {1,2,...,6} %
   \foreach \m in {0,1,...,3} %
    \draw(1.5+1.8*\l,0.7+1.8*\m) -- (1.5+1.8*\l,0.7+1.8*\m+0.9);
Ulrike Fischer
  • 327,261
  • Great, those four lines appear. Thanks a lot. The other question, do you have better method simplifying the codes? – dozer Feb 23 '17 at 12:20
9

A different approach to drawing such patterns, using just two nested loops.

\documentclass[tikz,border=5pt]{standalone}
\begin{document}
\begin{tikzpicture}
\clip  (0,0) rectangle (10.8,7.2);
\draw  (0,0) rectangle (10.8,7.2);

\newcommand\dx{0.9} % horizontal distance between the line centers
\newcommand\dy{0.9} % vertical distance between the line centers
\pgfmathsetmacro\lx{\dx/2} % half length of horizontal line
\pgfmathsetmacro\ly{\dy/2} % half length of vertical line

\foreach \x in {-2,...,15} {
   \foreach \y in {-1,...,9} {
     \pgfmathsetmacro\ifhoriz{ifthenelse((-1)^(\x+\y)<0,0,1)}
     \ifnum \ifhoriz=0
       \draw (\x*\dx-\lx,\y*\dy) -- (\x*\dx+\lx,\y*\dy);
     \else
       \draw (\x*\dx,\y*\dy-\ly) -- (\x*\dx,\y*\dy+\ly);
    \fi
}}
\end{tikzpicture}
\end{document} 

Or if the spacing and line length is always the same for x and y, you can make do with a single \draw:

\documentclass[tikz,border=5pt]{standalone}
\begin{document}
\begin{tikzpicture}
\clip  (0,0) rectangle (10.8,7.2);
\draw  (0,0) rectangle (10.8,7.2);

\newcommand\dx{0.9} % distance between center of lines in pattern
\pgfmathsetmacro\lx{\dx/2} % half length of lines in pattern

\foreach \x in {-2,...,15} {
   \foreach \y in {-1,...,9} {
       \draw [rotate around={ifthenelse((-1)^(\x+\y)<0,0,90):(\x*\dx,\y*\dx)}]
            (\x*\dx-\lx,\y*\dx) -- (\x*\dx+\lx,\y*\dx);
}}
\end{tikzpicture}
\end{document} 

In both cases, instead of using explicit x and y values in the loop, I use integers as Ulrike does in her answer. To decide whether to draw a horizontal or vertical line, I calculate (-1)^(\x+\y), where \x and \y are the integers. If you write up a matrix of those values, it will look like

y\x  |  1  2  3  4  5
---------------------
1    |  1 -1  1 -1  1 
2    | -1  1 -1  1 -1
3    |  1 -1  1 -1  1
4    | -1  1 -1  1 -1

So every other 1 and -1, along both axes.

In the first case, I use ifthenelse((-1)^(\x+\y)<0,0,1) to set the macro \ifhoriz to either 0 or 1, and then I use \ifnum to draw a horizontal line if \ifhoriz is 0, and a vertical line if it is 1.

In the second case I draw a horizontal line, but I use a similar ifthenelse statement to rotate the line either 0 or 90 degrees.

Torbjørn T.
  • 206,688
  • Thank you very much! excellent computing power! but i can not understand your codes, where can I find the detained explanation of your codes, e.g., your expression. – dozer Feb 23 '17 at 14:19
  • @dozer I can add some more explanation later tonight. The key thing is (-1)^(\x+\y) I suppose. Consider \x and \y as indices of a matrix, one giving the row number, the other the column number. If \x+\y is an odd number, (-1)^(\x+\y) = -1, if \x+\y is an even number then (-1)^(\x+\y) = 1. This makes the pattern -1 1 -1 1 .. along both rows and columns. The ifthenelse and \ifnum is for making the code do different things depending on the whether we have 1 or -1. – Torbjørn T. Feb 23 '17 at 14:41
8

Instead of a \foreach you could use a new defined pattern

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

\tikzset{
    hatch thickness/.store in=\hatchthickness,
    hatch thickness=1pt
    }

\makeatletter
\pgfdeclarepatternformonly[\hatchthickness]{myhatch}
{\pgfpointorigin}{\pgfpoint{18mm}{18mm}}
{\pgfpoint{18mm}{18mm}}
{
    \pgfsetcolor{\tikz@pattern@color}
    \pgfsetlinewidth{\hatchthickness}
    \pgfpathmoveto{\pgfpoint{0mm}{4.5mm}}
    \pgfpathlineto{\pgfpoint{9mm}{4.5mm}}
    \pgfpathmoveto{\pgfpoint{9mm}{13.5mm}}
    \pgfpathlineto{\pgfpoint{18mm}{13.5mm}}
    \pgfpathmoveto{\pgfpoint{4.5mm}{9mm}}
    \pgfpathlineto{\pgfpoint{4.5mm}{18mm}}
    \pgfpathmoveto{\pgfpoint{13.5mm}{0mm}}
    \pgfpathlineto{\pgfpoint{13.5mm}{9mm}}
    \pgfusepath{stroke}
}
\makeatother

\begin{document}
\begin{tikzpicture}
\filldraw[pattern=myhatch, pattern color=red] (0,0) rectangle (10.8,7.2);
\end{tikzpicture}
\end{document}

enter image description here

Ignasi
  • 136,588