我正在尝试绘制一组椭圆体,其中Asymptote
由对称正定矩阵给出,或者换句话说,由三个v1,v2,v3
长度为 1 的向量形成 ONB(椭圆体主轴)及其长度l1,l2,l3
\documentclass[12pt]{scrartcl}
\usepackage{asypictureB}
\begin{document}
\begin{asypicture}{name=AsyTest}
import three;
import settings;
surface ellipsoid(triple v1,triple v2,triple v3,real l1,real l2, real l3, triple pos=O) {
transform3 T = identity4;
T[0][0] = l1*v1.x;
T[1][0] = l1*v1.y;
T[2][0] = l1*v1.z;
T[0][1] = l2*v2.x;
T[1][1] = l2*v2.y;
T[2][1] = l2*v2.z;
T[0][2] = l3*v3.x;
T[1][2] = l3*v3.y;
T[2][2] = l3*v3.z;
T[0][3] = pos.x;
T[1][3] = pos.y;
T[2][3] = pos.z;
return T*unitsphere;
}
size(9cm);
currentprojection=perspective(4.5,4,-11,Z, (4.5,4,0));
draw(ellipsoid( (1,0,0), (0,1,0), (0,0,1), 0.2, 0.3, 0.4, O), rgb(0,1,0));
\end{asypicture}
\end{document}
该函数应该能够缩放和移动单位球,从而创建由上述值和中心点给出的椭圆体pos
,其中倒数第三行是绿色椭圆体的 MWE。
应该perspective
从下方观察所有椭圆体的中间(是的, 9x8
这里的场)。
Camera too close
然而,即使我将它移得很远(-11
比如说替换-100
),上述代码仍然看起来像是一个错误。
这是什么原因?有什么想法吗?
在创建 MWE 时我注意到一件事:l3
从 中删除transform3 T
,即保持v3
在单位长度使此文件编译。尽管如此,我需要缩放所有 3 个轴(一般来说,当然不是像这个 MWE 中的单位轴)。
答案1
最终解决方案
问题在于,通过设置T = identity4
,您实际上是在T
为 创建一个别名identity4
,以便对 的更改T
会反映在 中identity4
。令人惊讶的是,这并没有造成更多问题。
可以通过初始化T
为复制的identity4
:
transform3 T = copy(identity4);
完整代码:
\documentclass[12pt]{scrartcl}
\usepackage{asypictureB}
\begin{document}
\begin{asypicture}{name=AsyTest}
import three;
import settings;
surface ellipsoid(triple v1,triple v2,triple v3,real l1,real l2, real l3, triple pos=O) {
transform3 T = copy(identity4);
T[0][0] = l1*v1.x;
T[1][0] = l1*v1.y;
T[2][0] = l1*v1.z;
T[0][1] = l2*v2.x;
T[1][1] = l2*v2.y;
T[2][1] = l2*v2.z;
T[0][2] = l3*v3.x;
T[1][2] = l3*v3.y;
T[2][2] = l3*v3.z;
T[0][3] = pos.x;
T[1][3] = pos.y;
T[2][3] = pos.z;
return T*unitsphere;
}
size(9cm);
currentprojection=perspective(4.5,4,-11,Z, (4.5,4,0));
draw(ellipsoid( (1,0,0), (0,1,0), (0,0,1), 0.2, 0.3, 0.4, O), rgb(0,1,0));
\end{asypicture}
\end{document}
下列编辑仅因历史原因而保留。
更新 2
下面是该问题的一个真正最小(非)工作示例(作为一个 asy 文件,以表明该问题是 Asymptote 固有的,与 TeX 嵌入无关):
import three;
transform3 T = identity4;
T[2][2] = 0.4;
draw(unitsphere);
结果出现错误:
/usr/local/texlive/2014/texmf-dist/asymptote/three.asy: 2903.30: camera too close
我有提交错误报告。
更新
经过进一步的研究,我发现了一些非常奇怪的事情。不知何故,T
无论计算是否用于任何事情,仅仅像你这样进行计算就会导致错误。
错误显示定义
surface ellipsoid(triple v1,triple v2,triple v3,real l1,real l2, real l3, triple pos=O) {
transform3 T = identity4;
T[0][0] = l1*v1.x;
T[1][0] = l1*v1.y;
T[2][0] = l1*v1.z;
T[0][1] = l2*v2.x;
T[1][1] = l2*v2.y;
T[2][1] = l2*v2.z;
T[0][2] = l3*v3.x;
T[1][2] = l3*v3.y;
T[2][2] = l3*v3.z;
T[0][3] = pos.x;
T[1][3] = pos.y;
T[2][3] = pos.z;
/*transform3*/ T = scale(l1, l2, l3);
return T*unitsphere;
}
但不是定义
surface ellipsoid(triple v1,triple v2,triple v3,real l1,real l2, real l3, triple pos=O) {
/*transform3 T = identity4;
T[0][0] = l1*v1.x;
T[1][0] = l1*v1.y;
T[2][0] = l1*v1.z;
T[0][1] = l2*v2.x;
T[1][1] = l2*v2.y;
T[2][1] = l2*v2.z;
T[0][2] = l3*v3.x;
T[1][2] = l3*v3.y;
T[2][2] = l3*v3.z;
T[0][3] = pos.x;
T[1][3] = pos.y;
T[2][3] = pos.z;
*/
transform3 T = scale(l1, l2, l3);
return T*unitsphere;
}
这两个应该给出完全相同的结果;唯一的区别是第一个进行计算T
(然后覆盖它),而第二个不进行计算。
底线:我不知道这个错误来自哪里。
问题似乎是你错误地构建了transform3
矩阵,结果球体被吹大到天文数字。因此 Asymptote 抛出的错误是合理的。
我没有想过这个矩阵是如何构建的,但是我有两个证据,结合起来,强烈地证明了我的结论。
首先:对于您的特定测试用例,主轴只是标准基础,因此 - 如果我正确理解您在做什么 - 如果您ellipsoid
通过以下方式定义函数,此示例应该会给出相同的结果
surface ellipsoid(triple v1,triple v2,triple v3,real l1,real l2, real l3, triple pos=O) {
transform3 T = scale(l1, l2, l3);
return T*unitsphere;
}
但是,使用此定义,文件编译没有任何问题。因此,定义 的逻辑几乎肯定存在错误transform3
。
第二:虽然最初看起来将视点移得更远并没有什么不同,但这并不完全正确——只是非常小的变化l3
会导致椭球体尺寸的巨大差异。但我能够通过设置找到一个边界情况l3=0.591
:
currentprojection=perspective((4.5,4,-11), up=Z, (4.5,4,0));
draw(ellipsoid( (1,0,0), (0,1,0), (0,0,1), 0.2, 0.3, 0.591, O), rgb(0,1,0));
无法编译,但如果将相机距离乘以十倍
currentprojection=perspective(10*(4.5,4,-11), up=Z, (4.5,4,0));
draw(ellipsoid( (1,0,0), (0,1,0), (0,0,1), 0.2, 0.3, 0.591, O), rgb(0,1,0));
它确实可以编译。