The following example defines a new shape rectangle16
. It inherits the anchors from the shape rectangle
and adds anchors t0
(= north west
) to t16
(= north east
) and b0
(= south west
) to b16
(= south east
).
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{topaths}
\usetikzlibrary{calc}
\usetikzlibrary{hobby}
\makeatletter
\newcommand*{\define@anchor@t}[2]{%
\anchor{t#1}{%
\pgf@process{\southwest}%
\pgf@xa=\pgf@x
\pgf@process{\northeast}%
\pgf@x=\dimexpr\pgf@xa + (\pgf@x-\pgf@xa)*#1/#2\relax
}%
}
\newcommand*{\define@anchor@b}[2]{%
\anchor{b#1}{%
\pgf@process{\northeast}%
\pgf@xa=\pgf@x
\pgf@process{\southwest}%
\pgf@x=\dimexpr\pgf@x + (\pgf@xa-\pgf@x)*#1/#2\relax
}%
}
\pgfdeclareshape{rectangle16}{%
\inheritsavedanchors[from=rectangle]
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{north west}
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{mid}
\inheritanchor[from=rectangle]{mid west}
\inheritanchor[from=rectangle]{mid east}
\inheritanchor[from=rectangle]{base}
\inheritanchor[from=rectangle]{base west}
\inheritanchor[from=rectangle]{base east}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{south east}
\inheritbackgroundpath[from=rectangle]
\count@=0 %
\@whilenum\count@<17 \do{%
\expandafter\define@anchor@t\expandafter{\the\count@}{16}%
\expandafter\define@anchor@b\expandafter{\the\count@}{16}%
\advance\count@\@ne
}%
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[draw,rectangle16] (N)
{Rectangular node with additional anchors at the top and bottom};
\foreach \i in {0, ..., 16} {
\draw[<-, node font=\footnotesize]
(N.t\i) -- ++(0, .5) node[above] {t\i}
;
\draw[<-, node font=\footnotesize]
(N.b\i) -- ++(0, -.5) node[below] {b\i}
;
}
\node[draw, rectangle16] (ST) at (N.center |- 0, -3) {Some Text};
\draw
\foreach \i in {1, ..., 14} { (ST.t\i) -- ++(0, .5) }
(ST.south east) ++(-2, -1)
node[
rectangle16,
draw,
rotate=-45,
minimum width=15mm,
minimum height=5mm,
] (R) {}
(ST.b1) to (R.t4)
;
\draw[use Hobby shortcut]
(ST.t15)
-- ([out angle=90]$(ST.t15) + (0, .1)$)
.. ($(ST.east) + (.5, 0)$)
.. ([in angle=-90]$(ST.b15) + (0, -.1)$)
-- (ST.b15)
;
\fill[
red,
radius=.5pt,
]
\foreach \i in {0, ..., 16} {
\foreach \tb in {t, b} {
(R.\tb\i) circle[]
}
}
;
\end{tikzpicture}
\end{document}

Generalization
The following example defines \declareshaperectxy{<h>}{<v>}
with two arguments for the horizontal and vertical number of anchors for the four sides of a rectangular shape and defines the shape with the name
rectangle <h>x<v>
. For example, after \declareshaperectxy{16}{8}
the shape rectangle 16x8
can be used, which provides the additional anchors t0
to t16
at the top, b0
to b16
at the bottom, l0
to l8
at the left side and r0
to r8
at the right side.
\documentclass{article}
\usepackage{tikz}
\makeatletter
\newcommand*{\rectxy@anchor@top}[2]{%
\anchor{t#1}{%
\pgf@process{\southwest}%
\pgf@xa=\pgf@x
\pgf@process{\northeast}%
\pgf@x=\dimexpr\pgf@xa + (\pgf@x-\pgf@xa)*#1/#2\relax
}%
}
\newcommand*{\rectxy@anchor@bottom}[2]{%
\anchor{b#1}{%
\pgf@process{\northeast}%
\pgf@xa=\pgf@x
\pgf@process{\southwest}%
\pgf@x=\dimexpr\pgf@x + (\pgf@xa-\pgf@x)*#1/#2\relax
}%
}
\newcommand*{\rectxy@anchor@left}[2]{%
\anchor{l#1}{%
\pgf@process{\northeast}%
\pgf@ya=\pgf@y
\pgf@process{\southwest}%
\pgf@y=\dimexpr\pgf@y + (\pgf@ya-\pgf@y)*#1/#2\relax
}%
}
\newcommand*{\rectxy@anchor@right}[2]{%
\anchor{r#1}{%
\pgf@process{\southwest}%
\pgf@ya=\pgf@y
\pgf@process{\northeast}%
\pgf@y=\dimexpr\pgf@ya + (\pgf@y-\pgf@ya)*#1/#2\relax
}%
}
\newcommand*{\declareshaperectxy}[2]{%
\pgfdeclareshape{rectangle #1x#2}{%
\inheritsavedanchors[from=rectangle]
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{north west}
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{mid}
\inheritanchor[from=rectangle]{mid west}
\inheritanchor[from=rectangle]{mid east}
\inheritanchor[from=rectangle]{base}
\inheritanchor[from=rectangle]{base west}
\inheritanchor[from=rectangle]{base east}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{south east}
\inheritbackgroundpath[from=rectangle]
\count@=\m@ne
\@whilenum\count@<#1 \do{%
\advance\count@\@ne
\expandafter\rectxy@anchor@top\expandafter{\the\count@}{#1}%
\expandafter\rectxy@anchor@bottom\expandafter{\the\count@}{#1}%
}%
\count@=\m@ne
\@whilenum\count@<#2 \do{%
\advance\count@\@ne
\expandafter\rectxy@anchor@left\expandafter{\the\count@}{#2}%
\expandafter\rectxy@anchor@right\expandafter{\the\count@}{#2}%
}%
}%
}
\makeatother
\declareshaperectxy{16}{8}
\declareshaperectxy{5}{3}
\begin{document}
\begin{tikzpicture}
\node[
draw,
rectangle 16x8,
minimum width=80mm,
minimum height=30mm,
] (N) {};
\foreach \i in {0, ..., 16} {
\draw[<-, node font=\footnotesize]
(N.t\i) -- ++(0, .5) node[above] {t\i}
;
\draw[<-, node font=\footnotesize]
(N.b\i) -- ++(0, -.5) node[below] {b\i}
;
}
\foreach \i in {0, ..., 8} {
\draw[<-, node font=\footnotesize]
(N.l\i) -- ++(-.5, 0) node[left] {l\i}
;
\draw[<-, node font=\footnotesize]
(N.r\i) -- ++(.5, 0) node[right] {r\i}
;
}
\node[
draw,
rectangle 5x3,
minimum width=80mm,
minimum height=30mm,
at={(0, -55mm)},
] (N) {};
\foreach \i in {0, ..., 5} {
\draw[<-, node font=\footnotesize]
(N.t\i) -- ++(0, .5) node[above] {t\i}
;
\draw[<-, node font=\footnotesize]
(N.b\i) -- ++(0, -.5) node[below] {b\i}
;
}
\foreach \i in {0, ..., 3} {
\draw[<-, node font=\footnotesize]
(N.l\i) -- ++(-.5, 0) node[left] {l\i}
;
\draw[<-, node font=\footnotesize]
(N.r\i) -- ++(.5, 0) node[right] {r\i}
;
}
\end{tikzpicture}
\end{document}
