3

My question is how can I customize hatch patterns(grid, vertical line, etc.) for different nodepart in a node?

The following is a failed try.

\documentclass[border=2mm,convert]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart,patterns}

\begin{document}
\begin{tikzpicture}
\node[rectangle split,rectangle split parts =2,rectangle split part fill={red!30,red!10},
rectangle split part pattern={grid,},draw]{one \nodepart{second}two};
\end{tikzpicture}
\end{document}
  • Welcome to TeX.SX! Please add a minimal working example (MWE) that illustrates your problem. It will be much easier for us to reproduce your situation and find out what the issue is when we see compilable code, starting with \documentclass{...} and ending with \end{document}. — What is drect? Can you explain what you mean by “hatch a nodepart”? – Qrrbrbirlbel Jun 18 '13 at 21:38
  • Thanks, hatch a nodepart means fill a part of node with a pattern, like grid or west line. I will try to improve my problem. – foool Jun 19 '13 at 0:47
3

Assuming you want to use patterns for parts of the node part, you can’t use rectangle split part fill as its items are directly used as a filling color.

We can however use the same process to install patterns for every part node with the same rules applying, i.e. the last entry gets repeated for any remaining node parts.

By changing the lines

\pgfsetfillcolor{\csname pgf@lib@sh@rs@\pgf@lib@sh@rs@number @item\endcsname}%
\pgfusepath{fill}%

from the definition of the behindbackground path of the rectangle split shape to

\edef\pgf@temp{\noexpand\pgfqkeys{/tikz/rectangle split pattern}{\csname pgf@lib@sh@rs@\pgf@lib@sh@rs@number @item\endcsname}}%
\pgf@temp
\iftikz@mode@fill
  \pgfsetfillpattern{\tikz@pattern}{\tikz@pattern@color}%
  \pgfusepath{fill}%
\else
  \pgfusepath{}%
\fi

we can mimic TikZ’ original pattern options. The \csname pgf@lib@sh@rs@\pgf@lib@sh@rs@number @item\endcsname macro is defined by the same processor of the fill list:

\pgf@lib@sh@rs@process@list{\pgf@lib@sh@rs@list@pattern}{\parts}%

I have created an extra PGF key path /tikz/rectangle split pattern for it to apply the options on a lower level.

The sequence pattern=none can be used to disable the pattern for one or more node parts.

Code

