如何消除Z方向的子向量绘制误差?

发布于 2024-04-05 16:42:38

按老师的指点,能绘制出已知曲面上点的法向量。我尝试再添加绘制已知点的X,Y,Z三个子向量时,出现Z子向量的误差,如何避免呢?请老师有空再分析看看,感激不尽。
vector_quest7.png

\documentclass[svgnames]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\makeatletter
\newcommand\computegrad[4][0.00025]{% [delta], function, x, y
    \begingroup\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
    \def\@tempdelta{#1}%
    \pgfmathparse{#2(#3,#4)}\let\@tempz\pgfmathresult
    \pgfmathparse{#2(#3+\@tempdelta,#4)}\let\@temppxa\pgfmathresult
    \pgfmathparse{#2(#3-\@tempdelta,#4)}\let\@temppxb\pgfmathresult
    \edef\@temppx{\fpeval{(\@temppxa-\@temppxb)/(2*\@tempdelta)}}%
    \pgfmathparse{#2(#3,#4+\@tempdelta)}\let\@temppya\pgfmathresult
    \pgfmathparse{#2(#3,#4-\@tempdelta)}\let\@temppyb\pgfmathresult
    \edef\@temppy{\fpeval{(\@temppya-\@temppyb)/(2*\@tempdelta)}}%
    \edef\@tempu{\fpeval{(\@temppx,\@temppy,-1)/sqrt(\@temppx^2+\@temppy^2+1)}}%
    \edef\?{\endgroup\def\noexpand\pgfmathresult{\@tempu}%
        \def\noexpand\pgfmathresulta{\fpeval{1*(#3,#4,\@tempz)-\@tempu}}}%
    \?}
%%%%%%%%%%%%%%%%%green
\newcommand\computegraf[4][0.00025]{% [delta], function, x, y
    \begingroup\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
    \def\@tempdelta{#1}%
    \pgfmathparse{#2(#3,#4)}\let\@tempz\pgfmathresult
    \pgfmathparse{#2(#3+\@tempdelta,#4)}\let\@temppxa\pgfmathresult
    \pgfmathparse{#2(#3-\@tempdelta,#4)}\let\@temppxb\pgfmathresult
    \edef\@temppx{\fpeval{(\@temppxa-\@temppxb)/(2*\@tempdelta)}}%
    \pgfmathparse{#2(#3,#4+\@tempdelta)}\let\@temppya\pgfmathresult
    \pgfmathparse{#2(#3,#4-\@tempdelta)}\let\@temppyb\pgfmathresult
    \edef\@temppy{\fpeval{(\@temppya-\@temppyb)/(2*\@tempdelta)}}%
    \edef\@tempu{\fpeval{(\@temppx,\@temppy,-1)/sqrt(\@temppx^2+\@temppy^2+1)}}%
    \edef\?{\endgroup\def\noexpand\pgfmathresult{\@tempu}%
        \def\noexpand\pgfmathresulta{\fpeval{1*(#3,#4,\@tempz)-\@tempu}}}%
    \?}
%%%%%%%%%%%%%%%%%yellow
\newcommand\computegrag[4][0.00025]{% [delta], function, x, y
    \begingroup\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
    \def\@tempdelta{#1}%
    \pgfmathparse{#2(#3,#4)}\let\@tempz\pgfmathresult
    \pgfmathparse{#2(#3+0,#4)}\let\@temppxa\pgfmathresult
    \pgfmathparse{#2(#3-0,#4)}\let\@temppxb\pgfmathresult
    \edef\@temppx{\fpeval{(\@temppxa-\@temppxb)/(2*\@tempdelta)}}%
    \pgfmathparse{#2(#3,#4+\@tempdelta)}\let\@temppya\pgfmathresult
    \pgfmathparse{#2(#3,#4-\@tempdelta)}\let\@temppyb\pgfmathresult
    \edef\@temppy{\fpeval{(\@temppya-\@temppyb)/(2*\@tempdelta)}}%
    \edef\@tempu{\fpeval{(\@temppx,\@temppy,0)/sqrt(\@temppx^2+\@temppy^2+1)}}%
    \edef\?{\endgroup\def\noexpand\pgfmathresult{\@tempu}%
        \def\noexpand\pgfmathresulta{\fpeval{1*(#3,#4,1*\@tempz)-\@tempu}}}%
    \?}
%%%%%%%%%%%%%%%%%red
\newcommand\computegrah[4][0.00025]{% [delta], function, x, y
    \begingroup\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
    \def\@tempdelta{#1}%
    \pgfmathparse{#2(#3,#4)}\let\@tempz\pgfmathresult
    \pgfmathparse{#2(#3+\@tempdelta,#4)}\let\@temppxa\pgfmathresult
    \pgfmathparse{#2(#3-\@tempdelta,#4)}\let\@temppxb\pgfmathresult
    \edef\@temppx{\fpeval{(\@temppxa-\@temppxb)/(2*\@tempdelta)}}%
    \pgfmathparse{#2(#3,#4+0)}\let\@temppya\pgfmathresult
    \pgfmathparse{#2(#3,#4-0)}\let\@temppyb\pgfmathresult
    \edef\@temppy{\fpeval{(\@temppya-\@temppyb)/(2*\@tempdelta)}}%
    \edef\@tempu{\fpeval{(\@temppx,\@temppy,0)/sqrt(\@temppx^2+\@temppy^2+1)}}%
    \edef\?{\endgroup\def\noexpand\pgfmathresult{\@tempu}%
        \def\noexpand\pgfmathresulta{\fpeval{1*(#3,#4,\@tempz)-\@tempu}}}%
    \?}
%%%%%%%%%%%%%%%%%blue
\newcommand\computegral[4][0.00025]{% [delta], function, x, y
    \begingroup\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
    \def\@tempdelta{#1}%
    \pgfmathparse{#2(#3,#4)}\let\@tempz\pgfmathresult
    \pgfmathparse{#2(#3+0,#4)}\let\@temppxa\pgfmathresult
    \pgfmathparse{#2(#3-0,#4)}\let\@temppxb\pgfmathresult
    \edef\@temppx{\fpeval{(\@temppxa-\@temppxb)/(2*\@tempdelta)}}%
    \pgfmathparse{#2(#3,#4+0)}\let\@temppya\pgfmathresult
    \pgfmathparse{#2(#3,#4-0)}\let\@temppyb\pgfmathresult
    \edef\@temppy{\fpeval{(\@temppya-\@temppyb)/(2*\@tempdelta)}}%
    \edef\@tempu{\fpeval{(\@temppx,\@temppy,-1)/sqrt(\@temppx^2+\@temppy^2+1)}}%
    \edef\?{\endgroup\def\noexpand\pgfmathresult{\@tempu}%
        \def\noexpand\pgfmathresulta{\fpeval{1*(#3,#4,\@tempz)-\@tempu}}}%
    \?}
\makeatother    
\begin{tikzpicture}
[declare function={f(\x,\y)=0.6*sin(deg(\x))*cos(deg(\y);}]
\begin{axis}[scale=2,axis equal,view={0}{0},axis lines=center,axis on top,zmax=4.5,zmin=-1,samples=30,xlabel={$X$},ylabel={$Y$},zlabel={$F(x,y)$}]%ticks=none,
\addplot3[surf,color=DarkBlue,opacity=0.5,domain=0:2*pi, y domain=0:3,faceted color=black] {f(x,y)};
%%define P
\addplot3+ [mark=ball,mark size=2pt,scatter src=rand,ball color=yellow!80!black!60]
coordinates {({0.7},{0.25},{f(x,y)})};
\addplot3+ [mark=ball,mark size=2pt,scatter src=rand,ball color=yellow!80!black!60]
coordinates {({2.8},{0.5},{f(x,y)})};
%space vector
\draw[->,green,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegraf{f}{0.7}{0.25}} --\pgfmathresulta;
%y vector
\draw[->,yellow,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegrag{f}{0.7}{0.25}} --\pgfmathresulta;
%x vector
\draw[->,red,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegrah{f}{0.7}{0.25}} --\pgfmathresulta;
%z vector
\draw[->,blue,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegral{f}{0.7}{0.25}} --\pgfmathresulta;
%%%
%space vector
\draw[->,green,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegraf{f}{2.8}{0.5}} --\pgfmathresulta;
%y vector
\draw[->,yellow,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegrag{f}{2.8}{0.5}} --\pgfmathresulta;
%x vector
\draw[->,red,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegrah{f}{2.8}{0.5}} --\pgfmathresulta;
%z vector
\draw[->,blue,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegral{f}{2.8}{0.5}} --\pgfmathresulta;
\end{axis}
\end{tikzpicture}
\end{document}

查看更多

关注者
0
被浏览
625
1 个回答
雾月
雾月 2024-04-05
这家伙很懒,什么也没写!

应该用 \computegrad 的结果提取对应分量,你这个的模长不一样。
image.png

\documentclass[svgnames]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\makeatletter
\newcommand\computegrad[4][0.00025]{% [delta], function, x, y
    \begingroup\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
    \def\@tempdelta{#1}%
    \pgfmathparse{#2(#3,#4)}\let\@tempz\pgfmathresult
    \pgfmathparse{#2(#3+\@tempdelta,#4)}\let\@temppxa\pgfmathresult
    \pgfmathparse{#2(#3-\@tempdelta,#4)}\let\@temppxb\pgfmathresult
    \edef\@temppx{\fpeval{(\@temppxa-\@temppxb)/(2*\@tempdelta)}}%
    \pgfmathparse{#2(#3,#4+\@tempdelta)}\let\@temppya\pgfmathresult
    \pgfmathparse{#2(#3,#4-\@tempdelta)}\let\@temppyb\pgfmathresult
    \edef\@temppy{\fpeval{(\@temppya-\@temppyb)/(2*\@tempdelta)}}%
    \edef\@tempu{\fpeval{(\@temppx,\@temppy,-1)/sqrt(\@temppx^2+\@temppy^2+1)}}%
    \edef\?{\endgroup\def\noexpand\pgfmathresult{\@tempu}%
        \def\noexpand\pgfmathresulta{\fpeval{1*(#3,#4,\@tempz)-\@tempu}}}%
    \?}
\def\gradcomponent#1#2#3{%
  \edef\pgfmathresult{\fpeval{#2+\expanded{\noexpand\gradcomponent@#1}{#3}}}}
\def\gradcomponent@(#1,#2,#3)#4{\ifcase                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
    \if#4x 1 \else\if#4y 2 \else\if#4z 3 \else 4 \fi\fi\fi
  \or (0,#2,#3)\or (#1,0,#3)\or (#1,#2,0)\else(#1,#2,#3)\fi}
%%%%%%%%%%%%%%%%%green
\newcommand\computegraf[4][0.00025]{\computegrad[#1]{#2}{#3}{#4}}
%%%%%%%%%%%%%%%%%yellow
\newcommand\computegrag[4][0.00025]{\computegrad[#1]{#2}{#3}{#4}%
  \let\pgfmathresultb\pgfmathresult
  \gradcomponent\pgfmathresult\pgfmathresulta{y}%
  \let\pgfmathresulta\pgfmathresult \let\pgfmathresult\pgfmathresultb}
%%%%%%%%%%%%%%%%%red
\newcommand\computegrah[4][0.00025]{\computegrad[#1]{#2}{#3}{#4}%
  \let\pgfmathresultb\pgfmathresult
  \gradcomponent\pgfmathresult\pgfmathresulta{x}%
  \let\pgfmathresulta\pgfmathresult \let\pgfmathresult\pgfmathresultb}
%%%%%%%%%%%%%%%%%blue
\newcommand\computegral[4][0.00025]{\computegrad[#1]{#2}{#3}{#4}%
  \let\pgfmathresultb\pgfmathresult
  \gradcomponent\pgfmathresult\pgfmathresulta{z}%
  \let\pgfmathresulta\pgfmathresult \let\pgfmathresult\pgfmathresultb}
\makeatother    
\begin{tikzpicture}
[declare function={f(\x,\y)=0.6*sin(deg(\x))*cos(deg(\y);}]
\begin{axis}[scale=2,axis equal,view={0}{0},axis lines=center,axis on top,zmax=4.5,zmin=-1,samples=30,xlabel={$X$},ylabel={$Y$},zlabel={$F(x,y)$}]%ticks=none,
\addplot3[surf,color=DarkBlue,opacity=0.5,domain=0:2*pi, y domain=0:3,faceted color=black] {f(x,y)};
%%define P
\addplot3+ [mark=ball,mark size=2pt,scatter src=rand,ball color=yellow!80!black!60]
coordinates {({0.7},{0.25},{f(x,y)})};
\addplot3+ [mark=ball,mark size=2pt,scatter src=rand,ball color=yellow!80!black!60]
coordinates {({2.8},{0.5},{f(x,y)})};
%space vector
\draw[->,green,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegraf{f}{0.7}{0.25}} --\pgfmathresulta;
%y vector
\draw[->,yellow,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegrag{f}{0.7}{0.25}} --\pgfmathresulta;
%x vector
\draw[->,red,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegrah{f}{0.7}{0.25}} --\pgfmathresulta;
%z vector
\draw[->,blue,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegral{f}{0.7}{0.25}} --\pgfmathresulta;
%%%
%space vector
\draw[->,green,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegraf{f}{2.8}{0.5}} --\pgfmathresulta;
%y vector
\draw[->,yellow,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegrag{f}{2.8}{0.5}} --\pgfmathresulta;
%x vector
\draw[->,red,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegrah{f}{2.8}{0.5}} --\pgfmathresulta;
%z vector
\draw[->,blue,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegral{f}{2.8}{0.5}} --\pgfmathresulta;
\end{axis}
\end{tikzpicture}
\end{document}

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览