// Copyright (c) 2007, author: Jens Schwaiger // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or (at // your option) any later version. // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301, USA. // INSTALLATION: // Paste this file in the sub-directory $HOME/.asy // Code: import graph3; // similar to roundedpath for 3D guide3 roundedguide(guide3 A, real r=0.2){ guide3 rounded; triple before, after, indir, outdir; int len=length(A); bool guideclosed=cyclic(A); if(len<2){return A;}; if(guideclosed){rounded=point(point(A,0)--point(A,1),r);} else {rounded=point(A,0);}; for(int i=1;i<len;i=i+1){ before=point(point(A,i)--point(A,i-1),r); after=point(point(A,i)--point(A,i+1),r); indir=dir(point(A,i-1)--point(A,i),1); outdir=dir(point(A,i)--point(A,i+1),1); rounded=rounded--before{indir}..{outdir}after; } if(guideclosed) { before=point(point(A,0)--point(A,len-1),r); indir=dir(point(A,len-1)--point(A,0),1); outdir=dir(point(A,0)--point(A,1),1); rounded=rounded--before{indir}..{outdir}cycle;} else rounded=rounded--point(A,len); return rounded; }; // returns a triple orthogonal to the triple p triple orthv(triple p=(0,0,1)){ if(abs((p.x,p.y))>0) {return unit((-p.y,p.x,0));} else {return (1,0,0);}; }; // used in constructin the array of Bishop frames triple nextnormal(triple p, triple q){ triple nw=p-(dot(p,q)*q); if(abs(nw)<0.001){return p;} else {return unit(nw);} }; // Bishop frame itself; for closed curves a modification guarantees // smoothness also at the // "closing" position of the guide3 g // tw<>0 means some additional twist (measured in radians) // for closed g twist should be a multiple of 2pi /* See http://ada.math.uga.edu/research/software/tube/tube.html */ triple[][] bframe(guide3 g, int subdiv=20, real tw=0){ triple[][] bf=new triple[subdiv+1][3]; real lg=arclength(g); for(int i=0;i<subdiv+1;i=i+1){bf[i][0]=dir(g,arctime(g,(i/subdiv)*lg));} bf[0][1]=orthv(bf[0][0]); bf[0][2]=cross(bf[0][0],bf[0][1]); for(int i=1;i<subdiv+1;i=i+1){bf[i][1]=nextnormal(bf[i-1][1],bf[i][0]); bf[i][2]=cross(bf[i][0],bf[i][1]); }; if(cyclic(g)){// Modify frame, such that surface closes smoothly triple[] startframe=new triple[3]; triple[] endframe=new triple[3]; startframe=bf[0]; endframe=bf[subdiv]; pair tmp=(dot(endframe[1],startframe[1]),-dot(endframe[2],startframe[1])); real alpha=angle(unit(tmp)); for(int i=1;i<subdiv+1;i=i+1){ bf[i][1]=rotate(-alpha*180/pi*i/subdiv,bf[i][0])*bf[i][1]; bf[i][2]=rotate(-alpha*180/pi*i/subdiv,bf[i][0])*bf[i][2]; }; }; for(int i=1;i<subdiv+1;i=i+1){ bf[i][1]=rotate(tw*180/pi*i/subdiv,bf[i][0])*bf[i][1]; bf[i][2]=rotate(tw*180/pi*i/subdiv,bf[i][0])*bf[i][2]; }; return bf; }; typedef guide crosssec(real); guide cs0(real s){return scale(0.3)*unitcircle;}; // produces a tubelike surface around g; sc ist the radius of the tube /* See http://ada.math.uga.edu/research/software/tube/tube.html */ picture spacetube(guide3 g, int nx=20, int ny=12, crosssec cs=cs0, real twist=0, bool cover=false, pen surfacepen=lightgray, pen meshpen=nullpen, light light=currentlight, projection P=currentprojection) { triple[][] bf=bframe(g,nx,twist); triple[] pt=new triple[]; real lg=arclength(g); for(int i=0;i<nx+1;i=i+1){ pt[i]=relpoint(g,i/nx);} triple[][] surfc=new triple[nx+1][ny+1]; for(int i=0;i<nx+1;i=i+1) for(int j=0;j<ny+1;j=j+1){ guide rhox=cs((i/nx)); if(cover){ if((!cyclic(g))&&(i==0||i==nx)){rhox=(0,0);};}; pair prhox=relpoint(rhox,j/ny); real scxx=prhox.x; real scyy=prhox.y; surfc[i][j]=pt[i]+scxx*bf[i][1]+ scyy*bf[i][2]; }; return surface(surfc,surfacepen,meshpen,light,P); };
Dernière modification/Last modified: Sun Aug 17 01:51:46 CEST 2008
Philippe Ivaldi