在渐近线中绘制椭圆体;相机太近

在渐近线中绘制椭圆体;相机太近

我正在尝试绘制一组椭圆体,其中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));

它确实可以编译。

相关内容