Auf golatex.de wurde die Frage gestellt, wie man zu einem bereits definierten shape weitere Anker hinzufügen kann. Konkret sollen zu einem rectangle zusätzliche Anker definiert werden, die bei jeweils 1/3 und 2/3 der Seitenlängen liegen.

Hier ist das bereits definierte rectangle

alt text

Code (im wesentlichen aus dem pgfmanual):

Open in writeLaTeX
\documentclass[tikz,margin=5mm]{standalone}

\tikzset{
shape example/.style= {color = black!30,draw,fill = yellow!30,
  line width = .5cm,inner xsep = 2.5cm,inner ysep = 0.5cm}
}

\begin{document}
\Huge
\begin{tikzpicture}
  \node[name=s,shape=rectangle,shape example] {Rectangle\vrule width 1pt height 2cm};
% bisherige Anker einzeichnen lassen
  \foreach \anchor/\placement in
    {north west/above left, north/above, north east/above right,
      west/left, center/above, east/right,
      mid west/right, mid/above, mid east/left,
      base west/left, base/below, base east/right,
      south west/below left, south/below, south east/below right,
      text/left, 15/right,150/above}
    \draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)}
      node[\placement,font=\scriptsize] {\texttt{(s.\anchor)}};
\end{tikzpicture}
\end{document}

Wie kann ich mir jetzt ein shape definieren, das zusätzlich die Anker north 1/3, north 2/3 etc. hat?

gefragt 26 Jun '14, 00:06

esdd's gravatar image

esdd
17.7k254256
Akzeptiert-Rate: 62%


Zunächst lohnt ein Blick in die Datei pgfmoduleshapes.code.tex in der das rectangle definiert wird. Dann definiere ich mir ein neues shape myrectangle und übernehme mit Hilfe von \inherit... Befehlen die Anker und den Pfad des rectangle:

Open in writeLaTeX
\pgfdeclareshape{myrectangle}{
  % es wird zunächst alles vom rectangle übernommen
  \inheritsavedanchors[from=rectangle]
  \inheritanchorborder[from=rectangle]
  \foreach \a in {%
      center,mid,base,north,south,west,east,%
      north west,mid west,base west,south west,%
      north east,mid east,base east,south east%
    }{\inheritanchor[from=rectangle]{\a}}
  \inheritbackgroundpath[from=rectangle]
}

Für das rectangle sind zwei saved anchors definiert: \southwest und \northeast. Die beiden können benutzt werden, um weitere Anker zu definieren. Dabei hilft es auch wieder, wenn man sich im Quelltext anschaut, wie die anderen Anker definiert wurden. Zu beachten ist dabei, dass die Koordinaten von \southwest negativ sind, da der Ursprung des nodeeigenen Koordinatensystems beim Anker text liegt.

Der Anker north 2/3 kann zum Beispiel so definiert werden:

Open in writeLaTeX
\anchor{north 2/3}{
  \southwest\pgf@xa=\pgf@x
  \northeast\pgfmathsetlength\pgf@x{\pgf@x-(\pgf@x-\pgf@xa)/3}
}

Dabei wird zunächst die x-Koordinate des \southwest Ankers in \pgf@xa gespeichert. Danach wird mit Hilfe von diesem gespeicherten Wert und der x-Koordinate des \northeast Ankers die Gesamtlänge der oberen Kante bestimmt und ein Drittel dieser Gesamtlänge von der x-Koordinate des \northeast Ankers abgezogen. Die y-Koordinate des Ankers north 2/3 stimmt dagegen schon mit der y-Koordinate von \northeast überein, so dass für diese keine Berechnungen notwendig sind.

alt text

Code:

