summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/base/three_surface.asy
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/base/three_surface.asy')
-rw-r--r--Build/source/utils/asymptote/base/three_surface.asy241
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);
- }
-}