漸近線上の表面上のグリッド(チューブ)の角を閉じる

漸近線上の表面上のグリッド(チューブ)の角を閉じる

次のような簡単な鞍面の図を考えてみましょう。asymptote

import graph3;

real f (pair p) {
  real x = p.x;
  real y = p.y;
  return 0.5*(x^2-y^2);
}

surface saddle=surface(f,(-2,-2),(2,2),nx=5,Spline);

draw(saddle,gray,0.1+blue);

出力のスナップショットを見てみましょう:

出力からのスナップショット

グリッド ラインを形成するチューブがサーフェスの角で結合する不快な方法がわかると思います。回避策として、適切な半径のボールを手動で角に追加することもできます。たとえば、次の行を追加します。

draw(shift(-2,-2,f((-2,-2)))*scale(0.05,0.05,0.05)*unitsphere,blue);

次のような改善が得られます。 ここに画像の説明を入力してください

もっと良い方法はないでしょうか? グリッド ライン (より正確にはチューブ) の接続をうまく閉じるにはどうすればよいでしょうか?

答え1

原則として、 を使用しない限りsettings.render=0、サーフェスを描画するときに オプションを使用しないことをお勧めしますmeshpen。メッシュを自分で描画することには多くの利点がありますが、問題を解決できることは、これらの利点の中でも最も重要でないものの 1 つです。

settings.outformat="png";
settings.render=8;
unitsize(1cm);

import graph3;

currentprojection=perspective(5,5,5);

pen meshpen = 2pt + 0.7blue + 0.1green;

real f (pair p) {
  real x = p.x;
  real y = p.y;
  return 0.5*(x^2-y^2);
}

surface saddle=surface(f,(-2,-2),(2,2),nx=5,Spline);

draw(saddle, surfacepen=gray);

for(int x = -2; x <= 2; ++x) {
  draw(graph(new triple(real y) {return (x,y,f((x,y)) );}, -2, 2), meshpen);
}
for (int y = -2; y <= 2; ++y) {
  draw(graph(new triple(real x) {return (x,y,f((x,y)) );}, -2, 2), meshpen);
}

結果が出ました

ここに画像の説明を入力してください

通常はもっと細いグリッド線を好みますが、問題が実際に現れるかどうかを確認できるように太めに作成しました。

一方、グリッド線を太くし、チューブのように陰影を付けたい場合は、このソリューションはかなり良いものです。基本的には、線に丸いキャップを追加します (チューブ陰影なしでグリッド線を描画すると、自動的に実行されます)。チューブ状のパスを手動で描画する場合は、モジュールのマニュアルtubeセクションthree(Asymptote 2.23 のマニュアルの 134 ページ) に記載されている方法を確認してください。このアプローチを使用する別の方法は、グリッドの端にグリッド線を描画する代わりに、またはグリッドの端に加えて、グラフの端に循環パス (のチューブ) を描画することです。


更新: メッシュを手で描く方法は次のとおりです (チューブと別のアウトラインを使用)。混乱を避けるためにペンの名前を変更しました。演算子は、&エンドポイントを共有する 2 つのパスを連結するためのものであることに注意してください。

settings.outformat="png";
settings.render=8;
unitsize(1cm);

import graph3;

surface operator cast(tube t) {
  return t.s;
}

currentprojection=perspective(5,5,5);

pen gridpen = blue;

real f (pair p) {
  real x = p.x;
  real y = p.y;
  return 0.5*(x^2-y^2);
}

int xmin = -2, xmax=2, ymin=-2, ymax=2;

surface saddle=surface(f,(xmin,ymin),(xmax,ymax),nx=5,Spline);

draw(saddle, surfacepen=gray);

int nx=5, ny=5;

path3 x_equals(real x) {
  return graph(new triple(real y) {return (x,y,f((x,y)));}, ymin, ymax);
}
path3 y_equals(real y) {
  return graph(new triple(real x) {return (x,y,f((x,y)));}, xmin, xmax);
}

real tubewidth = 0.1;

for(int i = 1; i < nx; ++i) {
  real x = (xmax-xmin)*(i/nx) + xmin;
  surface todraw = tube(x_equals(x), width=tubewidth);
  draw(todraw, gridpen);
}
for (int i = 1; i < ny; ++i) {
  real y = (ymax-ymin)*(i/ny) + ymin;
  surface todraw = tube(y_equals(y), width=tubewidth);
  draw(todraw, gridpen);
}

path3 outline = x_equals(xmin) & y_equals(ymax) & reverse(x_equals(xmax)) & reverse(y_equals(ymin)) & cycle;
draw(tube(outline,width=tubewidth), gridpen);

結果:

ここに画像の説明を入力してください

答え2

これが私がOPで述べた回避策です。

import graph3;

real gridWidth=0.05;
pen  gridPen=blue;

real f (pair p) {
  real x = p.x;
  real y = p.y;
  return 0.5*(x^2-y^2);
}

void fillGap (pair p) {
  real width=0.5*gridWidth;
  draw(shift(p.x,p.y,f(p))*scale(width,width,width)*unitsphere,gridPen);
}

real minVal = -2;
real maxVal = -minVal;

surface saddle=surface(f,(minVal,minVal),(maxVal,maxVal),nx=5,Spline);

draw(saddle,gray+opacity(0.95),gridWidth+gridPen);

fillGap((minVal,minVal));
fillGap((minVal,maxVal));
fillGap((maxVal,minVal));
fillGap((maxVal,maxVal));

適切な場所に球体を描画するのに役立ついくつかの追加パラメータと関数を定義しました。

関連情報