渐近线:是否有与表面轮廓相当的东西?

渐近线:是否有与表面轮廓相当的东西?

更新

如果没有等价于silhouette您能否对我的以下想法发表评论:我可以使用变换获得表面的投影planeproject。这仍然是一个三维表面,但也许从这个更简单的表面提取轮廓路径更容易?如果这也不可能,也许以下算法可以奏效:

  1. planeproject表面
  2. 提取变换表面上的密集点网格(这些点应位于同一平面内);或者甚至可以通过某种方式提取平坦表面的边界点(可能通过使它们的斜率不同于平坦表面其他点的斜率)
  3. 使用一些凹壳算法(当然,必须首先实现)来找到上述点的凹壳。
  4. 使用沿凹壳的路径作为轮廓

这里我特别不确定是否有简单的方法可以完成第 2 步。我必须考虑当凹壳由多条路径组成时该怎么做,例如对于圆环,你可以得到外部轮廓和中间的洞。你认为这可能吗?

原始问题

solids包定义了revolution一些对象,它们的轮廓可以通过 来访问silhouette。例如:

size(200);
import solids;
settings.render=0;
settings.prc=false;

currentprojection=perspective(4,4,3);
revolution hyperboloid=revolution(new real(real x) {return sqrt(1+x*x);},
                              -2,2,20,operator..,X);
draw(hyperboloid.silhouette(64),blue);

在此处输入图片描述

有没有等效的方法来获取 的轮廓路径surface?例如这样的 的轮廓surface(我知道此示例中的对象是球对称的,因此我可以定义 来revolution描述它,但我想知道是否有通用的方法来获取 的轮廓surface):

import graph3;
import palette;
size(200);
currentprojection=orthographic(6,8,2);
viewportmargin=(1cm,0);

real c0=0.1;

real f(real r) {return r*(1-r/6)*exp(-r/3);}

triple f(pair t) {
  real r=t.x;
  real phi=t.y;
  real f=f(r);
  real s=max(min(c0/f,1),-1);
  real R=r*sqrt(1-s^2);
  return (R*cos(phi),R*sin(phi),r*s);
}

bool cond(pair t) {return f(t.x) != 0;}

real R=abs((20,20,20));
surface s=surface(f,(0,0),(R,2pi),100,8,Spline,cond);

s.colors(palette(s.map(abs),Gradient(palegreen,heavyblue)));

render render=render(compression=Low,merge=true);
draw(s,render);
draw(zscale3(-1)*s);

在此处输入图片描述

答案1

好的,我想我或多或少已经找到解决方案了。

Silhouette函数由以下代码定义:

import graph3;
import contour;

// A bunch of auxiliary functions.

real fuzz = .001;

real umin(surface s) { return 0; }
real vmin(surface s) { return 0; }
pair uvmin(surface s) { return (umin(s), vmin(s)); }
real umax(surface s, real fuzz=fuzz) {
  if (s.ucyclic()) return s.index.length;
  else return s.index.length - fuzz;
}
real vmax(surface s, real fuzz=fuzz) {
  if (s.vcyclic()) return s.index[0].length;
  return s.index[0].length - fuzz;
}
pair uvmax(surface s, real fuzz=fuzz) { return (umax(s,fuzz), vmax(s,fuzz)); }

typedef real function(real, real);

function normalDot(surface s, triple eyedir) {
  real toreturn(real u, real v) {
    return dot(s.normal(u, v), eyedir);
  }
  return toreturn;
}

guide[] normalpathuv(surface s, triple eyedir, int n = ngraph) {
  return contour(normalDot(s, eyedir), uvmin(s), uvmax(s), new real[] {0}, nx=n)[0];
}

path3 onSurface(surface s, path p) {
  triple f(real t) {
    pair point = point(p,t);
    return s.point(point.x, point.y);
  }
  if (cyclic(p)) {
    guide3 toreturn = f(0);
    for (int i = 1; i < size(p); ++i)
      toreturn = toreturn -- f(i);
    toreturn = toreturn -- cycle;
    return toreturn;
  }
  return graph(f, 0, length(p));
}

/*
 * This method returns an array of paths that trace out all the
 * points on s at which s is parallel to eyedir.
 */
path3[] silhouetteNoEdges(surface s, triple eyedir, int n = ngraph) {
  guide[] uvpaths = normalpathuv(s, eyedir, n);
  path3[] toreturn = new path3[uvpaths.length];
  for (int i = 0; i < uvpaths.length; ++i) {
    toreturn[i] = onSurface(s, uvpaths[i]);
  }
  return toreturn;
}

/*
 * Now, add in the edges (if there are any).
 */
path3[] silhouette(surface s, triple eyedir, int n = ngraph) {
  path3[] toreturn = silhouetteNoEdges(s, eyedir, n);
  if (!s.ucyclic()) {
    toreturn.push(s.uequals(umin(s)));
    toreturn.push(s.uequals(umax(s)));
  }
  if (!s.vcyclic()) {
    toreturn.push(s.vequals(vmin(s)));
    toreturn.push(s.vequals(vmax(s)));
  }
  return toreturn;
}

将上述代码保存在名为的文件中后silhouette.asy,您可以按照以下方式绘制表面轮廓:

settings.outformat="pdf";
int resolutionfactor = 4;
settings.render=2.resolutionfactor;
settings.prc=false;

import silhouette;

size(200);
triple eye = (6,8,2);
currentprojection=orthographic(eye);
viewportmargin=(1cm,0);

real c0=0.1;

real f(real r) {return r*(1-r/6)*exp(-r/3);}

/* Note that the function below has been modified so as not to throw a divide by zero error
 * when f(r) == 0.
 */
triple f(pair t) {
  real r=t.x;
  real phi=t.y;
  real f=f(r);
  real s;
  //This assumes c0 > 0
  if (0 > f && f > -c0) s = -1;
  else if (0 <= f && f < c0) s = 1;
  else s = c0/f;
  //real s=max(min(c0/f,1),-1);
  real R=r*sqrt(1-s^2);
  return (R*cos(phi),R*sin(phi),r*s);
}

bool cond(pair t) {return f(t.x) != 0;}

real R=abs((20,20,20));
surface s=surface(f,(0,0),(R,2pi),nu=100,nv=8,Spline);

draw(silhouette(s,eye,n=200));
draw(s,surfacepen=emissive(white));

surface s2 = zscale3(-1)*s;
draw(silhouette(s2, eye, n=200));
draw(s2, surfacepen=emissive(white));

shipout(scale(resolutionfactor)*currentpicture.fit());

结果如下:

相关内容