Ich würde gern solche shapes bzw. Formen zeichnen, Rechtecke mit abgerundeten Ecken, aber auch invers abgerundet:

Beispielgrafik

Ein echter Node mit Ankern wäre natürlich gut, um solche Teile zusammenzusetzen, wie im Bild Metabolism Pathways auf Wikipedia. Wie kann man sowas machen?

Grafik

Mein Ansatz, basierend auf meinen vorangehenden Fragen und erhaltenen Antworten, ist erstmal ein Rechteck-Knoten mit abgerundeten Ecken, darin ein Bild mit multipart-Node:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\begin{document}
  \begin{tikzpicture}
    \node[fill=yellow!96!black,rectangle, rounded corners=4ex,
      align=center,inner sep=4ex,font=\sffamily] {
        \begin{tikzpicture}
          \node[draw, very thick, shape=rectangle split, rectangle split parts=2,
            inner sep=1ex, rounded corners=0pt, fill=white,
            font=\vphantom{Q}\sffamily] (A) {Glucosamina \nodepart{two} Quitina};
    \end{tikzpicture}};
  \end{tikzpicture}
\end{document}

gefragt 05 Aug '13, 19:34

Felix's gravatar image

Felix
1.3k525667
Akzeptiert-Rate: 47%

bearbeitet 21 Aug '13, 19:47

stefan's gravatar image

stefan ♦♦
18.3k163148

Puh, gute Frage. Ich würde hier vermutlich weder verschachtelte TikZ-Pictures noch abgerundete Shapes dafür verwenden, sondern einfache Pfade, die ein paar wenige, aber wohl definierte insert path-Keys verwendet. Shapes und Anchors werden sehr komplex und spätestens bei dem pinken Feld oben rechts hört der Spaß auf.

