笔记:

笔记:

我有以下一段 TikZ 代码,我想知道它是否可以优化?(我确信它可以!)

主要问题是:当我旋转椭圆包围的第一批节点以创建第二批节点时,椭圆的位置不对。(它不在我希望的位置。我不确定旋转中哪个点是固定的。)我必须盲目地调整它以将其移动到所需的位置。

标签“社区 2”和“社区 3”也是如此。旋转后的坐标似乎与我的预期不符,我不得不盲目地调整它们,但效果有限。

无关的说明:我也尝试过 for 循环,但由于我想让每个社区的边缘略有不同,所以直接复制粘贴似乎更容易?

也欢迎其他优化。

代码

\documentclass[tikz]{standalone}

\begin{document}
\begin{tikzpicture}[scale = 1,node distance = 10mm]

\tikzset{
  every node/.append style={circle, thick,
    inner sep=0pt, minimum size = 3mm},
  every label/.append style={red},
  c1/.style={draw=blue!50,fill=blue!20},
  c2/.style={draw=green!80,fill=green!40},
  c3/.style={draw=red!80,fill=red!40}
}   

\filldraw[rotate=30,blue!10] (0.8,0.1) ellipse (30pt and 25pt);
\node at (1,1.7) {Community 1};
\node[c1] (1) at (0,0) {};
\node[c1] (2) at (1,1)  {}
edge (1);
\node[c1] (3) at (0.7,0.2) {}
edge (2)
edge (1);
\node[c1] (4) at (0.2,0.7) {}
edge (3)
edge (2);
\node[c1] (5) at (1.3,0.5) {}
edge (2)
edge (4);

\begin{scope}[yshift=-2cm,rotate around={-40:(0,0)}]
\filldraw[rotate=30,green!10] (0.8,0.1) ellipse (30pt and 25pt);
\node at (1.2,-0.2) {Community 2};
\node[c2] (A) at (0,0) {};
\node[c2] (B) at (1,1)  {}
edge (A);
\node[c2] (C) at (0.7,0.2) {}
edge (B)
edge (A);
\node[c2] (D) at (0.2,0.7) {}
edge (C)
edge (B);
\node[c2] (E) at (1.3,0.5) {}
edge (C)
edge (D);
\end{scope}

\begin{scope}[xshift=2cm,yshift=-0.5cm,rotate around={-40:(0,0)}]
\filldraw[rotate=30,red!10] (0.8,0.1) ellipse (30pt and 25pt);   
\node[c3] (a) at (0,0) {};
\node[c3] (b) at (1,1)  {}
edge (a);
\node[c3] (c) at (0.7,0.2) {}
edge (b)
edge (a);
\node[c3] (d) at (0.2,0.7) {}
edge (a)
edge (b);
\node[c3] (e) at (1.3,0.5) {}
edge (c)
edge (d);
\node[above of=b] {Community 3};
\end{scope}

\draw (3) -- (A);
\draw (4) -- (D);
\draw (5) -- (a);
\draw (c) -- (E);
\draw (e) -- (B);

\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

答案1

您应该为绘图定义一个宏,以便可以重复使用它:

在此处输入图片描述

笔记:

  • 由于我不知道绘图的目的以及您想如何仔细地选择位置和连接性,因此我根据给定的代码进行绘图。
  • 重复做某件事时要记住的一点是,每项任务都应以类似的方式考虑。例如,在放置节点文本时,两次使用绝对坐标,第三次使用相对位置。我决定选择绝对位置,但这可能并不理想。这当然使得第三个节点标签的位置有点像通过反复试验来猜测。请参阅Relative Placement of Labels下面的部分,这可能是更好的选择。
  • 节点被标记为A<color>,... D<color>(其中<color>是的第三个参数\MyNodes),以便可以系统地命名它们,然后在节点绘图之外根据需要引用它们。

代码:标签的固定位置

\documentclass[tikz, border=2pt]{standalone}

\begin{document}
\begin{tikzpicture}[scale = 1,node distance = 10mm]

\tikzset{
  every node/.append style={circle, thick,
    inner sep=0pt, minimum size = 3mm},
  every label/.append style={red},
  c1/.style={draw=blue!50,fill=blue!20},
  c2/.style={draw=green!80,fill=green!40},
  c3/.style={draw=red!80,fill=red!40}
} 

