# TikZ - How to automate the creation of patterns having irregularities

This is a continuation of How to automatically calculate parameters of a TikZ repeating pattern?

I am trying to find the best way to draw a series of industrial patterns. Thanks to the help received, I was able to draw regular patterns. However I now need to draw patterns that have a distribution and size of cavities that vary. I was also forced to move the origin to the center of the envelope, a configuration less convenient than before. I have tried a different approach than before, making the exact shape I am looking for, however it is very much hard-coded, since the cavity numbering pattern does not follow the natural order. I have tried the \foreach \x / \n [count=\xi] option, that looked promising, but I have not found a way to use it for every row. Is there a way to optimize the code, and particularly the counter of cavities, missing here?

\documentclass{standalone}
\usepackage{tikz}
\renewcommand{\familydefault}{\sfdefault}
\begin{document}

\begin{tikzpicture}[scale=2.54, thick,
twenty/.style={circle, draw, very thin, fill,text=white, minimum size=.097in , text centered,font=\tiny, inner sep=0.1pt},
sixteen/.style={circle, draw, very thin, fill,text=white, minimum size=.150in, text centered,font=\tiny, inner sep=0.1pt},
]
\newlength{\hspacing} %Vertical spacing
\newlength{\vspacing} %Horiz spacing
\setlength{\hspacing}{.108cm}

%Begin envelope
\coordinate (O) at (0,0) ;
\coordinate (A) at ( - 0.7475,-0.435) ;
\coordinate (B) at ( 0.7475,-0.435) ;
\coordinate (C) at (0.7475, 0.249) ;
\coordinate (D) at (0.516 ,0.435) ;
\coordinate (E) at (-0.516 ,0.435) ;
\coordinate (F) at (-0.7475, 0.249) ;
\draw (A) --(B)--(C)--(D)-- (E)--(F)-- cycle ;
%End envelope

\node[red, very thin] at (O)  {+}; %origin

%--------------------------------
% Begin top row -mixed cavities- uneven spacing
\setlength{\vspacing}{.28cm}
%small cavity right side
\foreach \x / \n [count=\xi] in {4.5 / \xi,  3.5 / \xi} {
\node [twenty] at (\hspacing*\x, \vspacing){\xi};
}
%Begin large cavity
\foreach \x / \n  in {2 / 3,  0 / 4} {
\node [sixteen] at (\hspacing*\x, \vspacing){\n};
}
\foreach \x / \n  in {2 / 5} {
\node [sixteen] at (-\hspacing*\x, \vspacing){\n};
}
%small cavity left side
\foreach \x /  \n  in  {4.5/ 6,  3.5/ 7} {
\node [twenty] at (-\hspacing*\x, \vspacing){\n};
}
% end top row
%---------------------------
% Begin row 2 small cavity uneven spacing
\setlength{\vspacing}{.168cm}
%---------------------------
\foreach \x /  \n  in {6/ 8,  5 / 9,  4 / 10, 3/ 11, 1/12 } {
\node [twenty] at (\hspacing*\x, \vspacing){\n};
}
\foreach \x /  \n  in  {6/ 17,  5/ 16,  4 / 15, 3/ 14, 1/ 13 } {
\node [twenty] at (-\hspacing*\x, \vspacing){\n};
}
%End small cavity
% end row 2
%---------------------------
% Begin row 3 - small cavity
\setlength{\vspacing}{.056cm}
%Begin small cavity
\foreach \x / \n  in {5.5/18, 4.5/19, 3.5/20, 2.5/21, 1.5/22, 0.5/23} {
\node [twenty] at (\hspacing*\x, \vspacing){\n};
}
\foreach \x / \n  in   {5.5/29, 4.5/28, 3.5/27, 2.5/26, 1.5/25, 0.5/24} {
\node [twenty] at (-\hspacing*\x, \vspacing){\n};
}
%End small cavity
% end row 3
%---------------------------
% Begin row 4 - small cavity
\setlength{\vspacing}{-.056cm}
\foreach \x / \n  in {6/30, 5/31, 4/32, 3/33, 2/34, 1/35, 0/36} {
\node [twenty] at (\hspacing*\x,\vspacing){\n};
}
\foreach \x / \n  in   {6 /42, 5/41, 4/40, 3/39, 2/38, 1/37} {
\node [twenty] at (-\hspacing*\x, \vspacing){\n};
}
%End small cavity
% end row 5
%---------------------------
% Begin row 5  - small cavity
\setlength{\vspacing}{-0.162cm}
%Begin small cavity
\foreach \x / \n  in {5.5/43, 4.5/44, 3.5/45, 2.5/46, 1.5/47, 0.5/48} {
\node [twenty] at (\hspacing*\x, \vspacing){\n};
}
\foreach \x / \n  in {5.5/54, 4.5/53, 3.5/52, 2.5/51, 1.5/50, 0.5/49} {
\node [twenty] at (-\hspacing*\x, \vspacing){\n};
}
%---------------------------
% end row 5
% Begin row 6 -small cavity
\setlength{\vspacing}{-0.27cm}

