pgfplots 与路径的交点

pgfplots 与路径的交点

pgfplots我正在尝试通过库查找路径与图的交点intersection。找到的交点显然与可见交点不匹配。它们似乎被转换到了不同的坐标系。是否可以正确计算这些交点?

例子

平均能量损失

\documentclass{article}
\usepackage{pgfplots, tikz}
\usetikzlibrary{calc, intersections}    
\begin{document}
\begin{tikzpicture}

\begin{axis}[name=firstaxis]
\addplot[name path global=firstfunction]{e^x};
\end{axis}    
\begin{axis}[name=secondaxis, at={($(firstaxis.south)-(0,1cm)$)}, anchor=north]
\addplot[name path global=secondfunction]{x^3};
\end{axis}

% Draw intersection line 
\draw[color=black, opacity=1, name path global=intersectionline] (firstaxis.north) -- (secondaxis.south);

% Draw intersections points
\fill 
    [name intersections={of=intersectionline and firstfunction}] 
    (intersection-1) circle (2pt);          
\fill 
    [name intersections={of=intersectionline and secondfunction}] 
    (intersection-1) circle (2pt);

\end{tikzpicture}
\end{document}

答案1

我希望有更简单的方法来做到这一点但是......

首先,据我了解,PGFPlots 会计算绘图点,将绘制的路径放在轴框中,然后将轴框定位在图片中。将轴框移动到所需位置不会改变使用name path交叉库中的键获得的底层低级 PGF 路径表示的坐标。

axis如果在第二个环境之后直接手动绘制(红色)保存的绘制路径,则可以看到这一点:

