summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/base
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-09-11 00:21:50 +0000
committerKarl Berry <karl@freefriends.org>2009-09-11 00:21:50 +0000
commitf06a2c99f2a8bbd8f641712c772179e8ed9ce14f (patch)
treefcf4f2b9d0492da04d9bf3761fbce51fb316024f /Build/source/utils/asymptote/base
parentd4c54e52fe8e42b8ce9b160c70d897bb1d06eee7 (diff)
asymptote 1.86
git-svn-id: svn://tug.org/texlive/trunk@15218 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/base')
-rw-r--r--Build/source/utils/asymptote/base/three.asy81
-rw-r--r--Build/source/utils/asymptote/base/three_surface.asy257
2 files changed, 272 insertions, 66 deletions
diff --git a/Build/source/utils/asymptote/base/three.asy b/Build/source/utils/asymptote/base/three.asy
index 1f9392ee094..d79daf3586c 100644
--- a/Build/source/utils/asymptote/base/three.asy
+++ b/Build/source/utils/asymptote/base/three.asy
@@ -22,6 +22,11 @@ real rendermargin=0.02;
string defaultembed3Doptions;
string defaultembed3Dscript;
+string partname(string s, int i=0)
+{
+ return s == "" ? s : s+"-"+string(i);
+}
+
triple O=(0,0,0);
triple X=(1,0,0), Y=(0,1,0), Z=(0,0,1);
@@ -1972,21 +1977,25 @@ triple size3(frame f)
include three_light;
void draw(frame f, path3 g, material p=currentpen, light light=nolight,
- projection P=currentprojection);
+ string name="", projection P=currentprojection);
-void begingroup3(picture pic=currentpicture)
+void begingroup3(picture pic=currentpicture, string name="")
{
- pic.add(new void(frame f, transform3, picture opic, projection) {
- if(opic != null)
- begingroup(opic);
+ pic.add(new void(frame f, transform3, picture pic, projection) {
+ if(is3D())
+ begingroup(f,name);
+ if(pic != null)
+ begingroup(pic);
},true);
}
void endgroup3(picture pic=currentpicture)
{
- pic.add(new void(frame f, transform3, picture opic, projection) {
- if(opic != null)
- endgroup(opic);
+ pic.add(new void(frame f, transform3, picture pic, projection) {
+ if(is3D())
+ endgroup(f);
+ if(pic != null)
+ endgroup(pic);
},true);
}
@@ -2033,17 +2042,15 @@ pair max(frame f, projection P)
void draw(picture pic=currentpicture, Label L="", path3 g,
align align=NoAlign, material p=currentpen, margin3 margin=NoMargin3,
- light light=nolight)
+ light light=nolight, string name="")
{
pen q=(pen) p;
pic.add(new void(frame f, transform3 t, picture pic, projection P) {
path3 G=margin(t*g,q).g;
if(is3D()) {
- draw(f,G,p,light,null);
- if(pic != null && size(G) > 0) {
- pic.addPoint(min(G,P));
- pic.addPoint(max(G,P));
- }
+ draw(f,G,p,light,name,null);
+ if(pic != null && size(G) > 0)
+ pic.addBox(min(G,P),max(G,P),min(q),max(q));
}
if(pic != null)
draw(pic,project(G,P),q);
@@ -2060,7 +2067,8 @@ void draw(picture pic=currentpicture, Label L="", path3 g,
include three_tube;
draw=new void(frame f, path3 g, material p=currentpen,
- light light=nolight, projection P=currentprojection) {
+ light light=nolight, string name="",
+ projection P=currentprojection) {
pen q=(pen) p;
if(is3D()) {
p=material(p,(p.granularity >= 0) ? p.granularity : linegranularity);
@@ -2091,12 +2099,12 @@ draw=new void(frame f, path3 g, material p=currentpen,
T.s.append(shift(point(g,L))*align(dirL)*cap);
}
if(opacity(q) == 1)
- _draw(f,T.center,q);
+ _draw(f,T.center,q,name);
}
for(int i=0; i < T.s.s.length; ++i)
- draw3D(f,T.s.s[i],p,light);
- } else _draw(f,g,q);
- } else _draw(f,g,q);
+ draw3D(f,T.s.s[i],p,light,partname(name,i));
+ } else _draw(f,g,q,name);
+ } else _draw(f,g,q,name);
}
string type=linetype(adjust(q,arclength(g),cyclic(g)));
if(length(type) == 0) drawthick(g);
@@ -2123,15 +2131,16 @@ draw=new void(frame f, path3 g, material p=currentpen,
};
void draw(frame f, explicit path3[] g, material p=currentpen,
- light light=nolight, projection P=currentprojection)
+ light light=nolight, string name="", projection P=currentprojection)
{
- for(int i=0; i < g.length; ++i) draw(f,g[i],p,light,P);
+ for(int i=0; i < g.length; ++i) draw(f,g[i],p,light,name,P);
}
void draw(picture pic=currentpicture, explicit path3[] g,
- material p=currentpen, margin3 margin=NoMargin3, light light=nolight)
+ 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);
+ for(int i=0; i < g.length; ++i) draw(pic,g[i],p,margin,light,name);
}
include three_arrows;
@@ -2139,23 +2148,23 @@ include three_arrows;
void draw(picture pic=currentpicture, Label L="", path3 g,
align align=NoAlign, material p=currentpen, arrowbar3 arrow,
arrowbar3 bar=None, margin3 margin=NoMargin3, light light=nolight,
- light arrowheadlight=currentlight)
+ light arrowheadlight=currentlight, string name="")
{
begingroup3(pic);
bool drawpath=arrow(pic,g,p,margin,light,arrowheadlight);
if(bar(pic,g,p,margin,light,arrowheadlight) && drawpath)
- draw(pic,L,g,align,p,margin,light);
+ draw(pic,L,g,align,p,margin,light,name);
endgroup3(pic);
label(pic,L,g,align,(pen) p);
}
void draw(frame f, path3 g, material p=currentpen, arrowbar3 arrow,
light light=nolight, light arrowheadlight=currentlight,
- projection P=currentprojection)
+ string name="", projection P=currentprojection)
{
picture pic;
if(arrow(pic,g,p,NoMargin3,light,arrowheadlight))
- draw(f,g,p,light,P);
+ draw(f,g,p,light,name,P);
add(f,pic.fit());
}
@@ -2297,7 +2306,7 @@ private string Format(real x)
// Work around movie15.sty division by zero bug;
// e.g. u=unit((1e-10,1e-10,0.9));
if(abs(x) < 1e-9) x=0;
- assert(abs(x) < 1e18,"Number too large: "+string(x));
+ assert(abs(x) < 1e17,"Number too large: "+string(x));
return format("%.18f",x,"C");
}
@@ -2449,6 +2458,7 @@ struct scene
projection P;
bool adjusted;
real width,height;
+ pair viewportmargin;
transform3 T=identity4;
picture pic2;
@@ -2510,7 +2520,7 @@ struct scene
pair m2=pic2.min(s);
pair M2=pic2.max(s);
pair lambda=M2-m2;
- pair viewportmargin=viewportmargin(lambda);
+ viewportmargin=viewportmargin(lambda);
width=ceil(lambda.x+2*viewportmargin.x);
height=ceil(lambda.y+2*viewportmargin.y);
@@ -2600,22 +2610,23 @@ object embed(string label="", string text=label, string prefix=defaultfilename,
Q=P.copy();
light=modelview*light;
- pair viewportmargin=viewportmargin;
if(P.infinity) {
triple m=min3(S.f);
triple M=max3(S.f);
+
triple lambda=M-m;
- viewportmargin=viewportmargin((lambda.x,lambda.y));
+ S.viewportmargin=viewportmargin((lambda.x,lambda.y));
S.width=lambda.x+2*viewportmargin.x;
S.height=lambda.y+2*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) {
- Q.angle=P.angle=S.angle(P);
+ P.angle=S.angle(P);
modelview=S.T*modelview;
- if(viewportmargin.y != 0)
- P.angle=2*aTan(Tan(0.5*P.angle)-viewportmargin.y/P.target.z);
+ if(S.viewportmargin.y != 0)
+ P.angle=2*aTan(Tan(0.5*P.angle)-S.viewportmargin.y/P.target.z);
}
+ Q.angle=P.angle;
if(settings.verbose > 0) {
transform3 inv=inverse(modelview);
if(S.adjusted)
@@ -2661,7 +2672,7 @@ object embed(string label="", string text=label, string prefix=defaultfilename,
m=(m.x,m.y,zcenter-r);
if(P.infinity) {
- triple margin=(viewportmargin.x,viewportmargin.y,0);
+ triple margin=(S.viewportmargin.x,S.viewportmargin.y,0);
M += margin;
m -= margin;
} else if(M.z >= 0) abort("camera too close");
diff --git a/Build/source/utils/asymptote/base/three_surface.asy b/Build/source/utils/asymptote/base/three_surface.asy
index e545d87cf7b..823e6e4b498 100644
--- a/Build/source/utils/asymptote/base/three_surface.asy
+++ b/Build/source/utils/asymptote/base/three_surface.asy
@@ -933,6 +933,61 @@ private triple[] split(triple z0, triple c0, triple c1, triple z1, real t=0.5)
return new triple[] {m0,m3,m5,m4,m2};
}
+// Return the control points of the subpatches
+// produced by a horizontal split of P
+triple[][][] hsplit(triple[][] P)
+{
+ // get control points in rows
+ triple[] P0=P[0];
+ triple[] P1=P[1];
+ triple[] P2=P[2];
+ triple[] P3=P[3];
+
+ triple[] c0=split(P0[0],P1[0],P2[0],P3[0]);
+ triple[] c1=split(P0[1],P1[1],P2[1],P3[1]);
+ triple[] c2=split(P0[2],P1[2],P2[2],P3[2]);
+ triple[] c3=split(P0[3],P1[3],P2[3],P3[3]);
+ // bottom, top
+ return new triple[][][] {
+ {{c0[2],c1[2],c2[2],c3[2]},
+ {c0[3],c1[3],c2[3],c3[3]},
+ {c0[4],c1[4],c2[4],c3[4]},
+ {P3[0],P3[1],P3[2],P3[3]}},
+ {{P0[0],P0[1],P0[2],P0[3]},
+ {c0[0],c1[0],c2[0],c3[0]},
+ {c0[1],c1[1],c2[1],c3[1]},
+ {c0[2],c1[2],c2[2],c3[2]}}
+ };
+}
+
+// Return the control points of the subpatches
+// produced by a vertical split of P
+triple[][][] vsplit(triple[][] P)
+{
+ // get control points in rows
+ triple[] P0=P[0];
+ triple[] P1=P[1];
+ triple[] P2=P[2];
+ triple[] P3=P[3];
+
+ triple[] c0=split(P0[0],P0[1],P0[2],P0[3]);
+ triple[] c1=split(P1[0],P1[1],P1[2],P1[3]);
+ triple[] c2=split(P2[0],P2[1],P2[2],P2[3]);
+ triple[] c3=split(P3[0],P3[1],P3[2],P3[3]);
+ // left, right
+ return new triple[][][] {
+ {{P0[0],c0[0],c0[1],c0[2]},
+ {P1[0],c1[0],c1[1],c1[2]},
+ {P2[0],c2[0],c2[1],c2[2]},
+ {P3[0],c3[0],c3[1],c3[2]}},
+
+ {{c0[2],c0[3],c0[4],P0[3]},
+ {c1[2],c1[3],c1[4],P1[3]},
+ {c2[2],c2[3],c2[4],P2[3]},
+ {c3[2],c3[3],c3[4],P3[3]}}
+ };
+}
+
// Return the control points for a subpatch of P on [u,1] x [v,1].
triple[][] subpatchbegin(triple[][] P, real u, real v)
{
@@ -1009,9 +1064,8 @@ real[][] intersections(path3 p, surface s, real fuzz=-1)
for(real[] s: intersections(p,s.s[i].P,fuzz))
T.push(s);
- static real fuzzFactor=10.0;
- static real Fuzz=1000.0*realEpsilon;
- real fuzz=max(fuzzFactor*fuzz,Fuzz)*abs(max(s)-min(s));
+ static real Fuzz=1000*realEpsilon;
+ real fuzz=max(10*fuzz,Fuzz*max(abs(min(s)),abs(max(s))));
// Remove intrapatch duplicate points.
for(int i=0; i < T.length; ++i) {
@@ -1039,12 +1093,45 @@ triple[] intersectionpoints(path3 p, surface s, real fuzz=-1)
return sequence(new triple(int i) {return point(p,t[i][0]);},t.length);
}
+// Return true iff the bounding boxes of patch p and q overlap.
+bool overlap(triple[][] p, triple[][] q, real fuzz=-1)
+{
+ triple p0=p[0][0];
+ triple q0=q[0][0];
+ triple pmin=minbezier(p,p0);
+ triple pmax=maxbezier(p,p0);
+ triple qmin=minbezier(q,q0);
+ triple qmax=maxbezier(q,q0);
+
+ static real Fuzz=1000*realEpsilon;
+ real fuzz=max(10*fuzz,Fuzz*max(abs(pmin),abs(pmax)));
+
+ return
+ pmax.x+fuzz >= qmin.x &&
+ pmax.y+fuzz >= qmin.y &&
+ pmax.z+fuzz >= qmin.z &&
+ qmax.x+fuzz >= pmin.x &&
+ qmax.y+fuzz >= pmin.y &&
+ qmax.z+fuzz >= pmin.z; // Overlapping bounding boxes?
+}
+
triple point(patch s, real u, real v)
{
return s.point(u,v);
}
-void draw3D(frame f, patch s, material m, light light=currentlight)
+real PRCshininess(real shininess)
+{
+ // Empirical translation table from Phong-Blinn to PRC shininess model:
+ static real[] x={0.015,0.025,0.05,0.07,0.1,0.14,0.23,0.5,0.65,0.75,0.85,
+ 0.875,0.9,1};
+ static real[] y={0.05,0.1,0.15,0.2,0.25,0.3,0.4,0.5,0.55,0.6,0.7,0.8,0.9,1};
+ static realfunction s=fspline(x,y,monotonic);
+ return s(shininess);
+}
+
+void draw3D(frame f, patch s, material m, light light=currentlight,
+ string name="")
{
if(s.colors.length > 0)
m=mean(s.colors);
@@ -1052,17 +1139,11 @@ void draw3D(frame f, patch s, material m, light light=currentlight)
if(!lighton && !invisible((pen) m))
m=emissive(m);
real PRCshininess;
- if(prc()) {
- // Empirical translation table from Phong-Blinn to PRC shininess model:
- static real[] x={0.015,0.025,0.05,0.07,0.1,0.14,0.23,0.5,0.65,0.75,0.85,
- 0.875,0.9,1};
- static real[] y={0.05,0.1,0.15,0.2,0.25,0.3,0.4,0.5,0.55,0.6,0.7,0.8,0.9,1};
- static realfunction s=fspline(x,y,monotonic);
- PRCshininess=s(m.shininess);
- }
+ if(prc())
+ PRCshininess=PRCshininess(m.shininess);
real granularity=m.granularity >= 0 ? m.granularity : defaultgranularity;
draw(f,s.P,s.straight,m.p,m.opacity,m.shininess,PRCshininess,granularity,
- s.planar ? s.normal(0.5,0.5) : O,lighton,s.colors);
+ s.planar ? s.normal(0.5,0.5) : O,s.colors,lighton,name);
}
void tensorshade(transform t=identity(), frame f, patch s,
@@ -1078,12 +1159,12 @@ nullpens.cyclic=true;
void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1,
material[] surfacepen, pen[] meshpen=nullpens,
- light light=currentlight, light meshlight=light,
+ light light=currentlight, light meshlight=light, string name="",
projection P=currentprojection)
{
if(is3D()) {
for(int i=0; i < s.s.length; ++i)
- draw3D(f,s.s[i],surfacepen[i],light);
+ draw3D(f,s.s[i],surfacepen[i],light,partname(name,i));
pen modifiers=thin()+squarecap;
for(int k=0; k < s.s.length; ++k) {
pen meshpen=meshpen[k];
@@ -1130,26 +1211,26 @@ void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1,
void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1,
material surfacepen=currentpen, pen meshpen=nullpen,
- light light=currentlight, light meshlight=light,
+ light light=currentlight, light meshlight=light, string name="",
projection P=currentprojection)
{
material[] surfacepen={surfacepen};
pen[] meshpen={meshpen};
surfacepen.cyclic=true;
meshpen.cyclic=true;
- draw(t,f,s,nu,nv,surfacepen,meshpen,light,meshlight,P);
+ draw(t,f,s,nu,nv,surfacepen,meshpen,light,meshlight,name,P);
}
void draw(picture pic=currentpicture, surface s, int nu=1, int nv=1,
material[] surfacepen, pen[] meshpen=nullpens,
- light light=currentlight, light meshlight=light)
+ light light=currentlight, light meshlight=light, string name="")
{
if(s.empty()) return;
pic.add(new void(frame f, transform3 t, picture pic, projection P) {
surface S=t*s;
if(is3D()) {
- draw(f,S,nu,nv,surfacepen,meshpen,light,meshlight);
+ draw(f,S,nu,nv,surfacepen,meshpen,light,meshlight,name);
} else if(pic != null)
pic.add(new void(frame f, transform T) {
draw(T,f,S,nu,nv,surfacepen,meshpen,light,meshlight,P);
@@ -1180,22 +1261,22 @@ void draw(picture pic=currentpicture, surface s, int nu=1, int nv=1,
void draw(picture pic=currentpicture, surface s, int nu=1, int nv=1,
material surfacepen=currentpen, pen meshpen=nullpen,
- light light=currentlight, light meshlight=light)
+ light light=currentlight, light meshlight=light, string name="")
{
material[] surfacepen={surfacepen};
pen[] meshpen={meshpen};
surfacepen.cyclic=true;
meshpen.cyclic=true;
- draw(pic,s,nu,nv,surfacepen,meshpen,light,meshlight);
+ draw(pic,s,nu,nv,surfacepen,meshpen,light,meshlight,name);
}
void draw(picture pic=currentpicture, surface s, int nu=1, int nv=1,
material[] surfacepen, pen meshpen,
- light light=currentlight, light meshlight=light)
+ light light=currentlight, light meshlight=light, string name="")
{
pen[] meshpen={meshpen};
meshpen.cyclic=true;
- draw(pic,s,nu,nv,surfacepen,meshpen,light,meshlight);
+ draw(pic,s,nu,nv,surfacepen,meshpen,light,meshlight,name);
}
surface extrude(path3 p, path3 q)
@@ -1211,9 +1292,9 @@ surface extrude(path3 p, triple axis=Z)
return extrude(p,shift(axis)*p);
}
-surface extrude(path p, triple axis=Z)
+surface extrude(path p, triple plane(pair)=XYplane, triple axis=Z)
{
- return extrude(path3(p),axis);
+ return extrude(path3(p,plane),axis);
}
surface extrude(explicit path[] p, triple axis=Z)
@@ -1381,13 +1462,17 @@ surface extrude(Label L, triple axis=Z)
restricted surface nullsurface;
-surface labelsurface(Label L, surface s, real uoffset, real voffset,
- real height=0, bool bottom=false, bool top=true)
+// Embed a Label onto a surface.
+surface surface(Label L, surface s, real uoffset, real voffset,
+ real height=0, bool bottom=false, bool top=true)
{
int nu=s.index.length;
- if(nu == 0) return nullsurface;
- int nv=s.index[0].length;
- if(nv == 0) return nullsurface;
+ int nv;
+ if(nu == 0) nu=nv=1;
+ else {
+ nv=s.index[0].length;
+ if(nv == 0) nv=1;
+ }
path[] g=texpath(L);
pair m=min(g);
@@ -1402,7 +1487,7 @@ surface labelsurface(Label L, surface s, real uoffset, real voffset,
real v=voffset+(z.y-m.y)/lambda.y;
if(((u < 0 || u >= nu) && !s.ucyclic()) ||
((v < 0 || v >= nv) && !s.vcyclic()))
- abort("cannot fit string to surface");
+ warning("cannotfit","cannot fit string to surface");
return s.point(u,v)+height*unit(s.normal(u,v));
});
}
@@ -1556,3 +1641,113 @@ void dot(picture pic=currentpicture, Label L, triple v, align align=NoAlign,
dot(pic,v,p);
label(pic,L,v);
}
+
+pair minbound(triple[][] A, projection P)
+{
+ pair b=project(A[0][0],P);
+ for(triple[] a : A) {
+ for(triple v : a) {
+ b=minbound(b,project(v,P));
+ }
+ }
+ return b;
+}
+
+pair maxbound(triple[][] A, projection P)
+{
+ pair b=project(A[0][0],P);
+ for(triple[] a : A) {
+ for(triple v : a) {
+ b=maxbound(b,project(v,P));
+ }
+ }
+ return b;
+}
+
+triple[][] operator / (triple[][] a, real[][] b)
+{
+ triple[][] A=new triple[a.length][];
+ for(int i=0; i < a.length; ++i) {
+ triple[] ai=a[i];
+ real[] bi=b[i];
+ A[i]=sequence(new triple(int j) {return ai[j]/bi[j];},ai.length);
+ }
+ return A;
+}
+
+// Draw a NURBS surface.
+void draw(picture pic=currentpicture, triple[][] P, real[] uknot, real[] vknot,
+ real[][] weights=new real[][], material m=currentpen,
+ pen[] colors=new pen[], light light=currentlight, string name="")
+{
+ if(colors.length > 0)
+ m=mean(colors);
+ bool lighton=light.on();
+ pic.add(new void(frame f, transform3 t, picture pic, projection Q) {
+ if(is3D()) {
+ triple[][] P=t*P;
+ real granularity=m.granularity >= 0 ? m.granularity :
+ defaultgranularity;
+ real PRCshininess;
+ if(prc())
+ PRCshininess=PRCshininess(m.shininess);
+ draw(f,P,uknot,vknot,weights,m.p,m.opacity,m.shininess,PRCshininess,
+ granularity,colors,lighton,name);
+ if(pic != null) {
+ triple[][] R=weights.length > 0 ? P/weights : P;
+ pic.addBox(minbound(R,Q),maxbound(R,Q));
+ }
+ }
+ },true);
+ triple[][] R=weights.length > 0 ? P/weights : P;
+ pic.addBox(minbound(R),maxbound(R));
+}
+
+// A structure to subdivide two intersecting patches about their intersection.
+struct split
+{
+ // Container for subpatches of p.
+ triple[][][] T;
+
+ struct tree {
+ tree[] tree=new tree[2];
+ }
+ // Default subdivision depth.
+ int n=23;
+
+ // Subdivide p and q to depth n if they overlap.
+ void write(tree t, triple[][] p, triple[][] q, int depth=n) {
+ --depth;
+ triple[][][] split(triple[][] P)=depth % 2 == 0 ? hsplit : vsplit;
+ triple[][][] P=split(p);
+ triple[][][] Q=split(q);
+
+ for(int i=0; i < 2; ++i) {
+ for(int j=0; j < 2; ++j) {
+ if(overlap(P[i],Q[j])) {
+ if(!t.tree.initialized(i)) t.tree[i]=new tree;
+ if(depth > 0) write(t.tree[i],P[i],Q[j],depth);
+ }
+ }
+ }
+ }
+
+ // Output the subpatches of p from subdivision.
+ void read(tree t, triple[][] p, int depth=n) {
+ --depth;
+ triple[][][] split(triple[][] P)=depth % 2 == 0 ? hsplit : vsplit;
+ triple[][][] P=split(p);
+
+ for(int i=0; i < 2; ++i) {
+ if(t.tree.initialized(i))
+ read(t.tree[i],P[i],depth);
+ else T.push(P[i]);
+ }
+ }
+
+ void operator init(triple[][] p, triple[][] q, int depth=n) {
+ tree trunk;
+ write(trunk,p,q,depth);
+ read(trunk,p,depth);
+ }
+}