\foreach \x /  \n  in {6 /55, 5/56, 4/57, 3/58, 2/59, 1/60, 0/61} {
\node [twenty] at (\hspacing*\x,\vspacing){\n};
}
\foreach \x / \n  in  {6 /67, 5/65, 4/65, 3/64, 2/63, 1/62} {
\node [twenty] at (-\hspacing*\x, \vspacing){\n};
}
% end row 6
\end{tikzpicture}
\end{document}

-
What is the natural order of numbering in the irregular case? From lower left to upper right? –  percusse Oct 15 '12 at 21:47
In fact the "natural way" is the previous one, from the upper left corner to the right. This attempt was the result of the (non previously anticipated) need to show the rear of the device, where the numbers are mirrored. This effort tought me that the shift of the origin to the center, mimicking the original standard document for the pattern is not efficient, and I am considering reverting to the previous position (the lower left corner) I have difficulties to find a compromize between flexibility and decent automation, as there are many other configurations to handle.... –  Yves Oct 16 '12 at 10:57

The result:

And the code:

\documentclass{standalone}

\usepackage{tikz}

% e-TeX power  =)
\usepackage{etoolbox}

\newcounter{cavities}

% associates each cavity with its style
% #1: row number
% #2: column number
% #3: small or big (styles)
\newcommand\setcavitystyle[3]{\csgdef{cavitystyler#1c#2}{#3}}
\newcommand\getcavitystyle[2]{\csuse{cavitystyler#1c#2}}

% determines whether or not the cavity is drawn
% #1: row number
% #2: column number
% #3: 0 (disabled) or 1 (enabled)
\newcommand\setpointenabled[3]{\csnumgdef{styler#1c#2}{#3}}
\newcommand\getpointenabled[2]{\csuse{styler#1c#2}}

% builds the possible locations of the cavities
% #1: max absolute x
% #2: max absolute y
\newcommand{\makebase}[2]{
\pgfmathtruncatemacro{\x}{#1}
\pgfmathtruncatemacro{\y}{#2}
\foreach \i in { -\x, ..., \x} {
\foreach \j in { -\y, ..., \y} {
\coordinate (base-\i-\j) at (\i, \j);
}
}
\drawenvelope
}

% draw envelope and defines useful area
% from (-\xuseful, -\yuseful) to (\xuseful, \yuseful)
\newcommand{\drawenvelope} {
\pgfmathtruncatemacro{\xuseful}{\x - 1}
\pgfmathtruncatemacro{\yuseful}{\y - 1}
\draw [
line width = 1mm
] (-\x, -\y) -- (-\x, \yuseful) -- (-\xuseful, \y) -- (\xuseful, \y) -- (\x, \yuseful) -- (\x, -\y) -- cycle;
}

% defines all possible cavities to be used with a basic style.
% uses only useful area
\newcommand{\makebasicpoints}{
\foreach \j in {\yuseful, ..., -\yuseful} {
\foreach \i in {\xuseful, ..., -\xuseful} {
\ifboolexpr{
(test{\ifnumequal{\j}{\yuseful}} and test{\ifnumequal{\i}{\xuseful}})
or
(test{\ifnumequal{\j}{\yuseful}} and test{\ifnumequal{\i}{-\xuseful}})
}{
\setpointenabled{\i}{\j}{0}
}{
\ifboolexpr{
(test{\ifnumodd{\i}} and test{\ifnumodd{\j}})
or
(not(test{\ifnumodd{\i}}) and not(test{\ifnumodd{\j}}))
}{
\setpointenabled{\i}{\j}{0}
}{
\setpointenabled{\i}{\j}{1}
\setcavitystyle{\i}{\j}{small}
}
}
}
}
}

% defines a specific cavities with "big" style.
% disables drawing near cavities (above, below, right and left)
% #1: x
% #2: y
\newcommand{\makebiggerpoint}[2]{
\setpointenabled{#1}{#2}{1}
\setcavitystyle{#1}{#2}{big}

\pgfmathtruncatemacro{\ytemp}{#2}
\pgfmathtruncatemacro{\xtemp}{#1 - 1}
\setpointenabled{\xtemp}{\ytemp}{0}

\pgfmathtruncatemacro{\ytemp}{#2}
\pgfmathtruncatemacro{\xtemp}{#1 + 1}
\setpointenabled{\xtemp}{\ytemp}{0}

\pgfmathtruncatemacro{\ytemp}{#2 + 1}
\pgfmathtruncatemacro{\xtemp}{#1}
\setpointenabled{\xtemp}{\ytemp}{0}

\pgfmathtruncatemacro{\ytemp}{#2 - 1}
\pgfmathtruncatemacro{\xtemp}{#1}
\setpointenabled{\xtemp}{\ytemp}{0}
}

% draw each cavity if it is enabled.
\newcommand{\makecavities}{
\foreach \j in {\yuseful, ..., -\yuseful} {
\foreach \i in {\xuseful, ..., -\xuseful} {
\ifnumequal{\getpointenabled{\i}{\j}}{1}{
\stepcounter{cavities}
\coordinate (cavity-\thecavities) at (\i, \j);
\node [\getcavitystyle{\i}{\j}] at (cavity-\thecavities) {\thecavities};
}{
}
}
}
}

% styles
\tikzset{
small/.style = {
circle
, fill
, minimum size = 10mm
, inner sep = 0mm
, font = \small\bf
, text = white
, inner sep = 0pt
}
, big/.style = {
circle
, fill
, minimum size = 15mm
, inner sep = 0mm
, text = white
, font = \bf
, inner sep = 0pt
}
}

\begin{document}
\begin{tikzpicture}

\makebase{10}{5}
\draw [red, ultra thick] (0,0) +(0, 4mm) -- +(0, -4mm) +(4mm, 0) -- +(-4mm, 0);

\makebasicpoints

\foreach \k in {-6, -3, ..., 6} {\makebiggerpoint{\k}{3}}
\foreach \k in {-7, -4, ..., 8} {\makebiggerpoint{\k}{-2}}

\makecavities

\end{tikzpicture}
\end{document}

-
HTH = Hattori Hanzo? :P –  percusse Oct 20 '12 at 14:17
errr... maybe... =P –  tecepe Oct 20 '12 at 14:45
@percusse Great. I had gradually found some ways to add flexibility, thanks to the initial guidance from percusse (I should have investigated more carfully the problem initially... )but I have limited skills,and this sophisticated solution exceeds even my most optimistic expectations... –  Yves Oct 27 '12 at 12:55
thanks, @percusse! =D –  tecepe Oct 27 '12 at 18:33
Why am I involved in this? :) I have nothing to do with this nice answer. –  percusse Oct 27 '12 at 19:10