# Inconsistent TikZ multipart node anchors

In the following example, why aren't the node anchors placed consistently?

\input tikz
\usetikzlibrary{arrows,shapes.multipart}
\tikzset{
font=\tt, >= stealth, every picture/.style={thick}, pointer/.style={*->},
box/.style={draw, inner sep=2ex, fill=black!10, rounded corners,
rectangle, rectangle split, rectangle split parts=2,
rectangle split ignore empty parts=false, rectangle split horizontal}}
\tikzpicture[every node/.append style={at end}]
\node[box] (1) {};
\draw[pointer] (1.text) -- +(0,-1) node[anchor=north,box] (2) {};
\draw[pointer] (2.text) -- +(0,-1) node[anchor=north] {1};
\draw[pointer] (2.two) -- +(0,-1) node[anchor=north] {2};
\draw[pointer] (1.two) -- +(1,0) node[anchor=base west,box] (3) {};
\draw[pointer] (3.text) -- +(0,-1) node[anchor=north] {3};
\draw[pointer] (3.two) -- +(0,-1) node[anchor=north] {4};
\endtikzpicture
\bye


Ideally, I'd like the black dots to be exactly in the center.

-

I'm not sure you take the good way. In the pgfmanual, you can see that centers of the different parts are not given. I think the center of a part for example "one" is $(1.west)!.5!(1.one split)$. I write rapidly the next code and it's possible to write something more elegant.

Update version 2 : I found a way to create the coordinates of the centers for each part but I can't find how to create the circles with the style. (c1 3) désigne the center of the first part of the node (3). There are some modifications in the code like at end

\input tikz
\usetikzlibrary{arrows,shapes.multipart,calc}

\tikzset{
font=\tt,
>= stealth,
every picture/.style={thick},
box/.style={at end,
draw,
inner sep=2ex,
fill=black!10,
rounded corners,
rectangle,
rectangle split,
rectangle split parts=2,
rectangle split ignore empty parts=false,
rectangle split horizontal,
append after command={%
\pgfextra{%
\let\mainnode=\tikzlastnode}
coordinate (c1 \mainnode) at ($(\mainnode.west)!.5!(\mainnode.one split)$)
coordinate (c2 \mainnode) at ($(\mainnode.one split)!.5!(\mainnode.east)$)}}}
\tikzpicture
\node[box] (1) {};
\draw[->] (c1 1) -- +(0,-1) node[anchor=north,box] (2) {};
\draw[->] (c1 2) -- +(0,-1) node[anchor=north] {1};
\draw[->] (c2 2) -- +(0,-1) node[anchor=north] {2};
\draw[->] (c2 1) -- +(1,0)  node[anchor=west,box] (3) {};
\draw[->] (c1 3) -- +(0,-1) node[anchor=north] {3};
\draw[->] (c2 3) -- +(0,-1) node[anchor=north] {4};
\foreach \i in {1,2,3}{\draw[fill=black] (c1 \i)circle(2pt) (c2 \i)circle(2pt);}
\endtikzpicture
\bye


Difference with Marc's solution

\node[box] (1) { };
\draw[] (1.one|-1.west) circle(2pt);
\draw[fill=black] ($(1.west)!.5!(1.one split)$)circle(2pt);


gives

Update version 3. It's possible to draw the circle directly but in this case you can't draw the arrows at the same time. The code is interesting and perhaps someone can find a good idea for the arrows (only arrows when we use box)

\input tikz
\usetikzlibrary{arrows,shapes.multipart,calc}

\tikzset{
font=\tt,
>= stealth,
every picture/.style={thick},
box/.style={
draw,
inner sep=2ex,
fill=black!10,
rounded corners,
rectangle,
rectangle split,
rectangle split parts=2,
rectangle split ignore empty parts=false,
rectangle split horizontal,
append after command={%
\pgfextra{\let\mainnode=\tikzlastnode
\coordinate (c1 \mainnode) at ($(\mainnode.west)!.5!(\mainnode.one split)$);
\coordinate (c2 \mainnode) at ($(\mainnode.one split)!.5!(\mainnode.east)$);
\draw[fill=black] (c1 \mainnode)circle(2pt) (c2 \mainnode)circle(2pt);}
}}}
\tikzpicture
\node[box] (1) {};
\path (c1 1)     -- +(0,-1) node[anchor=north,box] (2) {};
\draw[->] (c1 2) -- +(0,-1) node[anchor=north] {1};
\draw[->] (c2 2) -- +(0,-1) node[anchor=north] {2};
\path (c2 1)     -- +(1,0)  node[anchor=west,box] (3) {};
\draw[->] (c1 3) -- +(0,-1) node[anchor=north] {3};
\draw[->] (c2 3) -- +(0,-1) node[anchor=north] {4};
\draw[->] (c1 1) --  (2.north);
\draw[->] (c2 1) --  (3.west);
\endtikzpicture
\bye


