如何在一条线上绘制三维矢量场?

如何在一条线上绘制三维矢量场?

如何在一条线上绘制三维矢量场?

我想可视化矢量场 $( m_x(x), m_y(x), m_z(x) )$。搜索“可视化矢量场”后,我发现大多数绘图软件要么在平面上绘制二维矢量场,如速度场,要么在三维空间中绘制三维矢量场,如 $( u(x,y,z), v(x,y,z), w(x,y,z))$。

我尝试使用 MATLAB 函数 quiver3 来绘制我的测试数据,

quiver3( x, zeros(1,N), zeros(1,N), mx, my, mz );

这是我得到的结果,相当不令人满意。 在此处输入图片描述

最好用下图这样替换(简单的3d渲染就可以了,不需要和下图一模一样), 在此处输入图片描述

[来源:MPQ,量子多体系统部门]

所以我想问一下,是否可以使用 asympotote/tikz/matlab/mathematica 进行这样的演示?这个矢量场是时间的函数,所以我将生成这些图的电影。

我并不要求它在 TeX 中生成,只要它最终可以合并到我的 TeX 文件中即可。严格来说,它不是一个 TeX 问题;如有必要,请将其迁移到适当的 StackExchange 站点。

答案1

使用 Asymptote 可以沿表面(而不是路径)绘制 3D 矢量场。调整此例程以沿路径绘制 3D 矢量场并不困难。但是复杂的箭头不可用,需要更多工作。请查找示例

import graph3;
size(200,0);

currentprojection=perspective(10,8,4);

real f(pair z) {return 0.5+exp(-abs(z)^2);}
triple F(pair z){ return (z.x,z.y,f(z));}
path3 gradient(pair z) {
    static real dx=sqrtEpsilon, dy=dx;
    return O--(-(f(z+dx)-f(z-dx))/2dx,
         -(f(z+I*dy)-f(z-I*dy))/2dy,
         1);
    }

add(vectorfield(gradient,F,(-1,-1),(1,1),red));

draw((-1,-1,0)--(1,-1,0)--(1,1,0)--(-1,1,0)--cycle);

surface s=surface(f,(-1,-1),(1,1),nx=5,Spline);

xaxis3(Label("$x$"),red,Arrow3);
yaxis3(Label("$y$"),red,Arrow3);
zaxis3(XYZero(extend=true),red,Arrow3);

draw(s,lightgray,meshpen=black+thick(),nolight,render(merge=true));
label("$O$",O,-Z+Y,red);

结果 在此处输入图片描述

最后,Python/Matplotlib/Numpy/Scipy 解决方案(可以生成电影)怎么样?

编辑于 2014 年 11 月 17 日。我尝试修改 Asymptote 的矢量场函数并包含特殊箭头。因为我不知道你的路径和矢量场如何依赖,所以以下例程沿曲线绘制矢量场,在 f(t) 上绘制的矢量场取决于 (f(x),f(y))。对于特殊箭头,我不会在 Asymptote 意义上创建新的 Arrow3,而是在矢量场例程中添加球体

import graph3;
real maxilength(triple f(real z), real a, real b, int nu) 
{

  real du=1/nu;
  real  maxi = abs(f(a+(b-a)/nu)-f(a));
  for(int i=0; i < nu; ++i) {
    real x=interp(a,b,i*du);
    real y=interp(a,b,(i+1)*du); 
    maxi=min(maxi,abs(f(y)-f(x)));
  }
  return maxi;
}

