3

I need to draw some groups of overlapping rectangles, for example:

rectangles

They are labeled by numbers, rectangle 1 is overlapping rectangle 2 etc.

Is there a way to change automatically the position of numbers so that they are all visible? Or to place all numbers over all the rectangles?

The code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes,backgrounds}

\usepackage{etoolbox}% provides \preto
\makeatletter
\newcommand*{\collect@draws}{}
\newcommand*{\reversedraws}{%
  \renewcommand*{\collect@draws}{}% initialize
  \look@for@draw
}
\newcommand*{\look@for@draw}{%
  \@ifnextchar\draw{%
    \catch@draw
  }{%
    \collect@draws % output the result
  }%
}
\def\catch@draw\draw#1;{%
  \preto\collect@draws{\draw#1;}%
  \look@for@draw
}
\makeatother

\begin{document}

\begin{tikzpicture}[scale = 4]
\reversedraws
\draw [fill=yellow] (0.445041,0.801937) rectangle (0,1) node[midway] {$1$};
\draw [fill=yellow] (0.692021,0.356896) rectangle (1,1) node[midway] {$2$};
\draw [fill=yellow] (0.692021,0.356895) rectangle (0,0) node[midway] {$3$};
\draw [fill=yellow] (0.137063,0.158832) rectangle (0,1) node[midway] {$4$};
\draw [fill=yellow] (0.384043,0.713791) rectangle (1,0) node[midway] {$5$};
\draw [fill=yellow] (0.829084,0.515727) rectangle (0,1) node[midway] {$6$};
\draw [fill=yellow] (0.521105,0.872622) rectangle (0,0) node[midway] {$7$};
\end{tikzpicture}

\begin{tikzpicture}[scale = 4]
\reversedraws
\draw [fill=yellow] (0.145041,0.801937) rectangle (0,1) node[midway] {$1$};
\draw [fill=yellow] (0.692021,0.356896) rectangle (0.7,1) node[midway] {$2$};
\draw [fill=yellow] (0.392021,0.356895) rectangle (0,0) node[midway] {$3$};
\draw [fill=yellow] (0.384043,0.713791) rectangle (0.7,0) node[midway] {$4$};
\draw [fill=yellow] (0.529084,0.515727) rectangle (0,1) node[midway] {$5$};
\draw [fill=yellow] (0.521105,0.872623) rectangle (0.7,1) node[midway] {$6$};
\draw [fill=yellow] (0.221105,0.872622) rectangle (0,0) node[midway] {$7$};
\draw [fill=yellow] (0.213127,0.229518) rectangle (0.7,1) node[midway] {$8$};
\end{tikzpicture}

\end{document}
Helena
  • 117

2 Answers2

1

You can move the labels with xshift and yshift options (see the rectangle with number 5 like label)

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes,backgrounds}

\usepackage{etoolbox}% provides \preto
\makeatletter
\newcommand*{\collect@draws}{}
\newcommand*{\reversedraws}{%
  \renewcommand*{\collect@draws}{}% initialize
   \look@for@draw
}
\newcommand*{\look@for@draw}{%
  \@ifnextchar\draw{%
    \catch@draw
  }{%
    \collect@draws % output the result
  }%
}
\def\catch@draw\draw#1;{%
  \preto\collect@draws{\draw#1;}%
  \look@for@draw
}
\makeatother

\begin{document}

\begin{tikzpicture}[scale = 4]
\reversedraws
\draw [fill=yellow] (0.445041,0.801937) rectangle (0,1) node[midway] {$1$};
\draw [fill=yellow] (0.692021,0.356896) rectangle (1,1) node[midway] {$2$};
\draw [fill=yellow] (0.692021,0.356895) rectangle (0,0) node[midway] {$3$};
\draw [fill=yellow] (0.137063,0.158832) rectangle (0,1) node[midway] {$4$};
\draw [fill=yellow] (0.384043,0.713791) rectangle (1,0) node[yshift=-5pt,xshift=5pt,midway] {$5$};
\draw [fill=yellow] (0.829084,0.515727) rectangle (0,1) node[midway] {$6$};
\draw [fill=yellow] (0.521105,0.872622) rectangle (0,0) node[midway] {$7$};
\end{tikzpicture}

\end{document}

enter image description here

juanuni
  • 1,987
1

Automatically changing the position of nodes might be hard but doable if you know all the cases beforehand. I'm not sure it's worth it.

You can however put nodes in the foreground, also they need to have a background (to cover the lines behind), I think it's the best I can suggest considering the current information.

You can add [mid] to the node you want on the foreground, but if you want this to be applied to all, just include the mid style in the every node one. Although I suggest against this since you might affect other nodes that are better left alone (like node 6 in this example).

The options

every node/.style={midway},
every path/.style={fill=yellow},

apply to all nodes and all paths respectively. So you don't need to specify those anymore in your code. Generally, it's better to set general rules for things that are repeated a lot of times.

This is a modified solution from Loop Space's answer.

Output

figure 1

Code

\documentclass{article}
\usepackage{tikz}
\usepackage{etoolbox}% provides \preto

\usetikzlibrary{shapes,backgrounds}

\makeatletter
\newcommand*{\collect@draws}{}
\newcommand*{\reversedraws}{%
  \renewcommand*{\collect@draws}{}% initialize
  \look@for@draw
}
\newcommand*{\look@for@draw}{%
  \@ifnextchar\draw{%
    \catch@draw
  }{%
    \collect@draws % output the result
  }%
}
\def\catch@draw\draw#1;{%
  \preto\collect@draws{\draw#1;}%
  \look@for@draw
}
\makeatother

%%%% Declaring layers
\pgfdeclarelayer{foreground}
\pgfsetlayers{main,foreground}

%%%% The node on layer definition
\makeatletter
\pgfkeys{%
  /tikz/node on layer/.code={
    \gdef\node@@on@layer{%
      \setbox\tikz@tempbox=\hbox\bgroup\pgfonlayer{#1}\unhbox\tikz@tempbox\endpgfonlayer\egroup}
    \aftergroup\node@on@layer
  }}
\def\node@on@layer{\aftergroup\node@@on@layer}
\makeatother

%%%% Options
\tikzset{
    every node/.style={midway},
    every path/.style={fill=yellow},
    mid/.style={midway, inner sep=2pt, outer sep=0,minimum size=1mm, fill=yellow,node on layer=foreground},
}

\begin{document}
    \begin{tikzpicture}[scale = 4]
        \reversedraws
        \draw (0.445041,0.801937) rectangle (0,1) node {$1$};
        \draw (0.692021,0.356896) rectangle (1,1) node {$2$};
        \draw (0.692021,0.356895) rectangle (0,0) node {$3$};
        \draw (0.137063,0.158832) rectangle (0,1) node {$4$};
        \draw (0.384043,0.713791) rectangle (1,0) node[mid] {$5$};
        \draw (0.829084,0.515727) rectangle (0,1) node {$6$};
        \draw (0.521105,0.872622) rectangle (0,0) node {$7$};
    \end{tikzpicture}
\end{document}
Alenanno
  • 37,338