We get the same result.

-
That's perfect! Thanks! :-) If only one could somehow automate the center calculation… hmmm –  morbusg Feb 12 '12 at 13:26
Not obvious ! Perhaps it's possible to add some code to define the centers after the creation of the nodes. No idea actually, it will be useful to modify box/.style to do this. –  Alain Matthes Feb 12 '12 at 14:47
@Altermundus: Note that the third box (the rightmost one) in your code for Update version 2 is placed a bit above the first one (the top left one), while the two really should be aligned horizontally. I found that if you change "base west" to just "west", the two ends up aligned in the same vertical placement, although I don't know why this works (why?). The same method also works for the code under Update version 3, but then the arrow connecting the two boxes will be pointing slightly downwards instead (why?). –  StrawberryFieldsForever Jul 25 '12 at 22:18
@StrawberryFieldsForever I used the code from morbusg but you are right if you want to align the first boxes you need to use westand not base west. To understand you can look at the pgfmanual section Shape Library. I will update my answer. –  Alain Matthes Jul 26 '12 at 11:40
Also, if you have many parts and want to get the middle of all of those parts, you can use $(\mainnode.west)!0.5!(\mainnode.one split)$ for the first one, $(\mainnode.west)!1.5!(\mainnode.one split)$ for the second one, $(\mainnode.west)!2.5!(\mainnode.one split)$ for the third one etc. In that way you just need to change one digit! :) –  StrawberryFieldsForever Jul 26 '12 at 13:25

It looks as if this is a bug. Two things are going on. The pointer style results in the wrong positions for the start of the arrows. On top of that, the positioning inside the text parts of the boxes looks suspicious. In the following I show how you can get around these problems by using a normal arrow and by computing (what appears to be) the centre of the two text parts.

\usetikzlibrary{calc}

\usetikzlibrary{arrows,shapes.multipart}
\begin{document}
\tikzset{
font=\tt, >= stealth, every picture/.style={thick}, pointer/.style={*->},
box/.style={draw, inner sep=2ex, fill=black!10, rounded corners,
rectangle, rectangle split, rectangle split parts=2,
rectangle split ignore empty parts=false, rectangle split horizontal}}
\tikzpicture[every node/.append style={at end}]
\node[box] (1) {};
\draw[->] (1.mid) -- +(0,-1) node[anchor=north,box] (2) {};
\draw[->] (2.mid) -- +(0,-1) node[anchor=north] {1};
\draw[->] (2.two|-2.east) -- +(0,-1) node[anchor=north] {2};
\draw[->] (1.two|-1.east) -- +(1,0) node[anchor=base west,box] (3) {};
\draw[->] (3.mid) -- +(0,-1) node[anchor=north] {3};
\draw[->] (3.two|-3.east) -- +(0,-1) node[anchor=north] {4};
\endtikzpicture

-
Fantastic answer! :) (I'm out of votes again, but I promise to upvote it ASAP) :) –  Paulo Cereda Feb 12 '12 at 10:20
I wouldn't say that the arrows start in the wrong place, just not in the place one might expect. This has been covered before: tex.stackexchange.com/questions/19191/… –  Jake Feb 12 '12 at 10:48
2.two|-2.east is not the exact center of the two part ! –  Alain Matthes Feb 12 '12 at 11:24
@Altermundus I noticed the position wasn't exactly the centre, which is why I wrote (what appears to be). I wasn't aware of the one split coordinate. It's not mentioned in the pgf manual, which is all I'm going to read: you won't see me reading the source files:-) –  Marc van Dongen Feb 12 '12 at 13:47
@MarcvanDongen In the pgfmanual you have text split, I try one split but it's a lucky try. –  Alain Matthes Feb 12 '12 at 16:12