填充由多条曲线界定的内部空间

填充由多条曲线界定的内部空间

我正在使用曲线坐标绘制两个“电视屏幕”,并希望前面的屏幕遮挡另一个屏幕。我想使用 \fillbetween 在外面的屏幕内进行绘制,但由于所有边都是弯曲的,因此我无法仅通过引用两条曲线来实现。有没有办法 \fillbetween 限制内部的多条曲线?

在此处输入图片描述

\documentclass{article}

\usepackage{pgfplots}
\usepackage{tikz}
\usepgfplotslibrary{fillbetween}
\begin{document}
    
    \newcommand{\xa}{0.1}
    \newcommand{\xb}{0.7}
    \newcommand{\ya}{0.8}
    \newcommand{\yb}{-0.2}
    \newcommand{\za}{1}
    
    \begin{tikzpicture}[scale=1]
        \begin{axis}[
            axis equal,
            hide axis
            ]
            
            \renewcommand{\za}{0.5}
            \addplot [name path=A1,domain=0:1, samples=100,draw=black,line width=1pt] ({ ((1-x)*\xa + x*\xb)/sqrt(((1-x)*\xa + x*\xb)^2 + (\ya)^2+ (\za)^2) }, { (\ya)/sqrt(((1-x)*\xa + x*\xb)^2 + (\ya)^2+ (\za)^2) });
            \addplot [name path=A2,domain=0:1, samples=100,draw=black,line width=1pt] ({ ((1-x)*\xa + x*\xb)/sqrt(((1-x)*\xa + x*\xb)^2 + (\yb)^2+ (\za)^2) }, { (\yb)/sqrt(((1-x)*\xa + x*\xb)^2 + (\yb)^2+ (\za)^2) });
            \addplot [name path=A3,domain=0:1, samples=100,draw=black,line width=1pt] ({ (\xa)/sqrt((\xa)^2 + ((1-x)*\ya + x*\yb)^2 + (\za)^2) }, { ((1-x)*\ya + x*\yb)/sqrt((\xa)^2 + ((1-x)*\ya + x*\yb)^2 + (\za)^2) });
            \addplot [name path=A4,domain=0:1, samples=100,draw=black,line width=1pt] ({ (\xb)/sqrt((\xb)^2 + ((1-x)*\ya + x*\yb)^2 + (\za)^2) }, { ((1-x)*\ya + x*\yb)/sqrt((\xb)^2 + ((1-x)*\ya + x*\yb)^2 + (\za)^2) });
            
            
            \renewcommand{\za}{1}
            \addplot [name path=B1,domain=0:1, samples=100,draw=black,line width=1pt] ({ ((1-x)*\xa + x*\xb)/sqrt(((1-x)*\xa + x*\xb)^2 + (\ya)^2+ (\za)^2) }, { (\ya)/sqrt(((1-x)*\xa + x*\xb)^2 + (\ya)^2+ (\za)^2) });
            \addplot [name path=B2,domain=0:1, samples=100,draw=black,line width=1pt] ({ ((1-x)*\xa + x*\xb)/sqrt(((1-x)*\xa + x*\xb)^2 + (\yb)^2+ (\za)^2) }, { (\yb)/sqrt(((1-x)*\xa + x*\xb)^2 + (\yb)^2+ (\za)^2) });
            \addplot [name path=B3,domain=0:1, samples=100,draw=black,line width=1pt] ({ (\xa)/sqrt((\xa)^2 + ((1-x)*\ya + x*\yb)^2 + (\za)^2) }, { ((1-x)*\ya + x*\yb)/sqrt((\xa)^2 + ((1-x)*\ya + x*\yb)^2 + (\za)^2) });
            \addplot [name path=B4,domain=0:1, samples=100,draw=black,line width=1pt] ({ (\xb)/sqrt((\xb)^2 + ((1-x)*\ya + x*\yb)^2 + (\za)^2) }, { ((1-x)*\ya + x*\yb)/sqrt((\xb)^2 + ((1-x)*\ya + x*\yb)^2 + (\za)^2) });
            
            \addplot[green!20] fill between [of = A1 and A2, soft clip = {domain = -1:1}];
            
        \end{axis}
    \end{tikzpicture}
    
\end{document}

答案1

您可以将常规\path\fill命令与结合使用intersection segments。但是这样您一次只能将两条路径拼接在一起,因此您需要执行几个步骤。

如果希望较小的屏幕显示在较大的屏幕上,则需要更改绘制它们的顺序(或使用backgrounds)。

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{fillbetween}
\pgfplotsset{compat=1.18}

