Very often we need to draw points. Every one of us has it's favorite method to do this.
What is yours ?
Do you use nodes, pics, marks, … ? In a style ?
Some backgrounds
In the tikz/pgf manual this is done very often by \tikz\fill circle (2pt);
.
In the example of the key /tikz/insert path
we can see this code
\tikz [c/.style={insert path={circle[radius=2pt]}}]
\draw (0,0) -- (1,1) [c] -- (3,2) [c];
There is also an example for the key handler /.pic
(p.255) to produce the same filled circle.
These methods has the advantage to be really simple, but are not good for me because:
- The appearance of the point depend on the path command action (draw, fill, …).
- When you scale the image the line width is not scaled (nor the font size) but the points are scaled (you can easily overcome this by putting the size in
em
for example). - When you draw a line after drawing the point, the line is drawn over the point.
And more …
What I'm looking for
Here is a list of things that I would like to be able to do with only one definition of "point" (or with more than one definition but with consistent syntax).
For every requirement I gave the test to pass with the expected result. In the test you can replace "point" by your favorite syntax.
1) Points must be scaled properly. And for me this is not clear if the size should be proportional to the line width or to the font size. Probably the best is to size it using the line width and then if necessary ot be able (see point 3)) to set the size in em
if we want a font scaling compatibility. What do you think ?
\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) We should be able to style points easly. For example we sould be able to say something like "draw thick red point".
(see the following point for the test)
3) Draw, fill and opacity of points could be set to inherit
in which case this parameters are inherited from the scope/path. But only the draw sould be set to inherit
by default, the other defaults (personal taste) should be fill=white and opacity=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) The point could be easily named in place to use coordinate
and if the point is drawn with node
the name should point to the center of the node and not to the node itself.
\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}
5) Points could be used in every situation where we can normally use another command to draw it.
This is already illustrated with the previous examples, but it will be nice if we could use it with \node at
and \coordinate at
(which is not obvious because at
don't change the current coordinate).
(see the following point for the test)
6) Points are drawn on top of any line (on the foreground layer).
\begin{tikzpicture}
\node[left] {A} at (0,1) "ultra thick point";
\coordinate["thick point"] (B) at (1,0);
\draw (A) -- (B);
\end{tikzpicture}
7) The solution must be non hacky one, so that the definition of "point" could be (hopefully) compatible with future versions of tikz.
What is my personal incomplete solution
I'll publish it as an answer.
Best Answer
Method I (using node)
and some extra stuff :
Satisfies 1.
Satisfies 2 with styling like this
[point={fill=red, very thick}]
Partially satisfies 3. I don't know how to define
draw opacity=inherit
orfill=inherit
. I define new styleinherit
which will redefine the entirepoint
by removing theopacity=1
andfill=white
, but this is ugly ;).Partially satisfy 4 : you can use
point name=A
. I would like to be able to use quotes for saying something like[point={red, "A"}]
but I don't know how to do this.Almost satisfy 5 : we can put [point] almost anywhere, like
(A) [point]
, ornode[point, above]{A}
, orcoordinate[point](A)
. But can't be used with\coordinate at
or\node at
(except if you repeat yourself like this\coordinate (A) at (1,1) (A) [point];
)FAILS on 6. I know that there is a hacky solution to put node on layer, but this is in contradiction with 7).
Satisfies 7.
The full code of all tests and the result
Method II (using pic)
FAILS on 1. I don't know how to inherit styles from path to pic. Is there some style like
current path style
?Satisfies 2. Same as method I.
FAILS on 3. We can style as in method I, but because (1) fails, (3) fails.
Partially satisfies 4. Same as method I.
FAILS on 5 : as there is a bug in 'pic' we can't use node after it in PGF 3.0. When this bug will be fixed, this method will be equivalent to the first one at this test.
Satisfies 6. This is the main interest of this method.
Satisfies 7.
The full code of all tests and the result