3

The following code uses a decorator to add an arrow tip to an edge. Logically, the tip is part of the edge, and so I want it to be colored with the line-color. However, because the tip is rendered using \fill, it takes its color from the fill parameter. How can I make the color to respond to draw=red, and also not respond to fill=blue?

enter image description here

\documentclass[tikz, crop,border=1]{standalone}
\usetikzlibrary{decorations.markings, decorations.pathreplacing}

\newcommand{\drawArrow}[2]{
    \draw[
        decoration={
            markings,
            mark=at position 0.8 with {%
                \fill (0, 0.5pt) -- ++ (-0.25, 0.075) -- ++ (0, -0.075) -- cycle;
            }
        },
        postaction=decorate
    ] #1 -- #2;
}

\begin{document}
\begin{tikzpicture}[scale=2]
\tikzset{
    pe/.style={
        line width = 1pt,
        decoration={
            show path construction, 
            lineto code={%
                \drawArrow{(\tikzinputsegmentfirst)}{(\tikzinputsegmentlast)}
            },
            closepath code={%
                \drawArrow{(\tikzinputsegmentfirst)}{(\tikzinputsegmentlast)}
            }
        },
        postaction=decorate
    }
}

% Not what I want
\draw[pe, draw = red] (0, 0) -- (1, 0);

% Not what I want
\draw[pe, draw = red, fill=blue] (0, 0.25) -- (1, 0.25) -- (1, 0.5) -- (0, 0.5) -- cycle;

% What I want
\draw[pe, red] (0, 0.6) -- (1, 0.6);

% Not what I want
\draw[pe, red, fill=blue] (0, 0.75) -- (1, 0.75) -- (1, 1) -- (0, 1) -- cycle;

% What I want, simulated
\fill[pe, fill=blue] (0, 1.1) -- (1, 1.1) -- (1, 1.35) -- (0, 1.35) -- cycle;
\draw[pe, red] (0, 1.1) -- (1, 1.1) -- (1, 1.35) -- (0, 1.35) -- cycle;

\end{tikzpicture}
\end{document}
2

Update 2

You can make the color of the decoration a parameter of the style.

