渐近线中的 3D 矢量场

渐近线中的 3D 矢量场

我想使用 Asymptote 绘制 3D 矢量场,例如F(x,y,z) = <y+z,x+z,x+y>,其中返回矢量的矩形立体(例如,5 x 5 x 5)。结果肯定会很混乱,但这就是我想要的。我只能在 Asymptote 手册中看到如何沿表面绘制矢量场,我无法弄清楚如何调整示例文件以满足我的需求。在 Mathematica 中,有一个简单的VectorPlot3D命令可以精确地完成此操作。

如何做呢?

答案1

据我所知,你必须自己制作这样的函数(还有一个问题,要求在一条线上绘制一个矢量场)。所以我修改了vectorfield中的定义graph3.asy(我删除了这种bool cond(z)可能性)。正如詹姆斯所说,这是一些循环。还计算了一个比例。请考虑代码

import graph3;

size(12cm,0);
currentprojection=perspective((45,135,30));

path3 gradient1(triple z){
  return O--(z.y+z.z,z.x+z.z,z.x+z.y);
}


/* First solution : a loop on z

   void VectorAPlot3D(path3 vector(triple v), triple a, triple b,
   int nx=nmesh, int ny=nx, int nz=nx,bool truesize=false,
   //real maxlength=truesize ? 0 : maxlength(f,a,b,nu,nv),
   //  bool cond(pair z)=null,
   pen p=currentpen,
   arrowbar3 arrow=Arrow3, margin3 margin=PenMargin3,
   string name="", render render=defaultrender)
   {
   real dz=1/nz;
   for(int k=0; k <= nz; ++k)
   {
   real z=interp(a.z,b.z,k*dz);
   path3 gradient (pair r)
   {
   triple tmp=(r.x,r.y,z);
   return vector(tmp);
   }
   triple F(pair r) { return(r.x,r.y,z);}
   add(vectorfield(gradient,F,(a.x,a.y),(b.x,b.y),nx,ny,truesize,p,arrow,margin,name,render));
   }

   }
   VectorAPlot3D(gradient1,A,B,5,5,5);
*/
triple A=(0,0,0);
triple B=(5,5,5);

picture VectorPlot3D(path3 vector(triple t), triple a, triple b,
                     int nx=nmesh, int ny=nx, int nz=nx,bool truesize=false,
                     real maxlength=truesize ? 0 : min(abs(b.x-a.x)/nx,abs(b.y-a.y)/ny,abs(b.z-a.z)/nz),
                     //  bool cond(pair z)=null,
                     pen p=currentpen,
                     arrowbar3 arrow=Arrow3, margin3 margin=PenMargin3,
                     string name="", render render=defaultrender)
{
  picture pic;
  real dx=1/nx;
  real dy=1/ny;
  real dz=1/nz;
  real scale;
  if(maxlength > 0) {
    real size(triple t) {
      path3 g=vector(t);
      return abs(point(g,size(g)-1)-point(g,0));
    }
    real max=size((0,0,0));

    for(int i=0; i <= nx; ++i) {
      real x=interp(a.x,b.x,i*dx);
      for(int j=0; j <= ny; ++j)
        {
          real y=interp(a.y,b.y,j*dy);
          for(int k=0; k <= nz; ++k)
            max=max(max,size((x,y,interp(a.z,b.z,k*dz))));
        }}
    scale=max > 0 ? maxlength/max : 1;
  } else scale=1;
  bool group=name != "" || render.defaultnames;
  if(group)
    begingroup3(pic,name == "" ? "vectorfield" : name,render);
  for(int i=0; i <= nx; ++i) {
    real x=interp(a.x,b.x,i*dx);
    for(int j=0; j <= ny; ++j) {
      real y=interp(a.y,b.y,j*dy);
      for(int k=0; k <= nz; ++k)
        {      triple z=(x,y,interp(a.z,b.z,k*dz));
          {
            path3 g=scale3(scale)*vector(z);
            string name="vector";
            if(truesize) {
              picture opic;
              draw(opic,g,p,arrow,margin,name,render);
              add(pic,opic,z);
            } else
              draw(pic,shift(z)*g,p,arrow,margin,name,render);
          }
        }
    }}
  if(group)
    endgroup3(pic);
  return pic;

}
add(VectorPlot3D(gradient1,A,B,5,5,5));
xaxis3(XY()*"$x$",OutTicks(XY()*Label));
yaxis3(XY()*"$y$",InTicks(YX()*Label));
zaxis3("$z$",OutTicks);

结果 在此处输入图片描述

请注意,在代码中,还有一个先前的版本,即在高度为 的矩形内z和上有一个循环,在这种情况下,不同的 的比例可能会有所不同。vectorfieldzz

答案2

我没有寻找固定函数,但您始终可以使用for如下的一些循环手动完成它。

import three;
size(1inch);
currentprojection=perspective((45,135,30));

for (int x = 1; x <= 5; ++x) {
    for (int y = 1; y <= 5; ++y) {
        for (int z = 1; z <= 5; ++z) {
            triple start = (x,y,z);
            triple end = start + scale(0.1,0.1,0.1)*(y+z,x+z,x+y);
            draw(start--end, Arrow3(2));
        }
    }
}

在此处输入图片描述

相关内容