第一次尝试:

第一次尝试:

我怎样才能(有可能)制作一种装饰风格,以一条路径(或可能多条路径,那就完美了)作为参数,并在路径相交处制作圆弧、蛇形、椭圆形(无论什么)?我见过以下两种方法:

但是它们相当详尽,特别是如果一条路径与另一条路径有多个交点,那么这会变得非常详尽。此外,它们大多仅限于直线。

第一次尝试:

受到 Emma 的回答的启发这个问题我能够组装一个 MWE,但它仍然不够好,因为它不支持曲线路径,并且线条不会连接(如果使用多个坐标来构建路径)。除此之外,无法控制跳跃大小...

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing,intersections,calc}
\tikzset{
    over path/.style={
        decoration={show path construction, lineto code={
          \path[name path=this path] (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
          \path[name intersections={of=this path and #1, total=\t}, /utils/exec={\global\let\t=\t}]%
                                    let \n1={int(\t+1)} in%
                                    (\tikzinputsegmentfirst) coordinate (int-0)%
                                    foreach \i in {1,...,\n1}{%
                                      \ifnum \i<\n1%
                                          (intersection-\i) coordinate (int-\i)%
                                      \else
                                          (\tikzinputsegmentlast) coordinate (int-\n1)%
                                      \fi};
          \draw (\tikzinputsegmentfirst) foreach[remember=\i as \last (initially 0)] \i in {1,...,\t}{%
            let \p1=($(int-\last)-(int-\i)$), \n1={veclen(\x1,\y1)}, \n2={abs(4pt)}, \n3={\i+1}  in%
            [rounded corners=\n2/4] -- ($(int-\last)!\n1-\n2!(int-\i)$) to[bend left=90, looseness=1.7] ($(int-\last)!\n1+\n2!(int-\n3)$)} -- (\tikzinputsegmentlast);
                }
            },
            decorate
        }
    }

\begin{document}
\begin{tikzpicture}
    \coordinate (a) at (-1,0.5);
    \coordinate (b) at (8,0.5);
    \coordinate (c) at (3,-0.5);
    \draw[ultra thick, name path=sine, domain=-1:8, smooth, samples=50] plot (\x,{sin(\x r)});
    \draw[over path=sine] (a) -- (c) |- (b);
\end{tikzpicture}
\end{document}

在此处输入图片描述

线路连接不良:

在此处输入图片描述

答案1

这是使用spath3库。其工作原理如下:

  1. 在上方路径与下方路径的相交处分割上方路径。
  2. 在这些点处的路径上插入间隙。
  3. 将圆弧接合到这些间隙中(将其连接到现有路径,以使连接无缝)。
  4. 在下部路径与新的上部路径相交处分割下部路径。
  5. 在这些点的下方路径中插入小间隙。

开发版本(github——即将在 CTAN 上发布)包含一个版本的拼接代码,可确保弧线始终“直立”。这将很快在 CTAN 上发布。

结果如下:

正弦波上的桥梁

\documentclass{article}
%\url{https://tex.stackexchange.com/q/334483/86}
\usepackage{tikz}
\usetikzlibrary{spath3,intersections}


\begin{document}
\begin{tikzpicture}
\coordinate (a) at (-1,0.5);
\coordinate (b) at (8,0.5);
\coordinate (c) at (3,-0.5);
\path[
  ultra thick,
  spath/save=sine,
  domain=-1:8,
  smooth,
  samples=50
] plot (\x,{sin(\x r)});
\path[spath/save=over] (a) -- (c) |- (b);

\path[spath/save=arc] (0,0) arc[radius=1cm, start angle=180, delta angle=-180];

\tikzset{
  spath/split at intersections with={over}{sine},
  spath/insert gaps after components={over}{8pt},
  spath/join components with={over}{arc},
  spath/split at intersections with={sine}{over},
  spath/insert gaps after components={sine}{4pt},
}

\draw[spath/use=sine];
\draw[spath/use=over];
\end{tikzpicture}
\end{document}

答案2

这是一个解决方案。它是全自动的,即使对于曲线也应该很好。符号是avoid intersection={name of other path}{drawing options}。它会找到交叉点列表,然后执行一个装饰,测量到下一个交叉点的距离,当距离很近时,进行规避动作。使用选项avoid intersect amplitudeavoid intersect width和,avoid intersect offset您可以调整规避动作。

它并不完美。它非常慢(在我的电脑上,这两个示例分别需要 1.4 秒和 3.8 秒),这可能是不可避免的。此外,如果您smooth在下面的第二个示例中包含该选项,它会因“维度太大”错误而中断。我不知道为什么。我认为输出看起来非常好。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations}
\usetikzlibrary{intersections}

\makeatletter
\tikzset{
  avoid intersection amplitude/.store in=\avint@amplitude,
  avoid intersection width/.code={\edef\avint@width{\dimexpr#1/2}},
  avoid intersection offset/.store in=\avint@offset,
  avoid intersection has corners/.code={\pgfdecoratepathhascornerstrue}
}
\def\avint@amplitude{5pt}
\def\avint@width{5pt}
\def\avint@offset{0pt}

\pgfdeclaredecoration{avoidintersect}{initial}{
  \state{initial}[width=\pgfdecoratedinputsegmentlength/100,next state=measure]
  {
    \gdef\avint@intersectionnumber{1}
    \pgfpathlineto{\pgfpointorigin}
  }

  \state{measure}[width=\pgfdecoratedinputsegmentlength/100,next state=wait,auto corner on length=2pt,
               persistent postcomputation=\let\pgf@decorate@next@state\avint@smuggle@pgf@decorate@next@state]
  {
    \pgfpathlineto{\pgfpointorigin}
    \pgfgettransform\avint@temptransform
    \pgftransforminvert
    \pgfpointintersectionsolution{\avint@intersectionnumber}
    \pgf@pos@transform{\pgf@x}{\pgf@y}
    \pgfmathveclen{\pgf@x}{\pgf@y}
    \pgfsettransform\avint@temptransform
    \xdef\avint@waitcycles{\the\numexpr\dimexpr\pgfmathresult pt-\avint@width*3-\avint@offset\relax/\dimexpr\pgfdecoratedinputsegmentlength/100\relax}
    \ifnum\avint@waitcycles>50\relax\gdef\avint@waitcycles{50}\fi
    \global\let\avint@smuggle@pgf@decorate@next@state\pgf@decorate@next@state        
    \ifdim\pgfmathresult pt<\dimexpr\avint@width+\avint@offset\relax
        \gdef\avint@smuggle@pgf@decorate@next@state{zig}
    \else
        \ifdim\pgfmathresult pt<\dimexpr\avint@width*2+\avint@offset\relax
            \gdef\avint@smuggle@pgf@decorate@next@state{measure}    
        \fi
    \fi        
  }

  \state{wait}[width=\pgfdecoratedinputsegmentlength/100,next state=measure,repeat state=\avint@waitcycles,auto corner on length=2pt]{
    \pgfpathlineto{\pgfpointorigin}
  } 

  \state{zig}[width=\avint@width, next state=zag]{
    \pgfpathcurveto{\pgfqpoint{\avint@width}{0cm}}{\pgfqpoint{0pt}{\avint@amplitude}}{\pgfqpoint{\avint@width}{\avint@amplitude}}
  }
  \state{zag}[width=\avint@width, next state=measure,
              persistent postcomputation=\let\pgf@decorate@next@state\avint@smuggle@pgf@decorate@next@state]{
    \pgfpathcurveto{\pgfqpoint{\avint@width}{\avint@amplitude}}{\pgfqpoint{0pt}{0cm}}{\pgfqpoint{\avint@width}{0pt}}
    \xdef\avint@intersectionnumber{\the\numexpr\avint@intersectionnumber+1}
    \global\let\avint@smuggle@pgf@decorate@next@state\pgf@decorate@next@state
    \ifnum\avint@intersectionnumber>\pgfintersectionsolutions
      \gdef\avint@smuggle@pgf@decorate@next@state{done}
    \fi
  }

  \state{done}[width=\pgfdecoratedinputsegmentlength/100,auto corner on length=2pt]{
    \pgfpathlineto{\pgfpointorigin}
  }

  \state{final}{\pgfpathlineto{\pgfpointdecoratedpathlast}}
}    

\tikzset{
    avoid intersection/.code 2 args={
        \pgfkeysalso{name path=avint@temp,draw=none}
        \expandafter\def\expandafter\tikz@postactions\expandafter{\tikz@postactions
            \pgfintersectionsortbyfirstpath
            \tikz@intersect@namedpaths
            \pgfintersectionofpaths
                {\pgfsetpath\tikz@intersect@path@name@avint@temp}
                {\expandafter\pgfsetpath\csname tikz@intersect@path@name@#1\endcsname}
            \begin{pgfdecoration}{{avoidintersect}{\pgfdecoratedpathlength}}
            \pgfsetpath\tikz@intersect@path@name@avint@temp
            \end{pgfdecoration}
            \pgfgetpath\avint@temp@path
            \pgfusepath{discard}
            \draw[/utils/exec={\tikz@addmode{\pgfsyssoftpath@setcurrentpath\avint@temp@path}},#2](0,0)rectangle (0,0);%
        }
    }
}
\makeatother

\begin{document}
\begin{tikzpicture}
    \coordinate (a) at (-1,0.5);
    \coordinate (b) at (8,0.5);
    \coordinate (c) at (3,-0.5);
    \draw[ultra thick, name path=sine, domain=-1:8, smooth, samples=50] plot (\x,{sin(\x r)});
    \draw[avoid intersection={sine}{white,double=black},avoid intersection has corners] (a) -- (c) |- (b);
\end{tikzpicture}

\begin{tikzpicture}
    \coordinate (a) at (-1,0.5);
    \coordinate (b) at (8,0.5);
    \coordinate (c) at (3,-0.5);
    \draw[ultra thick,name path=line] (a) -- (c) |- (b);
    \draw[avoid intersection={line}{white,double=black},avoid intersection offset=1.5pt,domain=-1:8,samples=50] plot (\x,{sin(\x r)});
\end{tikzpicture}

\end{document}

输出如下:

您可以看到线连接工作正常: 在此处输入图片描述

相关内容