我使用 3d 中的 Asymptote 编写了我的第一个图形,这是一个骰子,其面按 1 到 6 个点编号,以经典方式代表 1 到 6 的数字。这个骰子可以用鼠标操作。
问题是,当你操纵骰子时,代表点的圆盘会闪闪发光。
当我注释掉 draw 语句(第 25 行)时draw(scale3(84a)*unitcube, surfacepen=white);
,圆盘根本不闪烁,但骰子突然变得透明。我得出结论,问题出在圆盘的蓝色覆盖了面的白色。因此,解决方案是分两步为面着色,就像 Tikz 中所做的那样:
- 空白处无圆盘的面
- 蓝色单碟
但是clip
,,,fill
命令不适用于 3d功能unfill
。filldraw
surface()
怎样才能给骰子表面涂上颜色而不使其闪烁?
Asymptote 文件.asy
如下,(代码未优化以便于阅读):
import three;
currentprojection =orthographic((5,2,3));
currentlight=nolight;
settings.tex="latex"; // Moteur LaTeX utilisé pour la compilation (latex, pdflatex, ...)
settings.outformat="pdf"; // Format de sortie ; eps par défaut
settings.prc=true; // Format PRC de la figure ; vrai par défaut
settings.render=-1; // Rendu des figures ; -1 par défaut
size(6cm,0);
real a = 0.05;
path carre = box ((0,0),(84a,84a)),
disque = scale(9a)*unitcircle,
patron1[] = shift(42a,42a)*disque,
patron2[] = shift(14a,70a)*disque^^shift(70a,14a)*disque,
patron3[] = shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(42a,42a)*disque,
patron4[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque,
patron5[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,42a)*disque,
patron6[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,70a)*disque^^shift(42a,14a)*disque;
transform3 tX=shift(84a*X), tY=shift(84a*Y), tZ=shift(84a*Z);
path3 facegauche[] =path3(patron6,ZXplane),
facedroite[] =path3(patron1,ZXplane),
faceavant[] =path3(patron2,YZplane),
facearriere[] =path3(patron5,YZplane),
facehaut[] =path3(patron4,XYplane),
facebas[] =path3(patron3,XYplane);
draw(scale3(84a)*unitcube, surfacepen=white);
draw(box(O, 84a*(X+Y+Z)), gray);
draw(surface(facegauche),blue);
draw(surface(tY*facedroite),blue);
draw(surface(tZ*facehaut),blue);
draw(surface(facebas),blue);
draw(surface(facearriere),blue);
draw(surface(tX*faceavant),blue);
答案1
在法语论坛上找到法语答案后,请找到一个近似的英语答案。事实上,圆盘位于立方体的表面上/内,但无法知道圆盘相对于立方体表面的相对位置。根据数值近似,圆盘位于立方体表面的上方/下方,数值伪影会产生闪烁。
解决方案 1):将每个圆盘移到正确的方向,这是这里提出的
import three;
currentprojection =orthographic((5,2,3));
currentlight=nolight;
settings.tex="latex"; // Moteur LaTeX utilisé pour la compilation (latex, pdflatex, ...)
settings.outformat="pdf"; // Format de sortie ; eps par défaut
settings.prc=true; // Format PRC de la figure ; vrai par défaut
settings.render=-1; // Rendu des figures ; -1 par défaut
size(6cm,0);
real a = 0.05;
path carre = box ((0,0),(84a,84a)),
disque = scale(9a)*unitcircle,
patron1[] = shift(42a,42a)*disque,
patron2[] = shift(14a,70a)*disque^^shift(70a,14a)*disque,
patron3[] = shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(42a,42a)*disque,
patron4[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque,
patron5[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,42a)*disque,
patron6[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,70a)*disque^^shift(42a,14a)*disque;
transform3 tX=shift((84a+00.1)*X), tY=shift((84a+.001)*Y), tZ=shift((84a+0.01)*Z);
path3 facegauche[] =shift(0,-0.001,0)*path3(patron6,ZXplane),
facedroite[] =path3(patron1,ZXplane),
faceavant[] =path3(patron2,YZplane),
facearriere[] =shift(-0.001,0,0)*path3(patron5,YZplane),
facehaut[] =path3(patron4,XYplane),
facebas[] =shift(0,0,-0.001)*path3(patron3,XYplane);
draw(scale3(84a)*unitcube, surfacepen=white);
draw(box(O, 84a*(X+Y+Z)), gray);
draw(surface(facegauche),blue);
draw(surface(tY*facedroite),blue);
draw(surface(tZ*facehaut),blue);
draw(surface(facebas),blue);
draw(surface(facearriere),blue);
draw(surface(tX*faceavant),blue);
解决方案 2):创建骰子面的真实表面。更新:请找到第二个解决方案。确实bezulate
可以将 2D 路径转换为 3D。根据文档,
平面贝塞尔曲面片是使用 Orest Shardt 的 bezulate 例程构建的,该例程将由简单循环路径(仅在端点相交)包围的(根据零蜿蜒填充规则)区域(可能是非单连通的)分解为由长度为 4 或更短的循环路径包围的子区域。
要创建孔,必须使用reverse
(沿路径向后运行):例如bezulate(unitsquate^^reverse(scale(.3)*unitcircle))
。然后surface(bezulate(unitsquate^^reverse(scale(.3)*unitcircle)))
创建一个带有小孔的单位正方形的表面。完整骰子的代码。
import three;
currentprojection =orthographic((5,2,3));
currentlight=nolight;
settings.tex="latex"; // Moteur LaTeX utilisé pour la compilation (latex, pdflatex, ...)
//settings.outformat="pdf"; // Format de sortie ; eps par défaut
settings.prc=true; // Format PRC de la figure ; vrai par défaut
settings.render=-1; // Rendu des figures ; -1 par défaut
size(6cm,0);
real a = 0.05;
path carre = box ((0,0),(84a,84a)),
// reverse est capital pour créer les trous avec bezulate
// c'est la règle : unitsquare et disque ne seront pas dans le
// même sens, donc bezulate comprend que c'est un trou
disque = scale(9a)*reverse(unitcircle),
patron1[] = shift(42a,42a)*disque,
patron2[] = shift(14a,70a)*disque^^shift(70a,14a)*disque,
patron3[] = shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(42a,42a)*disque,
patron4[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque,
patron5[] = shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,42a)*disque,
patron6[]= shift(14a,14a)*disque^^shift(14a,70a)*disque^^shift(70a,14a)*disque^^shift(70a,70a)*disque^^shift(42a,70a)*disque^^shift(42a,14a)*disque;
transform3 tX=shift((84a)*X), tY=shift((84a)*Y), tZ=shift((84a)*Z);
path3 facegauche[] =path3(patron6,ZXplane),
facedroite[] =path3(patron1,ZXplane),
faceavant[] =path3(patron2,YZplane),
facearriere[] =path3(patron5,YZplane),
facehaut[] =path3(patron4,XYplane),
facebas[] =path3(patron3,XYplane);
// draw(scale3(84a)*unitcube, surfacepen=white);
draw(box(O, 84a*(X+Y+Z)), gray);
draw(surface(facegauche),blue);
draw(surface(tY*facedroite),blue);
draw(surface(tZ*facehaut),blue);
draw(surface(facebas),blue);
draw(surface(facearriere),blue);
draw(surface(tX*faceavant),blue);
// les faces trouées
path[] gp6=bezulate(scale(84a)*unitsquare^^patron6);
path[] gp5=bezulate(scale(84a)*unitsquare^^patron5);
path[] gp4=bezulate(scale(84a)*unitsquare^^patron4);
path[] gp3=bezulate(scale(84a)*unitsquare^^patron3);
path[] gp2=bezulate(scale(84a)*unitsquare^^patron2);
path[] gp1=bezulate(scale(84a)*unitsquare^^patron1);
surface s1=shift((0,84a,84a))*rotate(90,Y)*rotate(90,X)*surface(gp1);
surface s2=shift(84a,0,0)*rotate(-90,Y)*surface(gp2);
surface s3=surface(gp3);
surface s4=shift((0,0,84a))*surface(gp4);
surface s5=shift((0,0,84a))*rotate(90,Y)*surface(gp5);
surface s6=shift((0,0,84a))*rotate(90,Y)*rotate(90,X)*surface(gp6);
draw(s6,red);
draw(s5,red);
draw(s4,red);
draw(s3,red);
draw(s2,red);
draw(s1,red);
结果
奥格