\newcommand*{\MyNodes}[6]{%
    % #1 = style
    % #2 = style
    % #3 = node name suffix.
    % #4 = node to connect to last node
    % #5 = label position
    % #6 = label text
    \filldraw[rotate=30,#1] (0.8,0.1) ellipse (30pt and 25pt);
    \node at #5 {#6};
    \node[#2] (A#3) at (0,0) {};
    \node[#2] (B#3) at (1,1)  {}
    edge (A#3);
    \node[#2] (C#3) at (0.7,0.2) {}
    edge (B#3)
    edge (A#3);
    \node[#2] (D#3) at (0.2,0.7) {}
    edge (C#3)
    edge (B#3);
    \node[#2] (E#3) at (1.3,0.5) {}
    edge (#4#3)
    edge (D#3);
}%  

\MyNodes{blue!10}{c1}{Blue}{B}{(1,1.7)}{Community 1}

\begin{scope}[yshift=-2cm,rotate around={-40:(0,0)}]
    \MyNodes{green!10}{c2}{Green}{C}{(1.2,-0.2)}{Community 2}
\end{scope}

\begin{scope}[xshift=2cm,yshift=-0.5cm,rotate around={-40:(0,0)}]
    \MyNodes{red!10}{c3}{Red}{C}{(0.5,1.75)}{Community 3}
\end{scope}

\draw (CBlue) -- (AGreen);
\draw (DBlue) -- (DGreen);
\draw (EBlue) -- (ARed);
\draw (CRed) -- (EGreen);
\draw (ERed) -- (BGreen);

\end{tikzpicture}
\end{document}

您还可以以相对方式放置节点标签,我认为这是更好的选择。要确定标签的放置位置,了解哪些标签位于何处会有所帮助,\Debug下面的宏可以让您看到这一点。如果您取消注释 MWE 中的后续行,节点标签将被抑制。

在此处输入图片描述

代码:标签的相对位置

\documentclass{article}
\usepackage{tikz}

\tikzset{%
  every node/.append style={circle, thick,
    inner sep=0pt, minimum size = 3mm},
  every label/.append style={red},
  c1/.style={draw=blue!50,fill=blue!20},
  c2/.style={draw=green!80,fill=green!40},
  c3/.style={draw=red!80,fill=red!40}
} 

\newcommand*{\Debug}[1]{\tiny#1}%
%\renewcommand*{\Debug}[1]{}% Comment this out for debugging

\newcommand*{\MyNodes}[6]{%
    % #1 = style
    % #2 = style
    % #3 = node name sufffix.
    % #4 = node to connect to last node
    % #5 = label position
    % #6 = label text
    \filldraw[rotate=30,#1] (0.8,0.1) ellipse (30pt and 25pt);
    \node[#2] (A#3) at (0,0) {\Debug{A}};
    \node[#2] (B#3) at (1,1)  {\Debug{B}}
    edge (A#3);
    \node[#2] (C#3) at (0.7,0.2) {\Debug{C}}
    edge (B#3)
    edge (A#3);
    \node[#2] (D#3) at (0.2,0.7) {\Debug{D}}
    edge (C#3)
    edge (B#3);
    \node[#2] (E#3) at (1.3,0.5) {\Debug{E}}
    edge (#4#3)
    edge (D#3);
    \node [#5#3] {#6};
}%  

\begin{document}
\begin{tikzpicture}[scale = 1,node distance = 10mm, thick]

\MyNodes{blue!10}{c1}{Blue}{B}{above of=D}{Community 1}

\begin{scope}[yshift=-2cm,rotate around={-40:(0,0)}]
    \MyNodes{green!10}{c2}{Green}{C}{below of=C}{Community 2} 
\end{scope}

\begin{scope}[xshift=2cm,yshift=-0.5cm,rotate around={-40:(0,0)}]
    \MyNodes{red!10}{c3}{Red}{C}{above of=B}{Community 3}
\end{scope}

\draw (CBlue) -- (AGreen);
\draw (DBlue) -- (DGreen);
\draw (EBlue) -- (ARed);
\draw (CRed)  -- (EGreen);
\draw (ERed)  -- (BGreen);

\end{tikzpicture}
\end{document}

答案2

再次尝试优化。这使用 PGF 键。

免责声明:结果并不完全相同,因为我使用了节点ellipse而不是路径ellipse(并且我不得不稍微调整坐标)。
我在这里看到的优势是使用选项label来添加“社区”标签。此外,您可以参考它以供以后使用。

有一个命令:

\drawBlob[<optional arguments](<coordinate>);

是局部坐标系的(<coordinate>)位置。 由于图片中有一些变换,所以我不完全确定斑点在哪里。请注意,如果没有旋转,第一个小斑点()将位于。(0,0)
A(<coordinate>)

您可以使用样式

  • every blob picture
  • every mini blob
  • every blob, 和
  • every mini blob edge

自定义内容。设置与every node样式类似。每种every <something>样式都存在一种<something>样式,将其元素附加到相应的every样式中。

此外,还有三个键:

  • connect mini blobs
  • blob name, 和
  • rotate blob

rotate blob键使整个图片(大斑点和小斑点)围绕大斑点的中心旋转。

密钥的值blob name将用于命名大 blob(以密钥命名)和小 blob(以位于和之间的<value of blob name>-<char>位置命名)。<char>AE

如果blob name没有给出(例如,如果未指定默认值,则为空),节点将获得一个内部名称(由于内部计数器,它们稍后仍可通过该名称引用)。
当节点稍后不会被引用时,计数器实际上并不是必需的……

最后,还有connect mini blobs。此键应给出一个应在 blob 内连接的 mini-blob 列表。
由于您的示例似乎暗示它们始终以相同的方式连接,因此我使用预设此样式

\tikzset{connect mini blobs={A/B,A/C,B/C,B/D,C/D,C/E,D/E}}

这体现了使用 PGF 键的优势。您可以设置默认值,可以在文档中更改它们,可以.append设置,并且可以为每个新 blob 设置不同的设置。

您还可以设置mini blob <char>样式,以进一步定制每个小斑点。

还有every minin blob edge,用于在小斑点之间内部绘制边缘线。

改进或者也许是fit图书馆?

注意绘制小斑点时有相似的线条吗?

一个改进是还可以自定义这些小块的数量和位置。只需几个键和一个\foreach就可以了。

然后,在库的帮助下,可以background使用 绘制椭圆fit(例如fit=(\qrr@blob@name-A)(\qrr@blob@name-B)…),但必须手动定义此椭圆的旋转,并且实际大小取决于rotate blob。同样,需要进行太多转换。

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{shapes.geometric}
\makeatletter
%% Setup
\tikzset{
    connect mini blobs/.store in=\qrr@blob@connections,
    connect mini blobs=,
    blob name/.store in=\qrr@blob@name,
    blob name=,
    rotate blob/.store in=\qrr@blob@rotate,
    rotate blob=0,
    % short-cut styles
    blob picture/.style={every blob picture/.append style={#1}},
    mini blob/.style={every mini blob/.append style={#1}},
    blob/.style={every blob/.append style={#1}},
    mini blob edge/.style={every mini blob edge/.append style=#1},
    % a few defaults
    every blob picture/.style={},
    every mini blob/.style={shape=circle, thick, draw, minimum size=3mm},
    every blob/.style={shape=ellipse, draw, fill, inner sep=0pt, minimum width=60pt, minimum height=50pt},
    every mini blob edge/.style={thick},
}

\newcount\c@qrr@blob@count
\newcommand*{\drawBlob}[1][]{\begingroup\tikzset{#1}\draw@blob}
\def\draw@blob(#1){%
    \ifx\qrr@blob@name\pgfutil@empty
        \edef\qrr@blob@name{qrr@mini-blob@\the\c@qrr@blob@count}%
    \fi
    \scope[absolute, every blob picture/.try]
        \node[shift={(#1)}, rotate=30+\qrr@blob@rotate, every blob/.try] (\qrr@blob@name) at (0.6,0.5) {};
        \node[every mini blob/.try, mini blob A/.try,  shift={(#1)}, ] (\qrr@blob@name-A) at ([rotate around={\qrr@blob@rotate:(0.6,0.5)}] 0,0)     {};
        \node[every mini blob/.try, mini blob B/.try,  shift={(#1)}, ] (\qrr@blob@name-B) at ([rotate around={\qrr@blob@rotate:(0.6,0.5)}] 1,1)     {};
        \node[every mini blob/.try, mini blob C/.try,  shift={(#1)}, ] (\qrr@blob@name-C) at ([rotate around={\qrr@blob@rotate:(0.6,0.5)}] 0.7,0.2) {};
        \node[every mini blob/.try, mini blob D/.try,  shift={(#1)}, ] (\qrr@blob@name-D) at ([rotate around={\qrr@blob@rotate:(0.6,0.5)}] 0.2,0.7) {};
        \node[every mini blob/.try, mini blob E/.try,  shift={(#1)}, ] (\qrr@blob@name-E) at ([rotate around={\qrr@blob@rotate:(0.6,0.5)}] 1.3,0.5) {};
        \foreach \qrr@blob@connection@start/\qrr@blob@connection@target in \qrr@blob@connections {
            \path[every mini blob edge/.try] (\qrr@blob@name-\qrr@blob@connection@start) edge (\qrr@blob@name-\qrr@blob@connection@target);}
    \endscope
    \endgroup
    \advance\c@qrr@blob@count\@ne
}
\makeatother

%%% Standard connections
\tikzset{connect mini blobs={A/B,A/C,B/C,B/D,C/D,C/E,D/E}} % that's always the same

%%% Custom styles
\tikzset{
  c1/.style={draw=blue!50,fill=blue!20},
  c2/.style={draw=green!80,fill=green!40},
  c3/.style={draw=red!80,fill=red!40}
}
\begin{document}
\begin{tikzpicture}
\drawBlob[
    mini blob=c1,
    blob={color=blue!10, label=above:Community 1},
    blob name=Comm1
    ](0,0)

\drawBlob[
    mini blob=c2,
    blob={color=green!10, label=below:Community 2},
    blob name=Comm2,
    rotate blob=-40
    ](0,-3)

\drawBlob[
    mini blob=c3,
    blob={color=red!10, label=above:Community 3},
    blob name=Comm3,
    rotate blob=-40
    ](2.5,-.5)

\foreach \start/\target in {1-C/2-A,1-D/2-D,1-E/3-A,3-C/2-E,3-E/2-B} \draw[every mini blob edge] (Comm\start) -- (Comm\target);
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

相关内容