\begin{document}
    \newcommand{\xa}{0.1}
    \newcommand{\xb}{0.7}
    \newcommand{\ya}{0.8}
    \newcommand{\yb}{-0.2}
    \newcommand{\za}{1}
    
    \begin{tikzpicture}[scale=1]
        \begin{axis}[
            axis equal,
            hide axis
        ]
            
            \renewcommand{\za}{0.5}
            \addplot[name path=A1, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ ((1 - x)*\xa + x*\xb)/sqrt(((1 - x)*\xa + x*\xb)^2 + (\ya)^2 + (\za)^2) }, 
                 { (\ya)/sqrt(((1 - x)*\xa + x*\xb)^2 + (\ya)^2 + (\za)^2) });
            \addplot[name path=A2, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ ((1 - x)*\xa + x*\xb)/sqrt(((1 - x)*\xa + x*\xb)^2 + (\yb)^2 + (\za)^2) }, 
                 { (\yb)/sqrt(((1 - x)*\xa + x*\xb)^2 + (\yb)^2 + (\za)^2) });
            \addplot[name path=A3, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ (\xa)/sqrt((\xa)^2 + ((1 - x)*\ya + x*\yb)^2 + (\za)^2) }, 
                 { ((1 - x)*\ya + x*\yb)/sqrt((\xa)^2 + ((1 - x)*\ya + x*\yb)^2 + (\za)^2) });
            \addplot[name path=A4, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ (\xb)/sqrt((\xb)^2 + ((1 - x)*\ya + x*\yb)^2 + (\za)^2) }, 
                 { ((1 - x)*\ya + x*\yb)/sqrt((\xb)^2 + ((1 - x)*\ya + x*\yb)^2 + (\za)^2) });
            
            \renewcommand{\za}{1}
            \addplot[name path=B1, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ ((1 - x)*\xa + x*\xb)/sqrt(((1 - x)*\xa + x*\xb)^2 + (\ya)^2 + (\za)^2) }, 
                 { (\ya)/sqrt(((1 - x)*\xa + x*\xb)^2 + (\ya)^2+ (\za)^2) });
            \addplot[name path=B2, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ ((1 - x)*\xa + x*\xb)/sqrt(((1 - x)*\xa + x*\xb)^2 + (\yb)^2 + (\za)^2) }, 
                 { (\yb)/sqrt(((1 - x)*\xa + x*\xb)^2 + (\yb)^2 + (\za)^2) });
            \addplot[name path=B3, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ (\xa)/sqrt((\xa)^2 + ((1 - x)*\ya + x*\yb)^2 + (\za)^2) }, 
                 { ((1 - x)*\ya + x*\yb)/sqrt((\xa)^2 + ((1 - x)*\ya + x*\yb)^2 + (\za)^2) });
            \addplot[name path=B4, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ (\xb)/sqrt((\xb)^2 + ((1 - x)*\ya + x*\yb)^2 + (\za)^2) }, 
                 { ((1 - x)*\ya + x*\yb)/sqrt((\xb)^2 + ((1 - x)*\ya + x*\yb)^2 + (\za)^2) });
            
            \path[name path=A13, intersection segments={of=A1 and A3, sequence={L*[reverse] -- R*}}];
            \path[name path=A24, intersection segments={of=A2 and A4, sequence={L* -- R*[reverse]}}];
            \fill[green!20, draw=black, intersection segments={of=A13 and A24, sequence={L* -- R*}}] -- cycle;
            
        \end{axis}
    \end{tikzpicture}
\end{document}

在此处输入图片描述


定义函数以避免重复代码可能是一个好主意。此外,在全局级别定义名称非常短的宏可能会与其他包或命令发生冲突。

这是一个使用先前定义的函数的解决方案,这样就避免了在全局级别定义命令的需要。输出与上面相同。

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{fillbetween}
\pgfplotsset{compat=1.18}

\begin{document}
    \begin{tikzpicture}[scale=1]
        \begin{axis}[
            axis equal,
            hide axis,
            /pgf/declare function = {
                xa = 0.1;
                xb = 0.7;
                ya = 0.8;
                yb = -0.2;
                zx = 0.5;
                zy = 1;
                fa(\a,\b,\c,\d) = ((1 - x)*\a + x*\b)/sqrt(((1 - x)*\a + x*\b)^2 + (\c)^2 + (\d)^2);
                fb(\a,\b,\c,\d) = (\a)/sqrt(((1 - x)*\b + x*\c)^2 + (\a)^2 + (\d)^2);
                fc(\a,\b,\c,\d) = (\a)/sqrt((\a)^2 + ((1 - x)*\b + x*\c)^2 + (\d)^2);
                fd(\a,\b,\c,\d) = ((1 - x)*\a + x*\b)/sqrt((\c)^2 + ((1 - x)*\a + x*\b)^2 + (\d)^2);
            }
        ]
            \addplot[name path=A1, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ fa(xa,xb,ya,zx) }, { fb(ya,xa,xb,zx) });
            \addplot[name path=A2, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ fa(xa,xb,yb,zx) }, { fb(yb,xa,xb,zx) });
            \addplot[name path=A3, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ fc(xa,ya,yb,zx) }, { fd(ya,yb,xa,zx) });
            \addplot[name path=A4, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ fc(xb,ya,yb,zx) }, { fd(ya,yb,xb,zx) });

            \addplot[name path=B1, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ fa(xa,xb,ya,zy) }, { fb(ya,xa,xb,zy) });
            \addplot[name path=B2, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ fa(xa,xb,yb,zy) }, { fb(yb,xa,xb,zy) });
            \addplot[name path=B3, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ fc(xa,ya,yb,zy) }, { fd(ya,yb,xa,zy) });
            \addplot[name path=B4, domain=0:1, samples=100, draw=black, line width=1pt] 
                ({ fc(xb,ya,yb,zy) }, { fd(ya,yb,xb,zy) });
            
            \path[name path=A13, intersection segments={of=A1 and A3, sequence={L*[reverse] -- R*}}];
            \path[name path=A24, intersection segments={of=A2 and A4, sequence={L* -- R*[reverse]}}];
            \fill[green!20, draw=black, intersection segments={of=A13 and A24, sequence={L* -- R*}}] -- cycle;
            
        \end{axis}
    \end{tikzpicture}
\end{document}

相关内容