summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/base/three.asy
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/base/three.asy')
-rw-r--r--Build/source/utils/asymptote/base/three.asy220
1 files changed, 162 insertions, 58 deletions
diff --git a/Build/source/utils/asymptote/base/three.asy b/Build/source/utils/asymptote/base/three.asy
index d79daf3586c..23a23223141 100644
--- a/Build/source/utils/asymptote/base/three.asy
+++ b/Build/source/utils/asymptote/base/three.asy
@@ -21,6 +21,15 @@ real rendermargin=0.02;
string defaultembed3Doptions;
string defaultembed3Dscript;
+real defaulteyetoview=63mm/1000mm;
+
+string defaultlabelname="label";
+string Billboard=" "+defaultlabelname;
+
+string defaultlabelname()
+{
+ return settings.billboard ? Billboard : defaultlabelname;
+}
string partname(string s, int i=0)
{
@@ -245,9 +254,9 @@ projection orthographic(triple camera, triple up=Z, triple target=O,
real zoom=1, pair viewportshift=0,
bool showtarget=true, bool center=false)
{
- return projection(camera,up,target,zoom,viewportshift,showtarget,center=center,
- new transformation(triple camera, triple up,
- triple target) {
+ return projection(camera,up,target,zoom,viewportshift,showtarget,
+ center=center,new transformation(triple camera, triple up,
+ triple target) {
return transformation(look(camera,up,target));});
}
@@ -313,11 +322,24 @@ projection LeftView=orthographic(-X,showtarget=true);
projection RightView=orthographic(X,showtarget=true);
projection FrontView=orthographic(-Y,showtarget=true);
projection BackView=orthographic(Y,showtarget=true);
-projection BottomView=orthographic(-Z,showtarget=true);
-projection TopView=orthographic(Z,showtarget=true);
+projection BottomView=orthographic(-Z,up=-Y,showtarget=true);
+projection TopView=orthographic(Z,up=Y,showtarget=true);
currentprojection=perspective(5,4,2);
+projection projection()
+{
+ projection P;
+ real[] a=_projection();
+ if(a[10] == 0.0) return currentprojection;
+ int k=0;
+ return a[0] == 1 ?
+ orthographic((a[++k],a[++k],a[++k]),(a[++k],a[++k],a[++k]),
+ (a[++k],a[++k],a[++k]),a[++k],(a[k += 2],a[++k])) :
+ perspective((a[++k],a[++k],a[++k]),(a[++k],a[++k],a[++k]),
+ (a[++k],a[++k],a[++k]),a[++k],a[++k],(a[++k],a[++k]));
+}
+
// Map pair z to a triple by inverting the projection P onto the
// plane perpendicular to normal and passing through point.
triple invert(pair z, triple normal, triple point,
@@ -1040,9 +1062,14 @@ path3 invert(path p, triple normal, triple point,
return path3(p,new triple(pair z) {return invert(z,normal,point,P);});
}
+path3 invert(path p, triple point, projection P=currentprojection)
+{
+ return path3(p,new triple(pair z) {return invert(z,P.vector(),point,P);});
+}
+
path3 invert(path p, projection P=currentprojection)
{
- return path3(p,new triple(pair z) {return invert(z,P);});
+ return path3(p,new triple(pair z) {return invert(z,P.vector(),P.target,P);});
}
// Construct a path from a path3 by applying P to each control point.
@@ -1763,11 +1790,11 @@ transform3 align(triple u)
// return a rotation that maps X,Y to the projection plane.
transform3 transform3(projection P=currentprojection)
{
- triple v=unit(P.oblique ? P.camera : P.vector());
- triple u=unit(perp(P.up,v));
- if(u == O) u=cross(perp(v),v);
- v=cross(u,v);
- return v != O ? transform3(v,u) : identity(4);
+ triple w=unit(P.oblique ? P.camera : P.vector());
+ triple v=unit(perp(P.up,w));
+ if(v == O) v=cross(perp(w),w);
+ triple u=cross(v,w);
+ return u != O ? transform3(u,v,w) : identity(4);
}
triple[] triples(real[] x, real[] y, real[] z)
@@ -2133,14 +2160,16 @@ draw=new void(frame f, path3 g, material p=currentpen,
void draw(frame f, explicit path3[] g, material p=currentpen,
light light=nolight, string name="", projection P=currentprojection)
{
- for(int i=0; i < g.length; ++i) draw(f,g[i],p,light,name,P);
+ for(int i=0; i < g.length; ++i)
+ draw(f,g[i],p,light,partname(name,i),P);
}
void draw(picture pic=currentpicture, explicit path3[] g,
material p=currentpen, margin3 margin=NoMargin3, light light=nolight,
string name="")
{
- for(int i=0; i < g.length; ++i) draw(pic,g[i],p,margin,light,name);
+ for(int i=0; i < g.length; ++i)
+ draw(pic,g[i],p,margin,light,partname(name,i));
}
include three_arrows;
@@ -2365,6 +2394,7 @@ void writeJavaScript(string name, string preamble, string script)
file out=output(name);
write(out,preamble);
if(script != "") {
+ write(out,endl);
file in=input(script);
while(true) {
string line=in;
@@ -2616,8 +2646,8 @@ object embed(string label="", string text=label, string prefix=defaultfilename,
triple lambda=M-m;
S.viewportmargin=viewportmargin((lambda.x,lambda.y));
- S.width=lambda.x+2*viewportmargin.x;
- S.height=lambda.y+2*viewportmargin.y;
+ S.width=lambda.x+2*S.viewportmargin.x;
+ S.height=lambda.y+2*S.viewportmargin.y;
S.f=shift((-0.5(m.x+M.x),-0.5*(m.y+M.y),0))*S.f; // Eye will be at (0,0,0)
} else {
if(P.angle == 0) {
@@ -2797,54 +2827,119 @@ frame embedder(string prefix, frame f, string format, bool view,
},prefix,format,view,light);
}
-void addViews(picture dest, picture src, bool group=true,
- filltype filltype=NoFill)
-{
- if(group) begingroup(dest);
- frame Front=src.fit(FrontView);
- add(dest,Front,filltype);
- frame Top=src.fit(TopView);
- add(dest,shift(0,min(Front).y-max(Top).y)*Top,filltype);
- frame Right=src.fit(RightView);
- add(dest,shift(min(Front).x-max(Right).x)*Right,filltype);
- if(group) endgroup(dest);
-}
+projection[][] ThreeViewsUS={{TopView},
+ {FrontView,RightView}};
-void addViews(picture src, bool group=true, filltype filltype=NoFill)
-{
- addViews(currentpicture,src,group,filltype);
-}
+projection[][] SixViewsUS={{null,TopView},
+ {LeftView,FrontView,RightView,BackView},
+ {null,BottomView}};
-void addAllViews(picture dest, picture src,
- real xmargin=0, real ymargin=xmargin,
- bool group=true,
- filltype filltype=NoFill)
-{
- picture picL,picM,picR,picLM;
- if(xmargin == 0) xmargin=sqrtEpsilon;
- if(ymargin == 0) ymargin=sqrtEpsilon;
+projection[][] ThreeViewsFR={{RightView,FrontView},
+ {null,TopView}};
- add(picL,src.fit(FrontView),(0,0),ymargin*N);
- add(picL,src.fit(BackView),(0,0),ymargin*S);
+projection[][] SixViewsFR={{null,BottomView},
+ {RightView,FrontView,LeftView,BackView},
+ {null,TopView}};
- add(picM,src.fit(TopView),(0,0),ymargin*N);
- add(picM,src.fit(BottomView),(0,0),ymargin*S);
+projection[][] ThreeViews={{FrontView,TopView,RightView}};
- add(picR,src.fit(RightView),(0,0),ymargin*N);
- add(picR,src.fit(LeftView),(0,0),ymargin*S);
+projection[][] SixViews={{FrontView,TopView,RightView},
+ {BackView,BottomView,LeftView}};
- add(picLM,picL.fit(),(0,0),xmargin*W);
- add(picLM,picM.fit(),(0,0),xmargin*E);
+void addViews(picture dest, picture src, projection[][] views=SixViewsUS,
+ bool group=true, filltype filltype=NoFill)
+{
+ frame[][] F=array(views.length,new frame[]);
+ pair[][] M=array(views.length,new pair[]);
+ pair[][] m=array(views.length,new pair[]);
+
+ for(int i=0; i < views.length; ++i) {
+ projection[] viewsi=views[i];
+ frame[] Fi=F[i];
+ pair[] Mi=M[i];
+ pair[] mi=m[i];
+ for(projection P : viewsi) {
+ if(P != null) {
+ frame f=src.fit(P);
+ mi.push(min(f));
+ Mi.push(max(f));
+ Fi.push(f);
+ } else {
+ pair Infinity=(infinity,infinity);
+ mi.push(Infinity);
+ Mi.push(-Infinity);
+ Fi.push(newframe);
+ }
+ }
+ }
+
+ real[] my=new real[views.length];
+ real[] My=new real[views.length];
+
+ int Nj=0;
+ for(int i=0; i < views.length; ++i) {
+ my[i]=minbound(m[i]).y;
+ My[i]=maxbound(M[i]).y;
+ Nj=max(Nj,views[i].length);
+ }
+
+ real[] mx=array(Nj,infinity);
+ real[] Mx=array(Nj,-infinity);
+ for(int i=0; i < views.length; ++i) {
+ pair[] mi=m[i];
+ pair[] Mi=M[i];
+ for(int j=0; j < views[i].length; ++j) {
+ mx[j]=min(mx[j],mi[j].x);
+ Mx[j]=max(Mx[j],Mi[j].x);
+ }
+ }
if(group) begingroup(dest);
- add(dest,picLM.fit(),(0,0),xmargin*W,filltype);
- add(dest,picR.fit(),(0,0),xmargin*E,filltype);
+
+ real y;
+ for(int i=0; i < views.length; ++i) {
+ real x;
+ pair[] mi=m[i];
+ for(int j=0; j < views[i].length; ++j) {
+ if(size(F[i][j]) != 0)
+ add(dest,shift(x-mx[j],y+my[i])*F[i][j],filltype);
+ x += (Mx[j]-mx[j]);
+ }
+ y -= (My[i]-my[i]);
+ }
+
if(group) endgroup(dest);
}
-void addAllViews(picture src, bool group=true, filltype filltype=NoFill)
+void addViews(picture src, projection[][] views=SixViewsUS, bool group=true,
+ filltype filltype=NoFill)
{
- addAllViews(currentpicture,src,group,filltype);
+ addViews(currentpicture,src,views,group,filltype);
+}
+
+void addStereoViews(picture dest, picture src, bool group=true,
+ filltype filltype=NoFill, real eyetoview=defaulteyetoview,
+ bool leftright=true, projection P=currentprojection)
+{
+ triple v=P.vector();
+ triple h=0.5*abs(v)*eyetoview*unit(cross(P.up,v));
+ projection leftEye=P.copy();
+ leftEye.camera -= h;
+ leftEye.calculate();
+ projection rightEye=P.copy();
+ rightEye.camera += h;
+ rightEye.calculate();
+ addViews(dest,src,leftright ?
+ new projection[][] {{leftEye,rightEye}} :
+ new projection[][] {{rightEye,leftEye}},group,filltype);
+}
+
+void addStereoViews(picture src, bool group=true,
+ filltype filltype=NoFill,
+ real eyetoview=defaulteyetoview, bool leftright=true,
+ projection P=currentprojection)
+{
+ addStereoViews(currentpicture,src,group,filltype,eyetoview,leftright,P);
}
// Fit an array of 3D pictures simultaneously using the sizing of picture all.
@@ -2859,24 +2954,33 @@ frame[] fit3(string prefix="", picture[] pictures, picture all,
triple M=all.max(S.t);
out=new frame[pictures.length];
int i=0;
- bool loop=settings.loop;
+ bool reverse=settings.reverse;
+ settings.animating=true;
+
for(picture pic : pictures) {
picture pic2;
frame f=pic.fit3(S.t,pic2,S.P);
- if(loop && !settings.loop) break;
+ if(settings.interrupt) break;
add(f,pic2.fit2());
draw(f,m,nullpen);
draw(f,M,nullpen);
- out[i]=loop ? f : embedder(prefix,f,format,view,options,script,light,S.P);
+ out[i]=f;
++i;
}
- while(settings.loop)
- for(int i=0; i < pictures.length; ++i) {
- if(!settings.loop) break;
+ while(!settings.interrupt) {
+ for(int i=settings.reverse ? pictures.length-1 : 0;
+ i >= 0 && i < pictures.length && !settings.interrupt;
+ settings.reverse ? --i : ++i) {
embedder(prefix,out[i],format,view,options,script,light,S.P);
- }
+ }
+ if(!settings.loop) break;
+ }
+ settings.animating=false;
+ settings.interrupt=false;
+ settings.reverse=reverse;
+
return out;
}