22

I have the following image:

\documentclass{article}
\usepackage[pdftex,active,tightpage]{preview}
\setlength\PreviewBorder{2mm}

\usepackage{tkz-fct}
\usetikzlibrary{arrows, decorations.pathreplacing}

\tikzstyle{line}=[very thick, black]
\tikzstyle{point}=[thick,fill=gray,gray]

\begin{document}
\begin{preview}
\begin{tikzpicture}
       \tkzInit [xmin=0,xmax=21,ymin=0,ymax=7]
        \begin{scriptsize}
            \tkzGrid[color = gray!30!white]
            \tkzAxeXY
        \end{scriptsize}
        \draw[line] (1,4) -- (6,1);
        \draw[line] (2,1) -- (5,4);
        \draw[line] (3,1) -- (6,4);
        \draw[line] (4,1) -- (8,5);
        \draw[line] (3,4) -- (9,3);
        \draw[line] (7,2) -- (9,3);
        \draw[line] (6,7) -- (9,1);

        \draw[line] (11,1) -- (16,5);
        \draw[line] (13,2) -- (14,2);
        \draw[line] (14,1) -- (14,2);
        \draw[line] (14,3) -- (15,2);
        \draw[line] (15,4) -- (15,3);
        \draw[line] (13,4) -- (13,3);

        \draw[line] (17,3) -- (21,3);
        \draw[line] (19,1) -- (19,5);

        \draw[point] (1,4) circle (2pt);

\end{tikzpicture}
\end{preview}
\end{document}

Which looks like this:

enter image description here

I would like to mark each end of a line with a cross. It's okay for me to make this manually, like I did with circle (see (1|4)) at the end, but I would like to have a cross. How do I get this?

(How can I make the tikz-style point look like a cross?)

Martin Thoma
  • 18,799

3 Answers3

21

A different idea, define a new arrow shape named for example X (thanks to Qrrbrbirlbel to note that \pgarrowrightextend{0pt} was neccessary):

\documentclass{article}
\usepackage{tikz}
\makeatletter
\pgfarrowsdeclare{X}{X}
{
  \pgfutil@tempdima=0.3pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfutil@tempdimb=5.5\pgfutil@tempdima\advance\pgfutil@tempdimb by.5\pgflinewidth%
  \pgfarrowsleftextend{+-\pgfutil@tempdimb}
  \pgfarrowsrightextend{0pt}
}
{
  \pgfutil@tempdima=0.3pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetmiterjoin
  \pgfpathmoveto{\pgfqpoint{-5.5\pgfutil@tempdima}{-6\pgfutil@tempdima}}
  \pgfpathlineto{\pgfqpoint{5.5\pgfutil@tempdima}{6\pgfutil@tempdima}}
  \pgfpathmoveto{\pgfqpoint{-5.5\pgfutil@tempdima}{6\pgfutil@tempdima}}
  \pgfpathlineto{\pgfqpoint{5.5\pgfutil@tempdima}{-6\pgfutil@tempdima}}
  \pgfusepathqstroke 
}
\makeatother

\begin{document} \tikz{ \draw[X-X] (0,0) -- (2,1); \draw[X-X] (0,2) -- (1,0); } \end{document}

Result

Using arrow shapes instead of node shapes makes the X to be rotated according with the slope of the line drawn. This can be an advantage or a problem, depending on what do you want.

Update

A much simpler solution, using the same idea, is to combine two existing arrow tips, instead of defining a new one. The following code would produce exactly the same result than the one above (note this code was modified from its first version. Now it ensures that the X lies at the specified endpoints):

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows}
\pgfarrowsdeclarecombine[-12*(0.3pt+.25\pgflinewidth)-\pgflinewidth]
{X}{X}{angle 90 reversed}{angle 90 reversed}{angle 90}{angle 90}

\begin{document} \tikz{ \draw[X-X] (0,0) -- (2,1); \draw[X-X] (0,2) -- (1,0); } \end{document}

JLDiaz
  • 55,732
  • 1
    The end of lines do not lie on the specified points. Test with \draw (0,0) grid (2,2);. \pgfarrowsrightextend{0pt} could solve this. The combine solution is even worse as it shortens the line of the “right extend” of angle 90 reversed. Also, why did you use 5.5 and 6 in the \pgfpath????to macros? A right-angled cross needs both factors to be equal. – Qrrbrbirlbel Jan 05 '13 at 23:45
  • @Qrrbrbirlbel Thank you for detecting the bug. I edited the definition of the X arrow using \pgfarrowsrightextend{0pt} as you suggested, and it fixes it. I also changed the code for \pgfarrowsdeclarecombine so that it places the X at the given points too. – JLDiaz Jan 06 '13 at 00:07
