![Tikz:在路径旁边绘制并填充图案](https://linux22.com/image/465728/Tikz%EF%BC%9A%E5%9C%A8%E8%B7%AF%E5%BE%84%E6%97%81%E8%BE%B9%E7%BB%98%E5%88%B6%E5%B9%B6%E5%A1%AB%E5%85%85%E5%9B%BE%E6%A1%88.png)
在TikZ:如何在未封闭的 tikz 路径的边界上绘制图案,解决方案在一条线旁边绘制了一个阴影图案。我想调整它以填充图案后面的空间以掩盖阴影之前绘制的东西,但在我认为合乎逻辑的地方添加“填充”不起作用(根据% MODIFIED: added fill=white
MWE 中的评论)。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
我能够拼凑出一些可行的东西。需要做的更改如下:
- 在应用填充的块
\path
中添加一个单独的\pgfextra{}
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}
我可以接受左上角阴影线外面延伸的蓝色部分。