在 TikZ 中勾勒出由交叉点定义的形状的边界

在 TikZ 中勾勒出由交叉点定义的形状的边界

我想在下图中的白色区域周围添加粗边框,同时保留灰色区域的虚线。有没有简单的方法可以做到这一点?

在此处输入图片描述

我的代码如下。谢谢!

\begin{tikzpicture}

\clip (-4.5,-4) rectangle (4.5,4);
\filldraw[fill=white](-4.5,-4) rectangle (4.5,4);

\fill[fill=gray!50] (115 : 2 + 5) circle (5);
\fill[fill=gray!50] (45 : 2 + 8) circle (8);
\fill[fill=gray!50] (180 : 2 + 10) circle (10);
\fill[fill=gray!50] (345 : 2 + 7) circle (7);
\fill[fill=gray!50] (270 : 2 + 9) circle (9);

\draw[dashed] (115 : 2 + 5) circle (5);
\draw[dashed] (45 : 2 + 8) circle (8);
\draw[dashed] (180 : 2 + 10) circle (10);
\draw[dashed] (345 : 2 + 7) circle (7);
\draw[dashed] (270 : 2 + 9) circle (9);

\end{tikzpicture}

更新:

使用建议的方法Q238967,我已经能够接近了,但其中一行有问题。我在下面添加了更新的代码以及新图像。

\begin{tikzpicture}

    \clip (-4.5,-4) rectangle (4.5,4);
    \filldraw[fill=white](-4.5,-4) rectangle (4.5,4);

    \fill[fill=gray!50] (45 : 2 + 8) circle (8);
    \fill[fill=gray!50] (115 : 2 + 5) circle (5);
    \fill[fill=gray!50] (180 : 2 + 10) circle (10);
    \fill[fill=gray!50] (270 : 2 + 9) circle (9);    
    \fill[fill=gray!50] (345 : 2 + 7) circle (7);


    \draw[name path=one, dashed] (45 : 2 + 8) circle (8);
    \draw[name path=two, dashed] (115 : 2 + 5) circle (5);
    \draw[name path = three, dashed] (180 : 2 + 10) circle (10);
    \draw[name path = four, dashed] (270 : 2 + 9) circle (9);
    \draw[name path = five, dashed] (345 : 2 + 7) circle (7);


    \path[name path = temp1, red, intersection segments={of=one and two,sequence=R2}];
    \draw[red,ultra thick, intersection segments={of=temp1 and three,sequence=L3}];
    
    \path[name path = temp2, red, intersection segments={of=one and five,sequence=L1}];
    \draw[red,ultra thick, intersection segments={of=temp2 and two,sequence=L3}];

    \path[name path = temp3, red, intersection segments={of=four and five,sequence=L3}];
    \draw[red,ultra thick, intersection segments={of=temp3 and three, sequence=L1}];

    \path[name path = temp4, red, intersection segments={of=three and four,sequence=L1}];
    \draw[red,ultra thick, intersection segments={of=temp4 and two, sequence=L1}];

    \path[name path = temp5, red, intersection segments={of=one and five,sequence=R3}];
    \draw[red,ultra thick, intersection segments={of=temp5 and four, sequence=L1}];


\end{tikzpicture}

在此处输入图片描述

答案1

左边的圆确实很麻烦,因为从内部看,它仍然是一个从 0 角开始向四周延伸的圆弧。这将导致额外的分割。

这是我对此的看法,将虚线部分做成圆弧,这样就不会发生这种分割。通过选择一个小角度,我们在每对圆(现在是圆弧)之间也只有一个交点。

fillbetween觉得没有一个好的解决方案,那就是在两个片段之间只保留一条路径,而没有移动,这就是我line cap = round在这里使用的原因,以隐藏这一事实。inner moveto(实际上它似乎在/pgf/fill between/名称空间中)但我不知道应该如何使用它。示例甚至没有使用它。

这就是我提供spath3解决方案的原因。

在我们完成split at intersections每对路径并移除每条路径上的第一个和第三个/最后一个段之后,我们剩下五个只需要连接的路径段。

fillbetween解决方案相反,我们实际上可以将各部分连接起来,这样它就会成为一条连续的路径。现在,连接不仅看起来不错,而且我们还可以使用路径包含的整个区域来正确填充、着色或图案化。


请记住,所有圆和圆弧都是逆时针构造的,并且圆的枚举方式相同。但是,这意味着我们必须顺时针构造内部区域,这就是为什么\draw两个解决方案中的最终结果都是 4、3、2、1、0。

是的,我开始计数,0因为这样可以更容易地对路径进行模运算(如spath3解决方案所示)。