16

Notes:

  • I have replaced the scriptsize environment (that does not even exist) with the option font=\scriptsize on the \tkzAxeXY macro.
  • I used the standalone class.

With plain TikZ you have a few possibilities:

  1. The cross out shape from the shapes.misc library offers you the possibility to cross out a node. Normally this is used to visualize something on text (like this), but with the options minimum height and minimum width along side with a zero inner sep we get a well-defined cross. The line-width settings (thick) is recognized as well.

    point/.style={
        thick,
        draw=gray,
        cross out,
        inner sep=0pt,
        minimum width=4pt,
        minimum height=4pt,
    },
    

    This point node can now be applied either manually:

    \node[point] at (1,4) {};
    

    or automatically with a special to path (in the line style):

    to path={% works only with "to" and not "--"
        -- (\tikztotarget) node[at start,point] {} node [at end,point] {} \tikztonodes
    }
    
  2. The plot paths of TikZ offers quite the same with a lot of outher “marks”. The pline style is similar to the previous line style. It contains also the every plot options:

    pline/.style={% plot line
        every plot/.style={
            mark=x,
            mark options={
                gray,
                thick,
            },
            mark size=4pt,
        },
        very thick,
        black,
    },
    

Code (shape)

\documentclass[tikz,border=2mm]{standalone}
\usepackage{tkz-fct}
\usetikzlibrary{shapes.misc}

\tikzset{
    line/.style={
        very thick,
        black,
        to path={% works only with "to" and not "--"
            -- (\tikztotarget) node[at start,point] {} node [at end,point] {} \tikztonodes
        }
    },
    point/.style={
        thick,
        draw=gray,
        cross out,
        inner sep=0pt,
        minimum width=4pt,
        minimum height=4pt,
    },
}

\begin{document}
\begin{tikzpicture}
    \tkzInit [xmin=0,xmax=21,ymin=0,ymax=7]

    \tkzGrid[color = gray!30!white]
    \tkzAxeXY[font=\scriptsize]

    \draw[line] (1,4) -- (6,1);
    \draw[line] (2,1) to (5,4)
                (3,1) to (6,4)
                (4,1) to (8,5)
                (3,4) to (9,3)
                (7,2) to (9,3)
                (6,7) to (9,1);

    \draw[line] (11,1) to (16,5)
                (13,2) to (14,2)
                (14,1) to (14,2)
                (14,3) to (15,2)
                (15,4) to (15,3)
                (13,4) to (13,3);

    \draw[line] (17,3) to (21,3)
                (19,1) to (19,5);

    \path[every node/.style={point}]
         node at (1,4) {}
         node at (6,1) {};
\end{tikzpicture}
\end{document}

Output (shape)

enter image description here

Code (plot)

\documentclass[tikz,border=2mm]{standalone}

\usepackage{tkz-fct}

\tikzset{
    pline/.style={% plot line
        every plot/.style={
            mark=x,
            mark options={
                gray,
                thick,
            },
            mark size=4pt,
        },
        very thick,
        black,
    },
}

\begin{document}
\begin{tikzpicture}
    \tkzInit [xmin=0,xmax=21,ymin=0,ymax=7]
    \tkzGrid[color = gray!30!white]
    \tkzAxeXY[font=\scriptsize]
    \draw[pline] plot coordinates {(1,4) (6,1)}
                 plot coordinates {(2,1) (5,4)}
                 plot coordinates {(3,1) (6,4)}
                 plot coordinates {(4,1) (8,5)}
                 plot coordinates {(3,4) (9,3)}
                 plot coordinates {(7,2) (9,3)}
                 plot coordinates {(6,7) (9,1)};

    \draw[pline] plot coordinates {(11,1) (16,5)}
                 plot coordinates {(13,2) (14,2)}
                 plot coordinates {(14,1) (14,2)}
                 plot coordinates {(14,3) (15,2)}
                 plot coordinates {(15,4) (15,3)}
                 plot coordinates {(13,4) (13,3)};

    \draw[pline] plot coordinates {(17,3) (21,3)}
                 plot coordinates {(19,1) (19,5)};
\end{tikzpicture}
\end{document}

Output (plot)

enter image description here

Qrrbrbirlbel
  • 119,821
5

Just another answer with PSTricks.

The input:

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-eucl}
\addtopsstyle{gridstyle}{gridlabels=0}
\begin{document}
\begin{pspicture}[showgrid](4,3)
    \pstGeonode[
        PointName=none,
        PointSymbol={x,none,x},
        dotscale=2]
    (0,0){A}
    (1,3){B}
    (4,1){C}
    \psline(A)(B)(C)
\end{pspicture}
\end{document}

The output:

enter image description here