diff options
Diffstat (limited to 'Build/source/utils/asymptote/base/three_surface.asy')
-rw-r--r-- | Build/source/utils/asymptote/base/three_surface.asy | 241 |
1 files changed, 124 insertions, 117 deletions
diff --git a/Build/source/utils/asymptote/base/three_surface.asy b/Build/source/utils/asymptote/base/three_surface.asy index 88e42cf6640..7d356e45e22 100644 --- a/Build/source/utils/asymptote/base/three_surface.asy +++ b/Build/source/utils/asymptote/base/three_surface.asy @@ -17,7 +17,7 @@ struct patch { bool3 planar; // Patch is planar. path3 external() { - return + return straight ? P[0][0]--P[3][0]--P[3][3]--P[0][3]--cycle : P[0][0]..controls P[1][0] and P[2][0].. P[3][0]..controls P[3][1] and P[3][2].. P[3][3]..controls P[2][3] and P[1][3].. @@ -93,9 +93,16 @@ struct patch { static real fuzz=1000*realEpsilon; + triple partialu(real u, real v) { + return bezier(BuP(0,u),BuP(1,u),BuP(2,u),BuP(3,u),v); + } + + triple partialv(real u, real v) { + return bezier(BvP(0,v),BvP(1,v),BvP(2,v),BvP(3,v),u); + } + triple normal(real u, real v) { - triple n=cross(bezier(BuP(0,u),BuP(1,u),BuP(2,u),BuP(3,u),v), - bezier(BvP(0,v),BvP(1,v),BvP(2,v),BvP(3,v),u)); + triple n=cross(partialu(u,v),partialv(u,v)); real epsilon=fuzz*change2(P); return (abs(n) > epsilon) ? n : normal0(u,v,epsilon); } @@ -940,59 +947,105 @@ private triple[] split(triple z0, triple c0, triple c1, triple z1, real t=0.5) // 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]}} - }; + // 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]); + // bottom, top + 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 of the subpatches // produced by a vertical split of P triple[][][] vsplit(triple[][] P) { - // get control points in rows + // 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]); + // left, right + return new triple[][][] { + {{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]}}, + {{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]}} + }; +} + +// Return a 2D array of the control point arrays of the subpatches +// produced by horizontal and vertical splits of P at u and v +triple[][][][] split(triple[][] P, real u=1/2, real v=1/2) +{ 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]}} - }; + + // slice horizontally + triple[] c0=split(P0[0],P0[1],P0[2],P0[3],v); + triple[] c1=split(P1[0],P1[1],P1[2],P1[3],v); + triple[] c2=split(P2[0],P2[1],P2[2],P2[3],v); + triple[] c3=split(P3[0],P3[1],P3[2],P3[3],v); + + // bottom patch + triple[] c4=split(P0[0],P1[0],P2[0],P3[0],u); + triple[] c5=split(c0[0],c1[0],c2[0],c3[0],u); + triple[] c6=split(c0[1],c1[1],c2[1],c3[1],u); + triple[] c7=split(c0[2],c1[2],c2[2],c3[2],u); + + // top patch + triple[] c8=split(c0[3],c1[3],c2[3],c3[3],u); + triple[] c9=split(c0[4],c1[4],c2[4],c3[4],u); + triple[] cA=split(P0[3],P1[3],P2[3],P3[3],u); + +// {{bottom-left, top-left}, {bottom-right, top-right}} + return new triple[][][][] { + {{{P0[0],c0[0],c0[1],c0[2]}, + {c4[0],c5[0],c6[0],c7[0]}, + {c4[1],c5[1],c6[1],c7[1]}, + {c4[2],c5[2],c6[2],c7[2]}}, + {{c0[2],c0[3],c0[4],P0[3]}, + {c7[0],c8[0],c9[0],cA[0]}, + {c7[1],c8[1],c9[1],cA[1]}, + {c7[2],c8[2],c9[2],cA[2]}}}, + {{{c4[2],c5[2],c6[2],c7[2]}, + {c4[3],c5[3],c6[3],c7[3]}, + {c4[4],c5[4],c6[4],c7[4]}, + {P3[0],c3[0],c3[1],c3[2]}}, + {{c7[2],c8[2],c9[2],cA[2]}, + {c7[3],c8[3],c9[3],cA[3]}, + {c7[4],c8[4],c9[4],cA[4]}, + {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) +triple[][] subpatchend(triple[][] P, real u, real v) { triple[] P0=P[0]; triple[] P1=P[1]; @@ -1004,21 +1057,20 @@ triple[][] subpatchbegin(triple[][] P, real u, real v) triple[] c2=split(P2[0],P2[1],P2[2],P2[3],v); triple[] c3=split(P3[0],P3[1],P3[2],P3[3],v); - u=1.0-u; - - triple[] c7=split(c3[2],c2[2],c1[2],c0[2],u); - triple[] c8=split(c3[3],c2[3],c1[3],c0[3],u); - triple[] c9=split(c3[4],c2[4],c1[4],c0[4],u); - triple[] c10=split(P3[3],P2[3],P1[3],P0[3],u); - - return new triple[][] {{c7[2],c8[2],c9[2],c10[2]}, - {c7[1],c8[1],c9[1],c10[1]}, - {c7[0],c8[0],c9[0],c10[0]}, + triple[] c7=split(c0[2],c1[2],c2[2],c3[2],u); + triple[] c8=split(c0[3],c1[3],c2[3],c3[3],u); + triple[] c9=split(c0[4],c1[4],c2[4],c3[4],u); + triple[] cA=split(P0[3],P1[3],P2[3],P3[3],u); + + return new triple[][] { + {c7[2],c8[2],c9[2],cA[2]}, + {c7[3],c8[3],c9[3],cA[3]}, + {c7[4],c8[4],c9[4],cA[4]}, {c3[2],c3[3],c3[4],P3[3]}}; } // Return the control points for a subpatch of P on [0,u] x [0,v]. -triple[][] subpatchend(triple[][] P, real u, real v) +triple[][] subpatchbegin(triple[][] P, real u, real v) { triple[] P0=P[0]; triple[] P1=P[1]; @@ -1030,28 +1082,31 @@ triple[][] subpatchend(triple[][] P, real u, real v) triple[] c2=split(P2[0],P2[1],P2[2],P2[3],v); triple[] c3=split(P3[0],P3[1],P3[2],P3[3],v); - u=1.0-u; - - triple[] c4=split(P3[0],P2[0],P1[0],P0[0],u); - triple[] c5=split(c3[0],c2[0],c1[0],c0[0],u); - triple[] c6=split(c3[1],c2[1],c1[1],c0[1],u); - triple[] c7=split(c3[2],c2[2],c1[2],c0[2],u); + triple[] c4=split(P0[0],P1[0],P2[0],P3[0],u); + triple[] c5=split(c0[0],c1[0],c2[0],c3[0],u); + triple[] c6=split(c0[1],c1[1],c2[1],c3[1],u); + triple[] c7=split(c0[2],c1[2],c2[2],c3[2],u); return new triple[][] { {P0[0],c0[0],c0[1],c0[2]}, - {c4[4],c5[4],c6[4],c7[4]}, - {c4[3],c5[3],c6[3],c7[3]}, + {c4[0],c5[0],c6[0],c7[0]}, + {c4[1],c5[1],c6[1],c7[1]}, {c4[2],c5[2],c6[2],c7[2]}}; } +triple[][] subpatch(triple[][] P, pair a, pair b) +{ + return subpatchend(subpatchbegin(P,b.x,b.y),a.x/b.x,a.y/b.y); +} + patch subpatch(patch s, pair a, pair b) { assert(a.x >= 0 && a.y >= 0 && b.x <= 1 && b.y <= 1 && a.x < b.x && a.y < b.y); - return patch(subpatchbegin(subpatchend(s.P,b.x,b.y),a.x/b.x,a.y/b.y), - s.straight,s.planar); + return patch(subpatch(s.P,a,b),s.straight,s.planar); } + // return an array containing all intersection times of path p and patch s. real[][] intersections(path3 p, patch s, real fuzz=-1) { @@ -1216,7 +1271,8 @@ void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1, light light=currentlight, light meshlight=light, string name="", render render=defaultrender, projection P=currentprojection) { - if(is3D()) { + bool is3D=is3D(); + if(is3D) { begingroup3(f,name == "" ? "surface" : name,render); for(int i=0; i < s.s.length; ++i) draw3D(f,s.s[i],surfacepen[i],light); @@ -1238,7 +1294,8 @@ void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1, endgroup3(f); } } - } else { + } + if(!is3D || settings.render == 0) { begingroup(f); // Sort patches by mean distance from camera triple camera=P.camera; @@ -1299,11 +1356,10 @@ void draw(picture pic=currentpicture, surface s, int nu=1, int nv=1, surface S=t*s; if(is3D()) draw(f,S,nu,nv,surfacepen,meshpen,light,meshlight,name,render); - else if(pic != null) + if(pic != null) { pic.add(new void(frame f, transform T) { draw(T,f,S,nu,nv,surfacepen,meshpen,light,meshlight,P); },true); - if(pic != null) { pic.addPoint(min(S,P)); pic.addPoint(max(S,P)); } @@ -1941,52 +1997,3 @@ void draw(picture pic=currentpicture, triple[][] P, real[] uknot, real[] vknot, },true); pic.addBox(minbound(P),maxbound(P)); } - -// 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); - } -} |