\documentclass[tikz,border=2mm,convert=false]{standalone}
\usetikzlibrary{shapes.multipart,patterns}
\makeatletter
\newif\ifpgfrectanglesplitusecustompattern
\def\pgf@lib@sh@rs@list@pattern{none}
\tikzset{
  rectangle split part pattern/.code=\def\pgf@lib@sh@rs@list@pattern{#1}\pgfrectanglesplitusecustompatterntrue,
  rectangle split uses custom pattern/.is if=pgfrectanglesplitusecustompattern,
  rectangle split pattern/.code={\pgfqkeys{/tikz/rectangle split pattern}{#1}},
  rectangle split pattern/.cd,
    pattern color/.code=\edef\tikz@pattern@color{#1},
    pattern/.code=%
      \edef\tikz@temp{#1}%
      \ifx\tikz@temp\tikz@nonetext%
        \tikz@mode@fillfalse
      \else%
        \ifx\tikz@temp\pgfutil@empty%
          \let\tikz@pattern\pgfutil@empty
        \else%
          \def\tikz@pattern{#1}%
        \fi%
        \tikz@mode@filltrue%
      \fi,%
      .unknown/.code=
        \let\tikz@pattern@key\pgfkeyscurrentname
        \pgfutil@ifundefined{pgf@pattern@name@\tikz@pattern@key}{% must be a pattern color then:
          \pgfqkeys{/tikz/rectangle split pattern}{pattern color/.try/.expanded=\tikz@pattern@key}%
          \ifpgfkeyssuccess\else
            \pgfkeys{/errors/unknown key={/tikz/\tikz@pattern@key}{#1}}%
          \fi
        }{\pgfqkeys{/tikz/rectangle split pattern}{pattern/.expanded=\tikz@pattern@key}}%
  }
\expandafter\def\csname pgf@sh@bbg@rectangle split\expandafter\expandafter\expandafter\endcsname\expandafter\expandafter\expandafter{\csname pgf@sh@bbg@rectangle split\endcsname
    \ifpgfrectanglesplitusecustompattern%
      \pgf@lib@sh@rs@process@list{\pgf@lib@sh@rs@list@pattern}{\parts}%
      {%
        \ifpgfrectanglesplithorizontal%
          \expandafter\let\expandafter\pgf@lib@sh@rs@fill@bottomleft\expandafter=%
            \csname pgf@anchor@rectangle split@south west\endcsname%
          \pgfmathloop%
            \ifnum\pgfmathcounter>\parts%
            \else%
              \pgf@lib@sh@getalpha\pgf@lib@sh@rs@number{\pgfmathcounter}%
              \ifnum\pgfmathcounter=\parts%
                \expandafter\let\expandafter\pgf@lib@sh@rs@fill@topright\expandafter=%
                  \csname pgf@anchor@rectangle split@north east\endcsname%
              \else%
                \expandafter\let\expandafter\pgf@lib@sh@rs@fill@topright\expandafter=%
                  \csname pgf@anchor@rectangle split@\pgf@lib@sh@rs@number\space split north\endcsname%
              \fi%
              \expandafter\ifx\csname pgf@lib@sh@rs@empty@\pgf@lib@sh@rs@number\endcsname\pgfutil@empty%
              \else%
                \expandafter\ifx\csname pgf@lib@sh@rs@\pgf@lib@sh@rs@number @item\endcsname\pgf@lib@sh@rs@nonetext%
                \else%
                  \pgfextract@process\pgf@lib@sh@rs@fill@bottomleft{%
                    \pgf@lib@sh@rs@fill@bottomleft%
                    \advance\pgf@y by\outerysep\relax%
                    \ifnum\pgfmathcounter=1\relax%
                      \advance\pgf@x by\outerxsep\relax%
                    \fi%
                  }%
                  \pgfextract@process\pgf@lib@sh@rs@fill@topright{%
                    \pgf@lib@sh@rs@fill@topright%
                    \advance\pgf@y by-\outerysep\relax%
                    \ifnum\pgfmathcounter=\parts\relax%
                      \advance\pgf@x by-\outerxsep\relax%
                    \fi%
                  }%
                  \ifnum\pgfmathcounter>1\relax%
                    \begingroup\pgfsetcornersarced{\pgfpointorigin}%
                  \fi%
                  \pgfpathmoveto{%
                    \pgf@lib@sh@rs@fill@topright%
                    \pgf@xa=\pgf@x%
                    \pgf@lib@sh@rs@fill@bottomleft%
                    \pgf@x=\pgf@xa%
                  }%
                  \pgfpathlineto{\pgf@lib@sh@rs@fill@bottomleft}%
                  \pgfpathlineto{%
                    \pgf@lib@sh@rs@fill@bottomleft%
                    \pgf@xa=\pgf@x%
                    \pgf@lib@sh@rs@fill@topright%
                    \pgf@x=\pgf@xa%
                  }%
                  \ifnum\pgfmathcounter>1\relax%
                    \endgroup%
                  \fi%
                  \ifnum\pgfmathcounter<\parts%
                    \begingroup\pgfsetcornersarced{\pgfpointorigin}%
                  \fi%
                  \pgfpathlineto{\pgf@lib@sh@rs@fill@topright}%
                  \pgfpathclose%
                  \ifnum\pgfmathcounter<\parts%
                    \endgroup%
                  \fi%
                  \edef\pgf@temp{\noexpand\pgfqkeys{/tikz/rectangle split pattern}{\csname pgf@lib@sh@rs@\pgf@lib@sh@rs@number @item\endcsname}}%
                  \pgf@temp
                  \iftikz@mode@fill
                    \pgfsetfillpattern{\tikz@pattern}{\tikz@pattern@color}%
                    \pgfusepath{fill}%
                  \else
                    \pgfusepath{}%
                  \fi
                \fi%
              \fi%
              \pgfextract@process\pgf@lib@sh@rs@fill@bottomleft{%
                \pgf@lib@sh@rs@fill@bottomleft%
                \pgf@ya=\pgf@y%
                \pgf@lib@sh@rs@fill@topright%
                \pgf@y=\pgf@ya%
                \advance\pgf@y by-\outerysep%
              }%
          \repeatpgfmathloop%  
        \else%
          \expandafter\let\expandafter\pgf@lib@sh@rs@fill@topright\expandafter=%
            \csname pgf@anchor@rectangle split@north east\endcsname%
          \pgfmathloop%
            \ifnum\pgfmathcounter>\parts%
            \else%
              \pgf@lib@sh@getalpha\pgf@lib@sh@rs@number{\pgfmathcounter}%
              \ifnum\pgfmathcounter=\parts%
                \expandafter\let\expandafter\pgf@lib@sh@rs@fill@bottomleft\expandafter=%
                  \csname pgf@anchor@rectangle split@south west\endcsname%
              \else%                
                \expandafter\let\expandafter\pgf@lib@sh@rs@fill@bottomleft\expandafter=%
                  \csname pgf@anchor@rectangle split@\pgf@lib@sh@rs@number\space split west\endcsname%
              \fi%
              \expandafter\ifx\csname pgf@lib@sh@rs@empty@\pgf@lib@sh@rs@number\endcsname\pgfutil@empty%
              \else%
                \expandafter\ifx\csname pgf@lib@sh@rs@\pgf@lib@sh@rs@number @item\endcsname\pgf@lib@sh@rs@nonetext%
                \else%
                  \pgfextract@process\pgf@lib@sh@rs@fill@bottomleft{%
                    \pgf@lib@sh@rs@fill@bottomleft%
                    \advance\pgf@x by\outerxsep\relax%
                    \ifnum\parts=1\relax%
                      \advance\pgf@y by\outerysep\relax%
                    \else%
                      \ifnum\pgfmathcounter=\parts
                        \advance\pgf@y by\outerysep\relax%
                      \fi%
                    \fi%
                  }%
                  \pgfextract@process\pgf@lib@sh@rs@fill@topright{%
                    \pgf@lib@sh@rs@fill@topright%
                    \advance\pgf@x by-\outerxsep\relax%
                    \ifnum\parts=1\relax%
                      \advance\pgf@y by-\outerysep\relax%
                    \else%
                      \ifnum\pgfmathcounter=1\relax%
                        \advance\pgf@y by-\outerysep\relax%
                      \fi%
                    \fi%
                  }%
                  \pgfpathmoveto{\pgf@lib@sh@rs@fill@bottomleft}%
                  \ifnum\pgfmathcounter>1\relax%
                    \begingroup\pgfsetcornersarced{\pgfpointorigin}%
                  \fi%
                  \pgfpathlineto{%
                    \pgf@lib@sh@rs@fill@bottomleft%
                    \pgf@xa=\pgf@x%
                    \pgf@lib@sh@rs@fill@topright%
                    \pgf@x=\pgf@xa%
                  }%
                  \pgfpathlineto{\pgf@lib@sh@rs@fill@topright}%
                  \ifnum\pgfmathcounter>1\relax%
                    \endgroup%
                  \fi%
                  \ifnum\pgfmathcounter<\parts%
                    \begingroup\pgfsetcornersarced{\pgfpointorigin}%
                  \fi%
                  \pgfpathlineto{%
                    \pgf@lib@sh@rs@fill@topright%
                    \pgf@xa=\pgf@x%
                    \pgf@lib@sh@rs@fill@bottomleft%
                    \pgf@x=\pgf@xa%
                  }%
                  \pgfpathclose%
                  \ifnum\pgfmathcounter<\parts%
                    \endgroup%
                  \fi%
                  \edef\pgf@temp{\noexpand\pgfqkeys{/tikz/rectangle split pattern}{\csname pgf@lib@sh@rs@\pgf@lib@sh@rs@number @item\endcsname}}%
                  \pgf@temp
                  \iftikz@mode@fill
                    \pgfsetfillpattern{\tikz@pattern}{\tikz@pattern@color}%
                    \pgfusepath{fill}%
                  \else
                    \pgfusepath{}%
                  \fi
                \fi%
              \fi%
              \pgfextract@process\pgf@lib@sh@rs@fill@topright{%
                \pgf@lib@sh@rs@fill@topright%
                \pgf@xa=\pgf@x%
                \pgf@lib@sh@rs@fill@bottomleft%
                \pgf@x=\pgf@xa%  
                \advance\pgf@x by\outerxsep\relax%
              }%
          \repeatpgfmathloop%
        \fi%
      }%
    \fi%
}
\makeatother
\newcommand*{\everyRectangleSplitContents}{0020\nodepart{two}001A\nodepart{three}01A0\nodepart{four}0320}
\begin{document}
\begin{tikzpicture}[nodes=rectangle split,x=1.2cm]
   \node[rectangle split part fill={red!60,blue!60,olive!60,magenta!60}] {\everyRectangleSplitContents};
   \node[rectangle split part pattern={{grid, red!60},
                                       {dots, blue!60},
                                       {horizontal lines, olive!60},
                                       {vertical lines, magenta!60}}
         ] at (1,0) {0020\nodepart{two}001A\nodepart{three}01A0\nodepart{four}0320};

    \node[rectangle split pattern/pattern=grid, % rectangle split pattern
          rectangle split part pattern={red!60,blue!60,olive!60,magenta!60}
         ] at (2,0) {0020\nodepart{two}001A\nodepart{three}01A0\nodepart{four}0320};

   \node[rectangle split pattern/pattern color=red!60,
         rectangle split part pattern={grid,dots,horizontal lines,vertical lines}
         ] at (3,0) {0020\nodepart{two}001A\nodepart{three}01A0\nodepart{four}0320};

\end{tikzpicture}
\end{document}

Output

enter image description here

  • You answer is reasonable, but I must learn more to understand your codes. – foool Jun 19 '13 at 1:29
  • @foool The most part is copied from the already existing code that produces the filling. Actually, the code can be used to do nearly anything with that rectangular path. I simply adapted it to work with pattern and added the code to the behind-background path. Everything between \makeatletter and \makeatother is best be saves in a separate .tex file and simply \input. By the way, I have updated my answer so that you can omit pattern and pattern color (as long as you do not define a color with the same name as a pattern). – Qrrbrbirlbel Jun 19 '13 at 2:54
5

I think it's not possible to use something like rectangle split part fill for hatching backgrounds. But if you need to do it, you can always draw hatch patterns for each part on background.

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

\usetikzlibrary{shapes.multipart,positioning,patterns,backgrounds}

\begin{document}
\begin{tikzpicture}
   \node[rectangle split,% 
         rectangle split part fill={red!60,blue!60,olive!60,magenta!60}] (d)   
        {0020%
         \nodepart{two}001A%
         \nodepart{three}01A0%
         \nodepart{four}0320};

   \node[rectangle split, right=1cm of d, fill=none] (e)
        {0020\nodepart{two}001A\nodepart{three}01A0\nodepart{four}0320};

   \begin{pgfonlayer}{background}
       \draw[pattern=grid, pattern color=red!60] (e.north west) rectangle (e.text split east);
       \draw[pattern=dots, pattern color=blue!60] (e.text split west) rectangle (e.two split east);
       \draw[pattern=horizontal lines, pattern color=olive!60] (e.two split west) rectangle (e.three split east);
       \draw[pattern=vertical lines, pattern color=magenta!60] (e.three split west) rectangle (e.south east);
    \end{pgfonlayer}
\end{tikzpicture}
\end{document}

enter image description here

As Qrrbrbirlbel has pointed, previous solution hatches an area wider and taller than the one covered with fill. It's possible to better adjust with:

\begin{pgfonlayer}{background}
    \fill[pattern=grid, pattern color=red!60]%  
         ([shift={(.5\pgflinewidth,-.5\pgflinewidth)}]e.north west) rectangle 
         ([shift={(-.5\pgflinewidth,0)}]e.text split east);
    \fill[pattern=grid, pattern color=blue!60]%     
         ([shift={(.5\pgflinewidth,0)}]e.text split west) rectangle 
         ([shift={(-.5\pgflinewidth,0)}]e.two split east);
    \fill[pattern=grid, pattern color=olive!60]%    
         ([shift={(.5\pgflinewidth,0)}]e.two split west) rectangle 
         ([shift={(-.5\pgflinewidth,0)}]e.three split east);
    \fill[pattern=grid, pattern color=magenta!60]%  
         ([shift={(.5\pgflinewidth,0)}]e.three split west) rectangle 
         ([shift={(-.5\pgflinewidth,.5\pgflinewidth)}]e.south east);
\end{pgfonlayer}

Previous code works if node outer sep has its default value, otherwise will be necessary to adjust shift values according it.

Next figure shows the result with first and second codes.

enter image description here

  • Strictly speaking you need to subtract the outer separators from the anchors to get the same path as you would if you draw the rectangle split shape directly. The anchors usually lie (default outer sep=.5\pgflinewidth) on the border of the line. – Qrrbrbirlbel Jun 18 '13 at 21:28

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.