tikz:将圆角应用于圆弧

tikz:将圆角应用于圆弧

似乎选项rounded corners(尤其是半径较大时)和arcTi 中的 sZ 并不总是能很好地结合在一起。通常,应用圆角的完全相同的路径不会与未使用圆角的另一条路径完全重叠。我认为这是因为圆角碰到了圆弧。

有没有可行的方法可以获得这样的圆角(最好具有不同的半径)而不会产生这种扭曲效果?我已经尝试缩短弧线或暂时关闭圆角,但我仍然经常得到无法与弧线很好地融合的圆角,而且我不太喜欢像这样拼凑路径。

\documentclass[border=5pt,tikz]{standalone} 

\usetikzlibrary{spy}

\begin{document} 

\begin{tikzpicture}[
  pshift/.style args={(#1:#2)}{%
    shift={({sin(-#1)*#2},{cos(-#1)*#2})}
  },
  line/.style={%
    line width=5pt
  },
  spy using outlines={%
    circle,
    magnification=5, 
    size=2cm, 
    connect spies
  }
]

\begin{scope}[opacity=.5]
\draw[line, green!75!black] 
    (30:3cm) 
    -- (30:6cm) 
    arc (30:60:6cm) 
    -- (60:9cm) 
    arc (60:90:9cm) 
    -- (90:3cm);

\draw[line, green!50!black]
    ([pshift={(30:10pt)}]30:3cm) 
    -- ([pshift={(30:10pt)}]30:{6cm-10pt}) 
    arc ({30+asin(10pt/(6cm-10pt))}:{60+asin(10pt/(6cm-10pt))}:{6cm-10pt}) 
    -- ([pshift={(60:10pt)}]60:{9cm-10pt}) 
    arc ({60+asin(10pt/(9cm-10pt))}:{90-asin(10pt/(9cm-10pt))}:{9cm-10pt}) 
    -- ([pshift={(90:-10pt)}]90:3cm);
\end{scope}

\draw[line, red!75!black, rounded corners=12pt] 
    (30:3cm) 
    -- (30:6cm) 
    [rounded corners=4pt]
    arc (30:60:6cm) 
    [rounded corners=12pt]
    -- (60:9cm) 
    arc (60:90:9cm) 
    -- (90:3cm);

\draw[line, red!50!black, rounded corners=4pt] 
    ([pshift={(30:10pt)}]30:3cm) 
    -- ([pshift={(30:10pt)}]30:{6cm-10pt}) 
    [rounded corners=12pt]
    arc ({30+asin(10pt/(6cm-10pt))}:{60+asin(10pt/(6cm-10pt))}:{6cm-10pt}) 
    [rounded corners=4pt]
    -- ([pshift={(60:10pt)}]60:{9cm-10pt}) 
    arc ({60+asin(10pt/(9cm-10pt))}:{90-asin(10pt/(9cm-10pt))}:{9cm-10pt}) 
    -- ([pshift={(90:-10pt)}]90:3cm);

\spy on (57.5:{6cm-10pt}) in node at (60:4cm);

\spy on (85:9cm) in node at (75:7cm);

\end{tikzpicture}

\end{document}

在此处输入图片描述


暂时禁用圆角的示例,效果更好,但仍然有点不对:

\documentclass[border=5pt,tikz]{standalone} 

\usetikzlibrary{spy}

\begin{document} 

\begin{tikzpicture}[
  pshift/.style args={(#1:#2)}{%
    shift={({sin(-#1)*#2},{cos(-#1)*#2})}
  },
  line/.style={%
    line width=5pt
  },
  spy using outlines={%
    circle,
    magnification=5, 
    size=2cm, 
    connect spies
  }
]

\begin{scope}[opacity=.5]
\draw[line, green!75!black] 
    (60:6cm) 
    -- (60:9cm) 
    arc (60:90:9cm) 
    -- (90:6cm);
\end{scope}

\draw[line, blue!75!black, rounded corners=12pt] 
    (60:6cm) 
    -- (60:9cm) 
    [rounded corners=0pt]
    -- ([pshift={(60:12pt)}]60:9cm)
    arc (({60+asin(12pt/(9cm-12pt))}:({90-asin(12pt/(9cm-12pt))}:9cm) 
    [rounded corners=12pt]
    -- (90:9cm)
    -- (90:6cm);

\spy on (85:9cm) in node at (75:7cm);

\spy on (65:9cm) in node at (75:11cm);

\end{tikzpicture}

\end{document}

在此处输入图片描述

答案1

问题实际上与命令无关arc。它与 TikZ 如何缩短任何曲线路径有关。使用arccontrolsto[in= , out=]all 会产生相同的问题。

考虑一下这个图像:

在此处输入图片描述

这是用代码创建的

\begin{tikzpicture}[scale=10]
\draw[line width=5mm, color=green!75!black] (0,0)--(30:1) arc(30:80:1) -- cycle;
\draw[line width=5mm, color=red!75!black, rounded corners=10mm] (0,0)--(30:1) arc(30:80:1) -- cycle;
\draw[line width=5mm, color=blue!75!black, shorten >=10mm, shorten <=10mm] (30:1) arc(30:80:1);
\end{tikzpicture}

绿色路径由两段和一段弧组成。红色路径完全相同,但角是圆的,因此会产生不想要的位移。蓝色路径只是一段弧,但两端都缩短了 10 毫米,说明了 出了什么问题。简单地rounded corners使用路径 — 蓝色和红色路径完全相同。rounded cornersshorten

因此,我们不需要缩短弧线,而是需要擦除部分弧线。下图说明了这个想法:

在此处输入图片描述

圆圈(此处用黑色绘制)位于我们想要圆角的角落中心。它们用于计算原始路径上的交点(使用库intersections)。然后删除路径的某些部分(此处用黄色覆盖),并用通过两个交点之间的原始角落绘制的普通路径(蓝色)替换rounded corners。圆线帽用于建立平滑的连接。

这一切都放入一个\roundarc带有两个参数的宏中:

\newcommand{\roundarc}[2]{\path[name path=C1] (#1) circle[radius=#2];  
    \draw[name intersections={of=C1 and P1, by={a1,a2}}, double distance=0, color=white] (a1)--(#1)--(a2);
    \draw[rounded corners=#2, line cap=round] (a1)--(#1)--(a2);}

第一个参数是要圆角的坐标(不带括号)。第二个参数是圆角的半径。原始路径必须命名为P1。不绘制圆圈。覆盖线用白色绘制。

然后是代码

\begin{tikzpicture}[line width=5mm, color=red!75!black]
\draw[color=green!75!black] (0,0)--(30:10) arc(30:80:10) -- cycle;
\draw[name path=P1] {[rounded corners=10mm] (80:10) -- (0,0)} -- (30:10) arc(30:80:10);
\roundarc{80:10}{10mm}
\roundarc{30:10}{10mm}
\end{tikzpicture}

创建所需的图像。

在此处输入图片描述

请注意,绿色圆弧是先绘制的,但完全被隐藏了。还请注意,由两个直线段形成的角使用普通的 进行圆角处理rounded corners

完整代码如下:

\documentclass{article} 

\usepackage{tikz}
\usetikzlibrary{intersections}

\newcommand{\roundarc}[2]{\path[name path=C1] (#1) circle[radius=#2];  
    \draw[name intersections={of=C1 and P1, by={a1,a2}}, double distance=0, color=white] (a1)--(#1)--(a2);
    \draw[rounded corners=#2, line cap=round] (a1)--(#1)--(a2);}

\begin{document}

\begin{tikzpicture}[line width=5mm, color=red!75!black]
\draw[color=green!75!black] (0,0)--(30:10) arc(30:80:10) -- cycle;
\draw[name path=P1] {[rounded corners=10mm] (80:10) -- (0,0)} -- (30:10) arc(30:80:10);
\roundarc{80:10}{10mm}
\roundarc{30:10}{10mm}
\end{tikzpicture}

\end{document}

更新:

为了关闭路径,这些都可以成为一个新的键。我们可以定义,newrounded corners以便代码

\draw[newrounded corners=10mm] (0,0)--(30:8) arc(30:80:8) -- cycle;

将产生所需的图像。(透明的原始路径被覆盖。)最后指出了一些问题。

在此处输入图片描述

以下是代码:

\documentclass{article} 

\usepackage{tikz}
\usetikzlibrary{intersections, decorations.pathreplacing}

\tikzset{
    newrounded corners/.style={
        name path=P1,
        decoration={
            show path construction,
            lineto code={
                \path[name path=C1] (\tikzinputsegmentlast) circle[radius=#1];
                \draw[name intersections={of=C1 and P1, by={a1,a2}}, double distance=0, color=white] (a1)--(\tikzinputsegmentlast)--(a2);
                \draw[rounded corners=#1, line cap=round] (a1)--(\tikzinputsegmentlast)--(a2);
            },
            curveto code={
                \path[name path=C1] (\tikzinputsegmentlast) circle[radius=#1];
                \draw[name intersections={of=C1 and P1, by={a1,a2}}, double distance=0, color=white] (a1)--(\tikzinputsegmentlast)--(a2);
                \draw[rounded corners=#1, line cap=round] (a1)--(\tikzinputsegmentlast)--(a2);
            },
            closepath code={
                \path[name path=C1] (\tikzinputsegmentlast) circle[radius=#1];
                \draw[name intersections={of=C1 and P1, by={a1,a2}}, double distance=0, color=white] (a1)--(\tikzinputsegmentlast)--(a2);
                \draw[rounded corners=#1, line cap=round] (a1)--(\tikzinputsegmentlast)--(a2);
            },
        },
        postaction={decorate}
    },
    newrounded corners/.default=4mm
}

\begin{document}

\begin{tikzpicture}[line width=5mm, color=red!75!black]
\draw[newrounded corners=10mm] (0,0)--(30:8) arc(30:80:8) -- cycle;
\draw[opacity=.3] (0,0)--(30:8) arc(30:80:8) -- cycle;
\end{tikzpicture}

\end{document}

已知的问题:

  • 如果圆角半径相对于线宽太小,则会产生意外结果。
  • 覆盖原始图像的白色路径也可能覆盖 tikz 图片的其他部分。

答案2

Sandy G 对该问题进行了出色的分析,并提出了一个很好的解决方案。这是一个替代解决方案,最终会生成一条路径,因此更适合需要考虑这一点的情况,例如需要填充区域的情况。

它使用我的spath3TikZ 库,我刚刚添加了一些实现此目的所需的额外功能,因此在撰写本文时需要开发版本(spath3_code.dtx从该存储库下载并运行tex spath3_code.dtx以生成文件)。经过全面测试后,我会将其上传到 CTAN。

代码如下:

\documentclass{article}
%\url{https://tex.stackexchange.com/q/588089/86}

\usepackage{tikz}
\usetikzlibrary{spath3}

\begin{document}
\begin{tikzpicture}[scale=10]
\draw[line width=5mm, color=green!75!black,spath/save=wedge] (0,0)--(30:1) arc(30:80:1) -- cycle;
\draw[line width=5mm, color=red!75!black, rounded corners=10mm] (0,0)--(30:1) arc(30:80:1) -- cycle;
\draw[line width=5mm, color=blue!75!black, shorten >=10mm, shorten <=10mm] (30:1) arc(30:80:1);
\tikzset{
  spath/insert gaps after segments={wedge}{20mm},
  spath/join components with bezier={wedge},
  spath/close with curve={wedge}
}
\draw[
  fill=white,
  fill opacity=.5,
  ultra thick,spath/use={wedge}];
\end{tikzpicture}
\end{document}

结果如下:

使用 spath3 实现圆角

它的工作原理如下。原始路径被拆分成(这是最小的绘图片段)。每个部分都缩短了沿着它的长度(与 TikZ 通常的缩短程序不同,这保证沿着原始路径)。然后通过在间隙中插入贝塞尔曲线重新组合这些段。曲线被设计为与间隙两端的切线相匹配。

我选择贝塞尔曲线而不是圆弧有几个原因。一个是实用性——在较低级别,TikZ 中的所有曲线路径都是贝塞尔曲线——另一个是计算合适的圆弧可能非常复杂,因为它会影响曲线必须缩短的程度(因此您不能只缩短曲线然后插入圆弧)。贝塞尔曲线的灵活性更高,可以避免这个问题。

相关内容