多くの場合、ポイントを描く必要があります。私たち一人一人には、これを行うためのお気に入りの方法があります。
あなたのは何ですか?
ノード、画像、マークなどを使用しますか? スタイルで?
いくつかの背景
tikz/pgf マニュアルでは、これが によって頻繁に実行されます\tikz\fill circle (2pt);
。
キーの例では/tikz/insert path
このコードを見ることができます
\tikz [c/.style={insert path={circle[radius=2pt]}}]
\draw (0,0) -- (1,1) [c] -- (3,2) [c];
また、キーハンドラー /.pic
(p.255) 同じ塗りつぶされた円を生成します。
これらの方法は非常にシンプルであるという利点がありますが、次の理由から私には適していません。
- ポイントの外観は、パス コマンドのアクション (描画、塗りつぶしなど) によって異なります。
- 画像を拡大縮小すると、線の幅は拡大縮小されません (フォント サイズも拡大縮小されません) が、ポイントは拡大縮小されます (たとえば、サイズを入力することでこれを簡単に克服できます
em
)。 - 点を描いた後に線を描くと、点の上に線が描かれます。
もっと ...
私が探しているもの
以下は、「ポイント」の定義を 1 つだけ使用して (または定義は複数使用して、構文は一貫している) 実行できるようにしたいことのリストです。
すべての要件に対して、期待される結果で合格するためのテストを行いました。テストでは、「point」を好みの構文に置き換えることができます。
1) ポイントは適切に拡大縮小する必要があります。サイズを線幅に比例させるべきか、フォント サイズに比例させるべきか、私にはわかりません。おそらく、線幅を使用してサイズを設定し、必要に応じて (ポイント 3) を参照)、em
フォント スケーリングの互換性が必要な場合にサイズを設定できるようにするのが最善でしょう。どう思われますか?
\begin{tikzpicture}
\foreach[count=\i] \w in {ultra thin, thin, ultra thick} {
\draw[yshift=-\i em, \w] (0,0) -- (.5,0) "point" -- (1,0);
}
\foreach[count=\i] \s in {.2, .5, 1} {
\draw[xshift=1.5cm, yshift=-\i em, scale=\s] (0,0) -- (.5,0) "point" -- (1,0);
}
\end{tikzpicture}
2) ポイントのスタイルを簡単に設定できる必要があります。たとえば、「太い赤いポイントを描画する」などのように指定できるようになります。
(テストについては以下の点を参照)
3) ポイントの描画、塗りつぶし、不透明度を設定できますinherit
。その場合、これらのパラメータはスコープ/パスから継承されます。ただし、描画のみをinherit
デフォルトで設定し、その他のデフォルト (個人の好み) は、塗りつぶし = 白、不透明度 = 1 にする必要があります。
\begin{tikzpicture}[scale=2, very thick]
\filldraw[draw opacity=.5, draw=red, fill opacity=.3, densely dotted]
(0,0) "point" -- (.5,0) "ultra thick point filled in green" -- (.5,.5) "point with inherited draw, fill and opacity" -- cycle;
\end{tikzpicture}
4) ポイントは、使用時に簡単に名前を付けることができcoordinate
、ポイントがnode
名前付きで描画される場合、そのポイントはノード自体ではなく、ノードの中心を指す必要があります。
\begin{tikzpicture}
\draw[very thick] (0,1) "point" -- (1,0) "thick point filled in green with name=A";
\draw[ultra thick, purple] (0,0) "point" -- (A);
\end{tikzpicture}
\node at
5) ポイントは、通常別のコマンドを使用して描画できるあらゆる状況で使用できます。これは前の例ですでに説明されていますが、および と一緒に使用できると便利です(現在の座標を変更しない\coordinate at
ため、明らかではありません)。at
(テストについては以下の点を参照)
6) ポイントは任意の線の上(前景レイヤー上)に描画されます。
\begin{tikzpicture}
\node[left] {A} at (0,1) "ultra thick point";
\coordinate["thick point"] (B) at (1,0);
\draw (A) -- (B);
\end{tikzpicture}
7) 解決策はハッキーなものであってはならず、その結果、「ポイント」の定義は (願わくば) tikz の将来のバージョンと互換性を持つことになります。
私の個人的な不完全な解決策は何ですか
回答として公開させていただきます。
答え1
方法I(ノードを使用)
\tikzset{
every point/.style = {circle, inner sep={.75\pgflinewidth}, opacity=1, draw, solid, fill=white},
point/.style={insert path={node[every point, #1]{}}}, point/.default={},
point name/.style = {insert path={coordinate (#1)}},
}
そしていくつか追加事項:
\tikzset{
colored point/.style = {point={fill=#1}},
inherit/.style = {point/.style={insert path={node[circle, inner sep={.75\pgflinewidth}, draw, fill, #1]{}}}}
}
1 を満たします。
このようなスタイリングで2人を満足させる
[point={fill=red, very thick}]
draw opacity=inherit
3 を部分的に満たします。または の定義方法がわかりません。およびを削除して全体を再定義するfill=inherit
新しいスタイルを定義しますが、これは見苦しいです ;)。inherit
point
opacity=1
fill=white
4 を部分的に満たす: を使用できます
point name=A
。 のようなことを言うときに引用符を使用できるようにしたいのです[point={red, "A"}]
が、方法がわかりません。(A) [point]
ほぼ 5 を満たしています: 、 、 のように、[ポイント] をほぼどこにでも置くことができます。ただし、node[point, above]{A}
やとcoordinate[point](A)
一緒に使用することはできません( のように繰り返す場合を除く)\coordinate at
\node at
\coordinate (A) at (1,1) (A) [point];
失敗6. 私は知っているレイヤーにノードを配置するハッキーな解決策がありますしかし、これは7)と矛盾している。
7を満たします。
すべてのテストの完全なコードと結果
\documentclass[varwidth,border=50]{standalone}
\usepackage{tikz}
% not clear how to use layers with this method
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}
\tikzset{
every point/.style = {circle, inner sep={.75\pgflinewidth}, opacity=1, draw, solid, fill=white},
point/.style={insert path={node[every point, #1]{}}}, point/.default={},
colored point/.style = {point={fill=#1}},
point name/.style = {insert path={coordinate (#1)}},
inherit/.style = {point/.style={insert path={node[circle, inner sep={.75\pgflinewidth}, draw, fill, #1]{}}}}
}
\begin{document}
\begin{itemize}
% ---------------------------------
\item Test 1 : ok.\\[1em]
\begin{tikzpicture}
\foreach[count=\i] \w in {ultra thin, thin, ultra thick} {
\draw[yshift=-\i em, \w] (0,0) -- (.5,0) [point] -- (1,0);
}
\foreach[count=\i] \s in {.2, .5, 1} {
\draw[xshift=1.5cm, yshift=-\i em, scale=\s] (0,0) -- (.5,0) [point] -- (1,0);
}
\end{tikzpicture}
% ---------------------------------
\item Test 2 : ok.
% ---------------------------------
\item Test 3 : partialy ok, there is no good \texttt{inherit}.\\
\begin{tikzpicture}[scale=2, very thick]
\filldraw[draw opacity=.5, draw=red, fill opacity=.3, densely dotted]
(0,0) [point] -- (.5,0) [point={ultra thick, fill=green}] -- (.5,.5) [inherit, point] -- cycle;
\end{tikzpicture}
% ---------------------------------
\item Test 4 : almost ok (using \texttt{point name})\\
\begin{tikzpicture}
\draw[very thick] (0,1) [point] -- (1,0) [point={thick, fill=green, point name=A}];
\draw[ultra thick, purple] (0,0) [point] -- (A);
\end{tikzpicture}
% ---------------------------------
\item Test 5 : almost ok.
% ---------------------------------
\item Test 6 : fails ! (visible in test 4 too)\\
\begin{tikzpicture}
\coordinate (A) at (0,1) (A) node[point=ultra thick, left] {A};
\coordinate (B) at (1,0) (B) [thick, point];
\draw (A) -- (B);
\end{tikzpicture}
\end{itemize}
\end{document}
方法 II(写真使用)
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}
\tikzset{
every point/.style = {radius={\pgflinewidth}, opacity=1, draw, solid, fill=white},
pt/.pic = {
\begin{pgfonlayer}{foreground}
\path[every point, #1] circle;
\end{pgfonlayer}
},
point/.style={insert path={pic{pt={#1}}}}, point/.default={},
point name/.style = {insert path={coordinate (#1)}}
}
失敗1. パスから pic にスタイルを継承する方法がわかりません。 のようなスタイルはありますか
current path style
?2 を満たします。方法 I と同じです。
失敗3. 方法Iのようにスタイルを設定できますが、(1)が失敗するため、(3)は失敗します。
4を部分的に満たします。方法Iと同じです。
失敗5: があるので「pic」のバグPGF 3.0 では、それ以降のノードは使用できません。このバグが修正されると、このメソッドはこのテストの最初のメソッドと同等になります。
6 を満たします。これがこの方法の主な目的です。
7を満たします。
すべてのテストの完全なコードと結果
\documentclass[varwidth,border=50]{standalone}
\usepackage{tikz}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}
\tikzset{
every point/.style = {radius={\pgflinewidth}, opacity=1, draw, solid, fill=white},
pt/.pic = {
\begin{pgfonlayer}{foreground}
\path[every point, #1] circle;
\end{pgfonlayer}
},
point/.style={insert path={pic{pt={#1}}}}, point/.default={},
colored point/.style = {point={fill=#1}},
point name/.style = {insert path={coordinate (#1)}}
}
\begin{document}
\begin{itemize}
\item Test 1 : fails for sizing from path width, scale is ok.\\[1em]
\begin{tikzpicture}
\foreach[count=\i] \w in {ultra thin, thin, ultra thick} {
\draw[yshift=-\i em, \w] (0,0) -- (.5,0) [point] -- (1,0);
}
\foreach[count=\i] \s in {.2, .5, 1} {
\draw[xshift=1.5cm, yshift=-\i em, scale=\s] (0,0) -- (.5,0) [point] -- (1,0);
}
\end{tikzpicture}
\item Test 2 : partialy ok, there is no \texttt{inherit} (at all).
\item Test 3 : fails ! Can't inherit style from path.\\
\begin{tikzpicture}[scale=2, very thick, densely dotted]
\filldraw[draw opacity=.5, draw=red, fill opacity=.3]
(0,0) [point] -- (.5,0) [point={ultra thick, fill=green}] -- (.5,.5) [point] -- cycle;
\end{tikzpicture}
\item Test 4 : almost ok (using \texttt{point name})\\
\begin{tikzpicture}
\draw[very thick] (0,1) [point] -- (1,0) [point={thick, fill=green, point name=A}];
\draw[ultra thick, purple] (0,0) [point] -- (A);
\end{tikzpicture}
\item Test 5 : fails ! (can't put node after [point] )
\item Test 6 : ok.\\
\begin{tikzpicture}
\path (0,1) node[left] {A} coordinate (A) [point=ultra thick];
\coordinate (B) at (1,0) (B) [thick, point];
\draw (A) -- (B);
\end{tikzpicture}
\end{itemize}
\end{document}
答え2
注記:私はこの回答に基づいて小さなtikzライブラリを作成し、
nicepoints
それを利用できるようにしました。GitHub。
ついに、すべての基準を満たす点を描画する方法が見つかりました (色の継承については若干異なる方法で)。
完全なソリューションを提供する前に、話の最初から始めましょう。
最も簡単な方法
おそらく、ポイントを示す最良の方法は「ドット」を使用することだということに気付きました.
。
\tikz\draw[very thin,red] (0,0) -- node{.} (1,0);
色は継承されるのでとても便利だと思います。ポイントの色はテキストの色と同じです。
\tikz\draw[very thin,red,text=violet] (0,0) -- node{.} node[above]{A} (1,0);
しかし、このようなポイントは太い線には小さすぎます。
\tikz\draw[very thick,red,text=violet] (0,0) -- node{.} (1,0);
を使用してスケーリングしline width
、スタイルを作成することでこれらすべてを自動化できます。
\tikzset{point/.style={insert path={ node[scale=2.5*sqrt(\pgflinewidth)]{.} }}}
\tikz\draw[very thick,red,text=violet] (0,0) -- node[point,above]{A} (1,0);
の選択はsqrt
個人の好みです。この方法では、細い線の場合は点が小さすぎず、太い線の場合は太すぎません。実際、この方法では、点の表面積は線の幅に比例します。
より洗練されたポイント
点を塗りつぶしたい場合は、最初の点の上にもう一つ小さな点を描くだけです。
\tikzset{
outer dot/.style = {scale=2.5*sqrt(\pgflinewidth)},
inner dot/.style = {scale=sqrt(\pgflinewidth),#1},inner dot/.default={white},
point/.style={insert path={ node[outer dot]{.} node[inner dot=#1]{.}}}
}
\tikz\draw[very thick,blue] (0,0) -- node[point]{} (1,0) [point=red];
まだ解決されていない問題は、点の後に描かれた線が次のように重なり合う可能性があることです。
\begin{tikzpicture}[scale=2]
\draw[very thick,blue] (0,0) -- node[point]{} (1,0) [point=red];
\draw[red] (0,0) -- node[point]{} (1,.2);
\draw[very thick] (0,.2) -- (1,0);
\end{tikzpicture}
ソリューション
私たちが望むのは、ポイントを最上位レイヤーに配置し、その後に描画される線がポイントの下に留まるようにすることです。これには を使用できますpgfonlayer
が、2 つの問題があります。
を自動的に挿入する方法はそれほど多くありません
pgfonlayer
。 いくつかのハックを使用することもできます (ただし、これは望ましくありません)。 を使用することもできますpic
が、この場合、ポイントの後のノードを使用できるようにするには、TikZ 3.0.0 のバグを修正する必要があります。 そして、私が知っている 3 番目のオプションは を使用することですpath picture
。
ここで注意すべき点があります。レイヤーを変更して内部に何かを描画するとpath picture
、クリッピングが最初のレイヤーに適用されるため、描画はクリッピングされません。レイヤーを変更すると、線の幅、描画色、塗りつぶし色、不透明度など、ほぼすべてがリセットされます。しかし、次のように書くと、とても驚きました。この質問、テキストの色と不透明度はレイヤーの変更によってリセットされないことに注意してください。したがって、注意する必要があるのは だけです
line width
。ただし、レイヤーの変更前に保存して新しいレイヤーで使用できるため、これはそれほど難しくありませんpgflinewidth
。
最初の質問に対する解決策の「引用なし」バージョンは次のとおりです。
\pgfdeclarelayer{points}
\pgfsetlayers{main,points}
\tikzset{
set point size/.code={\pgfmathsetmacro{\pointsize}{sqrt(\pgflinewidth)}},
point size/.style={set point size/.prefix style={line width=#1}},
every dot/.style = {inner sep=0, outer sep=0,font=},
outer dot/.style = {every dot, scale=2.5*\pointsize},
inner dot/.style = {every dot, scale=\pointsize, text=#1}, inner dot/.default={white},
point fill/.style = {inner dot/.default={#1}},
point coordinate/.style={insert path={coordinate(#1)}},
point/.style={insert path={
node[inner sep=0, overlay, every point/.try, #1, set point size,
path picture={
\begin{pgfonlayer}{points}
\node[outer dot]{.} node[inner dot]{.};
\end{pgfonlayer}
}
]{}
}
}
}
ここで 1 つのテストを実行します。
\begin{tikzpicture}[scale=2]
\draw[blue] (0,0)[point] -- node[thick,point={name=A},below]{$A$} (1,0) [point=red];
\draw[red] (0,0) -- node[point]{} (1,.2) [point=thick];
\draw[very thick] (0,.2)[point={point coordinate=B, label=$B$}] -- (1,0);
\draw[green] (A)--(B);
\end{tikzpicture}
方法 ...
- スタイルの使い方は
point
?- 単に
(1,1) [point]
、 - または、このように別のノード内にあります
node[point,below]{$A$}
。
- 単に
- セグメントの中央にポイントを配置するにはどうすればよいでしょうか?構文は使用できません
-- [point]
が、次のことは可能です:- このように別のノード内に置く
-- node[point]{}
- またはセグメントの終了後に、このように
--(1,1)[point=midway]
- このように別のノード内に置く
draw
ポイントの色を設定するにはどうすればいいですか?すべてのノードのテキストの色を設定するのと同じです。- このようにパス上に色を設定すると
\path[red] ...
、パス上のポイントに色が継承されます (この場合はテキストの色も設定されているため)。
\tikz\draw[red] (0,0. -- (1,0) [point=midway];
- パス/スコープに描画/塗りつぶしの色のみを設定し、テキストの色を設定していない場合、ポイントはデフォルトで黒(テキストと同じ)になります。
\tikz\path[draw=red] (0,0) -- (1,0) [point=midway];
- 次の例のようにポイントの色を指定できます。
- このようにパス上に色を設定すると
\begin{tikzpicture}[スケール=2] \draw[塗りつぶし=青!14] (0,0) [ポイント] -- (1,0) [ポイント=青] -- node[red,point,left]{赤い点とテキスト} (1,1) ノード[ポイント、上、赤]{赤のテキストのみ} -- (0,1) node[point=red,below]{赤い点のみ}; \end{tikzpicture}
fill
ポイントの色を設定するにはどうすればいいですか?キーを使用することによりpoint fill
。- パス上のすべてのポイントに設定したい場合は、次のようにします。
\path[point fill=red] ...
- 1 点に設定したい場合は、 を実行します
[point={point fill=red}]
。
- パス上のすべてのポイントに設定したい場合は、次のようにします。
\tikz\path[極太、赤、点塗りつぶし=青] (0,0) [ポイント] (.5,0) [ポイント={ポイント塗りつぶし=緑}] (1,0) [ポイント];
- ポイントサイズを設定するには?ポイントのサイズはパスの線の幅から継承されます。
- 1点だけ変更するには、
[point=very thick]
例えば - 線幅に関係なくスコープ内のすべてのポイントに設定するには、例えば次
point size=.8pt
のようにします。
- 1点だけ変更するには、
every point
最後に、デフォルトのポイント スタイルを設定するために使用できます。
追加事項: 引用点
point="A"
座標を に設定し(A)
、その点の横にテキストを表示したい場合は$A$
、ライブラリを使用できますquotes
。
この点に関する完全なコードは次のとおりですquoted
。
\usetikzlibrary{quotes}
\pgfdeclarelayer{points}
\pgfsetlayers{main,points}
\tikzset{
set point size/.code={\pgfmathsetmacro{\pointsize}{sqrt(\pgflinewidth)}},
point size/.style={set point size/.prefix style={line width=#1}},
every dot/.style = {inner sep=0, outer sep=0,font=},
outer dot/.style = {every dot, scale=2.5*\pointsize},
inner dot/.style = {every dot, scale=\pointsize, text=#1}, inner dot/.default={white},
point fill/.style = {inner dot/.default={#1}},
point coordinate/.style={insert path={coordinate(#1)}},
quotes mean point/.style={'/.style={empty label/.style={node contents=}},
node quotes mean/.try={point coordinate=##1,
label={[direction shorthands, every label quotes/.try, ##2,
node contents=\ensuremath{##1}, empty label/.try]}}},
point/.style={quotes mean point, insert path={
node[inner sep=0, overlay, every point/.try, #1, set point size,
path picture={
\begin{pgfonlayer}{points}
\node[outer dot]{.} node[inner dot]{.};
\end{pgfonlayer}
}]{}
}
}
}
引用ポイントの使い方
- と言う場合
[point="B"red]
、まずcoordinate(B)
が挿入され、次に と同等のものがlabel={[red]$B$}
使用されます。 [point="B"']
( とともに'
)を使用すると、$B$
は表示されず (空のラベルが追加されます)、 がcoordinate(B)
挿入されます。- 座標なしのラベルのみが必要な場合は、
[point={label=$B$}]
または を使用できますnode[point,above]{$B$}
。
この短い回答を、「引用ポイント」の使用例で締めくくりましょう。
\begin{tikzpicture}[scale=2]
\draw[fill=yellow!30,very thick]
(0,0) [point="A"] -- (1,0) [point={"B"',blue}]
-- node[red,point="C"left]{} (1,1) [point="D"{above,red}]
-- (0,1) [point={red,"E"}];
\draw[thick,purple] (E) -- (B) to[bend right] (D) edge[bend right] (C) [point=near start];
\end{tikzpicture}
アップデート:\point
次のように定義できます
\def\point[#1] at (#2){\path (#2) [point={#1}]}
そして、次のように使用します。
\point["A"below] at (1,1);
更新2:PaulGaborit のコメントに従って、every dot
フォントをリセットするスタイルを追加しました。この方法では、ノードの中央に配置されていないドットを持つフォントを使用する場合、2 つの選択肢があります。
- 「ドット」フォントを標準フォントにする
- または、中央に配置するためにシフト(em 内)を行います。
たとえば、次のように記述できます。
\tikzset{
every dot/.style={inner sep=0, outer sep=0,
node font=\usefont{T1}{lmr}{m}{n}\fontsize{10pt}{0pt}\selectfont}
}