自动用渐近线虚线绘制路径的隐藏部分

自动用渐近线虚线绘制路径的隐藏部分

在一个很好的答案我的另一个问题关于渐近线,@Paolo Brasolin 设法用虚线绘制了路径的隐藏部分。

在此处输入图片描述

但据我所知,它不是自动化的,也不适用于各种视角。

我不知道渐近线如何渲染场景,但有什么方法可以告诉渲染器“背景”中的路径部分(IE位于不透明表面后面的物体应该用虚线渲染吗(也许在渲染场景时再次绘制)?

答案1

首先,渲染引擎中没有“分层”机制;参见此功能请求。因此,如果您想模拟一个(例如,使不透明物体后面的路径可见),您有两个选择:

  1. 通过设置 放弃隐藏对象移除。除非您使用类似模块,settings.render = 0;否则这对您的事业没有帮助surfacepaths这个答案或者这个答案实际计算对象前后路径的部分。(此模块不完整,可能适用于您的实际用例,也可能不适用。它还将隐藏的路径绘制为褪色,我发现这通常看起来比虚线更好。也许以后我会看看是否可以在这个答案中添加一些内容,显示允许使用虚线路径的修改版本。)
  2. 通过将一些物体移近(或远离)相机来模拟分层。这通常是首选解决方案,但对于透视投影来说,它比正交投影更难实现。

Paolo 的解决方案是 2 的一个巧妙变体,基于这样的观察:在实线曲线上绘制的虚线看起来与实线曲线完全一样。数学估算是不必要的;对于正交投影,正是将对象向相机shift(n * unit(currentprojection.camera))移动单位所需的变换。做得太大不太可能成为问题,因此您可以使用类似的方法(或从开始并将其加倍,直到图片看起来正确)。nnn=1000n=1

处理透视投影不可避免地是一个问题——尤其是因为靠近相机的线条实际上会显得更粗。这是我目前能做的最好的事情:

import graph3;
size(6cm,0);
settings.render = 4;
currentprojection=perspective(5*(4, 1, 1), showtarget=true, autoadjust=false, center=true);

// UTILITY FUNCTIONS
triple cameradirection(triple pt, projection P=currentprojection) {
  if (P.infinity) {
    return unit(P.camera);
  } else {
    return unit(P.camera - pt);
  }
}
triple towardcamera(triple pt, real distance=1, projection P=currentprojection) {
  return pt + distance * cameradirection(pt, P);
}
path3 towardcamera(path3 g, real distance=1, projection P=currentprojection) {
  triple f(real t) {
    return towardcamera(point(g,t), distance, P);
  }
  return graph(f, 0, length(g), operator..);
}
pen shortdashed = linetype(new real[] {4, 4});

// 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));
}

// GRAPHICAL ELEMENTS
surface s = surface(S, (0, 0), (2pi, pi/2), 64, 64, Spline);
path3 ds = graph(dS, 0, 2pi);

draw(s, surfacepen=material(diffusepen=gray(0.6),
                            emissivepen=gray(0.3),
                            specularpen=gray(0.1)));
                            
// Draw boundary.
draw(ds);

// Draw dashed version of boundary out in front. As long as it's exactly the
// same color and width as the solid path, the dashing pattern will only show up
// when the solid path isn't behind it.
//draw(shift(4*unit(currentprojection.camera))*ds, dashed);
draw(towardcamera(ds, 4), linetype(new real[] {4, 4}));

结果: 在此处输入图片描述

它在几个方面并不理想。首先,图片边缘有多余的空白。(这可以通过删除参数来解决autoadjust=false,但这也会弄乱虚线路径。)其次,虚线离相机更近,比实线更粗。这可以通过将相机移远来缓解——但如果你要这样做,你基本上只是试图让透视投影表现得像正交投影;为什么不一开始就使用正交投影呢?

相关内容