在 tikz 图中标记面和边

在 tikz 图中标记面和边

是否可以在不指定我们想要标签的位置的其他不可见节点的情况下标记图形的面/边?我目前正在使用的代码复制如下:

\documentclass{standalone}
\usepackage{tikz}
\NeedsTeXFormat{LaTeX2e}[1999/01/01]
\ProvidesPackage{freetikz}
\RequirePackage{tikz}

\pgfdeclarelayer{edgelayer}
\pgfdeclarelayer{nodelayer}
\pgfdeclarelayer{foreground}
\pgfdeclarelayer{background}
\pgfsetlayers{background,edgelayer,nodelayer,main,foreground,background}

\def\thickness{0.7pt}

\tikzstyle{dot}=[circle, draw=black, fill=black!25, inner sep=.4ex, line width=\thickness, node on layer=foreground]
\tikzstyle{blackdot}=[dot, fill=black!50]
\tikzstyle{blackdot}=[dot, fill=gray!40!white]
\tikzstyle{whitedot}=[dot, fill=white]
\tikzstyle{reddot}=[dot, fill=red]
\tikzstyle{greendot}=[dot, fill=green]

\makeatletter
\pgfkeys{%
  /tikz/on layer/.code={
    \pgfonlayer{#1}\begingroup
    \aftergroup\endpgfonlayer
    \aftergroup\endgroup
  },
  /tikz/node on layer/.code={
    \gdef\node@@on@layer{%
  \setbox\tikz@tempbox=\hbox\bgroup\pgfonlayer{#1}\unhbox\tikz@tempbox\endpgfonlayer\egroup}
\aftergroup\node@on@layer
  },
  /tikz/end node on layer/.code={
    \endpgfonlayer\endgroup\endgroup
  }
}
\def\node@on@layer{\aftergroup\node@@on@layer}
\makeatother

% Lengths
\newlength\morphismheight
\setlength\morphismheight{0.6cm}
\newlength\minimummorphismwidth
\setlength\minimummorphismwidth{0.6cm}
\newlength\stateheight
\setlength\stateheight{0.6cm}
\newlength\minimumstatewidth
\setlength\minimumstatewidth{0.89cm}
\newlength\connectheight
\setlength\connectheight{0.5cm}
\tikzset{width/.initial=\minimummorphismwidth}

% Keys
\newif\ifwedge\pgfkeys{/tikz/wedge/.is if=wedge}
\tikzset{wedge}
\newif\ifvflip\pgfkeys{/tikz/vflip/.is if=vflip}
\newif\ifhflip\pgfkeys{/tikz/hflip/.is if=hflip}
\newif\ifhvflip\pgfkeys{/tikz/hvflip/.is if=hvflip}
\newif\ifconnectnw\pgfkeys{/tikz/connect nw/.is if=connectnw}
\newif\ifconnectne\pgfkeys{/tikz/connect ne/.is if=connectne}
\newif\ifconnectsw\pgfkeys{/tikz/connect sw/.is if=connectsw}
\newif\ifconnectse\pgfkeys{/tikz/connect se/.is if=connectse}
\newif\ifconnectn\pgfkeys{/tikz/connect n/.is if=connectn}
\newif\ifconnects\pgfkeys{/tikz/connect s/.is if=connects}
\newif\ifconnectnwf\pgfkeys{/tikz/connect nw >/.is if=connectnwf}
\newif\ifconnectnef\pgfkeys{/tikz/connect ne >/.is if=connectnef}
\newif\ifconnectswf\pgfkeys{/tikz/connect sw >/.is if=connectswf}
\newif\ifconnectsef\pgfkeys{/tikz/connect se >/.is if=connectsef}
\newif\ifconnectnf\pgfkeys{/tikz/connect n >/.is if=connectnf}
\newif\ifconnectsf\pgfkeys{/tikz/connect s >/.is if=connectsf}
\newif\ifconnectnwr\pgfkeys{/tikz/connect nw </.is if=connectnwr}
\newif\ifconnectner\pgfkeys{/tikz/connect ne </.is if=connectner}
\newif\ifconnectswr\pgfkeys{/tikz/connect sw </.is if=connectswr}
\newif\ifconnectser\pgfkeys{/tikz/connect se </.is if=connectser}
\newif\ifconnectnr\pgfkeys{/tikz/connect n </.is if=connectnr}
\newif\ifconnectsr\pgfkeys{/tikz/connect s </.is if=connectsr}
\tikzset{keylengthnw/.initial=\connectheight}
\tikzset{keylengthn/.initial =\connectheight}
\tikzset{keylengthne/.initial=\connectheight}
\tikzset{keylengthsw/.initial=\connectheight}
\tikzset{keylengths/.initial =\connectheight}
\tikzset{keylengthse/.initial=\connectheight}
\tikzset{connect nw length/.style={connect nw=true, keylengthnw={#1}}}
\tikzset{connect n length/.style ={connect n =true, keylengthn ={#1}}}
\tikzset{connect ne length/.style={connect ne=true, keylengthne={#1}}}
\tikzset{connect sw length/.style={connect sw=true, keylengthsw={#1}}}
\tikzset{connect s length/.style ={connect s =true, keylengths ={#1}}}
\tikzset{connect se length/.style={connect se=true, keylengthse={#1}}}
\tikzset{connect nw < length/.style={connect nw <=true, keylengthnw={#1}}}
\tikzset{connect n < length/.style ={connect n <=true,  keylengthn ={#1}}}
\tikzset{connect ne < length/.style={connect ne <=true, keylengthne={#1}}}
\tikzset{connect sw < length/.style={connect sw <=true, keylengthnw={#1}}}
\tikzset{connect s < length/.style ={connect s <=true,  keylengths ={#1}}}
\tikzset{connect se < length/.style={connect se <=true, keylengthse={#1}}}
\tikzset{connect nw > length/.style={connect nw >=true, keylengthnw={#1}}}
\tikzset{connect n > length/.style ={connect n >=true,  keylengthn ={#1}}}
\tikzset{connect ne > length/.style={connect ne >=true, keylengthne={#1}}}
\tikzset{connect sw > length/.style={connect sw >=true, keylengthsw={#1}}}
\tikzset{connect s > length/.style ={connect s >=true,  keylengths ={#1}}}
\tikzset{connect se > length/.style={connect se >=true, keylengthse={#1}}}

% Shapes
\makeatletter
\pgfdeclareshape{morphism}
{
    \savedanchor\centerpoint
    {
        \pgf@x=0pt
        \pgf@y=0pt
    }
    \anchor{center}{\centerpoint}
    \anchorborder{\centerpoint}
    \saveddimen\savedlengthnw
    {
        \pgfkeysgetvalue{/tikz/keylengthnw}{\len}
        \pgf@x=\len
    }
    \saveddimen\savedlengthn
    {
        \pgfkeysgetvalue{/tikz/keylengthn}{\len}
        \pgf@x=\len
    }
    \saveddimen\savedlengthne
    {
        \pgfkeysgetvalue{/tikz/keylengthne}{\len}
        \pgf@x=\len
    }
    \saveddimen\savedlengthsw
    {
        \pgfkeysgetvalue{/tikz/keylengthsw}{\len}
        \pgf@x=\len
    }
    \saveddimen\savedlengths
    {
        \pgfkeysgetvalue{/tikz/keylengths}{\len}
        \pgf@x=\len
    }
    \saveddimen\savedlengthse
    {
        \pgfkeysgetvalue{/tikz/keylengthse}{\len}
        \pgf@x=\len
    }
    \saveddimen\overallwidth
    {
        \pgfkeysgetvalue{/tikz/width}{\minwidth}
        \pgf@x=\wd\pgfnodeparttextbox
        \ifdim\pgf@x<\minwidth
            \pgf@x=\minwidth
        \fi
    }
    \savedanchor{\upperrightcorner}
    {
        \pgf@y=.5\ht\pgfnodeparttextbox
        \advance\pgf@y by -.5\dp\pgfnodeparttextbox
        \pgf@x=.5\wd\pgfnodeparttextbox
    }
    \anchor{north}
    {
        \pgf@x=0pt
        \pgf@y=0.5\morphismheight
    }
    \anchor{north east}
    {
        \pgf@x=\overallwidth
        \multiply \pgf@x by 2
        \divide \pgf@x by 5
        \pgf@y=0.5\morphismheight
    }
    \anchor{east}
    {
        \pgf@x=\overallwidth
        \divide \pgf@x by 2
        \advance \pgf@x by 5pt
        \pgf@y=0pt
    }
    \anchor{west}
    {
        \pgf@x=-\overallwidth
        \divide \pgf@x by 2
        \advance \pgf@x by -5pt
        \pgf@y=0pt
    }
    \anchor{north west}
    {
        \pgf@x=-\overallwidth
        \multiply \pgf@x by 2
        \divide \pgf@x by 5
        \pgf@y=0.5\morphismheight
    }
    \anchor{connect nw}
    {
        \pgf@x=-\overallwidth
        \multiply \pgf@x by 2
        \divide \pgf@x by 5
        \pgf@y=0.5\morphismheight
        \advance\pgf@y by \savedlengthnw
    }
    \anchor{connect ne}
    {
        \pgf@x=\overallwidth
        \multiply \pgf@x by 2
        \divide \pgf@x by 5
        \pgf@y=0.5\morphismheight
        \advance\pgf@y by \savedlengthne
    }
    \anchor{connect sw}
    {
        \pgf@x=-\overallwidth
        \multiply \pgf@x by 2
        \divide \pgf@x by 5
        \pgf@y=-0.5\morphismheight
        \advance\pgf@y by -\savedlengthsw
    }
    \anchor{connect se}
    {
        \pgf@x=\overallwidth
        \multiply \pgf@x by 2
        \divide \pgf@x by 5
        \pgf@y=-0.5\morphismheight
        \advance\pgf@y by -\savedlengthse
    }
    \anchor{connect n}
    {
        \pgf@x=0pt
        \pgf@y=0.5\morphismheight
        \advance\pgf@y by \savedlengthn
    }
    \anchor{connect s}
    {
        \pgf@x=0pt
        \pgf@y=-0.5\morphismheight
        \advance\pgf@y by -\savedlengths
    }
    \anchor{south east}
    {
        \pgf@x=\overallwidth
        \multiply \pgf@x by 2
        \divide \pgf@x by 5
        \pgf@y=-0.5\morphismheight
    }
    \anchor{south west}
    {
        \pgf@x=-\overallwidth
        \multiply \pgf@x by 2
        \divide \pgf@x by 5
        \pgf@y=-0.5\morphismheight
    }
    \anchor{south}
    {
        \pgf@x=0pt
        \pgf@y=-0.5\morphismheight
    }
    \anchor{text}
    {
        \upperrightcorner
        \pgf@x=-\pgf@x
        \pgf@y=-\pgf@y
    }
    \backgroundpath
    {
        \pgfsetstrokecolor{black}
        \pgfsetlinewidth{\thickness}
        \begin{scope}
                \ifhflip
                    \pgftransformyscale{-1}
                \fi
                \ifvflip
                    \pgftransformxscale{-1}
                \fi
                \ifhvflip
                    \pgftransformxscale{-1}
                    \pgftransformyscale{-1}
                \fi
                \pgfpathmoveto{\pgfpoint
                    {-0.5*\overallwidth-5pt}
                    {0.5*\morphismheight}}
                \pgfpathlineto{\pgfpoint
                    {0.5*\overallwidth+5pt}
                    {0.5*\morphismheight}}
                \ifwedge
                    \pgfpathlineto{\pgfpoint
                        {0.5*\overallwidth + 15pt}
                        {-0.5*\morphismheight}}
                \else
                    \pgfpathlineto{\pgfpoint
                        {0.5*\overallwidth + 5pt}
                        {-0.5*\morphismheight}}
                \fi
                \pgfpathlineto{\pgfpoint
                    {-0.5*\overallwidth-5pt}
                    {-0.5*\morphismheight}}
                \pgfpathclose
                \pgfusepath{stroke}
        \end{scope}
        \ifconnectnw
            \pgfpathmoveto{\pgfpoint
                {-0.4*\overallwidth}
                {0.5*\morphismheight}}
            \pgfpathlineto{\pgfpoint
                {-0.4*\overallwidth}
                {0.5*\morphismheight+\savedlengthnw}}
            \pgfusepath{stroke}
        \fi
        \ifconnectne
            \pgfpathmoveto{\pgfpoint
                {0.4*\overallwidth}
                {0.5*\morphismheight}}
            \pgfpathlineto{\pgfpoint
                {0.4*\overallwidth}
                {0.5*\morphismheight+\savedlengthne}}
            \pgfusepath{stroke}
        \fi
        \ifconnectsw
            \pgfpathmoveto{\pgfpoint
                {-0.4*\overallwidth}
                {-0.5*\morphismheight}}
            \pgfpathlineto{\pgfpoint
                {-0.4*\overallwidth}
                {-0.5*\morphismheight-\savedlengthsw}}
            \pgfusepath{stroke}
        \fi
        \ifconnectse
            \pgfpathmoveto{\pgfpoint
                {0.4*\overallwidth}
                {-0.5*\morphismheight}}
            \pgfpathlineto{\pgfpoint
                {0.4*\overallwidth}
                {-0.5*\morphismheight-\savedlengthse}}
            \pgfusepath{stroke}
        \fi
        \ifconnectn
            \pgfpathmoveto{\pgfpoint
                {0pt}
                {0.5*\morphismheight}}
            \pgfpathlineto{\pgfpoint
                {0pt}
                {0.5*\morphismheight+\savedlengthn}}
            \pgfusepath{stroke}
        \fi
        \ifconnects
            \pgfpathmoveto{\pgfpoint
                {0pt}
                {-0.5*\morphismheight}}
            \pgfpathlineto{\pgfpoint
                {0pt}
                {-0.5*\morphismheight-\savedlengths}}
            \pgfusepath{stroke}
        \fi
        \ifconnectnwf
            \draw [forward arrow style] (-0.4*\overallwidth,0.5*\morphismheight)
                to (-0.4*\overallwidth,0.5*\morphismheight+\savedlengthnw);
        \fi
        \ifconnectnef
            \draw [forward arrow style] (0.4*\overallwidth,0.5*\morphismheight)
                to (0.4*\overallwidth,0.5*\morphismheight+\savedlengthne);
        \fi
        \ifconnectswf
            \draw [forward arrow style] (-0.4*\overallwidth,-0.5*\morphismheight-\savedlengthsw)
                to (-0.4*\overallwidth,-0.5*\morphismheight);
        \fi
        \ifconnectsef
            \draw [forward arrow style] (0.4*\overallwidth,-0.5*\morphismheight-\savedlengthse)
                to (0.4*\overallwidth,-0.5*\morphismheight);
    \fi
    \ifconnectnf
        \draw [forward arrow style] (0,0.5*\morphismheight)
            to (0,0.5*\morphismheight+\savedlengthn);
    \fi
    \ifconnectsf
        \draw [forward arrow style] (0,-0.5*\morphismheight-\savedlengths)
            to (0,-0.5*\morphismheight);
    \fi
    \ifconnectnwr
        \draw [reverse arrow style] (-0.4*\overallwidth,0.5*\morphismheight)
            to (-0.4*\overallwidth,0.5*\morphismheight+\savedlengthnw);
    \fi
    \ifconnectner
        \draw [reverse arrow style] (0.4*\overallwidth,0.5*\morphismheight)
            to (0.4*\overallwidth,0.5*\morphismheight+\savedlengthne);
    \fi
    \ifconnectswr
        \draw [reverse arrow style] (-0.4*\overallwidth,-0.5*\morphismheight-\savedlengthsw)
            to (-0.4*\overallwidth,-0.5*\morphismheight);
    \fi
    \ifconnectser
        \draw [reverse arrow style] (0.4*\overallwidth,-0.5*\morphismheight-\savedlengthse)
            to (0.4*\overallwidth,-0.5*\morphismheight);
    \fi
    \ifconnectnr
        \draw [reverse arrow style] (0,0.5*\morphismheight)
            to (0,0.5*\morphismheight+\savedlengthn);
    \fi
    \ifconnectsr
        \draw [reverse arrow style] (0,-0.5*\morphismheight-\savedlengths)
            to (0,-0.5*\morphismheight);
    \fi
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
  \node [whitedot] (d0) at (4, 8) {$\alpha$};
  \node [whitedot] (d1) at (2, 4) {$\beta$};
  \node [whitedot] (d2) at (6, 4) {$\gamma$};
  \draw (0,.01) to[out=0, in=180] (8,.01);
  \draw (d0.center) to[out=180, in=-90] (0,12);
  \draw (d0.center) to[out=0, in=-90] (8, 12);
  \draw (d0.center) to[out=-90, in=0] (d1.center);
  \draw (d0.center) to[out=-90, in=180] (d2.center);
  \draw (d1.center) to[out=180, in=90] (0, 0);
  \draw (d1.center) to[out=0, in=90] (4,0);
  \draw (d2.center) to[out=180, in=90] (4, 0);
  \draw (d2.center) to[out=0, in=90] (8, 0);
\end{tikzpicture}
\end{document}

输出结果如下:

我希望能够用大写字母 AF 标记负空间,用小写字母 fm 标记边缘:

在此处输入图片描述

我可以想象只需创建 14 个额外的节点并根据需要标记它们,但我希望有一个现有的功能或可以轻松添加的功能来标记图表的“空白空间”和“边缘”,因为我将不得不制作许多像这样的图表(但平均而言更复杂)。任何帮助都值得感激。

答案1

这里有一个稍微简化的方法。让我们来看看。

包裹有意吗?

如果你不这样做,你不需要所有这些:

\documentclass{standalone}
\usepackage{tikz}
\NeedsTeXFormat{LaTeX2e}[1999/01/01]
\ProvidesPackage{freetikz}
\RequirePackage{tikz}

如果你这样做,你的代码应该有点不同,我不会在这里详细说明。

图层

... 这里其实不需要。通过改变路径的顺序,可以轻松解决未填充节点的问题。为此,首先定义一些坐标很有用。

所以流程是这样的:

  • 定义\coordinate
  • \draw边界和路径相关标签并记住\coordinate一些
  • “放上框架”
  • 贴标签
  • 标记区域
  • 定义并使用样式(重构

坐标

为了稍后能够将节点放置在这些位置,只需执行以下操作:

    % ~~~ coordinates ~~~~~~~~~~~~~~~~~
    \coordinate (d0) at (4, 8);
    \coordinate (d1) at (2, 4);
    \coordinate (d2) at (6, 4);

边界

事实证明,将多个动作组合在一起很有用,同时记住,\draw开始一条路径,;结束一条路径,并且其间的所有其他动作都沿着这条路径放置或执行。

这里最复杂的结构是

\draw (d0.center) to[out=180, in=-90] node[posi_1]{f} (0, 12) coordinate (D);

包含:

  • 绘画\draw (d0.center) to[out=180, in=-90] (0, 12);
  • \node使用某种样式预先放置node[posi_1]{f}(请注意缺失的\)
  • 在结束路径之前记住最终坐标(0, 12) coordinate (D);

框架”

只是为了完成图片:\draw (B) -- (C) -- (D) -- (A);

但是,您最好\draw (B) -- (C) -- (D) -- (A) - cylce;对封闭路径进行操作,并从代码的其他位置删除从底部的 (A) 到 (B) 绘制的线。

为 alpha 等放置填充节点。

现在就可以了,因为您在调用坐标时稍后才执行此操作:

    % ~~~ putting labels ~~~~~~~~~~~~~~~~~~~
    \node [whitedot] at (d0) {$\alpha$};
    \node [whitedot] at (d1) {$\beta$};
    \node [whitedot] at (d2) {$\gamma$};

标记区域

直接:

    % ~~~ regions ~~~~~~~~~~~~~~~~~~~~~~~~~~
    \node[reg] at (4  ,10  ) {A};
    \node[reg] at (1.5, 7  ) {B};
    \node[reg] at (6.5, 7  ) {C};
    \node[reg] at (4  , 4.3) {D};
    \node[reg] at (2  , 2  ) {E};
    \node[reg] at (6  , 2  ) {F};

样式

您可以将它们放在开头,如下所示:

\begin{tikzpicture}[                            % styles
    dot/.style={circle, 
                draw=black, fill=black!25,
                inner sep=.4ex, line width=0.7},
    whitedot/.style={dot, fill=white},
    %
    posi_1/.style={yshift= 3mm,pos=0.3 },       % for f and g
    posi_2/.style={xshift=-3mm,pos=0.35},       % for h, j and l
    posi_3/.style={xshift=+3mm,pos=0.35},       % for i, k and m
    reg/.style={font={\huge\bfseries}},         % for the regions
]

并且只在一个地方更改所有内容。例如,您可以通过 微调 a、b、... 沿其路径的相对位置pos=...

据我所知,在其他地方定义的厚度没有太大意义,因为它只影响您发布的代码中的圆圈。

顺便提一句

(d0.center)有点多余:

  • 如果是\node,则默认锚点位于节点中心
  • 如果它是一个\coordinate根据其定义它没有大小,即一个anchor=northanchor=center

因此(d0)等等在这里就足够了。


结果

\documentclass[10pt,border=3mm,tikz]{standalone}
    %\def\thickness{2.7pt}% not the best way to do it % useless

\begin{document}
\begin{tikzpicture}[                            % styles
    dot/.style={circle, 
                draw=black, fill=black!25,
                inner sep=.4ex, line width=0.7},
    whitedot/.style={dot, fill=white},
    %
    posi_1/.style={yshift= 3mm,pos=0.3 },       % for f and g
    posi_2/.style={xshift=-3mm,pos=0.35},       % for h, j and l
    posi_3/.style={xshift=+3mm,pos=0.35},       % for i, k and m
    reg/.style={font={\huge\bfseries}},         % for the regions
]
    % ~~~ coordinates ~~~~~~~~~~~~~~~~~
    \coordinate (d0) at (4, 8);
    \coordinate (d1) at (2, 4);
    \coordinate (d2) at (6, 4);
    
    % ~~~ drawing the boundaries AND path-related labels ~~~~~~
    \draw (0,.01)     to[out=  0, in=180]                 (8,.01);
    \draw (d0.center) to[out=180, in=-90] node[posi_1]{f} (0, 12) coordinate (D);
    \draw (d0.center) to[out=  0, in=-90] node[posi_1]{g} (8, 12) coordinate (C);
    \draw (d0.center) to[out=-90, in=  0] node[posi_2]{h} (d1.center);
    \draw (d0.center) to[out=-90, in=180] node[posi_3]{i} (d2.center);
    \draw (d1.center) to[out=180, in= 90] node[posi_2]{j} (0, 0) coordinate (A);
    \draw (d1.center) to[out=  0, in= 90] node[posi_3]{k} (4,0);
    \draw (d2.center) to[out=180, in= 90] node[posi_2]{l} (4, 0);
    \draw (d2.center) to[out=  0, in= 90] node[posi_3]{m} (8, 0) coordinate (B);
    % ~~~ "frame" ~~~
    \draw (B) -- (C) -- (D) -- (A);
    
    % ~~~ putting labels ~~~~~~~~~~~~~~~~~~~
    \node [whitedot] at (d0) {$\alpha$};
    \node [whitedot] at (d1) {$\beta$};
    \node [whitedot] at (d2) {$\gamma$};
    % ~~~ retions ~~~~~~~~~~~~~~~~~~~~~~~~~~
    \node[reg] at (4  ,10  ) {A};
    \node[reg] at (1.5, 7  ) {B};
    \node[reg] at (6.5, 7  ) {C};
    \node[reg] at (4  , 4.3) {D};
    \node[reg] at (2  , 2  ) {E};
    \node[reg] at (6  , 2  ) {F};
\end{tikzpicture}
\end{document}

相关内容