最も簡単な方法

最も簡単な方法

多くの場合、ポイントを描く必要があります。私たち一人一人には、これを行うためのお気に入りの方法があります。

あなたのは何ですか?

ノード、画像、マークなどを使用しますか? スタイルで?

いくつかの背景

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 at5) ポイントは、通常別のコマンドを使用して描画できるあらゆる状況で使用できます。これは前の例ですでに説明されていますが、および と一緒に使用できると便利です(現在の座標を変更しない\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=inherit3 を部分的に満たします。または の定義方法がわかりません。およびを削除して全体を再定義するfill=inherit新しいスタイルを定義しますが、これは見苦しいです ;)。inheritpointopacity=1fill=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 つの問題があります。

  1. を自動的に挿入する方法はそれほど多くありませんpgfonlayer。 いくつかのハックを使用することもできます (ただし、これは望ましくありません)。 を使用することもできますpicが、この場合、ポイントの後のノードを使用できるようにするには、TikZ 3.0.0 のバグを修正する必要があります。 そして、私が知っている 3 番目のオプションは を使用することですpath picture
    ここで注意すべき点があります。レイヤーを変更して内部に何かを描画するとpath picture、クリッピングが最初のレイヤーに適用されるため、描画はクリッピングされません。

  2. レイヤーを変更すると、線の幅、描画色、塗りつぶし色、不透明度など、ほぼすべてがリセットされます。しかし、次のように書くと、とても驚きました。この質問、テキストの色と不透明度はレイヤーの変更によってリセットされないことに注意してください。したがって、注意する必要があるのは だけです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}

ここに画像の説明を入力してください

方法 ...

  1. スタイルの使い方はpoint
    • 単に(1,1) [point]
    • または、このように別のノード内にありますnode[point,below]{$A$}
  2. セグメントの中央にポイントを配置するにはどうすればよいでしょうか?構文は使用できません-- [point]が、次のことは可能です:
    • このように別のノード内に置く-- node[point]{}
    • またはセグメントの終了後に、このように--(1,1)[point=midway]
  3. 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}

ここに画像の説明を入力してください

  1. fillポイントの色を設定するにはどうすればいいですか?キーを使用することによりpoint fill
    • パス上のすべてのポイントに設定したい場合は、次のようにします。\path[point fill=red] ...
    • 1 点に設定したい場合は、 を実行します[point={point fill=red}]
  \tikz\path[極太、赤、点塗りつぶし=青]
    (0,0) [ポイント] (.5,0) [ポイント={ポイント塗りつぶし=緑}] (1,0) [ポイント];

ここに画像の説明を入力してください

  1. ポイントサイズを設定するには?ポイントのサイズはパスの線の幅から継承されます。
    • 1点だけ変更するには、[point=very thick]例えば
    • 線幅に関係なくスコープ内のすべてのポイントに設定するには、例えば次point size=.8ptのようにします。

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}
}

関連情報