// return a vector field on a parametric curve f defined on the interval
// [a,b].
// The vector field depends on the x and y coordinates of f. For example
// f is a curve lying on a surface and the vector field depends on the
// (x,y) point of the surface
picture vectorfield(path3 vector(pair v), triple f(real z), real a, real b,
                    int nu=nmesh, int nv=nu, bool truesize=false,
                    real maxlength=truesize ? 0 : maxilength(f,a,b,nu)
                    ,
                    bool cond(real z)=null, pen p=currentpen,
                    arrowbar3 arrow=Arrow3, margin3 margin=PenMargin3,
                    string name="", render render=defaultrender)
{
  picture pic;
  real du=1/nu;
  bool all=cond == null;
  real scale;
  if(maxlength > 0) {
    real size(pair z) {
      path3 g=vector(z);
      return abs(point(g,size(g)-1)-point(g,0));
    }
    real maxi=size((0,0));
    for(int i=0; i <= nu; ++i) {
      real x=interp(a,b,i*du);
      maxi=max(maxi,size((f(x).x,f(x).y)));
    }
    scale=maxi > 0 ? maxlength/maxi : 1;
  } else scale=1;

  bool group=name != "" || render.defaultnames;
  if(group)
    begingroup3(pic,name == "" ? "vectorfield" : name,render);
  for(int i=0; i <= nu; ++i) {
    real x=interp(a,b,i*du);
    real z=x;
    if(all || cond(z)) {
      path3 g=scale3(scale)*vector((f(z).x,f(z).y));
      string name="vector";
      if(truesize) {
        picture opic;
        draw(opic,g,p,arrow,margin,name,render);
        draw(opic,shift(point(g,.25))*scale3(abs(point(g,1)-point(g,0))/8)*unitsphere,p,name,render);
        add(pic,opic,f(z));
      } else
        {
          draw(pic,shift(f(z))*g,p,arrow,margin,name,render);
          draw(pic,shift(f(z))*shift(point(g,.25))*scale3(abs(point(g,1)-point(g,0))/8)*unitsphere,p,name,render);
        }
    }
    // }
  }
  if(group)
    endgroup3(pic);
  return pic;
}




import graph3;

size(200,0);

currentprojection=perspective(10,8,4);

real f(pair z) {return 0.5+exp(-abs(z)^2);}

//triple F(pair z){ return (z.x,z.y,f(z));}

triple FF(real x) {return (cos(x),sin(x),f((cos(x),sin(x))));}

path3 gradient(pair z) {
  static real dx=sqrtEpsilon, dy=dx;
  return O--(//(f(z+I*dy)-f(z-I*dy))/2dy,
             -(f(z+dx)-f(z-dx))/2dx,
             -             (f(z+I*dy)-f(z-I*dy))/2dy,
             1);
}


//add(vectorfield(gradient,F,(-1,-1),(1,1),red,Arrow3));
add(vectorfield(gradient,FF,-pi,pi-0.4,20,//maxlength=.2,
                1.5bp+red,Arrow3(DefaultHead3)));

draw((-1,-1,0)--(1,-1,0),Arrow3(DefaultHead3));

draw((-1,-1,0)--(1,-1,0)--(1,1,0)--(-1,1,0)--cycle);


surface s=surface(f,(-1,-1),(1,1),nx=5,Spline);

xaxis3(Label("$x$"),red,Arrow3);
yaxis3(Label("$y$"),red,Arrow3);
zaxis3(XYZero(extend=true),red,Arrow3);

draw(s,lightgray+opacity(.5),meshpen=black+thick(),nolight,render(merge=true));

label("$O$",O,-Z+Y,red);

请查找结果

在此处输入图片描述

答案2

使用pst-solides3d。从我的代码开始,完成您的示例。请注意,编译需要很长时间。

\documentclass{article}
\usepackage{etex}
\usepackage{pst-solides3d}
\newcommand\arrow[2]{
\psSolid[object=cylindre,h=.11,r=.04,
         fillcolor=#2,linewidth=.25pt,
         transform={0 0 -.2 translatepoint3d #1},ngrid=1 16]
\psSolid[object=sphere,r=.1,
         fillcolor=#2,linewidth=.25pt,
         transform={ #1},ngrid=16 16]%
\psSolid[object=cylindre,h=.11,r=.04,
         fillcolor=#2,linewidth=.25pt,
         transform={0 0 .09 translatepoint3d #1},ngrid=1 16]%
\psSolid[object=cone,h=.2,r=.075,
         fillcolor=#2,mode=4,linewidth=.25pt,
         transform={0 0 .2 translatepoint3d #1},ngrid=1 16]%
 }
\begin{document}
\psset{unit=.1\textwidth,viewpoint=10 45 25 rtp2xyz,
       Decran=10,lightsrc=10 10 10,lightintensity=2}
\begin{pspicture}(-5,-5)(5,5)
    \multido{\iA=0+1,\iB=0+30}{20}{
        \arrow{0 30 0 rotateOpoint3d 
               0 0 \iB\space rotateOpoint3d 
               0 \iA\space .6 mul 6 sub 0 translatepoint3d}{blue!50}
            }
\end{pspicture}     
\end{document}

在此处输入图片描述

相关内容