%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*- Mode: Latex -*- %%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% truchet.sty --- Truchet's tiling.
%%                 Idea of Philippe Esperet (Lycee Henri IV - Paris)
%% 
%% Author          : Denis GIROU (CNRS/IDRIS - France) <Denis.Girou@idris.fr>
%% Created the     : Fri Feb 17 22:35:22 1995
%% Last mod. by    : Denis GIROU (CNRS/IDRIS - France) <Denis.Girou@idris.fr>
%% Last mod. the   : Tue Sep 24 22:21:35 1996
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Caution!: with my TeX installation, there is a limitation at 17x17 for the
% second problem (coloration of curves) and at 13x13 for the third problem
% (filling). But it's for one test: the limits decrease if we make
% several tests in the same file (probable memory management problems
% somewhere...)

% Require of course PSTricks and the multido packages
\ifx\PSTricksLoaded\endinput\else
  \def\next{\input pstricks.tex }
  \expandafter\next
\fi
\ifx\MultidoLoaded\endinput\else
  \def\next{\input multido.tex }
  \expandafter\next
\fi

\input{random.sty}              % Define the \SRtest macro (for random tests)
\input{arrayjob.sty}            % To define arrays (in the meaning of Fortran)

\edef\PstAtCode{\the\catcode`\@}
\catcode`\@=11\relax

% Modification in arrayjob.sty
\long\def\assign@VEC#1(#2)=#3{\temp@count=#2 \relax
\get@max@count{total@#1}\temp@count
% Modification Denis GIROU (CNRS/IDRIS - France) <Denis.Girou@idris.fr> - 20 Mar. 1995
%\expandafter\gdef\csname#1#2\string~\endcsname{#3}
\expandafter\xdef\csname#1#2\string~\endcsname{#3}
}

% Initialization of random numbers generator
% (redefine it with an integer constant to generate always the same graphics)
\pst@cnta=\the\time
\multiply\pst@cnta\pst@cnta
\SRset{\the\pst@cnta}

% Boolean variable to fill the tiles or not (default = not)
\newif\ifTruchetTilingFill
\TruchetTilingFillfalse

% -------------------------------------------------------------------------
% | Problems numbers 1 and 3 : monocolor curves and filling of the tiling |
% -------------------------------------------------------------------------

% If \TruchetTilingFilltrue, the lines are drawn using \TruchetTilingStyleA
% and regions are filled using style names \TruchetTilingStyleB and
% \TruchetTilingStyleC

% Algorithm:
% ---------
% To note: * In fact, there are no dependancies between the tiles!!!
%            All that we must know to decide of their colors are the parities
%            of their numbers of row and column...
%          * We use a boolean function called random() which must return 0 or 1.
%
% do icol=1,nb_columns
%    do irow=1,nb_rows
%       if odd(icol+irow)
%          if random() = 0
%             put(icol,irow){tile(color1,color2)}
%           else
%             put(icol,irow){rotate{90}{tile(color2,color1)}}
%          end if
%        else
%          if random() = 0
%             put(icol,irow){tile(color2,color1)}
%           else
%             put(icol,irow){rotate{90}{tile(color1,color2)}}
%          end if
%        end if
%    end do
% end do

% Default styles for the tiles: black lines, and not filling
\newpsstyle{TruchetTilingStyleA}{linecolor=black}
\newpsstyle{TruchetTilingStyleB}{linestyle=none}
\newpsstyle{TruchetTilingStyleC}{linestyle=none}

\newcommand{\TruchetTiling}[2]{% #1 = number of rows, #2 = number of columns
\begin{pspicture}(#1,#2)
  \rput(-1,-1){% Because we start at (1,1)
    \multido{\icol=1+1}{#1}{%
      \pst@cnta=\icol
      \multido{\irow=1+1}{#2}{%
        \advance\pst@cnta\@ne
        \ifodd\pst@cnta
          \TruchetChoiceTile{TruchetTilingStyleB}{TruchetTilingStyleC}
        \else
          \TruchetChoiceTile{TruchetTilingStyleC}{TruchetTilingStyleB}
        \fi}}}
  \psframe[dimen=outer,linewidth=.8pt](#1,#2) % The border
\end{pspicture}}

% The choice of the tile (if needed with rotation and inversion of colors)
\newcommand{\TruchetChoiceTile}[2]{% #1 and #2 must be names of PSTricks styles
\SRtest{\rput(\icol,\irow){\TruchetTile{#1}{#2}}}
       {\rput(1,0){\rput{90}(\icol,\irow){\TruchetTile{#2}{#1}}}}}

% The elementary tile for Truchet tiling (fill with colors or not)
\newcommand\TruchetTile[2]{% #1 and #2 must be names of PSTricks styles
\ifTruchetTilingFill
  \psframe[style=#1](1,1)     % We fill the tile with the two specified colors
  \pswedge[style=#2](0,0){.5}{0}{90}
  \pswedge[style=#2](1,1){.5}{-180}{-90}  
\fi
\psarc[style=TruchetTilingStyleA](0,0){.5}{0}{90}
\psarc[style=TruchetTilingStyleA](1,1){.5}{-180}{-90}}

% -----------------------------------------------
% | Problem number 2 : coloration of the curves |
% -----------------------------------------------

% Algorithm:
% ---------
% To note: * The grid of tiles is transformed to a boolean matrix.
%          * We use a boolean function called random() which must return 0 or 1.
%          * We use a predefined array of colors, of dimension nb_colors_max.
%          * The tile is divided is four sections, two marked by 1 (when an arc is
%            defined), and two by 0 (otherwise).
%            So the representation of a tile is 0 1 or 1 0
%                                               1 0    0 1
%            and the "logical" grid used is 2xnb_columns X 2xnb_rows.
%
%%% First step: generation of the boolean matrix which describe the tile
% do icol=1,nb_columns
%    do irow=1,nb_rows
%       if random() = 0
%          grid(2*icol-1,2*irow-1)=1
%          grid(2*icol,2*irow)=1
%        else
%          grid(2*icol-1,2*irow)=1
%          grid(2*icol,2*irow-1)=1
%       end if
%    end do
% end do
%
%%% Second step: construction of the array of colored paths.
%%% We examine the grid bottom to top, left to right.
%%% Each defined cell is assigned with a new allocated color, or with the color
%%% assigned for the only possible neighbour (located differentely according to
%%% the parity of the column number and the row number.
%%% The only problem can occur for odd column and odd row: in this case we can
%%% have two neighbour cells (West and South, or South-West and South). In this
%%% case we must join the two paths. For that we use an indirect array of
%%% colors indices (otherwise, we must change all the previous cells assigned
%%% with the other color).
% indice_color=0
% do icol=1,2*nb_columns
%    do irow=1,2*nb_rows
%       if grid(icol,irow) != 0
%          if odd(irow)
%             if odd(icol)
%                if irow = 1
%                   color_cell_new_color(icol,irow)
%                else
%                   if grid(icol-1,irow) != 0
%                      grid(icol,irow)=grid(icol-1,irow)   % West
%                   else
%                      grid(icol,irow)=grid(icol-1,irow+1) % North-West
%                   end if
%                end if
%                % Potentially two paths to join
%                % (West and South or North-West and South)
%                if icol != 1
%                   if grid(icol,irow-1) != 0              % South
%                      do i=1,indice_color
%                          if array_indices_colors(i) =
%                               array_indices_colors(grid(icol,irow-1))
%                             array_indices_colors(i) =
%                               array_indices_colors(grid(icol,irow))
%                          end if
%                      end do
%                   end if
%                end if
%             else
%                if irow = 1
%                   color_cell_new_color(icol,irow)
%                else
%                   if grid(icol-1,irow) != 0
%                      grid(icol,irow)=grid(icol-1,irow)   % West
%                   else
%                      grid(icol,irow)=grid(icol-1,irow-1) % South-West
%                   end if
%                end if
%             end if
%          else
%             if odd(irow)
%                if irow = 1
%                   color_cell_new_color(icol,irow)
%                else
%                   if grid(icol-1,irow-1) != 0
%                      grid(icol,irow)=grid(icol-1,irow-1) % South-West
%                   else
%                      grid(icol,irow)=grid(icol,irow-1)   % South
%                   end if
%                end if
%             else
%                if irow=2*nb_rows
%                   color_cell_new_color(icol,irow)
%                else
%                   if grid(icol-1,irow+1) != 0
%                      grid(icol,irow)=grid(icol-1,irow+1) % North-West
%                   else
%                      color_cell_new_color(icol,irow)
%                   end if
%                end if
%             end if
%          end if
%       end if
%    end do
% end do
%
%%% Third step: the graphics itself
% do icol=1,2*nb_columns
%    do irow=1,2*nb_rows
%       if grid(icol,irow) != 0
%          color=array_colors(
%            array_indices_colors(modulo(grid(icol/2+1,irow/2+1),nb_colors_max))
%          if odd(icol)
%             if odd(irow)
%                put(icol,irow){arc[linecolor=color]{0}{90}}
%              else
%                put(icol,irow){arc[linecolor=color]{-90}{0}}
%             fi
%           else
%             if odd(irow)
%                put(icol,irow){arc[linecolor=color]{90}{180}}
%              else
%                put(icol,irow){arc[linecolor=color]{-180}{-90}}
%             fi
%       end if
%    end do
% end do
%
% With:
% color_cell_new_color(icol,irow)
%    indice_color=indice_color+1
%    array_indices_colors(indice_color)=indice_color
%    grid(icol,irow)=indice_color
% 
% Example: AB     0 1 1 0     0 3 3 0 (with A the tile, and B the rotated one)
% -------  AB --> 1 0 0 1 --> 2 0 0 2
%                 0 1 1 0     0 2 2 0
%                 1 0 0 1     1 0 0 4

% Counters
\newcount\TruchetNumberColors   % The number of colors defined
\newcount\TruchetIndiceColor    % The indice for allocation of new colors

% Boolean variable to print intermediate results or not (default = not)
\newif\ifTruchetDebug
\TruchetDebugfalse

% Arrays
\newarray\TruchetGrid           % Two dimensional array for the "logical" grid
\newarray\TruchetIndicesColors  % One dimensional array for indices in the
                                % array of the names of colors
\newarray\TruchetColors         % One dimensional array for names of colors
                                % (must be of length \TruchetNumberColors)

% Default colors used
\TruchetNumberColors=7
\readarray{TruchetColors}{red&yellow&black&blue&green&cyan&magenta}

\newcommand{\TruchetColorCurves}[2]{% #1 = number of rows, #2 = number of columns
%
% Initialization of constants
\pst@cntg=#1
\multiply\pst@cntg\tw@          % 2 x nb_columns
\pst@cnth=#2
\multiply\pst@cnth\tw@          % 2 x nb_rows

\dataheight=\pst@cnth           % We use a 2 dimensional array with \pst@cnth rows
%
% Initialization of the arrays (required if there are several consecutive runs)
\multido{\icol=1+1}{\pst@cntg}{%
  \multido{\irow=1+1}{\pst@cnth}{%
    \TruchetGrid(\icol,\irow)=\empty}}
%
% First step: generation of the boolean matrix (1 if the arc is defined)
% ----------
\multido{\icol=1+1}{#1}{%
  \pst@cntb=\icol
  \multiply\pst@cntb\tw@
  \pst@cnta=\pst@cntb
  \advance\pst@cnta\m@ne
  \multido{\irow=1+1}{#2}{%
    \pst@cntd=\irow
    \multiply\pst@cntd\tw@
    \pst@cntc=\pst@cntd
    \advance\pst@cntc\m@ne
    \SRtest{\TruchetGrid(\pst@cnta,\pst@cntc)={1}
            \TruchetGrid(\pst@cntb,\pst@cntd)={1}}
           {\TruchetGrid(\pst@cnta,\pst@cntd)={1}
            \TruchetGrid(\pst@cntb,\pst@cntc)={1}}}}
\TruchetColorCurvesDebug{1}
%
% Second step: construction of the array of colored paths
% -----------
\TruchetIndiceColor=0
\multido{\icol=1+1}{\pst@cntg}{%
  \multido{\irow=1+1}{\pst@cnth}{%
    \checkTruchetGrid(\icol,\irow)
    \ifemptydata
    \else
      \ifodd\icol
        \ifodd\irow
          % odd column, odd row: if the column is the first one, new color,
          %     otherwise it will be the color of West or North-West
          %     But if South is also defined, we must change his color
          %     to the same one to join the paths
          \ifnum\icol=\@ne
            \TruchetColorCellNewColor
          \else
            \TruchetColorCellSameColor{\m@ne}{\z@}   % West
            \TruchetColorCellSameColor{\m@ne}{\@ne}  % North-West
          \fi
          \ifnum\irow=\@ne
          \else
            % If South also exist, we must join the paths
            \TruchetJoinPaths{\z@}{\m@ne}            % South
          \fi
        \else
          % odd column, even row: if the column is the first one, new color,
          %     otherwise it will be the color of West or South-West
          \ifnum\icol=\@ne
            \TruchetColorCellNewColor
          \else
            \TruchetColorCellSameColor{\m@ne}{\z@}   % West
            \TruchetColorCellSameColor{\m@ne}{\m@ne} % South-West
          \fi
        \fi
      \else
        \ifodd\irow
          % even column, odd row: if the row is the first one, new color,
          %      otherwise it will be the color of South-West or South
          \ifnum\irow=\@ne
            \TruchetColorCellNewColor
          \else
            \TruchetColorCellSameColor{\m@ne}{\m@ne} % South-West
            \TruchetColorCellSameColor{\z@}{\m@ne}   % South
          \fi
        \else
          % even column, even row: if the row is the last one, new color,
          %      otherwise it will be the color of North-West if defined,
          %      and a new one if not
          \ifnum\irow=\pst@cnth
            \TruchetColorCellNewColor
          \else
            \TruchetColorCellSameColor{\m@ne}{\@ne}  % North-West
            \ifemptydata
              \TruchetColorCellNewColor
            \fi
          \fi
        \fi
      \fi
    \fi}}
\TruchetColorCurvesDebug{2}
%
% Third step: the graphic itself
% ----------
\advance\TruchetNumberColors\@ne
\begin{pspicture}(#1,#2)
  \rput(-1,-1){% Because we start at (1,1)
    \multido{\icol=1+1}{\pst@cntg}{%
      \pst@cnta=\icol
      \divide\pst@cnta\tw@
      \advance\pst@cnta\@ne
      \multido{\irow=1+1}{\pst@cnth}{%
        \pst@cntb=\irow
        \divide\pst@cntb\tw@
        \advance\pst@cntb\@ne
        \checkTruchetGrid(\icol,\irow)%
        \ifemptydata
        \else
          \checkTruchetIndicesColors(\cachedata)
          \TruchetIndiceColor=\cachedata
          % We use this indice in the array of colors,
          % modulo \TruchetNumberColors
          \pst@cntc=\TruchetIndiceColor
          \divide\pst@cntc\TruchetNumberColors
          \multiply\pst@cntc\TruchetNumberColors
          \advance\TruchetIndiceColor-\pst@cntc
          \checkTruchetColors(\TruchetIndiceColor)%
          \ifodd\icol
            \ifodd\irow
              \psarc[linecolor=\cachedata](\pst@cnta,\pst@cntb){.5}{0}{90}
            \else
              \psarc[linecolor=\cachedata](\pst@cnta,\pst@cntb){.5}{-90}{0}
            \fi
          \else
            \ifodd\irow
              \psarc[linecolor=\cachedata](\pst@cnta,\pst@cntb){.5}{90}{180}
            \else
              \psarc[linecolor=\cachedata](\pst@cnta,\pst@cntb){.5}{-180}{-90}
            \fi
          \fi
        \fi}}}
  \psframe[dimen=outer,linewidth=.8pt](#1,#2) % The border
\end{pspicture}}

% The current cell must have a new color assigned
\newcommand{\TruchetColorCellNewColor}{%
  \global\advance\TruchetIndiceColor\@ne
  \TruchetIndicesColors(\TruchetIndiceColor)={\the\TruchetIndiceColor}
  \TruchetGrid(\icol,\irow)={\the\TruchetIndiceColor}}

% The current cell must have the same color than the cell (\icol+#1,\irow+#2),
% if defined
\newcommand\TruchetColorCellSameColor[2]{%
\pst@cnta=\icol
\advance\pst@cnta#1
\pst@cntb=\irow
\advance\pst@cntb#2
\checkTruchetGrid(\pst@cnta,\pst@cntb)
\ifemptydata
\else
  \TruchetGrid(\icol,\irow)={\cachedata}
\fi}

% If defined, we must join the two paths between the cells (\icol,\irow)
% and (\icol+#1,\irow+#2)
\newcommand{\TruchetJoinPaths}[2]{%
\pst@cnta=\icol
\advance\pst@cnta#1
\pst@cntb=\irow
\advance\pst@cntb#2
\checkTruchetGrid(\pst@cnta,\pst@cntb)
\ifemptydata
\else
  \checkTruchetIndicesColors(\cachedata)
  \pst@cntd=\cachedata
  \checkTruchetGrid(\icol,\irow)
  \checkTruchetIndicesColors(\cachedata)
  \pst@cntc=\cachedata
  \ifTruchetDebug               % To debug
    \typeout{Modif. colors(\icol,\irow)=\the\pst@cntd-->\the\pst@cntc}
  \fi
  \multido{\i=1+1}{\TruchetIndiceColor}{%
    \checkTruchetIndicesColors(\i)
    \ifnum\cachedata=\pst@cntd
      \TruchetIndicesColors(\i)={\the\pst@cntc}
    \fi}
\fi}

% Debug function: printing of the "logical" grid
\newcommand{\TruchetColorCurvesDebug}[1]{%
\ifTruchetDebug
  \typeout{}
  \multido{\irow=\pst@cnth+-1}{\pst@cnth}{%
    \message{T(\irow)=}
    \multido{\icol=1+1}{\pst@cntg}{%
      \checkTruchetGrid(\icol,\irow)
      \ifnum#1=2
        \ifemptydata
        \else
          \checkTruchetIndicesColors(\cachedata)
        \fi
      \fi
      \message{\cachedata}}
    \message{^^J}}
\fi}

\catcode`\@=\PstAtCode\relax
\endinput
%%
%% END: truchet.sty