(05 Aug '13, 20:03) Qrrbrbirlbel

@Qrr Ist nicht ein Rechteck-Shape denkbar mit umgedrehter Ecke? Auch wenn man das Gesamtbild vielleicht anders ansetzen würde? Das pinke Feld wird einfach überlagert, es hat auch Rechteck-Kreisecken-Gestalt.

(05 Aug '13, 20:30) Felix

Fangen wir mal mit was an.

Der Code definiert ein Shape mit dem Namen rectangle with rounded corners. Dazu nötig sind außerdem die Keys

  • rectangle with rounded corners mode sowie
  • rectangle with rounded corners radius.

Beim Modus werden unterschieden:

  • none: keine Abrundung erfolgt.
  • inside: eine klassische Abrundung wie mit der Option rounded corners erfolgt.
  • outside: wie inside nur mit negativem Radius (ob das ein Feature von TikZ is, ist mir nicht bekannt, es kann also sein, dass das irgendwann nicht mehr geht).
  • vertical: es entsteht ein Zipfel in vertikaler Richtung.
  • horizontal: es entsteht ein Zipfel in horizontaler Richtung

Werden weniger als vier Einträge angegeben wird der letzte für alle folgende wiederholt. Der erste Eintrag gilt für die Nordost-Ecke, die anderen Ecken folgen gegen den Uhrzeigersinn (mathematisch positiv wie sonst auch in TikZ/PGF). Es kann auch nur der erste Buchstabe (n, i, o, v, h) angegeben werden, wobei alles andere als i, o, h oder v als n behandelt wird.

Der radius-Key funktioniert im Prinzip genauso. Er wird ignoriert, falls die Ecke im Modus none gezeichnet werden soll. Der outside-Modus funktioniert wie der inside-Modus nur mit negativem Radius. Achtung: Das aktualisiert nicht die Bounding Box (wie das Beispiel unten auch zeigt, da das Low-Level \pgfsetcornersarced verwendet wird (rounded corners in TikZ)).

Es fehlen dem Shape noch jegliche Anchors, die mit den abgerundeten Ecken zu tun haben, man kann also keine Koordinaten an den Enden der Bögen auswählen (das ist relativ einfach nachzuarbeiten). Genauso funktionieren die angulären Anchors nicht (die sogenannte Anchor-Border), das ist auch nicht so einfach nachzuarbeiten, da wie es mit Viertelkreisen zu tun haben. Vermutlich müsste man die intersections-Library dazu verwenden.

Achtung, es erfolgt keine Kontrolle auf Sinnhaftigkeit der Radien, sie sollten kleiner gewählt werden als die Hälfte der Breite und die Hälfte der Höhe des Nodes!

Code

\documentclass[tikz,convert=false]{standalone}
\makeatletter
\pgfset{
  rectangle with rounded corners radius/.initial=4pt,
  rectangle with rounded corners mode/.initial={i}
}
\def\pgf@lib@sh@rwrc@options@#1#2#3#4#5#6#7{%
  \edef\pgf@lib@sh@rwrc@options@R{\csname rwrcpR#1\endcsname}%
  \edef\pgf@lib@sh@rwrc@options@M{\csname rwrcpM#1\endcsname}%
  \def\pgf@lib@sh@rwrc@options@A{\pgfpointadd{\csname pgf@anchor@rectangle with rounded corners@#2\endcsname}{\pgfpoint{#4\outerxsep}{#5\outerysep}}}%
  \def\pgf@lib@sh@rwrc@options@B{\pgfpointadd{\csname pgf@anchor@rectangle with rounded corners@#3\endcsname}{\pgfpoint{#6\outerxsep}{#7\outerysep}}}%
}
\def\pgf@lib@sh@rwrc@options#1{%
  \expandafter\pgf@lib@sh@rwrc@options@
  \ifcase#1??????\or{ne}{north east}{north}--{0*}-\or
           {nw}{north west}{west}+-+{0*}\or
           {sw}{south west}{south}++{0*}+\or
           {se}{south east}{east}-+-{0*}\or
           ??????\fi}

\def\pgfutil@firstofmany#1#2\pgf@stop{#1}

\def\pgf@lib@sh@rwrc@r#1,#2,#3,#4,#5\pgf@stop{%
  \pgfmathsetlengthmacro\rwrcpRne{#1}%
  \edef\pgf@temp{#2}%
  \ifx\pgf@temp\pgfutil@empty
    \let\rwrcpRnw\rwrcpRne
  \else
    \pgfmathsetlengthmacro\rwrcpRnw{#2}%
  \fi
  \edef\pgf@temp{#3}%
  \ifx\pgf@temp\pgfutil@empty
    \let\rwrcpRsw\rwrcpRnw
  \else
    \pgfmathsetlengthmacro\rwrcpRsw{#3}%
  \fi
  \edef\pgf@temp{#4}%
  \ifx\pgf@temp\pgfutil@empty
    \let\rwrcpRse\rwrcpRsw
  \else
    \pgfmathsetlengthmacro\rwrcpRse{#4}%
  \fi
}
\def\pgf@lib@sh@rwrc@m#1,#2,#3,#4,#5\pgf@stop{%
  \edef\rwrcpMne{#1}%
  \edef\pgf@temp{#2}%
  \ifx\pgf@temp\pgfutil@empty
    \let\rwrcpMnw\rwrcpMne
  \else
    \let\rwrcpMnw\pgf@temp
  \fi
  \edef\pgf@temp{#3}%
  \ifx\pgf@temp\pgfutil@empty
    \let\rwrcpMsw\rwrcpMnw
  \else
    \let\rwrcpMsw\pgf@temp
  \fi
  \edef\pgf@temp{#4}%
  \ifx\pgf@temp\pgfutil@empty
    \let\rwrcpMse\rwrcpMsw
  \else
    \let\rwrcpMse\pgf@temp%
  \fi
}
\pgfdeclareshape{rectangle with rounded corners}{%
  \savedmacro\rectangleWithRoundedCornersParameters{
    \pgfkeysgetvalue{/pgf/rectangle with rounded corners radius}\pgf@temp
    \expandafter\pgf@lib@sh@rwrc@r\pgf@temp,,,,\pgf@stop
    \pgfkeysgetvalue{/pgf/rectangle with rounded corners mode}\pgf@temp
    \expandafter\pgf@lib@sh@rwrc@m\pgf@temp,,,,\pgf@stop
    %
    \addtosavedmacro\rwrcpRne
    \addtosavedmacro\rwrcpRnw
    \addtosavedmacro\rwrcpRsw
    \addtosavedmacro\rwrcpRse
    \addtosavedmacro\rwrcpMne
    \addtosavedmacro\rwrcpMnw
    \addtosavedmacro\rwrcpMsw
    \addtosavedmacro\rwrcpMse
    %
    \pgfutil@tempdima.5\pgflinewidth
    \edef\halflinewidth{\the\pgfutil@tempdima}%
    \addtosavedmacro\halflinewidth
    %
    \pgf@x=\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner xsep}}%
    \advance\pgf@x by 2\pgf@xc%
    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/minimum width}}%
    \ifdim\pgf@x>\pgf@xb%
      \pgf@xb=\pgf@x%
    \fi%
    %
    \pgf@y=\ht\pgfnodeparttextbox%
    \advance\pgf@y by\dp\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/inner ysep}}%
    \advance\pgf@y by 2\pgf@yc%
    \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/minimum height}}%
    \ifdim\pgf@y>\pgf@yb%
    \pgf@yb=\pgf@y%
    \fi%
    %
    \pgfextract@process\northeast{%
      \pgf@y\pgf@yb
      \pgf@x\pgf@xb
      %
      \pgf@x=.5\pgf@x%
      \advance\pgf@x by.5\wd\pgfnodeparttextbox%
      \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/outer xsep}}%
      \advance\pgf@x by\pgf@xa%
      %
      \pgf@y=.5\pgf@y%
      \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
      \advance\pgf@y by.5\ht\pgfnodeparttextbox%
      \pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/outer ysep}}%
      \advance\pgf@y by\pgf@ya%
    }
    \addtosavedmacro\northeast
    %
    \pgfextract@process\southwest{%
      \pgf@y\pgf@yb
      \pgf@x\pgf@xb
      %
      \pgf@x=-.5\pgf@x%
      \advance\pgf@x by.5\wd\pgfnodeparttextbox%
      \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/outer xsep}}%
      \advance\pgf@x by-\pgf@xa%
      %
      \pgf@y=-.5\pgf@y%
      \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
      \advance\pgf@y by.5\ht\pgfnodeparttextbox%
      \pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/outer ysep}}%
      \advance\pgf@y by-\pgf@ya%
    }
    \addtosavedmacro\southwest
  }
  \anchor{center}{
    \rectangleWithRoundedCornersParameters
    \pgf@process{\northeast}%
    \pgf@xa=.5\pgf@x%
    \pgf@ya=.5\pgf@y%
    \pgf@process{\southwest}%
    \pgf@x=.5\pgf@x%
    \pgf@y=.5\pgf@y%
    \advance\pgf@x by \pgf@xa%
    \advance\pgf@y by \pgf@ya%
  }
  \anchor{mid}{\csname pgf@anchor@rectangle with rounded corners@center\endcsname\pgfmathsetlength\pgf@y{.5ex}}
  \anchor{base}{\csname pgf@anchor@rectangle with rounded corners@center\endcsname\pgf@y=0pt}
  \anchor{north}{
    \rectangleWithRoundedCornersParameters
    \pgf@process{\southwest}%
    \pgf@xa=.5\pgf@x%
    \pgf@process{\northeast}%
    \pgf@x=.5\pgf@x%
    \advance\pgf@x by \pgf@xa%
  }
  \anchor{south}{
    \rectangleWithRoundedCornersParameters
    \pgf@process{\northeast}%
    \pgf@xa=.5\pgf@x%
    \pgf@process{\southwest}%
    \pgf@x=.5\pgf@x%
    \advance\pgf@x by \pgf@xa%
  }
  \anchor{west}{
    \rectangleWithRoundedCornersParameters
    \pgf@process{\northeast}%
    \pgf@ya=.5\pgf@y%
    \pgf@process{\southwest}%
    \pgf@y=.5\pgf@y%
    \advance\pgf@y by \pgf@ya%
  }
  \anchor{mid west}{\rectangleWithRoundedCornersParameters\southwest\pgfmathsetlength\pgf@y{.5ex}}
  \anchor{base west}{\rectangleWithRoundedCornersParameters\southwest\pgf@y=0pt}
  \anchor{north west}{
    \rectangleWithRoundedCornersParameters
    \southwest
    \pgf@xa=\pgf@x
    \northeast
    \pgf@x=\pgf@xa}
  \anchor{south west}{\rectangleWithRoundedCornersParameters\southwest}
  \anchor{east}{%
    \rectangleWithRoundedCornersParameters
    \pgf@process{\southwest}%
    \pgf@ya=.5\pgf@y%
    \pgf@process{\northeast}%
    \pgf@y=.5\pgf@y%
    \advance\pgf@y by \pgf@ya%
  }
  \anchor{mid east}{\rectangleWithRoundedCornersParameters\northeast\pgfmathsetlength\pgf@y{.5ex}}
  \anchor{base east}{\rectangleWithRoundedCornersParameters\northeast\pgf@y=0pt}
  \anchor{north east}{\rectangleWithRoundedCornersParameters\northeast}
  \anchor{south east}{
    \rectangleWithRoundedCornersParameters
    \northeast
    \pgf@xa=\pgf@x
    \southwest
    \pgf@x=\pgf@xa
  }
  \backgroundpath{%
    \rectangleWithRoundedCornersParameters
    \pgfmathsetlengthmacro\outerxsep{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlengthmacro\outerysep{\pgfkeysvalueof{/pgf/outer ysep}}%
    \pgfpathmoveto{\pgfpointadd{\csname pgf@anchor@rectangle with rounded corners@east\endcsname}{\pgfqpoint{-\outerxsep}{0pt}}}%
    \pgfmathloop
      \ifnum\pgfmathcounter>4\relax
        \pgfpathclose
      \else
        \pgf@lib@sh@rwrc@options\pgfmathcounter%
        \pgfsetcornersarced{\pgfqpoint{\pgf@lib@sh@rwrc@options@R}{\pgf@lib@sh@rwrc@options@R}}%
        \if o\pgf@lib@sh@rwrc@options@M
          \pgfsetcornersarced{\pgfqpoint{-\pgf@lib@sh@rwrc@options@R}{-\pgf@lib@sh@rwrc@options@R}}%
          \edef\pgf@lib@sh@rwrc@options@R{-\pgf@lib@sh@rwrc@options@R}%
          \def\pgf@lib@sh@rwrc@options@M{i}%
        \fi % 
        \if i\pgf@lib@sh@rwrc@options@M
          \pgfpathlineto{\pgf@lib@sh@rwrc@options@A}%
        \else\if h\pgf@lib@sh@rwrc@options@M
            \ifcase\pgfmathcounter
            \or % ne
              \pgfpathlineto{\pgf@lib@sh@rwrc@options@A}%
              \pgfpathlineto{\pgfpointadd{\pgf@lib@sh@rwrc@options@A}{\pgfqpoint{\pgf@lib@sh@rwrc@options@R}{0pt}}}
            \or % nw
              \pgfpathlineto{\pgfpointadd{\pgf@lib@sh@rwrc@options@A}{\pgfqpoint{-\pgf@lib@sh@rwrc@options@R}{0pt}}}
              \pgfpathlineto{\pgf@lib@sh@rwrc@options@A}%
            \or % sw
              \pgfpathlineto{\pgf@lib@sh@rwrc@options@A}%
              \pgfpathlineto{\pgfpointadd{\pgf@lib@sh@rwrc@options@A}{\pgfqpoint{-\pgf@lib@sh@rwrc@options@R}{0pt}}}
            \or % se
              \pgfpathlineto{\pgfpointadd{\pgf@lib@sh@rwrc@options@A}{\pgfqpoint{\pgf@lib@sh@rwrc@options@R}{0pt}}}
              \pgfpathlineto{\pgf@lib@sh@rwrc@options@A}%
            \fi
          \else\if v\pgf@lib@sh@rwrc@options@M
              \ifcase\pgfmathcounter
              \or % ne
                \pgfpathlineto{\pgfpointadd{\pgf@lib@sh@rwrc@options@A}{\pgfqpoint{0pt}{\pgf@lib@sh@rwrc@options@R}}}
                \pgfpathlineto{\pgf@lib@sh@rwrc@options@A}%
              \or % nw
                \pgfpathlineto{\pgf@lib@sh@rwrc@options@A}%
                \pgfpathlineto{\pgfpointadd{\pgf@lib@sh@rwrc@options@A}{\pgfqpoint{0pt}{\pgf@lib@sh@rwrc@options@R}}}
              \or % sw
                \pgfpathlineto{\pgfpointadd{\pgf@lib@sh@rwrc@options@A}{\pgfqpoint{0pt}{-\pgf@lib@sh@rwrc@options@R}}}
                \pgfpathlineto{\pgf@lib@sh@rwrc@options@A}%
              \or % se
                \pgfpathlineto{\pgf@lib@sh@rwrc@options@A}%
                \pgfpathlineto{\pgfpointadd{\pgf@lib@sh@rwrc@options@A}{\pgfqpoint{0pt}{-\pgf@lib@sh@rwrc@options@R}}}
              \fi
            \else
              \pgfsetcornersarced{\pgfpointorigin}%
              \pgfpathlineto{\pgf@lib@sh@rwrc@options@A}%
            \fi
          \fi
        \fi
        %
        \pgfpathlineto{\pgf@lib@sh@rwrc@options@B}%
    \repeatpgfmathloop
  }
}
\begingroup
  \expandafter\def\expandafter\pgf@temp\expandafter{\expandafter\gdef\csname pgf@anchor@rectangle with rounded corners@border\endcsname##1}
  \expandafter\pgf@temp\expandafter{\expandafter\rectangleWithRoundedCornersParameters\pgf@anchor@rectangle@border{#1}}
\endgroup
\makeatother
\tikzset{
  shape example/.style={
    color=black!30,
    draw,
    fill=yellow!30,
    line width=.1cm,
    inner xsep=2.5cm,
    inner ysep=0.5cm}
}
\begin{document}
\begin{tikzpicture}[
  rectangle with rounded corners mode={o,i,h,v},
  rectangle with rounded corners radius={40pt,10pt,20pt,30pt}
  ]\Huge
  \node[shape example,rectangle with rounded corners,name=s]{Rectangle\vrule width 1pt height 2cm};
  \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, 10/right, 130/above%
                                 }
  \draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} node[\placement] {\scriptsize\texttt{(s.\anchor)}};
\end{tikzpicture}
\end{document}

Output

alt text

Permanenter link

beantwortet 06 Aug '13, 01:48

Qrrbrbirlbel's gravatar image

Qrrbrbirlbel
2.9k3815
Akzeptiert-Rate: 53%

bearbeitet 06 Aug '13, 20:18

Wow, sehr cool! Funktioniert prima und die Verwendung ist sehr gut erklärt! 200+ :-)

(06 Aug '13, 08:59) Felix

@Felix Ich habe den Backgroundpfad nochmal aktualisiert. Er verwendet jetzt PGF’s Low-Level \pgfsetcornersarced, das vermutlich etwas effektiver/schneller ist als alle arcs. Das hat einen Nachteil, ich habe für den outside-Modus keine extra Positionierung eingebaut, das heißt er aktualisiert die Bounding Box nicht (mehr). Allerdings bezweifle ich, dass der outside-Modus überhaupt benutzt wird. ;)

(06 Aug '13, 20:20) Qrrbrbirlbel
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:

×731
×76
×12

gestellte Frage: 05 Aug '13, 19:34

Frage wurde gesehen: 27,315 Mal

zuletzt geändert: 21 Aug '13, 19:47