Final solution
The problem is that by setting T = identity4
, you are really making T
an alias for identity4
, so that changes to T
are reflected in identity4
. It's surprising this does not screw up more things than it does.
A correct version may be obtained by initializing T
to be a copy of identity4
:
transform3 T = copy(identity4);
The full code:
\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}
The following edits are maintained for historical reasons only.
Update 2
Here is a truly minimal (non-)working example of the problem (as an asy file, to show that the issue is intrinsic to Asymptote and not related to the TeX embedding):
import three;
transform3 T = identity4;
T[2][2] = 0.4;
draw(unitsphere);
The result is an error:
/usr/local/texlive/2014/texmf-dist/asymptote/three.asy: 2903.30: camera too close
I have filed a bug report.
Update
After further research, I've found something truly bizarre. Somehow, the mere fact of computing T
as you do is causing the error, regardless of whether the computation is used for anything.
The error shows up for the definition
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;
}
but not for the definition
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;
}
These two should give exactly the same result; the only difference is that the first one does the computation of T
(and then overwrites it), while the second does not do the computation.
Bottom line: I'm clueless as to where this error is coming from.
The problem appears to be that you are incorrectly constructing the transform3
matrix, with the result that the sphere is being blown up to something astronomically huge. So the error thrown by Asymptote is legitimate.
I have not gone through the reasoning about how the matrix is constructed, but I have two pieces of evidence that, taken together, strongly suggest the my conclusion.
First: For your particular test case, the major axes are simply the standard basis, so--if I understand correctly what you are doing--this example ought to give the same result if you define ellipsoid
function by
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;
}
However, with this definition, the file compiles with no problems. So there is almost certainly an error in your logic defining the transform3
.
Second: Although it initially appears that moving the viewpoint farther away makes no difference, this is not quite correct--it's just that very small changes in l3
can make astronomical differences in the size of the ellipsoid. But I was able to find a boundary case by setting 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));
does not compile, but if you multiply the camera distance by tenfold
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));
it does compile.
l3=0.595
, but not forl3=0.59
.l3=0.55
without error, but still get the samecamera too close
error withl3=0.5
.