Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I would like to draw some points in TikZ, and position them relative to the bounding box of the overall picture. Specifically, I would like to give their y-coordinate explicitly, and have their x-coordinate taken from the left-edge of the picture's bounding box. How can I do this?

Here is an example. Each time I invoke \myCircle or \mySquare, the circle/square is drawn, and a little "notch" is drawn on the left-hand side. (The purpose of the notch is to be a drawing aid, so users can see where shapes are positioned.) The y-coordinate of the notch is taken from the centre of the circle/square. The x-coordinate is currently fixed at 0, but I would prefer that to be something like bounding box of overall picture.west.

\documentclass[border=5mm]{standalone}
\usepackage{tikz}

\newcommand\myCircle[2]{%
  \fill[red] (#1,#2) circle (5);
  \draw (-2,#2) -- (0,#2);
}
\newcommand\mySquare[2]{%
  \fill[red] (#1-5,#2-5) rectangle (#1+5,#2+5);
  \draw (-2,#2) -- (0,#2);
}

\begin{document}
  \begin{tikzpicture}[x=1mm,y=1mm]
    \myCircle{7}{5}
    \mySquare{26}{0}
    \myCircle{8}{20}
  \end{tikzpicture}
\end{document}

enter image description here

share|improve this question
1  
One problem is that you won't know the bounding box until the very end of the picture. So I would store the y values in a list and then iterate over that list at the very end of the picture (using execute at end picture). –  Loop Space Jun 3 '13 at 10:17

2 Answers 2

up vote 1 down vote accepted

A possibility is to create labeled local bounding boxes for referencing later for each path.

\documentclass{article}
\usepackage{tikz}
\newcount\mycircle
\newcount\mysquare

\newcommand\myCircle[2]{%
\advance\mycircle by 1\relax
\begin{scope}[local bounding box/.expanded=c\the\mycircle]
    \draw[red] (#1,#2) circle (5);
\end{scope}
}
\newcommand\mySquare[2]{%
\advance\mysquare by 1\relax
\begin{scope}[local bounding box/.expanded=s\the\mysquare]
        \draw[red] ({#1-5},{#2-5}) rectangle ({#1+5},{#2+5});
\end{scope}
}

\tikzset{every picture/.style={
    execute at end picture={
        \ifnum\the\mycircle>0\relax%
            \foreach\myc in{1,...,\the\mycircle}{%
                \draw[overlay] (current bounding box.north west |- c\myc) -- ++(-3mm,0);%
            }%
        \fi%
        \ifnum\the\mysquare>0\relax%
            \foreach\myc in{1,...,\the\mysquare}{%
                \draw[overlay] (current bounding box.north west |- s\myc) -- ++(-3mm,0);%
            }%
        \fi%
        \mycircle=0\mysquare=0%
        }
    }
}
\begin{document}
  \begin{tikzpicture}[x=1mm,y=1mm]
    \myCircle{0}{5}
    \mySquare{26}{0}
    \myCircle{8}{20}
    \mySquare{10}{-3}
  \end{tikzpicture}

\vspace{2cm}

  \begin{tikzpicture}[x=1mm,y=1mm]
    \myCircle{-1}{5}
    \myCircle{3}{7}
  \end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
Hmm, I might have read the question wrong. So the point is not drawing the notches I guess... –  percusse Jun 4 '13 at 21:25
    
I’d additionally through in a \pgftransformreset so that the notches are not affected by any transformation (scaling/rotation). –  Qrrbrbirlbel Jun 4 '13 at 23:34
    
@JohnWickerson I thought notches are just indicators but the geometric shapes should have been placed only by referring to their x coordinate. But now I see that it doesn't make sense too. I guess it's me the problem. I need coffee. –  percusse Jun 5 '13 at 8:59

I ended up using a simplified version of percusse's answer, following Andrew's suggestion to keep just a list of y-coordinates. The code is below. I'd just like to point out two "gotchas" that gave me confusing error messages:

  • If A and B are nodes, you can use A |- B to calculate the coordinate with A's x-value and B's y-value. You might expect to be able to write the pair (x,y) instead of A or B, but note the following gotcha: The syntax is (A |- x,y) not (A |- (x,y)).

  • Be careful when using \x or \y as the iterating variable of a \foreach loop. In the code below, it would be fine, but in an earlier version I used let \p1 = (oldBBox.north west), instead of the |- syntax, to store the top-left point of the bounding box in \x1,\y1. This is a problem if the variables \x and \y are already in use.

Code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\gdef\ys{} 

\makeatletter
\newcommand*\snoc[2]{%
  \ifx#1\@empty
    \xdef#1{#2}
  \else
    \xdef#1{#1,#2}
  \fi
}
\makeatother

\newcommand\myCircle[2]{%
  \draw[red] (#1,#2) circle (5);
  \snoc\ys{#2}
}
\newcommand\mySquare[2]{%
  \draw[red] ({#1-5},{#2-5}) rectangle ({#1+5},{#2+5});
  \snoc\ys{#2}
}

\tikzset{every picture/.style={
  execute at end picture={
    \coordinate (oldBBox) at (current bounding box.north west);
    \foreach \yvalue in \ys {%
      \draw (oldBBox |- 0,\yvalue) -- ++(-3mm,0);
    }
    \gdef\ys{}    
  }
}}

\begin{document}
  \begin{tikzpicture}[x=1mm,y=1mm]
    \myCircle{0}{5}
    \mySquare{26}{0}
    \myCircle{8}{20}
    \mySquare{10}{-3}
  \end{tikzpicture}

\vspace{2cm}

  \begin{tikzpicture}[x=1mm,y=1mm]
    \myCircle{10}{5}
    \myCircle{3}{7}
  \end{tikzpicture}
\end{document}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.