\documentclass[border=0.125cm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{calc,intersections}  

\tikzset{
    name path global/.append code={%
        \csname tikz@addmode\endcsname{%
            \pgfgetpath\tmp%
            \expandafter\global\expandafter\let\csname tikz@intersect@path@name@#1\endcsname=\tmp%
        }%
    }%
}  
\begin{document}


\begin{tikzpicture}


\begin{axis}
[
    name=firstaxis, 
    domain=-5:5, 
    xmin=-6, xmax=6, 
    ymin=-10, ymax=160, 
    enlargelimits=false
]
    \addplot[name path global=firstfunction]{e^x};

\end{axis}    

\begin{axis}
[
    name=secondaxis, 
    domain=-5:5,
    xmin=-6, xmax=6, 
    ymin=-150, ymax=150, 
    enlargelimits=false, 
    at={($(firstaxis.south)-(0,1cm)$)}, 
    anchor=north
]
    \addplot[name path global=secondfunction]{x^3};

\end{axis}

\expandafter\pgfsetpath\csname tikz@intersect@path@name@secondfunction\endcsname
\pgfsetstrokecolor{red}
\pgfusepath{stroke}

\end{tikzpicture}
\end{document}

在此处输入图片描述

第二个问题是,该name path global密钥目前无法与 PGFPLots 正常配合使用,必须被黑客入侵(如上面的代码所示)。

这意味着尝试做你想做的事是可能的,但却非常麻烦。概念上最简单的方法是改变底层绘制的路径,但这对于复杂的绘图来说会很耗时,而且会涉及很多低级的东西。

在下面的方法中,必须将坐标intersectionline移至任何不在原点的轴的“坐标系”。然后,交点也必须移位。

这(有点简单)但你还必须使用enlargelimits=false(它的作用类似于一种“边距”)然后手动设置 |x| 和 |y| 轴的限制两个都斧头。

此外,name path global密钥需要破解一点。这是一项相当繁重的工作,我怀疑其他一些不涉及交叉点的解决方法很多更轻松:

\documentclass[border=0.125cm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{calc,intersections}  

\tikzset{
    name path global/.append code={%
        \csname tikz@addmode\endcsname{%
            \pgfgetpath\tmp%
            \expandafter\global\expandafter\let\csname tikz@intersect@path@name@#1\endcsname=\tmp%
        }%
    }%
}  
\begin{document}


\begin{tikzpicture}


\begin{axis}
[
    name=firstaxis, 
    domain=-5:5, 
    xmin=-6, xmax=6, 
    ymin=-10, ymax=160, 
    enlargelimits=false
]
    \addplot[name path global=firstfunction]{e^x};

\end{axis}    

\begin{axis}
[
    name=secondaxis, 
    domain=-5:5,
    xmin=-6, xmax=6, 
    ymin=-150, ymax=150, 
    enlargelimits=false, 
    at={($(firstaxis.south)-(0,1cm)$)}, 
    anchor=north
]
    \addplot[name path global=secondfunction]{x^3};

\end{axis}


\foreach \col/\from/\to in {red/west/east, green/north/south, blue/north west/south east}{
    % Draw intersection line 
    \draw 
        [color=\col, opacity=1, name path global=intersectionline] 
        (firstaxis.\from) -- (secondaxis.\to);


    % Draw intersections points
    \fill 
        [\col, name intersections={of=intersectionline and firstfunction}] 
        (intersection-1) circle [radius=2pt];    

    % Create the intersectionline in the secondaxis coordinate system.
    \path [overlay] let \p1=(secondaxis.south west) in
        [name path global=intersectionline] 
        ([shift={(-\x1,-\y1)}]firstaxis.\from) -- ([shift={(-\x1,-\y1)}]secondaxis.\to);

    % Draw the intersection point
    \fill 
        [\col, name intersections={of=intersectionline and secondfunction}] 
        ($(secondaxis.south west)+(intersection-1)$) circle [radius=2pt];
}
\end{tikzpicture}
\end{document}

在此处输入图片描述

好的,所以也可以用困难的方式完成。下面定义的宏\pgfpathretransform“重新转换”低级 PGF 路径。可以使用密钥使用结果,transform named path这样交叉点就不那么混乱了。

\documentclass[border=0.125cm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{calc,intersections}  
\makeatletter
\tikzset{
    name path global/.append code={%
        \tikz@addmode{%
            \pgfgetpath\tmp%
            \expandafter\global\expandafter\let\csname tikz@intersect@path@name@#1\endcsname=\tmp%
        }%
    },
    transform named path/.code args={#1 by #2}{
        \expandafter\let\expandafter\@tmp\csname tikz@intersect@path@name@#1\endcsname%
        \pgfpathretransform{\tikzset{#2}\tikz@transform}{\@tmp}{\@tmp}%
        \pgfinterruptpath%
            \path[name path=#1]\pgfextra{\pgfsetpath\@tmp};
        \endpgfinterruptpath%
    }
}  


% This macro 're-transforms' a soft-path
%
% #1 Pgf level transformation code
% #2 a macro containing the original soft path
% #3 a macro to store the transformed path
%

\def\pgfpathretransform#1#2#3{%
    % First get the transform...
    \begingroup%
        \pgftransformreset%
        #1%
        \pgfgettransform\pgfpath@retransform%
        \expandafter
    \endgroup%
    \expandafter\def\expandafter\pgfpath@retransform\expandafter{\pgfpath@retransform}%
    \global\let\pgfpath@retransform@path=\pgfutil@empty%
    \begingroup%
        \pgfprocessround{#2}{#2}%
        % Locally redefine the soft-path tokens so that they do most of the work.
        \def\pgfsyssoftpath@movetotoken{\pgfpath@retransform@point{moveto}}%
        \def\pgfsyssoftpath@linetotoken{\pgfpath@retransform@point{lineto}}%
        \def\pgfsyssoftpath@curvetosupportatoken{\pgfpath@retransform@point{curvetosupporta}}%
        \def\pgfsyssoftpath@curvetosupportbtoken{\pgfpath@retransform@point{curvetosupportblineto}}%
        \def\pgfsyssoftpath@curvetotoken{\pgfpath@retransform@point{curveto}}%
        \def\pgfsyssoftpath@rectcornertoken{\pgfpath@retransform@point{rectcorner}}%
        \def\pgfsyssoftpath@rectsizetoken{\pgfpath@retransform@point{rectsize}}%
        \def\pgfsyssoftpath@closepathtoken{\pgfpath@retransform@point{closepath}}%
        #2%
    \endgroup%
    % Now \pgfpath@retransform@path holds the transformed path
    \let#3=\pgfpath@retransform@path%
}

\def\pgfpath@retransform@point#1#2#3{%
    \pgf@process{%
        \pgf@x=#2\relax%
        \pgf@y=#3\relax%
        \pgfsettransform\pgfpath@retransform%
        \pgf@pos@transform{\pgf@x}{\pgf@y}%
    }%
    \edef\pgf@marshal{\expandafter\noexpand\csname pgfsyssoftpath@#1token\endcsname{\the\pgf@x}{\the\pgf@y}}%
    \expandafter\pgfutil@g@addto@macro\expandafter{\expandafter\pgfpath@retransform@path\expandafter}\expandafter{\pgf@marshal}%
}


\begin{document}


\begin{tikzpicture}
\begin{axis}
[
    name=firstaxis, 
    domain=-5:5, 
    xmin=-6, xmax=6, 
    ymin=-10, ymax=160, 
    enlargelimits=false
]
    \addplot[name path global=firstfunction]{e^x};

\end{axis}    

\begin{axis}
[
    name=secondaxis, 
    domain=-5:5,
    xmin=-6, xmax=6, 
    ymin=-150, ymax=150, 
    enlargelimits=false, 
    at={($(firstaxis.south)-(0,1cm)$)}, 
    anchor=north
]
    \addplot[name path global=secondfunction]{x^3};

\end{axis}

% Transform the named path.
\tikzset{transform named path=secondfunction by {shift=(secondaxis.south west)}}


\foreach \col/\from/\to in {red/west/east, green/north/south, blue/north west/south east}{
    % Draw intersection line 
    \draw 
        [color=\col, opacity=1, name path global=intersectionline] 
        (firstaxis.\from) -- (secondaxis.\to);


    % Draw intersections points
    \fill 
        [\col, name intersections={of=intersectionline and firstfunction}] 
        (intersection-1) circle [radius=2pt];    

    \fill 
        [\col, name intersections={of=intersectionline and secondfunction}] 
        (intersection-1) circle [radius=2pt];
}
\end{tikzpicture}
\end{document}

结果和以前一样。

相关内容