diff options
author | Karl Berry <karl@freefriends.org> | 2009-09-11 00:21:50 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2009-09-11 00:21:50 +0000 |
commit | f06a2c99f2a8bbd8f641712c772179e8ed9ce14f (patch) | |
tree | fcf4f2b9d0492da04d9bf3761fbce51fb316024f /Build/source/utils/asymptote/base | |
parent | d4c54e52fe8e42b8ce9b160c70d897bb1d06eee7 (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.asy | 81 | ||||
-rw-r--r-- | Build/source/utils/asymptote/base/three_surface.asy | 257 |
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); + } +} |