我想使用 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
和上有一个循环,在这种情况下,不同的 的比例可能会有所不同。vectorfield
z
z
答案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));
}
}
}