Tikz:在路径旁边绘制并填充图案

Tikz:在路径旁边绘制并填充图案

TikZ:如何在未封闭的 tikz 路径的边界上绘制图案,解决方案在一条线旁边绘制了一个阴影图案。我想调整它以填充图案后面的空间以掩盖阴影之前绘制的东西,但在我认为合乎逻辑的地方添加“填充”不起作用(根据% MODIFIED: added fill=whiteMWE 中的评论)。MWE:

\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usetikzlibrary{decorations,backgrounds}

% BEGIN from https://tex.stackexchange.com/questions/518580/tikz-how-to-draw-a-pattern-at-the-border-of-a-not-closed-tikz-path
\newcounter{tmp}
\newif\ifpathisclosed

\makeatletter
\def\pgfdecoratedcontourdistance{0pt}
\pgfset{
    decoration/contour distance/.code=%
    \pgfmathsetlengthmacro\pgfdecoratedcontourdistance{#1}}
\pgfdeclaredecoration{contour lineto closed}{start}{%
    \state{start}[
    next state=draw,
    width=0pt,
    persistent precomputation=\let\pgf@decorate@firstsegmentangle\pgfdecoratedangle]{%
        %\xdef\myList{}\xdef\mySecondList{}%
        \setcounter{tmp}{0}%
        \global\pathisclosedfalse%
        \pgfpathmoveto{\pgfpointlineattime{.5}
            {\pgfqpoint{0pt}{\pgfdecoratedcontourdistance}}
            {\pgfqpoint{\pgfdecoratedinputsegmentlength}{\pgfdecoratedcontourdistance}}}%
    }%
    \state{draw}[next state=draw, width=\pgfdecoratedinputsegmentlength]{%
        \ifpgf@decorate@is@closepath@%
        \pgfmathsetmacro\pgfdecoratedangletonextinputsegment{%
            -\pgfdecoratedangle+\pgf@decorate@firstsegmentangle}%
        \fi
        \pgfmathsetlengthmacro\pgf@decoration@contour@shorten{%
            -\pgfdecoratedcontourdistance*cot(-\pgfdecoratedangletonextinputsegment/2+90)}%
        \pgfpathlineto
        {\pgfpoint{\pgfdecoratedinputsegmentlength+\pgf@decoration@contour@shorten}
            {\pgfdecoratedcontourdistance}}%
        \stepcounter{tmp}%
        \pgfcoordinate{muemmel\number\value{tmp}}{\pgfpoint{\pgfdecoratedinputsegmentlength+\pgf@decoration@contour@shorten}
            {\pgfdecoratedcontourdistance}}%
        \pgfcoordinate{feep\number\value{tmp}}{\pgfpoint{\pgfdecoratedinputsegmentlength}{0pt}}%      
        \ifnum\value{tmp}=1\relax%
        \pgfcoordinate{muemmel0}{\pgfpoint{0pt}{\pgfdecoratedcontourdistance}}%
        \pgfcoordinate{feep0}{\pgfpoint{0pt}{0pt}}%      
        \xdef\myList{(muemmel\number\value{tmp})}%
        \xdef\mySecondList{(feep\number\value{tmp})}%
        \else
        \xdef\myList{\myList -- (muemmel\number\value{tmp})}%
        \xdef\mySecondList{(feep\number\value{tmp}) -- \mySecondList}%
        \fi 
        \ifpgf@decorate@is@closepath@%
        \pgfpathclose
        \global\pathisclosedtrue%
        \fi
    }%
    \state{final}{%\typeout{\myList,\mySecondList}%
        \ifpathisclosed%
        \xdef\myList{\myList -- cycle}% 
        \xdef\mySecondList{\mySecondList -- cycle}%
        %\typeout{closed \mySecondList \myList }
        \else
        %\typeout{\number\value{tmp}}%
        \xdef\myList{(muemmel0) -- \myList -- cycle}% 
        \xdef\mySecondList{\mySecondList -- (feep0) --}%
        %\typeout{not closed \mySecondList \myList }%   
        \fi
    }%
}
\makeatother
\tikzset{
    contour/.style={
        decoration={
            name=contour lineto closed,
            contour distance=#1
        },
        decorate}
}
    
\tikzset{EDR/.style={
        preaction={draw=red,line width=1pt},
        preaction={decoration={contour lineto closed, contour distance=6pt},
            decorate,
        },
        postaction={
            insert path={%
                \pgfextra{%
                    \pgfinterruptpath
                    \path[pattern=north west lines, pattern color=red,even odd rule] 
                    \mySecondList \myList 
                    ;
                    \endpgfinterruptpath}
        }},
}}
    
% END from https://tex.stackexchange.com/questions/518580/tikz-how-to-draw-a-pattern-at-the-border-of-a-not-closed-tikz-path

\tikzset{EDRB/.style={
        preaction={draw=red,line width=1pt},
        preaction={decoration={contour lineto closed, contour distance=6pt},
            decorate,
        },
        postaction={
            insert path={%
                \pgfextra{%
                    \pgfinterruptpath
                    \path[fill=white,pattern=north west lines, pattern color=red,even odd rule] % MODIFIED: added fill=white
                    \mySecondList \myList 
                    ;
                    \endpgfinterruptpath}
        }},
}}

\begin{document}
    
    \begin{tikzpicture}
        \node at (3,3.5) {Current};
        
            \draw[ultra thick,blue] (0,3) -- (6,2);
            \path [EDR,draw, red, line width=1pt] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1) 
                -- ++(-3.125cm-6pt,0);
                
        \begin{scope}[shift={(0,-3)}]
            
            \node at (3,3.5) {Desired};
            
            \begin{scope}
                \clip (6pt,3) rectangle (6cm-6pt,2cm+6pt);
                \draw[ultra thick,blue] (0,3) -- (6,2);
            \end{scope}

            \path [EDR,draw, red, line width=1pt] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1) 
            -- ++(-3.125cm-6pt,0);
            
        \end{scope}
    
        \begin{scope}[shift={(0,-6)}]
            
            \node at (3,3.5) {Attempt: ``EDRB'' Style};
            
            \draw[ultra thick,blue] (0,3) -- (6,2);
            
            \path [EDR,draw, red, line width=1pt] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1) 
            -- ++(-3.125cm-6pt,0);
            
        \end{scope}
    \end{tikzpicture}

    
