
私はパラメトリックサーフェスを持っています。これは次のように定義されています。ランバートW関数これを Asymptote で表示したいです。そのために、Lambert W 関数はニュートン法を使用して実装され、ゼロ除算の問題を回避するために元の (閉じた) 表面を 2 つの開いた表面に分割する必要がありました。これが MWE です。
settings.render=8;
settings.prc=false;
settings.outformat="pdf";
import graph3;
size(200);
currentprojection=orthographic(40,10,10);
// contour value
real c = 0.006;
// parameter ranges
real umin = asin(1.5*exp(1)*sqrt(c*(sqrt(2*pi))));
real umax = pi-asin(1.5*exp(1)*sqrt(c*(sqrt(2*pi))));
real vmin = 0;
real vmax = 1;
// Lambert W function
real w1(real w, real z, int i){return z<-1/exp(1) - 0.00001 ? 1/0 : z<-1/exp(1) ? -1 : i>0 && abs((w*exp(w)-z)/(exp(w)+w*exp(w))) > 1e-7 ? w1(w-(w*exp(w)-z)/(exp(w)+w*exp(w)),z,i-1) : w-(w*exp(w)-z)/(exp(w)+w*exp(w));};
// auxiliary functions
real y5(real h, real p){return (1/4.)*sqrt(15./pi) * sin(2*p) * sin(h)**2;};
real r1(real y){return -6*w1(-2,-sqrt(c*9*sqrt(30)/abs(y))/4,200);};
real r2(real y){return -6*w1(1,-sqrt(c*9*sqrt(30)/abs(y))/4,200);};
// x, y, and z coordinates of the surfaces
real x11(real u, real v){return r1(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2))))*sin(u)*cos(v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)));};
real y11(real u, real v){return r1(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2))))*sin(u)*sin(v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)));};
real z11(real u, real v){return r1(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)) ))*cos(u);};
real x12(real u, real v){return r2(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2))))*sin(u)*cos(v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)));};
real y12(real u, real v){return r2(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2))))*sin(u)*sin(v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)));};
real z12(real u, real v){return r2(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)) ))*cos(u);};
triple f11(pair p){return (x11(p.x,p.y),y11(p.x,p.y),z11(p.x,p.y));};
triple f12(pair p){return (x12(p.x,p.y),y12(p.x,p.y),z12(p.x,p.y));};
surface s11 = surface(f=f11,a=(umin, vmin),b=(umax,vmax)); // this works
surface s12 = surface(f=f12,a=(umin, vmin),b=(umax,vmax)); // this works
// surface s11 = surface(f=f11,a=(umin, vmin),b=(umax,vmax),Spline); // this doesn't work
// surface s12 = surface(f=f12,a=(umin, vmin),b=(umax,vmax),Spline); // this doesn't work
draw(s11, red+opacity(0.5));
draw(s12, red+opacity(0.5));
表面を滑らかに見せるためのディレクティブを追加すると、Spline
Asymptote がエラーでクラッシュしますsome path/graph_splinetype.asy: 89.10: function values are not periodic
。 と で何が間違っているのかを理解しようとしましたがgraph_splinetype.asy
、graph3.asy
残念ながら成功するほど熟練していません。そこで私の質問は次のとおりです。Spline
このパラメトリック サーフェスを操作したり、滑らかに見せるための別の方法を試したりするチャンスはありますか?
さらに不可解なのは、Spline
同様のパラメトリック サーフェス (ただし、このサーフェスは z 軸を中心に回転対称性があり、これが重要になる場合があります) では問題なく機能することです。具体的には、次のサーフェスです。
settings.render=8;
settings.prc=false;
settings.outformat="pdf";
import graph3;
size(200);
currentprojection=orthographic(40,10,10);
// contour value
real c = 0.006;
// parameter ranges
real umin = 0;
real umax = acos(2*exp(1)*c*sqrt(2*pi))-0.0000001;
real vmin = 0;
real vmax = 2*pi;
// Lambert W function
real w1(real w, real z, int i){return z<-1/exp(1) - 0.00001 ? 1/0 : z<-1/exp(1) ? -1 : i>0 && abs((w*exp(w)-z)/(exp(w)+w*exp(w))) > 1e-7 ? w1(w-(w*exp(w)-z)/(exp(w)+w*exp(w)),z,i-1) : w-(w*exp(w)-z)/(exp(w)+w*exp(w));};
// auxiliary functions
real y1(real h){return sqrt(3./pi)/2.*cos(h);};
real r1(real y){return -2*w1(-2,-c*sqrt(6)/abs(y),200);};
real r2(real y){return -2*w1(1,-c*sqrt(6)/abs(y),200);};
// x, y, and z coordinates of the surfaces
real x11(real u, real v){return r1(y1(u))*sin(u)*cos(v);};
real y11(real u, real v){return r1(y1(u))*sin(u)*sin(v);};
real z11(real u, real v){return r1(y1(u))*cos(u);};
real x12(real u, real v){return r2(y1(u))*sin(u)*cos(v);};
real y12(real u, real v){return r2(y1(u))*sin(u)*sin(v);};
real z12(real u, real v){return r2(y1(u))*cos(u);};
triple f11(pair p){return (x11(p.x,p.y),y11(p.x,p.y),z11(p.x,p.y));};
triple f12(pair p){return (x12(p.x,p.y),y12(p.x,p.y),z12(p.x,p.y));};
surface s11 = surface(f11,(umin,vmin),(umax,vmax),50,Spline);
surface s12 = surface(f12,(umin,vmin),(umax,vmax),50,Spline);
draw(s11, red+opacity(0.5));
draw(s12, red+opacity(0.5));
答え1
システムと Asymptote のバージョンを詳しく教えていただけますか? 私のコンピューター (Linux 64 ビット、Sid、Asymptote svn) では問題は発生せず、コードは滑らかな表面を生成します。
周期的スプラインと not_a_knot スプラインの選択はサーフェス ルーチンに実装されているため、最終的なパラメトリック スプライン ルーチンよりも制限が少ないようです (この滑らかなサーフェス ルーチンの一部をかなり前に書きました)。次のコードを使用して、「not a knot」の選択を強制することができます。
splinetype[] Notaknot={notaknot,notaknot,notaknot};
surface s11 = surface(f=f11,a=(umin,vmin),b=(umax,vmax),8,16,Notaknot,Notaknot);
surface s12 = surface(f=f12,a=(umin,vmin),b=(umax,vmax),8,16,Notaknot,Notaknot);
あなたのシステムでも動作することを願っています。
オリジナル