
次の TikZ コードがあるのですが、これを最適化できるかどうか知りたいです。(実際、最適化できると確信しています!)
主な問題は、楕円で囲まれた最初のノード バッチを回転して 2 番目のバッチを作成すると、楕円の位置がずれてしまうことです。(予想していた場所ではありません。回転でどのポイントが固定されているのかわかりません。) 目的の場所に移動するには、盲目的に調整する必要があります。
「コミュニティ 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
図面を再利用できるように、図面のマクロを定義する必要があります。
ノート:
- 図面の意図や、配置と接続をどの程度慎重に選択したいかがわからないため、指定されたコードに基づいて作成しました。
- 繰り返し作業を行う際に留意すべき点は、各タスクを同様の方法で考える必要があるということです。たとえば、ノード テキストを配置する場合、絶対座標を 2 回使用し、3 回目に相対配置を使用します。私は絶対位置を選択することにしましたが、これは理想的ではないかもしれません。もちろん、3 番目のノード ラベルの配置は試行錯誤による推測に近くなります。
Relative Placement of Labels
より適切なオプションについては、以下のセクションを参照してください。 - ノードには、
A<color>
、...D<color>
(<color>
の 3 番目のパラメータ\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
。さらに、後で使用するために参照できます。
コマンドは 1 つあります。
\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
さらに、次の 3 つのキーがあります。
connect mini blobs
、blob name
、 そしてrotate blob
。
キーrotate blob
は、画像全体 (大きなブロブと小さなブロブ) を大きなブロブの中心を中心に回転します。
キーの値は、blob name
大きな BLOB (キーにちなんで命名) とミニ BLOB ( がから の間にある名前<value of blob name>-<char>
)に名前を付けるために使用されます。<char>
A
E
が指定されていない場合blob name
(たとえば、空の場合、デフォルトの名前が指定されていない場合)、ノードには内部名が付けられます (内部カウンターにより、後でノードを参照できます)。
ノードが後で参照されない場合は、カウンターは実際には必要ありません...
最後に、 がありますconnect mini blobs
。このキーには、ブロブ内で接続されるミニブロブのリストを与える必要があります。
あなたの例では、常に同じ方法で接続されていることを示唆しているように見えるので、このスタイルを次のように事前設定します。
\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
?
小さな塊を描くときに、同じような線があることに気付きましたか?
1 つの機能強化としては、これらのミニ ブロブの数と位置もカスタマイズすることです。いくつかのキーと で\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}