代码 (fillbetween

\documentclass[tikz]{standalone}
\usepackage{pgfplots}\pgfplotsset{compat=newest}
\usetikzlibrary{pgfplots.fillbetween}
\begin{document}
\begin{tikzpicture}
\clip (-4.5,-4) rectangle (4.5,4);

\foreach \ang/\rad in {45/8, 115/5, 180/10, 270/9, 345/7}
  \fill[gray!50] (\ang:2+\rad) circle[radius=\rad];

\tikzset{
  arc path/.code args={#1/#2/#3}{% ungrouped loop
    \draw[dashed, name path=p#1] ([shift=(#2+135:#3)]#2:2+#3)
      arc[start angle=#2+135, delta angle=90, radius=#3];},
  arc path/.list={0/45/8, 1/115/5, 2/180/10, 3/270/9, 4/345/7},
  split paths/.code 2 args={
    \path[intersection segments={of=p#1 and p#2, sequence=R1}, name path=p#2 on p#1];},
  split paths/.list={01, 12, 23, 34, 40}
}
\draw[ultra thick, line cap=round,
  intersection segments/.list={{of=p4 and p3 on p2, sequence=R2},
                               {of=p3 and p2 on p1, sequence=R2},
                               {of=p2 and p1 on p0, sequence=R2},
                               {of=p1 and p0 on p4, sequence=R2},
                               {of=p0 and p4 on p3, sequence=R2}}];
\end{tikzpicture}
\end{document}

代码 (spath3

\documentclass[tikz]{standalone}
\usetikzlibrary{spath3, intersections}
\newcommand*\NextOf[2]{\pgfintmod{#1+1}{#2}}
%\newcommand*\PrevOf[2]{\pgfintmod{#1-1}{#2}}
\begin{document}
\begin{tikzpicture}
\clip (-4.5,-4) rectangle (4.5,4);

\foreach \ang/\rad in {45/8, 115/5, 180/10, 270/9, 345/7}
  \fill[gray!50] (\ang:2+\rad) circle[radius=\rad];

\tikzset{
  arc path/.code args={#1/#2/#3}{% ungrouped loop
    \draw[dashed, spath/save=p#1] ([shift=(#2+135:#3)]#2:2+#3)
      arc[start angle=#2+135, delta angle=90, radius=#3];},
  arc path/.list={0/45/8, 1/115/5, 2/180/10, 3/270/9, 4/345/7},
  split paths/.style={spath/split at intersections={p#1}{p\NextOf{#1}{5}}},
  split paths/.list={0, ..., 4},
  remove start and end/.style={spath/remove components={p#1}{1, 3}},
  remove start and end/.list={0, ..., 4},
}
\draw[
  line width=1ex,
  spath/append no move/.list={p4, p..., p0},
  spath/adjust and close=current];
\end{tikzpicture}
\end{document}

输出 (spath3

在此处输入图片描述

未剪辑

答案2

您也可以使用方便的buildcycle宏来执行此操作元帖子,但你需要小心如何构造圆。特别是你需要确保旋转它们,这样没有一个point 0点位于任何其他圆内。纯粹为了比较,这是我的努力:

在此处输入图片描述

使用以下命令进行编译lualatex

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
path C[];
C1 = fullcircle scaled 300 rotated 115 shifted 210 dir 115;
C2 = fullcircle scaled 480 rotated  45 shifted 300 dir 45;
C3 = fullcircle scaled 420 rotated 345 shifted 270 dir 345;
C4 = fullcircle scaled 540 rotated 270 shifted 330 dir 270;
C5 = fullcircle scaled 600 rotated 180 shifted 360 dir 180;

path S; S = unitsquare shifted -(1/2,1/2) scaled 300;
for i = 1 upto 5:
  C[i] := C[i] cutbefore S cutafter S;
endfor

path P; P = buildcycle(C1, C2, C3, C4, C5);

beginfig(1);
  fill S withcolor 7/8;
  fill P withcolor 7/8[red, white];
  draw S;
  draw P withpen pencircle scaled 1 withcolor 2/3 red;
  for i=1 upto 5: 
    draw C[i] dashed evenly; 
  endfor
endfig;
\end{mplibcode}
\end{document}

如果希望红线隐藏虚线,则将draw P线移到绘制圆弧的循环之后。而且您可能不想要任何颜色,因此类似这样的方法可能更好:

beginfig(1);
  fill S withcolor 7/8;
  fill P withcolor background;
  draw S;
  for i=1 upto 5: 
    draw C[i] dashed evenly; 
  endfor
  draw P withpen pencircle scaled 1;
endfig;

其结果为:

在此处输入图片描述

笔记

  • 单位为 PostScript 点 28.35 = 1cm

  • 您可以使用宏在 MP 中执行极坐标dir。表达式dir 100扩展为right rotated 100,从而给出位于单位圆上的<pair>值。表达式将此点缩放为半径为 200bp 和角度为 100° 的极坐标。(sind 100, cosd 100)200 dir 100

  • 如果你使用默认单位(PostScript 点),效果会更好,因为你可以200 dir 45直接书写。使用cm等等,但是你必须写得7 cm * dir 45不那么优雅。

  • 请注意,在这个习语中,fullcircle scaled 300 rotated 115 shifted 210 dir 115;数字分别代表点、度、点和度。

答案3

我对这个套餐不太熟悉,spath但只是为了好玩和空闲时间

根据@AndrewStacy 给出的答案推断出来的答案——

https://tex.stackexchange.com/a/682553/197451

发起者可以建议

\documentclass[margin=5mm]{standalone}
\usepackage{ pgfplots}
\usetikzlibrary{calc,intersections, fillbetween, spath3}

\begin{document}

\begin{tikzpicture}
    
    \clip (-5,-5) rectangle (5,5);
    \filldraw[fill=white](-5,-5) rectangle (5,5);
    
    \fill[fill=gray!50] (45 : 2 + 8) circle (8);
    \draw[spath/save=circle8, dashed] (45 : 2 + 8) circle (8);
    
    \fill[fill=gray!50] (115 : 2 + 5) circle (5);
    \draw[spath/save=circle5, dashed] (115 : 2 + 5) circle (5);
    
    \fill[fill=gray!50] (180 : 2 + 10) circle (10);
    \draw[spath/save=circle10, dashed] (180 : 2 + 10) circle (10);
    
    \fill[fill=gray!50] (270 : 2 + 9) circle (9);    
    \draw[spath/save=circle9, dashed] (270 : 2 + 9) circle (9);
    
    \fill[fill=gray!50] (345 : 2 + 7) circle (7);
    \draw[spath/save=circle7, dashed] (345 : 2 + 7) circle (7);
%   
\tikzset{%
  spath/split at intersections={circle8}{circle5},
    spath/split at intersections={circle5}{circle10},
        spath/split at intersections={circle10}{circle9},
            spath/split at intersections={circle9}{circle7},
                spath/split at intersections={circle7}{circle8},
  spath/get components of={circle8}\cptsA,
    spath/get components of={circle5}\cptsB,
        spath/get components of={circle10}\cptsC,
            spath/get components of={circle9}\cptsD,
                spath/get components of={circle7}\cptsE,
                    spath/get components of={circle8}\cptsF,
}

\draw[
red,
thick,
spath/use=\getComponentOf{\cptsA}{-2},
spath/use={\getComponentOf{\cptsB}{-3}},
spath/use={\getComponentOf{\cptsC}{-2}},
spath/use={\getComponentOf{\cptsD}{-2}},
spath/use={\getComponentOf{\cptsE}{-2}},
spath/use={\getComponentOf{\cptsF}{3}},
];
%   
    
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

编辑

根据@AndrewStacey 的评论,所有虚线也可见

\documentclass[margin=5mm]{standalone}
\usepackage{ pgfplots}
\usetikzlibrary{calc,intersections, fillbetween, spath3}

\begin{document}
    
    \begin{tikzpicture}
        
        \clip (-5,-5) rectangle (5,5);
        \filldraw[fill=white](-5,-5) rectangle (5,5);
        
        \fill[fill=gray!50] (45 : 2 + 8) circle (8);
            \fill[fill=gray!50] (115 : 2 + 5) circle (5);
                \fill[fill=gray!50] (180 : 2 + 10) circle (10);
                        \fill[fill=gray!50] (270 : 2 + 9) circle (9);    
                                \fill[fill=gray!50] (345 : 2 + 7) circle (7);
                
        \draw[spath/save=circle8, dashed] (45 : 2 + 8) circle (8);
            \draw[spath/save=circle5, dashed] (115 : 2 + 5) circle (5);
                \draw[spath/save=circle10, dashed] (180 : 2 + 10) circle (10);
                    \draw[spath/save=circle9, dashed] (270 : 2 + 9) circle (9);
                        \draw[spath/save=circle7, dashed] (345 : 2 + 7) circle (7);
        %   
        \tikzset{%
            spath/split at intersections={circle8}{circle5},
            spath/split at intersections={circle5}{circle10},
            spath/split at intersections={circle10}{circle9},
            spath/split at intersections={circle9}{circle7},
            spath/split at intersections={circle7}{circle8},
            spath/get components of={circle8}\cptsA,
            spath/get components of={circle5}\cptsB,
            spath/get components of={circle10}\cptsC,
            spath/get components of={circle9}\cptsD,
            spath/get components of={circle7}\cptsE,
            spath/get components of={circle8}\cptsF,
        }
        
        \draw[
        blue,
        thick,
        spath/use=\getComponentOf{\cptsA}{-2},
        spath/use={\getComponentOf{\cptsB}{-3}},
        spath/use={\getComponentOf{\cptsC}{-2}},
        spath/use={\getComponentOf{\cptsD}{-2}},
        spath/use={\getComponentOf{\cptsE}{-2}},
        spath/use={\getComponentOf{\cptsF}{3}},
        ];
        %   
        
    \end{tikzpicture}
\end{document}

输出

在此处输入图片描述

相关内容