Note: I have created a small tikz library based on this answer and named nicepoints
that is available on GitHub.
Finally I have a method to draw points that satisfy all criteria (in slightly different way for the color inheritance) and even more.
Before to give you the full solution, let's start from the beginning of the story.
The easiest way
I just realized that probably the best way to make a point is to use a "dot" .
:
\tikz\draw[very thin,red] (0,0) -- node{.} (1,0);

The color is inherited in a very useful way I think. The color of the point is the same as the text color.
\tikz\draw[very thin,red,text=violet] (0,0) -- node{.} node[above]{A} (1,0);

But points like this are too small for thicker lines.
\tikz\draw[very thick,red,text=violet] (0,0) -- node{.} (1,0);

We can scale it by using line width
, and automate all this by creating a style.
\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);

The choice of sqrt
is a personal taste : in this way for thinner lines the dots are not too small, and for thicker ones, not too fat. Actually, in this way, the surface of the point is proportional to the line width.
More sophisticated points
And if we want to fill the point, we can simply draw another smaller dot over the first one:
\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];

The problem that is not solved yet is that the lines drawn after a point can overlap it like this:
\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}

The solution
What we want is to put the point on a top layer, in a way that any line drawn after it stays under the point. For this we can use pgfonlayer
but there are two difficulties:
There are not so many ways to automatically insert pgfonlayer
. We can use some hacks (but I don't want this). We can use pic
, but in this case we have to fix the bug of TikZ 3.0.0 if we want to be able to use nodes after the point. And the third option that I know is to use path picture
.
Here is something tricky : if we draw something inside path picture
by changing the layer, the drawing is not clipped because the clipping is applied to the initial layer.
When we change layer, "almost" everything is reset : the line width, the draw and fill colors, the opacity. But I was nicely surprised when writing this question, that the text color and opacity are not reset by the layer change. So the only thing that we have to take care is the line width
. But this is not so hard because we have at our disposal pgflinewidth
that we can save before the layer change, and use it on the new layer.
Here is the "non quoted" version of the solution to the initial question:
\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}
}
]{}
}
}
}
And one test here:
\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}

How to ...
- How to use
point
style?
- simply as
(1,1) [point]
,
- or inside another node like this
node[point,below]{$A$}
.
- How to put a point in the middle of segment? We can't use
-- [point]
syntax, but we can :
- put inside another node like this
-- node[point]{}
- or after the end of the segment, like this
--(1,1)[point=midway]
- How to set the
draw
color of a point? Like we set the text color of all nodes.
- If the color is set on the path like this
\path[red] ...
then it is inherited by the points on the path(because the text color is set also in this case).
\tikz\draw[red] (0,0. -- (1,0) [point=midway];

- If we set only the draw/fill color on the path/scope, but not the text color, the points are by default black (as the text).
\tikz\path[draw=red] (0,0) -- (1,0) [point=midway];

- We can specify the point color as in the following example:
\begin{tikzpicture}[scale=2]
\draw[fill=blue!14]
(0,0) [point]
-- (1,0) [point=blue]
-- node[red,point,left]{red point and text}
(1,1) node[point,above,red]{red text only}
-- (0,1) node[point=red,below]{red point only};
\end{tikzpicture}

- How to set the
fill
color of a point ? By using point fill
key.
- If we want to set it for all points on the path, we can do
\path[point fill=red] ...
- If we want to set it for one point, we can do
[point={point fill=red}]
.
\tikz\path[ultra thick, red, point fill=blue]
(0,0) [point] (.5,0) [point={point fill=green}] (1,0) [point];

- How to set the point size ? The point inherit its size from the line width of the path.
- To change it for one point we can use
[point=very thick]
for example
- To set it for all points in the scope independently of the line width we can use
point size=.8pt
for example
And finally, we can use every point
to set the default point style.
Extra stuff : quoted points
If we want to be able to say point="A"
and to have coordinate set to (A)
and the text $A$
displayed next to the point, we can use the quotes
library.
Here is the full code for this quoted
points.
\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}
}]{}
}
}
}
How to use quoted points
- When you say
[point="B"red]
, first coordinate(B)
is inserted and then the equivalent of label={[red]$B$}
is used.
- If you use
[point="B"']
(with '
) then $B$
is not displayed (empty label is added), but coordinate(B)
is inserted.
- If we want only a label without coordinate, we can use
[point={label=$B$}]
or node[point,above]{$B$}
.
Let's finish this short answer with an example of "quoted points" in use:
\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}

UPDATE: We can define \point
like this
\def\point[#1] at (#2){\path (#2) [point={#1}]}
and then use it like this:
\point["A"below] at (1,1);
UPDATE 2: After the comments of PaulGaborit I added every dot
style that reset the font. In this way if we use a font with a dot that is not centerd in the middle of the node we have two choices :
- force the "dot" font to be the standratd font,
- or make some shift (in em) to put it in the center.
For example we can put :
\tikzset{
every dot/.style={inner sep=0, outer sep=0,
node font=\usefont{T1}{lmr}{m}{n}\fontsize{10pt}{0pt}\selectfont}
}
\tikz\fill circle (2pt);
in a book or a paper and by a cross at the blackboard. Then a point can be used for a vertex and it's possible tu use your representation. With a mathematical object I'm not sure if it's interesting to change the line width or the width of the points. The minimum is required. I think about this problem for tkz-euclid. The main problem was to avoid to scale the points with the picture.