我想要用asymptote
下图来说明斯托克斯定理。
这是我迄今为止所做的事情。
import three;
size(6cm,0);
path path2D = (1, 0) .. (2, 1) .. (0, 2) .. (-2.25, 1) .. (-1.5, 0) .. (-1, -1) .. (0, -1.75) .. (1, -2) .. cycle;
path3 path3D = path3(path2D, XYplane);
draw(path3D, red, arrow = Arrow3(emissive(black), position = Relative(.9)), L = Label("$\mathcal{C}$", align = S, position = Relative(.9)));
int imax = 10;
for(int i = 1; i < imax; ++i) {
draw(shift((0, 0, i / (imax / 2))) * scale3(sqrt((imax - i - .9)/imax)) * path3D);
}
我怎样才能绘制一个由黑色路径“引导”并“位于”红色路径上的表面?
我怎样才能使黑色引导线和表面更加“随机化”(斯托克斯定理指出人们可以选择路径上的任何表面)?
一旦定义了表面,给定一个属于它的点M,是否有可能得到M中的法向量(然后重用corkscrew 问题
:)
)?
答案1
在这个解决方案中,表面由函数定义
triple f(pair z){
path3 p;
p=shift((0, 0, log(1+z.y / (imax / 2)))) * scale3(sqrt(1-(z.y^2)/imax^2)) * path3D;
return relpoint(p,z.x);
}
它接受两个参数:z.x
定义水平路径弧长的分数,并z.y
定义垂直偏移。
M
给定表面上的一个点
triple M=f((Mxy,Mz));
u-path
法向量由曲面 (和)上两个路径的方向向量的叉积构成v-path
。在点 处M
。
完整代码:
import graph3;
size(6cm,0);
currentprojection=orthographic(camera=(4.3,2,4.5),
up=Z,target=(-0.1,0.1,0.06),zoom=0.9);
path path2D = (1, 0) .. (2, 1) .. (0, 2) .. (-2.25, 1) .. (-1.5, 0) .. (-1, -1) .. (0, -1.75) .. (1, -2) .. cycle;
path3 path3D = path3(path2D, XYplane);
int imax = 8;
triple f(pair z){
path3 p;
p=shift((0, 0, log(1+z.y / (imax / 2)))) * scale3(sqrt(1-(z.y^2)/imax^2)) * path3D;
return relpoint(p,z.x);
}
real Mxy=0.31;
real Mz=2;
triple M=f((Mxy,Mz));
real ux(real t) {return f((t,Mz)).x;}
real uy(real t) {return f((t,Mz)).y;}
real uz(real t) {return f((t,Mz)).z;}
real vx(real t) {return f((Mxy,t)).x;}
real vy(real t) {return f((Mxy,t)).y;}
real vz(real t) {return f((Mxy,t)).z;}
guide3 gu=graph(ux,uy,uz,0,1,operator..);
guide3 gv=graph(vx,vy,vz,0,imax,operator..);
real t=intersect(gu,gv)[1];
triple du=dir(gu,reltime(gu,Mxy));
triple dv=dir(gv,t);
triple normal=unit(cross(du,dv));
arrowbar3 ar=Arrow3(emissive(black), position = Relative(.9));
arrowbar3 arn=Arrow3(emissive(black));
draw(path3D, red, arrow = ar, L = Label("$\mathcal{C}$", align = S, position = Relative(.9)));
draw(surface(f,(0,0),(1,imax)
,nu=30
,Spline,Spline),orange+opacity(0.5)
);
draw(gu, deepblue);
draw(gv, brown);
dot(M);
draw(M--(M+normal),arn);
答案2
我不推荐你的方法。
我怎样才能绘制一个由黑色路径“引导”并“位于”红色路径上的表面?
我怎样才能使黑色引导线和表面更加“随机化”(斯托克斯定理指出人们可以选择路径上的任何表面)?
一旦定义了表面,给定一个属于它的点 M,是否有可能获得 M 中的法线向量(然后重新使用螺旋问题:))?
虽然“躺着”具有明确单一的含义(即路径是表面的边界),但“引导”和“随机化”的可能性却无穷无尽。此外,计算法向量的难易程度很大程度上取决于该选择。
也许我遗漏了一些东西,但如果你只关心说明斯托克斯定理,我认为没有理由从一系列截面中构建一些曲面。
我想说你只是希望表面看起来像摇摇晃晃的东西。我建议使用参数化的表面(和一些良好的照明):这样您就可以立即在一个容易选择的点上获得精确的参数法线向量。
import graph3;
size(6cm,0);
settings.render = 4;
currentprojection=orthographic(4, 1, 1);
// COORDINATE SYSTEM
label("$O$", (0, 0, 0), NW);
Label Lx = Label("$x$", EndPoint, W);
Label Ly = Label("$y$", EndPoint, S);
Label Lz = Label("$z$", EndPoint, W);
draw(Lx, O--2X, Arrow3(emissive(black)));
draw(Ly, O--2Y, Arrow3(emissive(black)));
draw(Lz, O--2Z, Arrow3(emissive(black)));
// SURFACE
triple S(pair uv) {
real x = cos(uv.x)*sin(uv.y);
real y = sin(uv.x)*sin(uv.y);
real z = cos(uv.y);
return (x-(1-z**2-y**2), y-0.3*sin(z*pi), z);
}
// BOUNDARY
triple dS(real u) {
return S((u, pi/2));
}
// TANGENT VECTORS
real e = 0.001; // *this... is... infinitesimal!*
triple U(pair t) { return (S((e,0)+t)-S(t))/e; }
triple V(pair t) { return (S((0,e)+t)-S(t))/e; }
// NORMAL VECTOR
triple N(pair uv) {
return cross(U(uv),V(uv))/length(cross(U(uv),V(uv)));
}
// GRAPHICAL ELEMENTS
surface s = surface(S, (0, 0), (2pi, pi/2), 64, 64, Spline);
path3 ds = graph(dS, 0, 2pi);
pair t = (-pi/8, pi/8);
path3 n = S(t) -- shift(-N(t))*S(t);
triple adj = (0,1.4,0.7);
s = shift(adj)*s;
ds = shift(adj)*ds;
n = shift(adj)*n;
label("$\Sigma$", shift(0,0,0.1)*shift(adj)*S((pi/2,pi/5)), NE);
Label LdS = Label("$\partial\Sigma$", Relative(0.95), S);
Label Ln = Label("$\mathbf n$", EndPoint, NW);
draw(s, surfacepen=material(diffusepen=gray(0.6),emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(LdS, ds, Arrow3(emissive(black)));
draw(shift(4*unit(currentprojection.camera))*ds, dashed);
draw(Ln, n, Arrow3(emissive(black)));
请求的附录:虚线上
(改编自评论)
我想在表面上绘制虚线边框。由于这是正交投影,最简单的方法是沿相机轴向它平移对象(而不是检查哪些部分可见,这可能很复杂):
draw(shift(4*unit(currentprojection.camera))*ds, dashed);
unit(currentprojection.camera)
是与相机轴平行并指向它的一个方向轴,因此它在平移时很有用。4
不是随机的。请注意,表面的边界体积也(显然)限制了边界。如果表面是一个单一球体,那么一个好的边界就是球体本身,因此2
(半径的两倍)的位移将保证表面和路径的边界球相切,因此它们不相交。不幸的是,我们的表面是一个变形球体:
triple S(pair uv) {
real x = cos(uv.x)*sin(uv.y);
real y = sin(uv.x)*sin(uv.y);
real z = cos(uv.y);
return (x-(1-z**2-y**2), y-0.3*sin(z*pi), z);
}
1
然而,每个点上的变形似乎都不会在任何方向上超过:
(-(1-z**2-y**2), -0.3*sin(z*pi), 0)
变形本身是否可能由一个单一球面局部约束?让我们来一探究竟:如果我用 Mathematica 的RegionPlot[{Norm[{-(1-z^2-y^2),-0.3*Sin[z*Pi],0}]<1,Norm[{0,y,z}]<1},{z,-2,2},{y,-2,2},PlotLegends->"Expressions"]
输出来扼杀它
这意味着可以安全使用假定变形边界的体积(截面为蓝色的圆柱体)远远超出了我们需要的范围(投影为橙色的球体表面)。胜利!
变形表面的边界体积是多少?取初始边界,即球体本身,并将变形边界(即一个单元球体)附加到每个点。我们得到了什么?半径为的边界球体2
。因此,根据我们的旧论点,位移4
(增强边界球半径的两倍)是安全的。
置换技巧本身适用于任何光线平行的投影(相机位于无穷远处)。这意味着它只对透视相机无效。