\end{document}

MWE 输出:

在此处输入图片描述

有没有办法在图案后面添加填充?

答案1

我能够拼凑出一些可行的东西。需要做的更改如下:

  1. 在应用填充的块\path中添加一个单独的\pgfextra{}
  2. draw在列表中添加一个新元素postaction,使边缘线位于填充上方(如果没有这个元素,边缘线将位于填充下方,因此其一半宽度会被遮挡

那么 MWE 就是:

\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usetikzlibrary{decorations,backgrounds}

% BEGIN from https://tex.stackexchange.com/questions/518580/tikz-how-to-draw-a-pattern-at-the-border-of-a-not-closed-tikz-path
\newcounter{tmp}
\newif\ifpathisclosed

\makeatletter
\def\pgfdecoratedcontourdistance{0pt}
\pgfset{
    decoration/contour distance/.code=%
    \pgfmathsetlengthmacro\pgfdecoratedcontourdistance{#1}}
\pgfdeclaredecoration{contour lineto closed}{start}{%
    \state{start}[
    next state=draw,
    width=0pt,
    persistent precomputation=\let\pgf@decorate@firstsegmentangle\pgfdecoratedangle]{%
        %\xdef\myList{}\xdef\mySecondList{}%
        \setcounter{tmp}{0}%
        \global\pathisclosedfalse%
        \pgfpathmoveto{\pgfpointlineattime{.5}
            {\pgfqpoint{0pt}{\pgfdecoratedcontourdistance}}
            {\pgfqpoint{\pgfdecoratedinputsegmentlength}{\pgfdecoratedcontourdistance}}}%
    }%
    \state{draw}[next state=draw, width=\pgfdecoratedinputsegmentlength]{%
        \ifpgf@decorate@is@closepath@%
        \pgfmathsetmacro\pgfdecoratedangletonextinputsegment{%
            -\pgfdecoratedangle+\pgf@decorate@firstsegmentangle}%
        \fi
        \pgfmathsetlengthmacro\pgf@decoration@contour@shorten{%
            -\pgfdecoratedcontourdistance*cot(-\pgfdecoratedangletonextinputsegment/2+90)}%
        \pgfpathlineto
        {\pgfpoint{\pgfdecoratedinputsegmentlength+\pgf@decoration@contour@shorten}
            {\pgfdecoratedcontourdistance}}%
        \stepcounter{tmp}%
        \pgfcoordinate{muemmel\number\value{tmp}}{\pgfpoint{\pgfdecoratedinputsegmentlength+\pgf@decoration@contour@shorten}
            {\pgfdecoratedcontourdistance}}%
        \pgfcoordinate{feep\number\value{tmp}}{\pgfpoint{\pgfdecoratedinputsegmentlength}{0pt}}%      
        \ifnum\value{tmp}=1\relax%
        \pgfcoordinate{muemmel0}{\pgfpoint{0pt}{\pgfdecoratedcontourdistance}}%
        \pgfcoordinate{feep0}{\pgfpoint{0pt}{0pt}}%      
        \xdef\myList{(muemmel\number\value{tmp})}%
        \xdef\mySecondList{(feep\number\value{tmp})}%
        \else
        \xdef\myList{\myList -- (muemmel\number\value{tmp})}%
        \xdef\mySecondList{(feep\number\value{tmp}) -- \mySecondList}%
        \fi 
        \ifpgf@decorate@is@closepath@%
        \pgfpathclose
        \global\pathisclosedtrue%
        \fi
    }%
    \state{final}{%\typeout{\myList,\mySecondList}%
        \ifpathisclosed%
        \xdef\myList{\myList -- cycle}% 
        \xdef\mySecondList{\mySecondList -- cycle}%
        %\typeout{closed \mySecondList \myList }
        \else
        %\typeout{\number\value{tmp}}%
        \xdef\myList{(muemmel0) -- \myList -- cycle}% 
        \xdef\mySecondList{\mySecondList -- (feep0) --}%
        %\typeout{not closed \mySecondList \myList }%   
        \fi
    }%
}
\makeatother
\tikzset{
    contour/.style={
        decoration={
            name=contour lineto closed,
            contour distance=#1
        },
        decorate}
}

\tikzset{D/.style={
        preaction={draw=blue,line width=1pt},
        preaction={decoration={contour lineto closed, contour distance=6pt},
            decorate,
        },
        postaction={
            insert path={%
                \pgfextra{%
                    \pgfinterruptpath
                    \path[fill=white,even odd rule] 
                    \mySecondList \myList 
                    ;
                    \path[pattern=north west lines, pattern color=red,even odd rule] 
                    \mySecondList \myList 
                    ;
                    \endpgfinterruptpath}
        }},
}}
\tikzset{EDR/.style={
        preaction={draw=red,line width=1pt},
        preaction={decoration={contour lineto closed, contour distance=6pt},
            decorate,
        },
        postaction={
            insert path={%
                \pgfextra{%
                    \pgfinterruptpath
                    \path[fill=white,even odd rule] 
                    \mySecondList \myList 
                    ;
                    \path[pattern=north west lines, pattern color=red,even odd rule] 
                    \mySecondList \myList 
                    ;
                    \endpgfinterruptpath}
        }},
}}
    
% END from https://tex.stackexchange.com/questions/518580/tikz-how-to-draw-a-pattern-at-the-border-of-a-not-closed-tikz-path

\tikzset{
    EDRB fill color/.initial=white, % NEW
    EDRB fill color/.get=\EDRBfillcolor, % NEW
    EDRB fill color/.store in=\EDRBfillcolor, % NEW
    EDRB/.style={
        preaction={decoration={contour lineto closed, contour distance=6pt},
            decorate,
        },
        postaction={
            insert path={%
                \pgfextra{%
                    \pgfinterruptpath
                    \path[fill=\EDRBfillcolor,even odd rule] % NEW
                    \mySecondList \myList % NEW
                    ; % NEW
                    \path[pattern=north west lines,pattern color=red,even odd rule]
                    \mySecondList \myList 
                    ;
                    \endpgfinterruptpath}
            },
            draw=red,% NEW
        },
    }
}

\begin{document}
    
    \begin{tikzpicture}
        \node at (3,3.5) {Current};
        
            \draw[ultra thick,blue] (0,3) -- (6,2);
            \path [EDR,draw, red, line width=1pt] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1) 
                -- ++(-3.125cm-6pt,0);
                
        \begin{scope}[shift={(0,-3)}]
            
            \node at (3,3.5) {Desired};
            
            \begin{scope}
                \clip (6pt,3) rectangle (6cm-6pt,2cm+6pt);
                \draw[ultra thick,blue] (0,3) -- (6,2);
            \end{scope}

            \path [EDR,draw, red, line width=1pt] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1) 
            -- ++(-3.125cm-6pt,0);
            
        \end{scope}
    
        \begin{scope}[shift={(0,-6)}]
            
            \node at (3,3.5) {Acceptable: ``EDRB'' Style};
            
            \draw[ultra thick,blue] (0,3) -- (6,2);
            
            \path [EDRB, line width=1pt] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1) 
            -- ++(-3.125cm-6pt,0);
            
        \end{scope}
    \end{tikzpicture}

    
\end{document}

输出: 在此处输入图片描述

我可以接受左上角阴影线外面延伸的蓝色部分。

相关内容