decoration={
    markings, mark=at position 0.8 with {%
        \fill[#1] (0, 0.5pt) -- ++ (-0.25, 0.075) -- ++ (0, -0.075) -- cycle;
    }

Just call this style pe=yellow, by default these style is red.

\documentclass[tikz, crop,border=1]{standalone}
\usetikzlibrary{decorations.markings}

\begin{document}
\begin{tikzpicture}
\tikzset{
    pe/.style={
        %line width = 1pt,
        decoration={
            markings, mark=at position 0.8 with {%
                \fill[#1] (0, 0.5pt) -- ++ (-0.25, 0.075) -- ++ (0, -0.075) -- cycle;
            }
        },
        postaction=decorate
    },
    pe/.default=red
}
% Incorrect
\draw[pe=yellow, draw = red] (0, 0) -- (1, 0);

% Incorrect
\draw[pe=black, draw = red, fill=blue] (0, 0.25) -- (1, 0.25) -- (1, 0.5) -- (0, 0.5) -- cycle;

% Correct
\draw[pe, red] (0, 0.6) -- (1, 0.6);

% Incorrect
\draw[pe, red, fill=blue] (0, 0.75) -- (1, 0.75) -- (1, 1) -- (0, 1) -- cycle;

% Correct, simulated
\fill[pe, fill=blue] (0, 1.1) -- (1, 1.1) -- (1, 1.35) -- (0, 1.35) -- cycle;
\end{tikzpicture}
\end{document}

pe default

Update

If I understood correctly, you must specify the color in the decoration.

decoration={
            markings, mark=at position 0.8 with {%
                \fill[red] (0, 0.5pt) -- ++ (-0.25, 0.075) -- ++ (0, -0.075) -- cycle;
            }
        },

decoration

\documentclass[tikz, crop,border=1]{standalone}
\usetikzlibrary{decorations.markings}

\begin{document}
\begin{tikzpicture}
\tikzset{
    pe/.style={
        %line width = 1pt,
        decoration={
            markings, mark=at position 0.8 with {%
                \fill[red] (0, 0.5pt) -- ++ (-0.25, 0.075) -- ++ (0, -0.075) -- cycle;
            }
        },
        postaction=decorate
    },
}

% Incorrect
\draw[pe, draw = red] (0, 0) -- (1, 0);

% Incorrect
\draw[pe, draw = red, fill=blue] (0, 0.25) -- (1, 0.25) -- (1, 0.5) -- (0, 0.5) -- cycle;

% Correct
\draw[pe, red] (0, 0.6) -- (1, 0.6);

% Incorrect
\draw[pe, red, fill=blue] (0, 0.75) -- (1, 0.75) -- (1, 1) -- (0, 1) -- cycle;

% Correct, simulated
\fill[pe, fill=blue] (0, 1.1) -- (1, 1.1) -- (1, 1.35) -- (0, 1.35) -- cycle;
\draw[pe, red] (0, 1.1) -- (1, 1.1) -- (1, 1.35) -- (0, 1.35) -- cycle;

\end{tikzpicture}
\end{document}

Simply by not specifying `draw=red`, but just `red`

    \draw[pe, red] (0, 0) -- (1, 0);

[![red][2]][2]

    \documentclass[tikz, crop,border=5mm]{standalone}
    \usetikzlibrary{decorations.markings}

    \begin{document}
    \begin{tikzpicture}
    \tikzset{
        pe/.style={
            decoration={
                markings, mark=at position 0.8 with {%
                    \fill (0, 0.5pt) -- ++ (-0.25, 0.075) -- ++ (0, -0.075) -- cycle;
                }
            },
            postaction=decorate
        }
    }
    \draw[pe, red] (0, 0) -- (1, 0);
    \end{tikzpicture}
    \end{document}
  • This modifies the fill color, which I want to control independently for filled polygons. – kaba Dec 10 '18 at 4:16
  • Show us an example of its effect. – AndréC Dec 10 '18 at 4:16
  • I was wrong in that it does not modify the fill color. However, specifying the fill color overrides the color for the arrow tip, which should not happen. – kaba Dec 10 '18 at 4:33
  • I don't understand what your problem is now, edit your question. – AndréC Dec 10 '18 at 4:34
  • Added new images. The arrow should respond to setting the draw color, and not respond to setting the fill color. – kaba Dec 10 '18 at 4:44
2

Just define a style for the arrow and set it accordingly.

\documentclass[tikz, crop,border=1]{standalone}
\usetikzlibrary{decorations.markings, decorations.pathreplacing}
\tikzset{pearrow/.style={fill},
peset/.code={\tikzset{pearrow/.style={#1}}}}
\newcommand{\drawArrow}[2]{
    \draw[
        decoration={
            markings,
            mark=at position 0.8 with {%
                \path[pearrow] (0, 0.5pt) -- ++ (-0.25, 0.075) -- ++ (0, -0.075) -- cycle;
            }
        },
        postaction=decorate
    ] #1 -- #2;
}

\begin{document}
\begin{tikzpicture}[scale=2]
\tikzset{
    pe/.style={
        line width = 1pt,
        decoration={
            show path construction, 
            lineto code={%
                \drawArrow{(\tikzinputsegmentfirst)}{(\tikzinputsegmentlast)}
            },
            closepath code={%
                \drawArrow{(\tikzinputsegmentfirst)}{(\tikzinputsegmentlast)}
            }
        },
        postaction=decorate
    }
}


% with peset
\draw[pe, red, fill=blue,peset={fill=red}] (0, 0.75) -- (1, 0.75) -- (1, 1) -- (0, 1) -- cycle;

% What I want, simulated
\fill[pe, fill=blue] (0, 1.1) -- (1, 1.1) -- (1, 1.35) -- (0, 1.35) -- cycle;
\draw[pe, red] (0, 1.1) -- (1, 1.1) -- (1, 1.35) -- (0, 1.35) -- cycle;

\end{tikzpicture}
\end{document}

enter image description here

2

The following findArrowColor style, based on this Georg Sievelson's answer, picks the current stroke color if such is available, then the current text color if such is available, and black color as the last resort.

enter image description here

\documentclass[tikz, crop,border=1]{standalone}
\usetikzlibrary{decorations.markings, decorations.pathreplacing}

\usepackage{ifthen}

\makeatletter
\tikzset{
  /tikz/findArrowColor/.style={/utils/exec={%
    \ifthenelse{\equal{\tikz@strokecolor}{}}%
    {%
        \ifthenelse{\equal{\tikz@textcolor}{}}%
        {%
            \colorlet{#1}{black}%
        }%
        {\colorlet{#1}{\tikz@textcolor}}%
    }%
    {%
        \colorlet{#1}{\tikz@strokecolor}%
    }%
  }}
}
\makeatother

\newcommand{\drawArrow}[2]{
    \draw[
        decoration={
            markings,
            mark=at position 0.8 with {%
                \begin{scope}
                    \tikzset{findArrowColor=arrowColor}
                    \fill[fill=arrowColor] (0, 0.5pt) -- ++ (-0.25, 0.075) -- ++ (0, -0.075) -- cycle;
                \end{scope}
            }
        },
        postaction=decorate
    ] #1 -- #2;
}

\begin{document}
\begin{tikzpicture}[scale=2]

\tikzset{
    pe/.style={
        line width = 1pt,
        decoration={
            show path construction, 
            lineto code={%
                \begin{scope}[#1]
                \drawArrow{(\tikzinputsegmentfirst)}{(\tikzinputsegmentlast)}
                \end{scope}
            },
            closepath code={%
                \begin{scope}[#1]
                \drawArrow{(\tikzinputsegmentfirst)}{(\tikzinputsegmentlast)}
                \end{scope}
            }
        },
        postaction=decorate
    }
}

\draw[pe, fill = blue] (0, -0.2) -- (1, -0.2);
\draw[pe, draw = red] (0, 0) -- (1, 0);
\draw[pe, draw = red, fill=blue] (0, 0.25) -- (1, 0.25) -- (1, 0.5) -- (0, 0.5) -- cycle;
\draw[pe, red, fill=blue] (0, 0.75) -- (1, 0.75) -- (1, 1) -- (0, 1) -- cycle;

\fill[fill=blue] (0, 1.1) -- (1, 1.1) -- (1, 1.35) -- (0, 1.35) -- cycle;
\draw[pe, red] (0, 1.1) -- (1, 1.1) -- (1, 1.35) -- (0, 1.35) -- cycle;

\end{tikzpicture}
\end{document}

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.