![TikZ: Cómo dibujar un patrón en el borde de un camino tikz no cerrado](https://rvso.com/image/405338/TikZ%3A%20C%C3%B3mo%20dibujar%20un%20patr%C3%B3n%20en%20el%20borde%20de%20un%20camino%20tikz%20no%20cerrado.png)
"Basado en la solución proporcionada enTikZ: Cómo dibujar un patrón en el borde de un camino tikzPude hacer todos los gráficos de mi tesis, excepto una forma. Como puedes ver en el gráfico" ( ;-)Regla de relleno y patrón en el borde.)
Me gustaría dibujar un patrón abierto, donde el principio y el final no estén conectados, como se muestra en el caso c) solo que quiero decorarlo con un patrón, como se puede ver en los casos a) y b). Actualmente trato de ayudarme ocultando una parte del camino con un rectángulo blanco. El problema es que sólo puedo aplicar el patrón a caminos cerrados. Tan pronto como elimino el cycle
al final de una ruta que tiene el estilo EDR
o EDO
aparece el error:Package tikz Error: Cannot parse this coordinate.
¿Cómo puedo decorar un camino abierto con un patrón? Como se muestra en esta figura (modificada con inkscape).
El 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}
Respuesta1
Esta es una generalización de su código que hace eso. Distingue entre caminos cerrados y no cerrados.
\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}
Contando desde arriba, la tercera (o penúltima) ruta es la que obtienes de forma predeterminada. Esto se debe a que el camino no sabe que el otro camino es lo que es. Para generar el resultado deseado, hay que utilizar shorten
, consulte la cuarta (o última) imagen.
Esta es una versión más simplificada del mismo.
\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}
Me limpié un poco. Sin embargo, hay una cosa que no hice: dejar de usarlo \pgfextra
para caminos. Esto es algo que se debe evitar. En este mismo caso parece estar bien. También se podría escribir una versión más limpia, pero esto requeriría agregar un comando adicional para el patrón. Por favor, avíseme si desea que esto se explique en detalle.
Respuesta2
Una forma de hacerlo es quitar la draw
parte de la decoración y luego dibujar las líneas después de hacer la decoración, como tercer ejemplo.
Modifiqué tu 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}
Respuesta3
Observo que el código anterior es necesariamente largo y completo, por lo que uso TikZ simple. El significado de los parámetros es claro y puedes cambiar el color como quieras.
La opción de relleno even odd rule
del north west lines
patrón hace el trabajo.
\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}