diff options
author | Karl Berry <karl@freefriends.org> | 2016-02-07 00:27:20 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2016-02-07 00:27:20 +0000 |
commit | 0f5e19a268f4d86c2897f590563f21c8277c18d1 (patch) | |
tree | 7e65891f29ccde62ed60cbcc94e7fb7631429ac2 /Build/source/utils/asymptote/base | |
parent | 1b8f7f1bf982c75d77d85ac6855d48332cd41ca4 (diff) |
asy 2.36 sources
git-svn-id: svn://tug.org/texlive/trunk@39610 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/base')
-rw-r--r-- | Build/source/utils/asymptote/base/animation.asy | 1 | ||||
-rw-r--r-- | Build/source/utils/asymptote/base/asy-mode.el | 24 | ||||
-rw-r--r-- | Build/source/utils/asymptote/base/bezulate.asy | 3 | ||||
-rw-r--r-- | Build/source/utils/asymptote/base/contour3.asy | 4 | ||||
-rw-r--r-- | Build/source/utils/asymptote/base/math.asy | 14 | ||||
-rw-r--r-- | Build/source/utils/asymptote/base/plain_strings.asy | 5 | ||||
-rw-r--r-- | Build/source/utils/asymptote/base/smoothcontour3.asy | 66 | ||||
-rw-r--r-- | Build/source/utils/asymptote/base/three_surface.asy | 290 | ||||
-rw-r--r-- | Build/source/utils/asymptote/base/three_tube.asy | 16 |
9 files changed, 259 insertions, 164 deletions
diff --git a/Build/source/utils/asymptote/base/animation.asy b/Build/source/utils/asymptote/base/animation.asy index 57e13ab6e03..270adce713a 100644 --- a/Build/source/utils/asymptote/base/animation.asy +++ b/Build/source/utils/asymptote/base/animation.asy @@ -139,6 +139,7 @@ struct animation { string pdf(enclosure enclosure=NoBox, real delay=animationdelay, string options="", bool keep=settings.keep, bool multipage=true) { + settings.twice=true; if(settings.inlinetex) multipage=true; if(!global) multipage=false; if(!pdflatex()) diff --git a/Build/source/utils/asymptote/base/asy-mode.el b/Build/source/utils/asymptote/base/asy-mode.el index 7ccdfdf1197..c1960e23035 100644 --- a/Build/source/utils/asymptote/base/asy-mode.el +++ b/Build/source/utils/asymptote/base/asy-mode.el @@ -1,10 +1,15 @@ -;;; asy-mode.el +;;; asy-mode.el --- Major mode for editing Asymptote source code. ;; Copyright (C) 2006-8 + ;; Author: Philippe IVALDI 20 August 2006 -;; http://www.piprime.fr/ -;; Modified by: John Bowman -;; +;; Maintainer: John Bowman +;; URL: https://github.com/vectorgraphics/asymptote +;; Version: 1.6 +;; Keywords: language, mode + +;;; License: + ;; This program is free software ; you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by ;; the Free Software Foundation ; either version 3 of the License, or @@ -19,7 +24,9 @@ ;; along with this program ; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -;; Emacs mode for editing Asymptote source code. +;;; Commentary + +;; Major mode for editing Asymptote source code. ;; INSTALLATION: ;; Place this file (asy-mode.el) and asy-keywords.el in your Emacs load path. @@ -43,6 +50,8 @@ ;; ;; See also paragraph II of the documentation below to automate asy-insinuate-latex. +;;; Code: + (defvar asy-mode-version "1.6") ;;;###autoload @@ -754,7 +763,7 @@ You should remove the line " (int-to-string (line-number-at-pos))))))) ;; Functions and 'advises' to restrict 'font-lock-unfontify-region' ;; and 'font-lock-fontify-syntactically-region' within lasy-mode - ;; Special thanks to Olivier Ramaré for his help. + ;; Special thanks to Olivier Ramaré for his help. (when (and (fboundp 'font-lock-add-keywords) (> emacs-major-version 21)) (defun lasy-mode-at-pos (pos &optional interior strictly) "If point at POS is in an asy environment return the list (start end)." @@ -1160,7 +1169,7 @@ See `asy-insinuate-latex'." (defvar lasy-run-tex nil) (defun lasy-asydef() - "Return the content between the tags \begin{asydef} and \end{asydef}." + "Return the content between the tags \\begin{asydef} and \\end{asydef}." (save-excursion (if (re-search-backward "\\\\begin{asydef}" 0 t) (buffer-substring @@ -1588,3 +1597,4 @@ If optional argument Force is t then force compilation." (define-key asy-mode-map (kbd "<C-M-S-return>") 'asy-master-tex-view-ps2pdf-f) (provide `asy-mode) +;;; asy-mode.el ends here diff --git a/Build/source/utils/asymptote/base/bezulate.asy b/Build/source/utils/asymptote/base/bezulate.asy index 60be8cb7045..d0b8958a4da 100644 --- a/Build/source/utils/asymptote/base/bezulate.asy +++ b/Build/source/utils/asymptote/base/bezulate.asy @@ -248,7 +248,8 @@ path subdivide(path p) path q; int l=length(p); for(int i=0; i < l; ++i) - q=q&subpath(p,i,i+0.5)&subpath(p,i+0.5,i+1); + q=q&(straight(p,i) ? subpath(p,i,i+1) : + subpath(p,i,i+0.5)&subpath(p,i+0.5,i+1)); return cyclic(p) ? q&cycle : q; } diff --git a/Build/source/utils/asymptote/base/contour3.asy b/Build/source/utils/asymptote/base/contour3.asy index 3d925be684e..4977a351bf2 100644 --- a/Build/source/utils/asymptote/base/contour3.asy +++ b/Build/source/utils/asymptote/base/contour3.asy @@ -473,9 +473,7 @@ surface surface(vertex[][] g) surface s=surface(g.length); for(int i=0; i < g.length; ++i) { vertex[] cur=g[i]; - s.s[i]=patch(new triple[] {cur[0].v,cur[0].v,cur[1].v,cur[2].v}, - normals=new triple[] {cur[0].normal,cur[0].normal, - cur[1].normal,cur[2].normal}); + s.s[i]=patch(cur[0].v--cur[1].v--cur[2].v--cycle); } return s; } diff --git a/Build/source/utils/asymptote/base/math.asy b/Build/source/utils/asymptote/base/math.asy index 47044a75df1..8cfd61f4344 100644 --- a/Build/source/utils/asymptote/base/math.asy +++ b/Build/source/utils/asymptote/base/math.asy @@ -423,3 +423,17 @@ pair[][] fft(pair[][] a, int sign=1) } return transpose(A); } + +// Given a matrix A with independent columns, return +// the unique vector y minimizing |Ay - b|^2 (the L2 norm). +// If the columns of A are not linearly independent, +// throw an error (if warn == true) or return an empty array +// (if warn == false). +real[] leastsquares(real[][] A, real[] b, bool warn=true) +{ + real[] solution=solve(AtA(A),b*A,warn=false); + if (solution.length == 0 && warn) + abort("Cannot compute least-squares approximation for " + + "a matrix with linearly dependent columns."); + return solution; +} diff --git a/Build/source/utils/asymptote/base/plain_strings.asy b/Build/source/utils/asymptote/base/plain_strings.asy index f4c856e8ad9..a5c72b2035d 100644 --- a/Build/source/utils/asymptote/base/plain_strings.asy +++ b/Build/source/utils/asymptote/base/plain_strings.asy @@ -179,6 +179,11 @@ string graphic(string name, string options="") return "\externalfigure["+name+"]["+options+"]"; } +string graphicscale(real x) +{ + return string(settings.tex == "context" ? 1000*x : x); +} + string minipage(string s, real width=100bp) { if(latex()) diff --git a/Build/source/utils/asymptote/base/smoothcontour3.asy b/Build/source/utils/asymptote/base/smoothcontour3.asy index 216f3269d92..9b34fc7c098 100644 --- a/Build/source/utils/asymptote/base/smoothcontour3.asy +++ b/Build/source/utils/asymptote/base/smoothcontour3.asy @@ -19,69 +19,7 @@ import graph_settings; // for nmesh import three; - -/***********************************************/ -/******** LINEAR ALGEBRA ROUTINES **************/ -/******** LEAST-SQUARES **************/ -/***********************************************/ - -// Apply a matrix to a vector. -real[] apply(real[][] matrix, real[] v) { - real[] ans = new real[matrix.length]; - for (int r = 0; r < matrix.length; ++r) { - ans[r] = 0; - for (int c = 0; c < v.length; ++c) { - ans[r] += matrix[r][c] * v[c]; - } - } - return ans; -} - -// Apply the transpose of a matrix to a vector, -// without actually forming the transpose. -real[] applytranspose(real[][] matrix, real[] v) { - real[] ans = new real[matrix[0].length]; - for (int r = 0; r < ans.length; ++r) ans[r] = 0; - for (int c = 0; c < matrix.length; ++c) { - for (int r = 0; r < ans.length; ++r) { - ans[r] += matrix[c][r] * v[c]; - } - } - return ans; -} - -// For a matrix A, returns the matrix product -// (A transposed) * A. -// The transpose of A is never actually formed. -real[][] AtA(real[][] matrix) { - real[][] toreturn = new real[matrix[0].length][matrix[0].length]; - for (int i = 0; i < toreturn.length; ++i) { - for (int j = 0; j < toreturn.length; ++j) { - toreturn [i][j] = 0; - } - } - for (int k = 0; k < matrix.length; ++k) { - for (int i = 0; i < toreturn.length; ++i) { - for (int j = 0; j < toreturn.length; ++j) { - toreturn[i][j] += matrix[k][i] * matrix[k][j]; - } - } - } - return toreturn; -} - -// Assuming A is a matrix with independent columns, returns -// the unique vector y minimizing |Ay - b|^2 (the L2 norm). -// If the columns of A are not linearly independent, -// throws an error (if warn == true) or returns an empty array -// (if warn == false). -real[] leastsquares(real[][] A, real[] b, bool warn = true) { - real[] solution = solve(AtA(A), applytranspose(A, b), warn=false); - if (solution.length == 0 && warn) - abort("Cannot compute least-squares approximation for " + - "a matrix with linearly dependent columns."); - return solution; -} +import math; /***********************************************/ /******** CREATING BEZIER PATCHES **************/ @@ -597,7 +535,7 @@ string operator cast(positionedvector vv) { // The angle, in degrees, between two vectors. real angledegrees(triple a, triple b) { - real lengthprod = abs(a) * abs(b); + real lengthprod = max(abs(a) * abs(b), abs(dot(a,b))); if (lengthprod == 0) return 0; return aCos(dot(a,b) / lengthprod); } diff --git a/Build/source/utils/asymptote/base/three_surface.asy b/Build/source/utils/asymptote/base/three_surface.asy index f2f21eb826c..175ef562d80 100644 --- a/Build/source/utils/asymptote/base/three_surface.asy +++ b/Build/source/utils/asymptote/base/three_surface.asy @@ -9,12 +9,21 @@ string meshname(string name) {return name+" mesh";} private real Fuzz=10.0*realEpsilon; private real nineth=1/9; +// Return the default Coons interior control point for a Bezier triangle +// based on the cyclic path3 external. +triple coons3(path3 external) { + return 0.25*(precontrol(external,0)+postcontrol(external,0)+ + precontrol(external,1)+postcontrol(external,1)+ + precontrol(external,2)+postcontrol(external,2))- + (point(external,0)+point(external,1)+point(external,2))/6; +} + struct patch { triple[][] P; - triple[] normals; // Optionally specify 4 normal vectors at the corners. pen[] colors; // Optionally specify 4 corner colors. bool straight; // Patch is based on a piecewise straight external path. bool3 planar; // Patch is planar. + bool triangular; // Patch is a Bezier triangle. path3 external() { return straight ? P[0][0]--P[3][0]--P[3][3]--P[0][3]--cycle : @@ -24,20 +33,40 @@ struct patch { P[0][3]..controls P[0][2] and P[0][1]..cycle; } + path3 externaltriangular() { + return + 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][2] and P[1][1]..cycle; + } + triple[] internal() { return new triple[] {P[1][1],P[2][1],P[2][2],P[1][2]}; } + triple[] internaltriangular() { + return new triple[] {P[2][1]}; + } + triple cornermean() { return 0.25*(P[0][0]+P[0][3]+P[3][0]+P[3][3]); } + triple cornermeantriangular() { + return (P[0][0]+P[3][0]+P[3][3])/3; + } + triple[] corners() {return new triple[] {P[0][0],P[3][0],P[3][3],P[0][3]};} + triple[] cornerstriangular() {return new triple[] {P[0][0],P[3][0],P[3][3]};} real[] map(real f(triple)) { return new real[] {f(P[0][0]),f(P[3][0]),f(P[3][3]),f(P[0][3])}; } + real[] maptriangular(real f(triple)) { + return new real[] {f(P[0][0]),f(P[3][0]),f(P[3][3])}; + } + triple Bu(int j, real u) {return bezier(P[0][j],P[1][j],P[2][j],P[3][j],u);} triple BuP(int j, real u) {return bezierP(P[0][j],P[1][j],P[2][j],P[3][j],u);} triple BuPP(int j, real u) { @@ -70,6 +99,13 @@ struct patch { return bezier(Bu(0,u),Bu(1,u),Bu(2,u),Bu(3,u),v); } + triple pointtriangular(real u, real v) { + real w=1-u-v; + return w^2*(w*P[0][0]+3*(u*P[1][0]+v*P[1][1]))+ + u^2*(u*P[3][0]+3*(w*P[2][0]+v*P[3][1]))+ + 6*u*v*w*P[2][1]+v^2*(v*P[3][3]+3*(w*P[2][2]+u*P[3][2])); + } + // compute normal vectors for degenerate cases private triple normal0(real u, real v, real epsilon) { triple n=0.5*(cross(bezier(BuPP(0,u),BuPP(1,u),BuPP(2,u),BuPP(3,u),v), @@ -131,13 +167,50 @@ struct patch { return abs(n) > epsilon ? n : normal0(0,1,epsilon); } + triple normal00triangular() { + triple n=9*cross(P[1][0]-P[0][0],P[1][1]-P[0][0]); + real epsilon=fuzz*change2(P); + return abs(n) > epsilon ? n : normal0(0,0,epsilon); + } + + triple normal10triangular() { + triple n=9*cross(P[3][0]-P[2][0],P[3][1]-P[2][0]); + real epsilon=fuzz*change2(P); + return abs(n) > epsilon ? n : normal0(1,0,epsilon); + } + + triple normal01triangular() { + triple n=9*cross(P[3][2]-P[2][2],P[3][3]-P[2][2]); + real epsilon=fuzz*change2(P); + return abs(n) > epsilon ? n : normal0(0,1,epsilon); + } + + // Compute one-third of the directional derivative of a Bezier triangle in the u + // direction at point (u,v). + private triple bu(real u, real v) { + real w=1-u-v; + return u*(w*2-u)*P[2][0]+2*v*(w-u)*P[2][1]+w*(w-2*u)*P[1][0]+ + u*(u*P[3][0]+2*v*P[3][1])+v*v*P[3][2]-w*(2*v*P[1][1]+w*P[0][0])- + v*v*P[2][2]; + } + + // Compute one-third of the directional derivative of a Bezier triangle in the v + // direction at point (u,v). + private triple bv(real u, real v) { + real w=1-u-v; + return u*2*(w-v)*P[2][1]+v*(2*w-v)*P[2][2]+w*(w-2*v)*P[1][1]+ + u*(u*P[3][1]+2*v*P[3][2])+v*v*P[3][3]-w*(2*u*P[1][0]+w*P[0][0])- + u*u*P[2][0]; + } + + // Compute the normal of a Bezier triangle at (u,v) + triple normaltriangular(real u, real v) { + // TODO: handle degeneracy + return 9*cross(bu(u,v),bv(u,v)); + } + pen[] colors(material m, light light=currentlight) { bool nocolors=colors.length == 0; - if(normals.length > 0) - return new pen[] {color(normals[0],nocolors ? m : colors[0],light), - color(normals[1],nocolors ? m : colors[1],light), - color(normals[2],nocolors ? m : colors[2],light), - color(normals[3],nocolors ? m : colors[3],light)}; if(planar) { triple normal=normal(0.5,0.5); return new pen[] {color(normal,nocolors ? m : colors[0],light), @@ -151,12 +224,38 @@ struct patch { color(normal01(),nocolors ? m : colors[3],light)}; } + pen[] colorstriangular(material m, light light=currentlight) { + bool nocolors=colors.length == 0; + if(planar) { + triple normal=normal(1/3,1/3); + return new pen[] {color(normal,nocolors ? m : colors[0],light), + color(normal,nocolors ? m : colors[1],light), + color(normal,nocolors ? m : colors[2],light)}; + } + return new pen[] {color(normal00(),nocolors ? m : colors[0],light), + color(normal10(),nocolors ? m : colors[1],light), + color(normal01(),nocolors ? m : colors[2],light)}; + } + triple min3,max3; bool havemin3,havemax3; void init() { havemin3=false; havemax3=false; + if(triangular) { + external=externaltriangular; + internal=internaltriangular; + cornermean=cornermeantriangular; + corners=cornerstriangular; + map=maptriangular; + point=pointtriangular; + normal=normaltriangular; + normal00=normal00triangular; + normal10=normal10triangular; + normal01=normal01triangular; + colors=colorstriangular; + } } triple min(triple bound=P[0][0]) { @@ -191,63 +290,81 @@ struct patch { return minratio(Q,d*bound)/d; // d is negative } - void operator init(triple[][] P, triple[] normals=new triple[], + void operator init(triple[][] P, pen[] colors=new pen[], bool straight=false, - bool3 planar=default, bool copy=true) { - init(); + bool3 planar=default, bool triangular=false, + bool copy=true) { this.P=copy ? copy(P) : P; - if(normals.length != 0) - this.normals=copy(normals); if(colors.length != 0) this.colors=copy(colors); - this.planar=planar; this.straight=straight; + this.planar=planar; + this.triangular=triangular; + init(); } void operator init(pair[][] P, triple plane(pair)=XYplane, - bool straight=false) { + bool straight=false, bool triangular=false) { triple[][] Q=new triple[4][]; for(int i=0; i < 4; ++i) { pair[] Pi=P[i]; Q[i]=sequence(new triple(int j) {return plane(Pi[j]);},4); } - operator init(Q,straight); - planar=true; + operator init(Q,straight,planar=true,triangular); } void operator init(patch s) { - operator init(s.P,s.normals,s.colors,s.straight); - } + operator init(s.P,s.colors,s.straight,s.planar,s.triangular); + } - // A constructor for a convex cyclic path3 of length <= 4 with optional - // arrays of 4 internal points, corner normals, and pens. - void operator init(path3 external, triple[] internal=new triple[], - triple[] normals=new triple[], pen[] colors=new pen[], + // A constructor for a cyclic path3 of length 3 with a specified + // internal point, corner normals, and pens (rendered as a Bezier triangle). + void operator init(path3 external, triple internal, pen[] colors=new pen[], bool3 planar=default) { + triangular=true; + this.planar=planar; init(); + if(colors.length != 0) + this.colors=copy(colors); + + P=new triple[][] { + {point(external,0)}, + {postcontrol(external,0),precontrol(external,0)}, + {precontrol(external,1),internal,postcontrol(external,2)}, + {point(external,1),postcontrol(external,1),precontrol(external,2), + point(external,2)} + }; + } + // A constructor for a convex cyclic path3 of length <= 4 with optional + // arrays of internal points (4 for a Bezier patch, 1 for a Bezier + // triangle), and pens. + void operator init(path3 external, triple[] internal=new triple[], + pen[] colors=new pen[], bool3 planar=default) { if(internal.length == 0 && planar == default) this.planar=normal(external) != O; else this.planar=planar; int L=length(external); + + if(L == 3) { + operator init(external,internal.length == 1 ? internal[0] : + coons3(external),colors,this.planar); + straight=piecewisestraight(external); + return; + } + if(L > 4 || !cyclic(external)) abort("cyclic path3 of length <= 4 expected"); if(L == 1) { external=external--cycle--cycle--cycle; if(colors.length > 0) colors.append(array(3,colors[0])); - if(normals.length > 0) normals.append(array(3,normals[0])); } else if(L == 2) { external=external--cycle--cycle; if(colors.length > 0) colors.append(array(2,colors[0])); - if(normals.length > 0) normals.append(array(2,normals[0])); - } else if(L == 3) { - external=external--cycle; - if(colors.length > 0) colors.push(colors[0]); - if(normals.length > 0) normals.push(normals[0]); } - if(normals.length != 0) - this.normals=copy(normals); + + init(); if(colors.length != 0) this.colors=copy(colors); @@ -261,7 +378,7 @@ struct patch { +3*(precontrol(external,j-1)+ postcontrol(external,j+1)) -point(external,j+2)); - } else straight=false; + } P=new triple[][] { {point(external,0),precontrol(external,0),postcontrol(external,3), @@ -275,16 +392,13 @@ struct patch { // A constructor for a convex quadrilateral. void operator init(triple[] external, triple[] internal=new triple[], - triple[] normals=new triple[], pen[] colors=new pen[], - bool3 planar=default) { + pen[] colors=new pen[], bool3 planar=default) { init(); if(internal.length == 0 && planar == default) this.planar=normal(external) != O; else this.planar=planar; - if(normals.length != 0) - this.normals=copy(normals); if(colors.length != 0) this.colors=copy(colors); @@ -313,41 +427,46 @@ struct patch { patch operator * (transform3 t, patch s) { patch S; - S.P=new triple[4][4]; - for(int i=0; i < 4; ++i) { + S.P=new triple[s.P.length][]; + for(int i=0; i < s.P.length; ++i) { triple[] si=s.P[i]; triple[] Si=S.P[i]; - for(int j=0; j < 4; ++j) + for(int j=0; j < si.length; ++j) Si[j]=t*si[j]; } - if(s.normals.length > 0) { - transform3 t0=shiftless(t); - t0=determinant(t0) == 0 ? identity4 : transpose(inverse(t0)); - for(int i=0; i < s.normals.length; ++i) - S.normals[i]=t0*s.normals[i]; - } - S.colors=copy(s.colors); S.planar=s.planar; S.straight=s.straight; + S.triangular=s.triangular; + S.init(); return S; } patch reverse(patch s) { + assert(!s.triangular); patch S; S.P=transpose(s.P); - if(s.normals.length > 0) - S.normals= - new triple[] {s.normals[0],s.normals[3],s.normals[2],s.normals[1]}; if(s.colors.length > 0) S.colors=new pen[] {s.colors[0],s.colors[3],s.colors[2],s.colors[1]}; - S.planar=s.planar; S.straight=s.straight; + S.planar=s.planar; return S; } +// Return a degenerate tensor patch representation of a Bezier triangle. +patch tensor(patch s) { + if(!s.triangular) return patch(s); + triple[][] P=s.P; + return patch(new triple[][] {{P[0][0],P[0][0],P[0][0],P[0][0]}, + {P[1][0],P[1][0]*2/3+P[1][1]/3,P[1][0]/3+P[1][1]*2/3,P[1][1]}, + {P[2][0],P[2][0]/3+P[2][1]*2/3,P[2][1]*2/3+P[2][2]/3,P[2][2]}, + {P[3][0],P[3][1],P[3][2],P[3][3]}}, + s.colors.length > 0 ? new pen[] {s.colors[0],s.colors[1],s.colors[2],s.colors[0]} : new pen[], + s.straight,s.planar,false,false); +} + // Return the tensor product patch control points corresponding to path p // and points internal. pair[][] tensor(path p, pair[] internal) @@ -589,7 +708,7 @@ path[] regularize(path p, bool checkboundary=true) struct surface { patch[] s; - int index[][]; + int index[][];// Position of patch corresponding to major U,V parameter in s. bool vcyclic; bool empty() { @@ -612,11 +731,11 @@ struct surface { this.vcyclic=s.vcyclic; } - void operator init(triple[][][] P, triple[][] normals=new triple[][], - pen[][] colors=new pen[][], bool3 planar=default) { + void operator init(triple[][][] P, pen[][] colors=new pen[][], + bool3 planar=default, bool triangular=false) { s=sequence(new patch(int i) { - return patch(P[i],normals.length == 0 ? new triple[] : normals[i], - colors.length == 0 ? new pen[] : colors[i],planar); + return patch(P[i],colors.length == 0 ? new pen[] : colors[i],planar, + triangular); },P.length); } @@ -701,8 +820,13 @@ struct surface { // A constructor for a possibly nonconvex simple cyclic path in a given plane. void operator init(path p, triple plane(pair)=XYplane) { bool straight=piecewisestraight(p); - for(path g : regularize(p)) - s.push(patch(coons(g),plane,straight)); + for(path g : regularize(p)) { + if(length(g) == 3) { + path3 G=path3(g,plane); + s.push(patch(G,coons3(G))); + } else + s.push(patch(coons(g),plane,straight)); + } } void operator init(explicit path[] g, triple plane(pair)=XYplane) { @@ -712,19 +836,17 @@ struct surface { // A general surface constructor for both planar and nonplanar 3D paths. void construct(path3 external, triple[] internal=new triple[], - triple[] normals=new triple[], pen[] colors=new pen[], - bool3 planar=default) { + pen[] colors=new pen[], bool3 planar=default) { int L=length(external); if(!cyclic(external)) abort("cyclic path expected"); if(L <= 3 && piecewisestraight(external)) { - s.push(patch(external,internal,normals,colors,planar=true)); + s.push(patch(external,internal,colors,planar)); return; } // Construct a surface from a possibly nonconvex planar cyclic path3. - if(planar != false && internal.length == 0 && normals.length == 0 && - colors.length == 0) { + if(planar != false && internal.length == 0 && colors.length == 0) { triple n=normal(external); if(n != O) { transform3 T=align(n); @@ -737,7 +859,7 @@ struct surface { } if(L <= 4 || internal.length > 0) { - s.push(patch(external,internal,normals,colors,planar)); + s.push(patch(external,internal,colors,planar)); return; } @@ -746,40 +868,33 @@ struct surface { pen[] p; triple[] n; bool nocolors=colors.length == 0; - bool nonormals=normals.length == 0; triple center; for(int i=0; i < L; ++i) center += point(external,i); center *= factor; if(!nocolors) p=new pen[] {mean(colors)}; - if(!nonormals) - n=new triple[] {factor*sum(normals)}; // Use triangles for nonplanar surfaces. int step=normal(external) == O ? 1 : 2; int i=0; int end; while((end=i+step) < L) { s.push(patch(subpath(external,i,end)--center--cycle, - nonormals ? n : concat(normals[i:end+1],n), nocolors ? p : concat(colors[i:end+1],p),planar)); i=end; } s.push(patch(subpath(external,i,L)--center--cycle, - nonormals ? n : concat(normals[i:],normals[0:1],n), nocolors ? p : concat(colors[i:],colors[0:1],p),planar)); } void operator init(path3 external, triple[] internal=new triple[], - triple[] normals=new triple[], pen[] colors=new pen[], - bool3 planar=default) { + pen[] colors=new pen[], bool3 planar=default) { s=new patch[]; - construct(external,internal,normals,colors,planar); + construct(external,internal,colors,planar); } void operator init(explicit path3[] external, triple[][] internal=new triple[][], - 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. @@ -801,14 +916,12 @@ struct surface { for(int i=0; i < external.length; ++i) construct(external[i], internal.length == 0 ? new triple[] : internal[i], - normals.length == 0 ? new triple[] : normals[i], colors.length == 0 ? new pen[] : colors[i],planar); } void push(path3 external, triple[] internal=new triple[], - triple[] normals=new triple[] ,pen[] colors=new pen[], - bool3 planar=default) { - s.push(patch(external,internal,normals,colors,planar)); + pen[] colors=new pen[], bool3 planar=default) { + s.push(patch(external,internal,colors,planar)); } // Construct the surface of rotation generated by rotating g @@ -1111,7 +1224,7 @@ triple[][] subpatch(triple[][] P, pair a, pair b) 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); + a.x < b.x && a.y < b.y && !s.triangular); return patch(subpatch(s.P,a,b),s.straight,s.planar); } @@ -1244,8 +1357,14 @@ void draw3D(frame f, int type=0, patch s, triple center=O, material m, if(prc()) PRCshininess=PRCshininess(m.shininess); - draw(f,s.P,center,s.straight,m.p,m.opacity,m.shininess,PRCshininess, - s.planar ? s.normal(0.5,0.5) : O,s.colors,interaction.type,prc); + if(s.triangular) + drawbeziertriangle(f,s.P,center,s.straight && s.planar,m.p, + m.opacity,m.shininess,PRCshininess,s.colors, + interaction.type); + else + draw(f,s.P,center,s.straight && s.planar,m.p,m.opacity,m.shininess, + PRCshininess,s.planar ? s.normal(0.5,0.5) : O,s.colors, + interaction.type,prc); } // Draw triangles on a frame. @@ -1337,11 +1456,13 @@ void draw(picture pic=currentpicture, triple[] v, int[][] vi, pic.addPoint(v[viij]); } -void drawPRCsphere(frame f, transform3 t=identity4, bool half=false, material m, - light light=currentlight, render render=defaultrender) +void drawPRCsphere(frame f, transform3 t=identity4, bool half=false, + material m, light light=currentlight, + render render=defaultrender) { m=material(m,light); - drawPRCsphere(f,t,half,m.p,m.opacity,PRCshininess(m.shininess),render.sphere); + drawPRCsphere(f,t,half,m.p,m.opacity,PRCshininess(m.shininess), + render.sphere); } void drawPRCcylinder(frame f, transform3 t=identity4, material m, @@ -1368,9 +1489,10 @@ void drawPRCtube(frame f, path3 center, path3 g, material m, void tensorshade(transform t=identity(), frame f, patch s, material m, light light=currentlight, projection P) { + + if(s.triangular) s=tensor(s); tensorshade(f,box(t*s.min(P),t*s.max(P)),m.diffuse(), - s.colors(m,light),t*project(s.external(),P,1), - t*project(s.internal(),P)); + s.colors(m,light),t*project(s.external(),P,1),t*project(s.internal(),P)); } restricted pen[] nullpens={nullpen}; @@ -1397,7 +1519,7 @@ void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1, real[][] depth=new real[s.s.length][]; for(int i=0; i < depth.length; ++i) - depth[i]=new real[] {abs(camera-s.s[i].cornermean()),i}; + depth[i]=new real[] {dot(P.normal,camera-s.s[i].cornermean()),i}; depth=sort(depth); @@ -1444,7 +1566,7 @@ void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1, real[][] depth=new real[s.s.length][]; for(int i=0; i < depth.length; ++i) - depth[i]=new real[] {abs(camera-s.s[i].cornermean()),i}; + depth[i]=new real[] {dot(P.normal,camera-s.s[i].cornermean()),i}; depth=sort(depth); diff --git a/Build/source/utils/asymptote/base/three_tube.asy b/Build/source/utils/asymptote/base/three_tube.asy index bbbd5a65633..25bb9385ec8 100644 --- a/Build/source/utils/asymptote/base/three_tube.asy +++ b/Build/source/utils/asymptote/base/three_tube.asy @@ -176,18 +176,24 @@ bool uperiodic(real[][] a) { int m=a[0].length; real[] a0=a[0]; real[] a1=a[n-1]; - real epsilon=sqrtEpsilon*norm(a); - for(int j=0; j < m; ++j) + for(int j=0; j < m; ++j) { + real norm=0; + for(int i=0; i < n; ++i) + norm=max(norm,abs(a[i][j])); + real epsilon=sqrtEpsilon*norm; if(abs(a0[j]-a1[j]) > epsilon) return false; + } return true; } bool vperiodic(real[][] a) { int n=a.length; if(n == 0) return false; int m=a[0].length-1; - real epsilon=sqrtEpsilon*norm(a); - for(int i=0; i < n; ++i) - if(abs(a[i][0]-a[i][m]) > epsilon) return false; + for(int i=0; i < n; ++i) { + real[] ai=a[i]; + real epsilon=sqrtEpsilon*norm(ai); + if(abs(ai[0]-ai[m]) > epsilon) return false; + } return true; } |