![TikZ: 閉じていない tikz パスの境界にパターンを描く方法](https://rvso.com/image/405338/TikZ%3A%20%E9%96%89%E3%81%98%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%20tikz%20%E3%83%91%E3%82%B9%E3%81%AE%E5%A2%83%E7%95%8C%E3%81%AB%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%82%92%E6%8F%8F%E3%81%8F%E6%96%B9%E6%B3%95.png)
「提供されたソリューションに基づいてTikZ: tikz パスの境界にパターンを描く方法1 つの図形を除いて、論文のすべてのグラフィックを作成できました。グラフィックでわかるように ( ;-)塗りつぶしルールと境界線のパターン)
ケース c) に示すように、開始と終了が接続されていないオープン パスを描画したいのですが、ケース a) と b) に示すように、パターンで装飾したいだけです。現在、パスの一部を白い四角形で隠すことで、この問題を解決しようとしています。問題は、パターンを適用できるのは閉じたパスだけであることです。cycle
スタイルを持つパスの末尾のまたは を削除するとすぐにEDR
、EDO
次のエラーが発生します。Package tikz Error: Cannot parse this coordinate.
開いたパスをパターンで装飾するにはどうすればよいでしょうか? この図に示すように (inkscape で修正)
MWE:
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usetikzlibrary{decorations,backgrounds}
% BEGIN from https://tex.stackexchange.com/a/419558/11820
\newcounter{tmp}
%\tikzstyle{D}=[draw=blue,line width=1pt,preaction={clip, postaction={draw=blue,opacity=0.5,line width=12pt}}]
%<- note that tikzstyle is deprecated
\tikzset{D/.style={
preaction={draw=blue,line width=1pt},
preaction={decoration={contour lineto closed, contour distance=6pt},
decorate,
},
postaction={
insert path={%
\pgfextra{%
\pgfinterruptpath
\begin{scope}[opacity=0.5, transparency group]
\path[fill=blue,even odd rule]
\mySecondList \myList
;
\end{scope}
\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[pattern=north west lines, pattern color=red,even odd rule]
\mySecondList \myList
;
\endpgfinterruptpath}
}},
}}
\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]{%
\pgfextra{\xdef\myList{}\xdef\mySecondList{}}
\pgfextra{\setcounter{tmp}{0}}
\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\thetmp}{\pgfpoint{\pgfdecoratedinputsegmentlength+\pgf@decoration@contour@shorten}
{\pgfdecoratedcontourdistance}}
\pgfcoordinate{feep\thetmp}{\pgfpoint{\pgfdecoratedinputsegmentlength}{0pt}}
\pgfextra{\xdef\myList{\myList (muemmel\thetmp) -- }%
\xdef\mySecondList{\mySecondList (feep\thetmp) -- }}
\ifpgf@decorate@is@closepath@%
\pgfpathclose
\pgfextra{\xdef\myList{\myList cycle}%
\xdef\mySecondList{\mySecondList cycle}}
\fi
}%
\state{final}{\pgfextra{%\typeout{\myList,\mySecondList}
}}%
}
\makeatother
\tikzset{
contour/.style={
decoration={
name=contour lineto closed,
contour distance=#1
},
decorate}}
% END from https://tex.stackexchange.com/a/419558/11820
\tikzset{EDO/.style={
preaction={draw=orange,line width=1pt},
preaction={decoration={contour lineto closed, contour distance=6pt},
decorate,
},
postaction={
insert path={%
\pgfextra{%
\pgfinterruptpath
\path[pattern=north east lines, pattern color=orange,even odd rule]
\mySecondList \myList
;
\endpgfinterruptpath}
}},
}}
\begin{document}
\begin{tikzpicture}[]
\node at (-.5,0) {a)};
\path [EDO] (2.875,0) -- ++(0,.75) -- ++(-2.875,0) -- ++(0,-.75) -- cycle;
\path [EDR] (0,0) -- ++(0,-1) -- ++(6,0) -- ++(0,1) -- ++(-3.125,0) -- cycle ;
\fill [white] (.21,.3) rectangle (2.655,-.3);
\begin{scope}[yshift=-2cm]
\node at (-.5,0) {b)};
\path [EDO] (2.875,0) -- ++(0,.75) -- ++(-2.875,0) -- ++(0,-.75) -- cycle;
\path [EDR] (0,0) -- ++(0,-1) -- ++(6,0) -- ++(0,1) -- ++(-3.125,0) -- cycle ;
\end{scope}
\begin{scope}[yshift=-4cm]
\node at (-.5,0) {c)};
\path [draw, orange, line width=1pt] (2.875,0) -- ++(0,.75) -- ++(-2.875,0) -- ++(0,-.75);
\path [draw, red, line width=1pt] (0,0) -- ++(0,-1) -- ++(6,0) -- ++(0,1) -- ++(-3.125,0);
\end{scope}
\end{tikzpicture}
\end{document}
答え1
これは、それを実行するコードの一般化です。閉じたパスと閉じていないパスを区別します。
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usetikzlibrary{decorations,backgrounds}
% BEGIN from https://tex.stackexchange.com/a/419558/11820
\newcounter{tmp}
\newif\ifpathisclosed
%\tikzstyle{D}=[draw=blue,line width=1pt,preaction={clip, postaction={draw=blue,opacity=0.5,line width=12pt}}]
%<- note that tikzstyle is deprecated
\tikzset{D/.style={
preaction={draw=blue,line width=1pt},
preaction={decoration={contour lineto closed, contour distance=6pt},
decorate,
},
postaction={
insert path={%
\pgfextra{%
\pgfinterruptpath
\begin{scope}[opacity=0.5, transparency group]
\path[fill=blue,even odd rule]
\mySecondList \myList
;
\end{scope}
\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[pattern=north west lines, pattern color=red,even odd rule]
\mySecondList \myList
;
\endpgfinterruptpath}
}},
}}
\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}}
% END from https://tex.stackexchange.com/a/419558/11820
\tikzset{EDO/.style={
preaction={draw=orange,line width=1pt},
preaction={decoration={contour lineto closed, contour distance=6pt},
decorate,
},
postaction={
insert path={%
\pgfextra{%
\pgfinterruptpath
\path[pattern=north east lines, pattern color=orange,even odd rule]
\mySecondList \myList
;
\endpgfinterruptpath}
}},
}}
\begin{document}
\begin{tikzpicture}[]
\path [EDO] (2.875,3) -- ++(0,.75) -- ++(-2.875,0) -- ++(0,-.75) -- cycle;
\path [EDR] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1) -- ++(-3.125,0) -- cycle ;
\fill [white] (.21,3.3) rectangle (2.655,2.7);
\begin{scope}[yshift=-2cm]
\path [EDO] (2.875,3) -- ++(0,.75) -- ++(-2.875,0) -- ++(0,-.75) -- cycle;
\path [EDR] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1) -- ++(-3.125,0) -- cycle ;
\end{scope}
\begin{scope}[yshift=-4cm]
\path [EDO,draw, orange, line width=1pt] (2.875,3) -- ++(0,.75) -- ++(-2.875,0) -- ++(0,-.75);
\path [EDR,draw, red, line width=1pt] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1) -- ++(-3.125,0);
\end{scope}
\begin{scope}[yshift=-6cm]
\path [EDO,draw, orange, line width=1pt] (2.875,3) -- ++(0,.75) -- ++(-2.875,0) -- ++(0,-.75);
\path [EDR,draw, red, line width=1pt,shorten >=6pt] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1)
-- ++(-3.125cm-6pt,0);
\end{scope}
\end{tikzpicture}
\end{document}
上から数えて 3 番目 (または最後から 2 番目) のパスがデフォルトで取得されます。これは、パスが他のパスが何であるかを認識していないためです。必要な出力を生成するには、 を使用する必要があります ( shorten
4 番目 (または最後) の図を参照)。
これは、より合理化されたバージョンです。
\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{patterns,decorations}
% BEGIN from https://tex.stackexchange.com/a/419558/11820
\tikzset{D/.style={
preaction={draw=blue,line width=1pt},
preaction={decoration={contour lineto closed, contour distance=6pt},
decorate,
},
postaction={
insert path={%
\pgfextra{%
\pgfinterruptpath
\begin{scope}[opacity=0.5, transparency group]
\path[fill=blue,even odd rule]
\mySecondList \myList
;
\end{scope}
\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[pattern=north west lines, pattern color=red,even odd rule]
\mySecondList \myList
;
\endpgfinterruptpath}
}},
}}
\makeatletter
\newif\ifdeco@path@is@closed
\newcounter{deco@count}
\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{deco@count}{0}%
\global\deco@path@is@closedfalse%
\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{deco@count}%
\pgfcoordinate{muemmel\number\value{deco@count}}{\pgfpoint{\pgfdecoratedinputsegmentlength+\pgf@decoration@contour@shorten}
{\pgfdecoratedcontourdistance}}%
\pgfcoordinate{feep\number\value{deco@count}}{\pgfpoint{\pgfdecoratedinputsegmentlength}{0pt}}%
\ifnum\value{deco@count}=1\relax%
\pgfcoordinate{muemmel0}{\pgfpoint{0pt}{\pgfdecoratedcontourdistance}}%
\pgfcoordinate{feep0}{\pgfpoint{0pt}{0pt}}%
\xdef\myList{(muemmel\number\value{deco@count})}%
\xdef\mySecondList{(feep\number\value{deco@count})}%
\else
\xdef\myList{\myList -- (muemmel\number\value{deco@count})}%
\xdef\mySecondList{(feep\number\value{deco@count}) -- \mySecondList}%
\fi
\ifpgf@decorate@is@closepath@%
\pgfpathclose
\global\deco@path@is@closedtrue%
\fi
}%
\state{final}{%\typeout{\myList,\mySecondList}%
\ifdeco@path@is@closed%
\xdef\myList{\myList -- cycle}%
\xdef\mySecondList{\mySecondList -- cycle}%
%\typeout{closed \mySecondList \myList }
\else
%\typeout{\number\value{deco@count}}%
\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}}
% END from https://tex.stackexchange.com/a/419558/11820
\tikzset{EDO/.style={
preaction={draw=orange,line width=1pt},
preaction={decoration={contour lineto closed, contour distance=6pt},
decorate,
},
postaction={
insert path={%
\pgfextra{%
\pgfinterruptpath
\path[pattern=north east lines, pattern color=orange,even odd rule]
\mySecondList \myList
;
\endpgfinterruptpath}
}},
}}
\begin{document}
\begin{tikzpicture}[]
\path [EDO,draw, orange, line width=1pt] (2.875,3) -- ++(0,.75) -- ++(-2.875,0) -- ++(0,-.75);
\path [EDR,draw, red, line width=1pt,shorten >=6pt-\pgflinewidth/2] (0,3) -- ++(0,-1) -- ++(6,0) -- ++(0,1)
-- ++(-3.125cm-6pt,0);
\end{tikzpicture}
\end{document}
少し整理しました。ただし、\pgfextra
パスに の使用をやめるという作業は行いませんでした。これは避けるべきことです。この場合は問題ないようです。よりクリーンなバージョンを書くこともできますが、パターンにコマンドを追加する必要があります。これを詳しく説明する必要がある場合はお知らせください。
答え2
1 つの方法は、draw
3 番目の例のように、装飾から部分を削除し、装飾を行った後に線を描くことです。
MWE を変更しました:
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usetikzlibrary{decorations,backgrounds}
% BEGIN from https://tex.stackexchange.com/a/419558/11820
\newcounter{tmp}
%\tikzstyle{D}=[draw=blue,line width=1pt,preaction={clip, postaction={draw=blue,opacity=0.5,line width=12pt}}]
%<- note that tikzstyle is deprecated
\tikzset{D/.style={
preaction={draw=blue,line width=1pt},
preaction={decoration={contour lineto closed, contour distance=6pt},
decorate,
},
postaction={
insert path={%
\pgfextra{%
\pgfinterruptpath
\begin{scope}[opacity=0.5, transparency group]
\path[fill=blue,even odd rule]
\mySecondList \myList
;
\end{scope}
\endpgfinterruptpath}
}},
}}
\tikzset{EDR/.style={
% preaction={draw=red,line width=1pt}, %<- remove this line
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}
}},
}}
\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]{%
\pgfextra{\xdef\myList{}\xdef\mySecondList{}}
\pgfextra{\setcounter{tmp}{0}}
\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\thetmp}{\pgfpoint{\pgfdecoratedinputsegmentlength+\pgf@decoration@contour@shorten}
{\pgfdecoratedcontourdistance}}
\pgfcoordinate{feep\thetmp}{\pgfpoint{\pgfdecoratedinputsegmentlength}{0pt}}
\pgfextra{\xdef\myList{\myList (muemmel\thetmp) -- }%
\xdef\mySecondList{\mySecondList (feep\thetmp) -- }}
\ifpgf@decorate@is@closepath@%
\pgfpathclose
\pgfextra{\xdef\myList{\myList cycle}%
\xdef\mySecondList{\mySecondList cycle}}
\fi
}%
\state{final}{\pgfextra{%\typeout{\myList,\mySecondList}
}}%
}
\makeatother
\tikzset{
contour/.style={
decoration={
name=contour lineto closed,
contour distance=#1
},
decorate}}
% END from https://tex.stackexchange.com/a/419558/11820
\tikzset{EDO/.style={
% preaction={draw=orange,line width=1pt}, %<- remove this line
preaction={decoration={contour lineto closed, contour distance=6pt},
decorate,
},
postaction={
insert path={%
\pgfextra{%
\pgfinterruptpath
\path[pattern=north east lines, pattern color=orange,even odd rule]
\mySecondList \myList
;
\endpgfinterruptpath}
}},
}}
\begin{document}
\begin{tikzpicture}[]
\node at (-.5,0) {a)};
\path [EDO] (2.875,0) -- ++(0,.75) -- ++(-2.875,0) -- ++(0,-.75) -- cycle;
\path [EDR] (0,0) -- ++(0,-1) -- ++(6,0) -- ++(0,1) -- ++(-3.125,0) -- cycle ;
\fill [white] (.21,.3) rectangle (2.655,-.3);
\path [draw, orange, line width=1pt] (2.875,0) -- ++(0,.75) -- ++(-2.875,0) -- ++(0,-.75);
\path [draw, red, line width=1pt] (0,0) -- ++(0,-1) -- ++(6,0) -- ++(0,1) -- ++(-3.125,0);
\end{tikzpicture}
\end{document}
答え3
上記のコードは必然的に長くて複雑になるので、単純な TikZ を使用します。パラメータの意味は明確で、好きなように色を変更できます。
even odd rule
パターンの塗りつぶしオプションnorth west lines
は役立ちます。
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{patterns}
\begin{document}
\begin{tikzpicture}[thick,declare function={a=3;b=1.2;c=3.5;d=1;m=.2;}]
\path
(0,0) coordinate (A) +(m,m) coordinate (At)
(a,b+d) coordinate (B) +(-m,-m) coordinate (Bt)
(a+c,b) coordinate (C) +(-m,-m) coordinate (Ct)
;
\draw[blue,pattern=north west lines,pattern color=red!50,even odd rule]
(A)|-(B)|-(C)|-cycle (At)|-(Bt)|-(Ct)|-cycle;
\end{tikzpicture}
\end{document}