![渐近线如何使不透明圆环上的圆圈逐渐消失](https://linux22.com/image/428028/%E6%B8%90%E8%BF%91%E7%BA%BF%E5%A6%82%E4%BD%95%E4%BD%BF%E4%B8%8D%E9%80%8F%E6%98%8E%E5%9C%86%E7%8E%AF%E4%B8%8A%E7%9A%84%E5%9C%86%E5%9C%88%E9%80%90%E6%B8%90%E6%B6%88%E5%A4%B1.png)
我需要在圆环上画点。3D 点没有用,因为它们是球体。我成功计算了范数向量并在圆环上画了圆,稍后我会填充它们。
可以看到,圆环是不透明的,所有圆圈都正常绘制。有没有办法让通常不可见的圆圈变得不透明?
我想到的一个解决方案是,从小圆的中心到透视点画一条线,并计算与圆环的交点。如果点的距离最小,则正常绘制圆,否则,将其绘制为不透明。
还有更好的解决办法吗?
settings.outformat="pdf";
settings.prc=false;
settings.render=0;
import graph3;
size(4cm,0);
pen surfPen=white+opacity(0.2);
pen xarcPen=deepblue+0.7bp;
pen yarcPen=deepred+0.7bp;
currentprojection=perspective(5,5,6);
real R=3; //Radius of big circle
real a=1; //Radius of little circle
triple fs(pair t) {
return ((R+a*Cos(t.y))*Cos(t.x),(R+a*Cos(t.y))*Sin(t.x),a*Sin(t.y));
}
triple centerXYNormal(pair t) {
triple P = (((R)*Cos(t.x)),(R)*Sin(t.x),0);
triple T = fs(t);
return (T.x - P.x, T.y - P.y, T.z - P.z);
}
surface s=surface(fs,(0,0),(360,360),8,8,Spline);
draw(s,surfPen,render(compression=Low,merge=true));
int m=3;
int n=16;
pair p,q,v;
for(int i=1;i<=n;++i){
for(int j=0;j<m;++j){
p=(j*360/m,(i%n)*360/n);
path3 mycircle = circle(c=fs(p), r=0.1,normal=centerXYNormal(p));
draw(mycircle, blue);
}
}
答案1
我认为你有两种选择:
- 自己找出哪些圆圈是隐藏的,哪些圆圈在前景,然后按照你的建议绘制它们。
- 选择
settings.render
不同于0
。在这种情况下,asymptote
您将免于进行 1 下的计算,但它也将生成像素图形而不是矢量图形。
在这个例子中,我选择选项 2,并稍微增加不透明度以使效果更加明显。
settings.outformat="pdf";
settings.prc=false;
settings.render=10;
import graph3;
size(4cm,0);
pen surfPen=white+opacity(0.5);
pen xarcPen=deepblue+0.7bp;
pen yarcPen=deepred+0.7bp;
currentprojection=perspective(5,5,6);
real R=3; //Radius of big circle
real a=1; //Radius of little circle
triple fs(pair t) {
return ((R+a*Cos(t.y))*Cos(t.x),(R+a*Cos(t.y))*Sin(t.x),a*Sin(t.y));
}
triple centerXYNormal(pair t) {
triple P = (((R)*Cos(t.x)),(R)*Sin(t.x),0);
triple T = fs(t);
return (T.x - P.x, T.y - P.y, T.z - P.z);
}
surface s=surface(fs,(0,0),(360,360),8,8,Spline);
draw(s,surfPen,render(compression=Low,merge=true));
int m=3;
int n=16;
pair p,q,v;
for(int i=1;i<=n;++i){
for(int j=0;j<m;++j){
p=(j*360/m,(i%n)*360/n);
path3 mycircle = circle(c=fs(p), r=0.1,normal=centerXYNormal(p));
draw(mycircle, blue);
}
}
PS 这些圆圈实际上并不在圆环上,但它们足够小,所以这并不重要。
答案2
Pumuckl 的回答如果只想要像素图形,而我并不需要,那么这很好。我使用光线追踪来实现它。对于每个圆,都会形成从透视点和圆心穿过的线。计算线与圆环的交点。方程取自余弦猫(没有 HTTPS!)这很有帮助,谢谢。最多有 4 个未知数,所以我使用了quarticroots
了数学。这个函数减少了实现时间,也感谢作者。
然后找到最小距离,但是,我遇到了一个由于浮点计算而导致的错误。我通过测试解决了它
if ( distance3D(min,fs(p)) < 0.005)
结果如下,目前丑陋的完整代码如下GitHub。