Open in writeLaTeX
\documentclass[tikz,margin=5mm,convert=false]{standalone}
\makeatletter
\pgfdeclareshape{myrectangle}{
  % es wird zunächst alles vom rectangle übernommen
  \inheritsavedanchors[from=rectangle]
  \inheritanchorborder[from=rectangle]
  \foreach \a in {%
      center,mid,base,north,south,west,east,%
      north west,mid west,base west,south west,%
      north east,mid east,base east,south east%
    }{\inheritanchor[from=rectangle]{\a}}
  \inheritbackgroundpath[from=rectangle]
  % dann werden die zusätzlichen Anker ergänzt
  \anchor{north 1/3}{
    \southwest\pgf@xa=\pgf@x
    \northeast\pgfmathsetlength\pgf@x{\pgf@xa-(\pgf@xa-\pgf@x)/3}
  }
  \anchor{north 2/3}{
    \southwest\pgf@xa=\pgf@x
    \northeast\pgfmathsetlength\pgf@x{\pgf@x-(\pgf@x-\pgf@xa)/3}
  }
  \anchor{south 1/3}{
    \northeast\pgf@xa=\pgf@x
    \southwest\pgfmathsetlength\pgf@x{\pgf@x-(\pgf@x-\pgf@xa)/3}
  }
  \anchor{south 2/3}{
    \northeast\pgf@xa=\pgf@x
    \southwest\pgfmathsetlength\pgf@x{\pgf@xa-(\pgf@xa-\pgf@x)/3}
  }
  \anchor{east 1/3}{
    \southwest\pgf@ya=\pgf@y
    \northeast\pgfmathsetlength\pgf@y{\pgf@ya-(\pgf@ya-\pgf@y)/3}
  }
  \anchor{east 2/3}{
    \southwest\pgf@ya=\pgf@y
    \northeast\pgfmathsetlength\pgf@y{\pgf@y-(\pgf@y-\pgf@ya)/3}
  }
  \anchor{west 1/3}{
    \northeast\pgf@ya=\pgf@y
    \southwest\pgfmathsetlength\pgf@y{\pgf@y-(\pgf@y-\pgf@ya)/3}
  }
  \anchor{west 2/3}{
    \northeast\pgf@ya=\pgf@y
    \southwest\pgfmathsetlength\pgf@y{\pgf@ya-(\pgf@ya-\pgf@y)/3}
  }
}
\makeatother

\tikzset{
  shape example/.style= {color = black!30,draw,fill = yellow!30,
    line width = .5cm,inner xsep = 2.5cm,inner ysep = 0.5cm}
}

\begin{document}
\Huge
\begin{tikzpicture}
  \node[name=s,shape=myrectangle,shape example] {Rectangle\vrule width 1pt height 2cm};
  % bisherige Anker einzeichnen lassen
  \foreach \anchor/\placement in
    {north west/above left, north/above, north east/above right,
      west/left, center/above, east/right,
      mid west/right, mid/above, mid east/left,
      base west/left, base/below, base east/right,
      south west/below left, south/below, south east/below right,
      text/left, 15/right,150/above}
    \draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)}
      node[\placement,font=\scriptsize] {\texttt{(s.\anchor)}};
  % neue Anker einzeichnen lassen
  \foreach \anchor/\placement in
    {{north 1/3}/above,{north 2/3}/above,{south 1/3}/below,{south 2/3}/below,
      {east 1/3}/right,{east 2/3}/right,{west 1/3}/left,{west 2/3}/left}
    \draw[shift=(s.\anchor),red] plot[mark=x] coordinates{(0,0)}
      node[\placement,font=\scriptsize\bfseries] {\texttt{(s.\anchor)}};
\end{tikzpicture}
\end{document}

Damit kann man dann zum Beispiel folgendes machen (Beispiel aus der Frage auf golatex.de):

Open in writeLaTeX
\begin{tikzpicture}[text width=3em] 
  \node[draw,myrectangle] (test1) {test1\\test1\\test1\\test1}; 
  \draw (test1.east 2/3) -|++(1,1){}; 
  \draw(test1.east 1/3)--
    +(2,0)node[draw,myrectangle,anchor=west 2/3](test2){test2\\test2\\test2}; 
  \draw(test2.west 1/3)-|+(-1,-1); 
\end{tikzpicture}

und erhält

alt text

Permanenter link

beantwortet 26 Jun '14, 00:34

esdd's gravatar image

esdd
17.7k254256
Akzeptiert-Rate: 62%

bearbeitet 26 Jun '14, 00:59

Sehr schön! Ich fand noch Martins Ansatz, der wohl mit TikZ 3 laut einem Kommentar nicht mehr so gehen sollte.

(26 Jun '14, 00:54) stefan ♦♦

@Stefan Das sieht interessant aus und wäre besser. Muss man halt mal testen.

(26 Jun '14, 01:11) esdd
Deine Antwort
Vorschau umschalten

Folgen dieser Frage

Per E-Mail:

Wenn sie sich anmelden, kommen Sie für alle Updates hier in Frage

Per RSS:

Antworten

Antworten und Kommentare

Markdown-Grundlagen

  • *kursiv* oder _kursiv_
  • **Fett** oder __Fett__
  • Link:[Text](http://url.com/ "Titel")
  • Bild?![alt Text](/path/img.jpg "Titel")
  • nummerierte Liste: 1. Foo 2. Bar
  • zum Hinzufügen ein Zeilenumbruchs fügen Sie einfach zwei Leerzeichen an die Stelle an der die neue Linie sein soll.
  • grundlegende HTML-Tags werden ebenfalls unterstützt

Frage-Themen:

×728
×117
×76
×12

gestellte Frage: 26 Jun '14, 00:06

Frage wurde gesehen: 12,169 Mal

zuletzt geändert: 26 Jun '14, 01:11