summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/base
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-06-08 00:57:31 +0000
committerKarl Berry <karl@freefriends.org>2009-06-08 00:57:31 +0000
commit9e32dd6aee7faf4e59888cfbd7a927d497b563ad (patch)
tree5068ec13390f4352be663383dd58e22147e68201 /Build/source/utils/asymptote/base
parent3f49bad6cd5234b4e0ea156f6f68f6430643c10f (diff)
asymptote 1.76
git-svn-id: svn://tug.org/texlive/trunk@13664 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/base')
-rw-r--r--Build/source/utils/asymptote/base/bezulate.asy37
-rw-r--r--Build/source/utils/asymptote/base/fontsize.asy2
-rw-r--r--Build/source/utils/asymptote/base/labelpath3.asy27
-rw-r--r--Build/source/utils/asymptote/base/plain_Label.asy20
-rw-r--r--Build/source/utils/asymptote/base/plain_paths.asy10
-rw-r--r--Build/source/utils/asymptote/base/plain_pens.asy6
-rw-r--r--Build/source/utils/asymptote/base/plain_strings.asy19
-rw-r--r--Build/source/utils/asymptote/base/three.asy106
-rw-r--r--Build/source/utils/asymptote/base/three_light.asy47
-rw-r--r--Build/source/utils/asymptote/base/three_surface.asy16
10 files changed, 190 insertions, 100 deletions
diff --git a/Build/source/utils/asymptote/base/bezulate.asy b/Build/source/utils/asymptote/base/bezulate.asy
index 01b3024f7b6..2b852623faf 100644
--- a/Build/source/utils/asymptote/base/bezulate.asy
+++ b/Build/source/utils/asymptote/base/bezulate.asy
@@ -1,13 +1,19 @@
// Bezier triangulation routines written by Orest Shardt, 2008.
-private real fuzz=1e-6;
+private real fuzz=sqrtEpsilon;
real duplicateFuzz=1e-3; // Work around font errors.
+private real[][] intersections(pair a, pair b, path p)
+{
+ pair delta=fuzz*unit(b-a);
+ return intersections(a-delta--b+delta,p,fuzz);
+}
+
int countIntersections(path[] p, pair start, pair end)
{
int intersects=0;
for(path q : p)
- intersects += intersections(q,start--end,fuzz).length;
+ intersects += intersections(start,end,q).length;
return intersects;
}
@@ -101,27 +107,23 @@ void connect(path[] paths, path[] result, path[] patch)
pair start=point(inners[curveIndex],0);
// find first intersection of line segment with outer curve
- path line = start--start+d*direction;
- real[][] ints=intersections(line,outer,fuzz);
+ real[][] ints=intersections(start,start+d*direction,outer);
assert(ints.length != 0);
real endtime=ints[0][1]; // endtime is time on outer
pair end = point(outer,endtime);
- line = start--end;
- path rline = reverse(line);
- // find first intersection of rline segment with any inner curve
+ // find first intersection of end--start with any inner curve
real starttime=0; // starttime is time on inners[curveIndex]
real earliestTime=1;
for(int j=0; j < inners.length; ++j) {
- real[][] ints=intersections(rline,inners[j],fuzz);
+ real[][] ints=intersections(end,start,inners[j]);
if(ints.length > 0 && ints[0][0] < earliestTime) {
- earliestTime=ints[0][0]; // time on rline
+ earliestTime=ints[0][0]; // time on end--start
starttime=ints[0][1]; // time on inner curve
curveIndex=j;
}
}
start=point(inners[curveIndex],starttime);
- line = start--end;
real timeoffset=2;
bool found=false;
@@ -146,7 +148,7 @@ void connect(path[] paths, path[] result, path[] patch)
}
}
- if(!found)timeoffset=-2;
+ if(!found) timeoffset=-2;
while(!found && timeoffset < -fuzz) {
timeoffset /= 2;
if(countIntersections(allCurves,start,
@@ -179,20 +181,11 @@ void connect(path[] paths, path[] result, path[] patch)
}
}
-int countIntersections(path g, pair p, pair q)
-{
- int ints=0;
- int l=length(g);
- for(int i=1; i <= l; ++i)
- ints += intersections(subpath(g,i-1,i),p--q,fuzz).length;
- return ints;
-}
-
bool checkSegment(path g, pair p, pair q)
{
pair mid=0.5*(p+q);
- return countIntersections(g,p,q) == 4 && inside(g,mid,zerowinding) &&
- intersections(g,mid).length == 0;
+ return intersections(p,q,g).length == 2 &&
+ inside(g,mid,zerowinding) && intersections(g,mid).length == 0;
}
path subdivide(path p)
diff --git a/Build/source/utils/asymptote/base/fontsize.asy b/Build/source/utils/asymptote/base/fontsize.asy
index 0c0c6a0dcca..4575f3480fa 100644
--- a/Build/source/utils/asymptote/base/fontsize.asy
+++ b/Build/source/utils/asymptote/base/fontsize.asy
@@ -1 +1 @@
-usepackage("fix-cm");
+if(latex()) usepackage("fix-cm");
diff --git a/Build/source/utils/asymptote/base/labelpath3.asy b/Build/source/utils/asymptote/base/labelpath3.asy
index acfa64d528f..b8a946a07ae 100644
--- a/Build/source/utils/asymptote/base/labelpath3.asy
+++ b/Build/source/utils/asymptote/base/labelpath3.asy
@@ -2,11 +2,7 @@
// Author: Jens Schwaiger
import three;
-size(7.5cm,0);
-real eps=100*realEpsilon;
-currentprojection=perspective(20,18,8);
-currentlight=light(8,10,2);
-//texpreamble("\textwidth=50cm"); // Avoid line breaking in long texts
+private real eps=100*realEpsilon;
triple nextnormal(triple p, triple q)
{
@@ -34,13 +30,14 @@ triple[] nextframe(path3 p, real reltimestart, triple[] start, real
real lg=reltimeend-reltimestart;
if(lg <= 0) return start;
bf[0]=start;
- for(int i=1; i < subdiv+1; i=i+1) {
+ int n=subdiv+1;
+ for(int i=1; i < n; ++i)
bf[i][0]=dir(p,reltime(p,reltimestart+(i/subdiv)*lg));
- };
- for(int i=1; i < subdiv+1; i=i+1) {
+
+ for(int i=1; i < n; ++i) {
bf[i][1]=nextnormal(bf[i-1][1],bf[i][0]);
bf[i][2]=cross(bf[i][0],bf[i][1]);
- };
+ }
return bf[subdiv];
}
@@ -48,8 +45,7 @@ surface labelpath(string txt, path3 p, real angle=90, triple optional=O)
{
real Cos=Cos(angle);
real Sin=Sin(angle);
- path[] text=shift(-labelmargin(currentpen)*NE)*
- texpath(Label(txt,(0,0),NE,basealign));
+ path[] text=texpath(Label(txt,(0,0),Align,basealign));
text=scale(1/(max(text).x-min(text).x))*text;
path[][] decompose=containmentTree(text);
@@ -59,7 +55,7 @@ surface labelpath(string txt, path3 p, real angle=90, triple optional=O)
xpos[i][1]=i;
real pos0=0.5(max(decompose[i]).x+min(decompose[i]).x);
xpos[i][0]=pos0;
- };
+ }
xpos=sort(xpos); // sort by distance from 0;
triple[] pos=new triple[decompose.length];
real lg=arclength(p);
@@ -70,17 +66,18 @@ surface labelpath(string txt, path3 p, real angle=90, triple optional=O)
triple[][] bfr=new triple[decompose.length][3];
for(int j=0; j < decompose.length; ++j) {
bfr[j]=nextframe(p,tm0,t0,xpos[j][0]);
- tm0=xpos[j][0]; t0=bfr[j];};
+ tm0=xpos[j][0]; t0=bfr[j];
+ }
transform3[] mt=new transform3[bfr.length];
for(int j=0; j < bfr.length; ++j) {
triple f2=Cos*bfr[j][1]+Sin*bfr[j][2];
triple f3=Sin*bfr[j][1]+Cos*bfr[j][2];
mt[j]=shift(relpoint(p,xpos[j][0]))*transform3(bfr[j][0],f2,f3);
- };
+ }
for(int j=0; j < bfr.length; ++j) {
path[] dc=decompose[(int) xpos[j][1]];
pair pos0=(0.5(max(dc).x+min(dc).x),0);
sf.append(mt[j]*surface(scale(lg)*shift(-pos0)*dc));
- };
+ }
return sf;
}
diff --git a/Build/source/utils/asymptote/base/plain_Label.asy b/Build/source/utils/asymptote/base/plain_Label.asy
index 1279880ca3a..3c11a2cedbd 100644
--- a/Build/source/utils/asymptote/base/plain_Label.asy
+++ b/Build/source/utils/asymptote/base/plain_Label.asy
@@ -571,7 +571,12 @@ path[] texpath(Label L, bool tex=settings.tex != "none")
path[] g;
string s=L.s;
- pen p=L.p;
+ pen p=fontcommand(font(L.p))+fontsize(fontsize(L.p));
+
+ // PDF tex engines lose track of the baseline.
+ bool adjust=tex && basealign(L.p) == 1 && pdf();
+ if(adjust) p=p+basealign;
+
int k=0;
int i;
while((i=find(stringcache == s,++k)) >= 0) {
@@ -582,7 +587,16 @@ path[] texpath(Label L, bool tex=settings.tex != "none")
}
if(i == -1) {
- g=tex ? _texpath(s,p) : textpath(s,p);
+ if(tex) {
+ if(adjust) {
+ g=_texpath("."+s,p);
+ if(g.length == 0) return g;
+ real y=min(g[0]).y;
+ g.delete(0);
+ g=shift(0,-y)*g;
+ } else g=_texpath(s,p);
+ } else g=textpath(s,p);
+
stringcache.push(s);
pencache.push(p);
pathcache.push(g);
@@ -593,7 +607,7 @@ path[] texpath(Label L, bool tex=settings.tex != "none")
pair m=min(g);
pair M=max(g);
pair dir=rectify(inverse(L.T)*-L.align.dir);
- if(basealign(p) == 1)
+ if(tex && basealign(L.p) == 1)
dir -= (0,(1-dir.y)*m.y/(M.y-m.y));
a=m+realmult(dir,M-m);
diff --git a/Build/source/utils/asymptote/base/plain_paths.asy b/Build/source/utils/asymptote/base/plain_paths.asy
index 486f3f0cc7b..d457fa5bc28 100644
--- a/Build/source/utils/asymptote/base/plain_paths.asy
+++ b/Build/source/utils/asymptote/base/plain_paths.asy
@@ -329,19 +329,21 @@ pair inside(path p, pen fillrule=currentpen)
int n=length(p);
for(int i=0; i < n; ++i) {
pair z=point(p,i);
- real[] T=intersections(p,z,z+I*dir(p,i));
+ pair dir=dir(p,i);
+ if(dir == 0) continue;
+ real[] T=intersections(p,z,z+I*dir);
// Check midpoints of line segments formed between the
// corresponding intersection points and z.
for(int j=0; j < T.length; ++j) {
if(T[j] != i) {
pair w=point(p,T[j]);
pair m=0.5*(z+w);
- if(inside(windingnumber(p,m),fillrule)) return m;
+ if(interior(windingnumber(p,m),fillrule)) return m;
}
}
}
- abort("cannot find an interior point");
- return 0;
+ // cannot find an interior point: path is degenerate
+ return point(p,0);
}
// Return all intersection times of path g with the vertical line through (x,0).
diff --git a/Build/source/utils/asymptote/base/plain_pens.asy b/Build/source/utils/asymptote/base/plain_pens.asy
index 003c79149c7..09993d44da8 100644
--- a/Build/source/utils/asymptote/base/plain_pens.asy
+++ b/Build/source/utils/asymptote/base/plain_pens.asy
@@ -25,7 +25,9 @@ restricted pen beveljoin=linejoin(2);
restricted pen zerowinding=fillrule(0);
restricted pen evenodd=fillrule(1);
-bool inside(int windingnumber, pen fillrule) {
+
+bool interior(int windingnumber, pen fillrule)
+{
return windingnumber != undefined &&
(fillrule(fillrule) == 1 ? windingnumber % 2 == 1 : windingnumber != 0);
}
@@ -351,5 +353,3 @@ pen[] mean(pen[][] palette, real opacity(real[])=min)
return sequence(new pen(int i) {return mean(palette[i],opacity);},
palette.length);
}
-
-
diff --git a/Build/source/utils/asymptote/base/plain_strings.asy b/Build/source/utils/asymptote/base/plain_strings.asy
index 801e63e83cf..e3d0a797d86 100644
--- a/Build/source/utils/asymptote/base/plain_strings.asy
+++ b/Build/source/utils/asymptote/base/plain_strings.asy
@@ -190,3 +190,22 @@ string phantom(string s)
{
return "\phantom{"+s+"}";
}
+
+restricted int ocgindex=0;
+
+void begin(picture pic=currentpicture, string name, string id="",
+ bool visible=true)
+{
+ if(!latex() || !pdf()) return;
+ settings.twice=true;
+ if(id == "") id=string(++ocgindex);
+ tex(pic,"\begin{ocg}{"+name+"}{"+id+"}{"+(visible ? "1" : "0")+"}");
+ layer(pic);
+}
+
+void end(picture pic=currentpicture)
+{
+ if(!latex() || !pdf()) return;
+ tex(pic,"\end{ocg}");
+ layer(pic);
+}
diff --git a/Build/source/utils/asymptote/base/three.asy b/Build/source/utils/asymptote/base/three.asy
index 8e0fab6e8d0..0af0d2c3bdf 100644
--- a/Build/source/utils/asymptote/base/three.asy
+++ b/Build/source/utils/asymptote/base/three.asy
@@ -3,10 +3,12 @@ private import math;
if(inXasyMode) settings.render=0;
if(prc0()) {
- access embed;
- Embed=embed.embed;
- Link=embed.link;
if(settings.tex == "context") settings.prc=false;
+ else {
+ access embed;
+ Embed=embed.embed;
+ Link=embed.link;
+ }
}
real defaultshininess=0.25;
@@ -14,12 +16,12 @@ real defaultgranularity=0;
real linegranularity=0.01;
real tubegranularity=0.003;
real dotgranularity=0.0001;
-pair viewportmargin=0; // Horizontal and vertical viewport margins.
-real viewportfactor=1.005; // Factor used to expand orthographic viewport.
-
-real angleprecision=1e-3; // Precision for centering perspective projections.
+pair viewportmargin=0; // Horizontal and vertical viewport margins.
+real viewportfactor=1.002; // Factor used to expand orthographic viewport.
+real viewportpadding=1.2; // Offset used to expand PRC viewport.
+real angleprecision=1e-3; // Precision for centering perspective projections.
real anglefactor=max(1.005,1+angleprecision);
- // Factor used to expand perspective viewport.
+// Factor used to expand perspective viewport.
string defaultembed3Doptions;
string defaultembed3Dscript;
@@ -1690,7 +1692,8 @@ transform3 transform3(projection P)
triple v=unit(P.oblique ? P.camera : P.vector());
triple u=unit(perp(P.up,v));
if(u == O) u=cross(perp(v),v);
- return transform3(cross(u,v),u);
+ v=cross(u,v);
+ return v != O ? transform3(v,u) : identity(4);
}
triple[] triples(real[] x, real[] y, real[] z)
@@ -2203,7 +2206,7 @@ function asyProjection() {"+
(infinity ? "activeCamera.projectionType=activeCamera.TYPE_ORTHOGRAPHIC;" :
"activeCamera.projectionType=activeCamera.TYPE_PERSPECTIVE;")+"
activeCamera.viewPlaneSize="+string(viewplanesize)+";
-activeCamera.binding=activeCamera.BINDING_VERTICAL;
+activeCamera.binding=activeCamera.BINDING_"+(infinity ? "MAX" : "VERTICAL")+";
}
asyProjection();
@@ -2252,7 +2255,7 @@ void writeJavaScript(string name, string preamble, string script)
file3.push(name);
}
-pair viewportmargin(projection P, real width, real height)
+pair viewportmargin(real width, real height)
{
pair viewportmargin=viewportmargin;
real xmargin=viewportmargin.x;
@@ -2281,10 +2284,11 @@ string embed3D(string label="", string text=label, string prefix,
real viewplanesize;
if(P.infinity) {
triple lambda=max3(f)-min3(f);
- real margin=(viewportfactor-1.0)*lambda.y+
- viewportmargin(P,lambda.x,lambda.y).y;
- viewplanesize=(lambda.y+2*margin)/cm;
- }
+ pair margin=viewportpadding*(1,1)+viewportmargin(lambda.x,lambda.y);
+ viewplanesize=(max(lambda.x+2*margin.x,lambda.y+2*margin.y))/cm;
+ } else
+ if(!P.absolute) angle=2*aTan(Tan(0.5*angle)-viewportpadding/P.target.z);
+
string name=prefix+".js";
writeJavaScript(name,lightscript+projection(P.infinity,viewplanesize),script);
@@ -2308,7 +2312,7 @@ string embed3D(string label="", string text=label, string prefix,
if(defaultembed3Doptions != "") options3 += ","+defaultembed3Doptions;
if((settings.render < 0 || !settings.embed) && settings.auto3D)
options3 += ",poster";
- options3 += ",text="+text+",label="+label+
+ options3 += ",text={"+text+"},label="+label+
",toolbar="+(settings.toolbar ? "true" : "false")+
",3Daac="+format(P.absolute ? P.angle : angle)+
",3Dc2c="+format(u)+
@@ -2402,7 +2406,7 @@ object embed(string label="", string text=label,
pair m2=pic2.min(s);
pair M2=pic2.max(s);
pair lambda=M2-m2;
- pair viewportmargin=viewportmargin(P,lambda.x,lambda.y);
+ pair viewportmargin=viewportmargin(lambda.x,lambda.y);
real width=ceil(lambda.x+2*viewportmargin.x);
real height=ceil(lambda.y+2*viewportmargin.y);
@@ -2435,6 +2439,11 @@ object embed(string label="", string text=label,
if(P.infinity) {
triple m=min3(f);
triple M=max3(f);
+ triple lambda=M-m;
+ viewportmargin=viewportmargin(lambda.x,lambda.y);
+ width=lambda.x+2*viewportmargin.x;
+ height=lambda.y+2*viewportmargin.y;
+
triple s=(-0.5(m.x+M.x),-0.5*(m.y+M.y),0);
f=shift(s)*f; // Eye will be at (0,0,0).
} else {
@@ -2513,13 +2522,14 @@ object embed(string label="", string text=label,
if(P.absolute) {
modelview=P.modelview();
f=modelview*f;
- P=modelview*P;
+ Q=modelview*P;
m=min3(f);
M=max3(f);
real r=0.5*abs(M-m);
zcenter=0.5*(M.z+m.z);
M=(M.x,M.y,zcenter+r);
m=(m.x,m.y,zcenter-r);
+ angle=P.angle;
} else {
m=min3(f);
M=max3(f);
@@ -2530,9 +2540,9 @@ object embed(string label="", string text=label,
}
if(P.infinity) {
- triple margin=(viewportfactor-1.0)*(abs(M.x-m.x),
- abs(M.y-m.y),0)+
- viewportfactor*(0,viewportmargin.y,0);
+ triple margin=(viewportfactor-1.0)*(abs(M.x-m.x),abs(M.y-m.y),0)
+ +(viewportmargin.x,viewportmargin.y,0);
+
M += margin;
m -= margin;
} else if(M.z >= 0) abort("camera too close");
@@ -2552,11 +2562,10 @@ object embed(string label="", string text=label,
if(settings.inlinetex) image += "_0";
image += "."+nativeformat();
if(!settings.inlinetex) file3.push(image);
- image=graphic(image);
+ image=graphic(image,"hiresbb");
}
if(prc) F.L=embed3D(label,text=image,prefix,f,format,
- width,height,angle,options,script,light,
- P.absolute ? P : Q);
+ width,height,angle,options,script,light,Q);
}
if(!is3D) {
@@ -2600,27 +2609,60 @@ currentpicture.fitter=new frame(string prefix, picture pic, string format,
if(currentlight.background != nullpen)
box(f,currentlight.background,Fill,above=false);
} else if(!view)
- label(f,graphic(prefix));
+ label(f,graphic(prefix,"hiresbb"));
}
}
return f;
};
void addViews(picture dest, picture src, bool group=true,
- filltype filltype=NoFill, bool above=true)
+ filltype filltype=NoFill)
{
+ if(group) begingroup(dest);
frame Front=src.fit(FrontView);
- add(dest,Front,group,filltype,above);
+ add(dest,Front,filltype);
frame Top=src.fit(TopView);
- add(dest,shift(0,min(Front).y-max(Top).y)*Top,group,filltype,above);
+ 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,group,filltype,above);
+ add(dest,shift(min(Front).x-max(Right).x)*Right,filltype);
+ if(group) endgroup(dest);
+}
+
+void addViews(picture src, bool group=true, filltype filltype=NoFill)
+{
+ addViews(currentpicture,src,group,filltype);
+}
+
+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;
+
+ add(picL,src.fit(FrontView),(0,0),ymargin*N);
+ add(picL,src.fit(BackView),(0,0),ymargin*S);
+
+ add(picM,src.fit(TopView),(0,0),ymargin*N);
+ add(picM,src.fit(BottomView),(0,0),ymargin*S);
+
+ add(picR,src.fit(RightView),(0,0),ymargin*N);
+ add(picR,src.fit(LeftView),(0,0),ymargin*S);
+
+ add(picLM,picL.fit(),(0,0),xmargin*W);
+ add(picLM,picM.fit(),(0,0),xmargin*E);
+
+ if(group) begingroup(dest);
+ add(dest,picLM.fit(),(0,0),xmargin*W,filltype);
+ add(dest,picR.fit(),(0,0),xmargin*E,filltype);
+ if(group) endgroup(dest);
}
-void addViews(picture src, bool group=true, filltype filltype=NoFill,
- bool above=true)
+void addAllViews(picture src, bool group=true, filltype filltype=NoFill)
{
- addViews(currentpicture,src,group,filltype,above);
+ addAllViews(currentpicture,src,group,filltype);
}
// Force an array of 3D pictures to be as least as large as picture all.
diff --git a/Build/source/utils/asymptote/base/three_light.asy b/Build/source/utils/asymptote/base/three_light.asy
index 54ca7a47151..8e5a6281795 100644
--- a/Build/source/utils/asymptote/base/three_light.asy
+++ b/Build/source/utils/asymptote/base/three_light.asy
@@ -82,42 +82,45 @@ struct light {
pen background; // Background color of the 3D canvas.
real specularfactor;
bool viewport; // Are the lights specified (and fixed) in the viewport frame?
- triple[] position; // Only directional lights are implemented.
+ triple[] position; // Only directional lights are currently implemented.
transform3 T=identity(4); // Transform to apply to normal vectors.
bool on() {return position.length > 0;}
- void operator init(pen[] diffuse=array(position.length,white),
- pen[] ambient=array(position.length,black),
- pen[] specular=diffuse, pen background=nullpen,
+ void operator init(pen[] diffuse,
+ pen[] ambient=array(diffuse.length,black),
+ pen[] specular=diffuse, pen background=nullpen,
real specularfactor=1,
- bool viewport=true, triple[] position) {
- this.position=new triple[position.length];
- this.diffuse=new real[position.length][];
- this.ambient=new real[position.length][];
- this.specular=new real[position.length][];
+ bool viewport=true, triple[] position) {
+ int n=diffuse.length;
+ assert(ambient.length == n && specular.length == n && position.length == n);
+
+ this.diffuse=new real[n][];
+ this.ambient=new real[n][];
+ this.specular=new real[n][];
this.background=background;
+ this.position=new triple[n];
for(int i=0; i < position.length; ++i) {
- this.position[i]=unit(position[i]);
this.diffuse[i]=rgba(diffuse[i]);
this.ambient[i]=rgba(ambient[i]);
this.specular[i]=rgba(specular[i]);
+ this.position[i]=unit(position[i]);
}
this.specularfactor=specularfactor;
this.viewport=viewport;
}
void operator init(pen diffuse=white, pen ambient=black, pen specular=diffuse,
- pen background=nullpen, real specularfactor=1,
- bool viewport=true...triple[] position) {
+ pen background=nullpen, real specularfactor=1,
+ bool viewport=true...triple[] position) {
int n=position.length;
operator init(array(n,diffuse),array(n,ambient),array(n,specular),
- background,specularfactor,viewport,position);
+ background,specularfactor,viewport,position);
}
void operator init(pen diffuse=white, pen ambient=black, pen specular=diffuse,
- pen background=nullpen, bool viewport=true,
+ pen background=nullpen, bool viewport=true,
real x, real y, real z) {
operator init(diffuse,ambient,specular,background,viewport,(x,y,z));
}
@@ -146,9 +149,9 @@ struct light {
triple L=viewport ? position[i] : T*position[i];
real Ldotn=max(dot(normal,L),0);
p += ambient[i]*Ambient+Ldotn*diffuse[i]*Diffuse;
-// Apply specularfactor to partially compensate non-pixel-based rendering.
+ // Apply specularfactor to partially compensate non-pixel-based rendering.
if(Ldotn > 0) // Phong-Blinn model of specular reflection
- p += dot(normal,unit(L+Z))^s*specularfactor*specular[i]*Specular;
+ p += dot(normal,unit(L+Z))^s*specularfactor*specular[i]*Specular;
}
return rgb(p[0],p[1],p[2])+opacity(opacity(m.diffuse()));
}
@@ -165,10 +168,14 @@ light operator * (transform3 t, light light)
light operator cast(triple v) {return light(v);}
-light currentlight=light(ambient=rgb(0.1,0.1,0.1),specularfactor=3,
+light currentlight=light(ambient=gray(0.1),specularfactor=3,
(0.25,-0.25,1));
-light adobe=light(gray(0.4),specularfactor=3,viewport=false,
- (0.5,-0.5,-0.25),(0.5,0.5,0.25),
- (0.5,-0.5,0.2),(-0.5,0.5,-0.2));
+light White=light(new pen[] {rgb(0.38,0.38,0.45),rgb(0.6,0.6,0.67),
+ rgb(0.5,0.5,0.57)},specularfactor=3,viewport=false,
+ new triple[] {(-2,-1.5,-0.5),(2,1.1,-2.5),(-0.5,0,2)});
+
+light Headlamp=light(gray(0.9),ambient=gray(0.1),specularfactor=3,
+ (0.5,0.5,1/sqrt(2)),specular=gray(0.7));
+
light nolight;
diff --git a/Build/source/utils/asymptote/base/three_surface.asy b/Build/source/utils/asymptote/base/three_surface.asy
index 55060cb516d..3c49b382133 100644
--- a/Build/source/utils/asymptote/base/three_surface.asy
+++ b/Build/source/utils/asymptote/base/three_surface.asy
@@ -681,6 +681,22 @@ struct surface {
triple[][] normals=new triple[][],
pen[][] colors=new pen[][], bool3 planar=default) {
s=new patch[];
+ if(planar == true) {// Assume all path3 elements share a common normal.
+ if(external.length != 0) {
+ triple n=normal(external[0]);
+ if(n != O) {
+ transform3 T=align(n);
+ external=transpose(T)*external;
+ T *= shift(0,0,point(external[0],0).z);
+ path[] g=sequence(new path(int i) {return path(external[i]);},
+ external.length);
+ for(patch p : surface(g).s)
+ s.push(T*p);
+ return;
+ }
+ }
+ }
+
for(int i=0; i < external.length; ++i)
construct(external[i],
internal.length == 0 ? new triple[] : internal[i],