// Auteur D. Comin, mars 2008 // Ce fichier est distribué sous licence GNU-GPL, je ne sais pas exactement ce que ça veut dire mais je trouve que ça a de la gueule. // merci à Gaetan Marris qui m'a signalé puis résolu un bug de gestions d'arêtes cachées. import math; import three; import markers; import geometry; import patterns; import solids; import labelpath; import polyhedron; real e=0.08; currentlight=nolight; //définit les directions pair nord,sud,est,ouest,nouest,nest,souest,sest; nord=(0,1); sud=(0,-1); est=(1,0); ouest=(-1,0); nouest=(-1,1); nest=(1,1); souest=(-1,-1); sest=(1,-1); //trace le point (la croix) placé en A void pointe(triple A, pen sty=currentpen){ draw(A+(0,e,e)--A-(0,e,e),p=sty); draw(A+(0,-e,e)--A-(0,-e,e),p=sty); } //nomme et trace le point (la croix) placé en A void nomme(picture pic=currentpicture, Label L, triple position,align align=NoAlign, pen p=currentpen, filltype filltype=NoFill){ pointe(position,p); label(pic, L, position,align,p,filltype); } //trace un tetraèdre de sommet D et de base ABC void tetraedre(triple A,triple B,triple C,triple D,pen sty=currentpen){ path3 f1=A--B--C--cycle; path3 f2=A--B--D--cycle; path3 f3=B--C--D--cycle; path3 f4=C--A--D--cycle; polyhedron faces; faces.push(f1); faces.push(f2); faces.push(f3); faces.push(f4); polyhedron[] parr={faces}; filldraw(parr,new pen[]{white},new pen[]{black},op=1); draw(A--B,dashed); draw(A--C,dashed); draw(B--C,dashed); draw(A--D,dashed); draw(B--D,dashed); draw(C--D,dashed); } //trace une pyramide de sommet S et de base ABCD void pyramide(triple A,triple B,triple C,triple D, triple S, pen sty=currentpen){ path3 f1=A--B--C--D--cycle; path3 f2=A--B--S--cycle; path3 f3=B--C--S--cycle; path3 f4=C--D--S--cycle; path3 f5=D--A--S--cycle; polyhedron faces; faces.push(f1); faces.push(f2); faces.push(f3); faces.push(f4); faces.push(f5); polyhedron[] parr={faces}; filldraw(parr,new pen[]{white},new pen[]{black},op=1); draw(A--B,dashed); draw(B--C,dashed); draw(C--D,dashed); draw(D--A,dashed); draw(S--A,dashed); draw(S--B,dashed); draw(S--C,dashed); draw(S--D,dashed); } //trace un pavé de sommet à partir du point A et de dimensions L*l*h //renvoie les sommets du pavé. triple[] pave(triple A,real L, real p,real h,pen sty=currentpen){ triple[] som; som[0]=A; som[1]=A+(0,0,h); som[2]=A+(0,L,h); som[3]=A+(0,L,0); som[4]=som[3]+(p,0,0); som[5]=som[2]+(p,0,0); som[6]=som[1]+(p,0,0); som[7]=som[0]+(p,0,0); path3 f1=som[0]--som[3]--som[4]--som[7]--cycle; path3 f2=som[0]--som[1]--som[2]--som[3]--cycle; path3 f5=som[0]--som[7]--som[6]--som[1]--cycle; path3 f3=shift(0,L,0)*f5; path3 f4=shift(p,0,0)*f2; path3 f6=shift(0,0,h)*f1; polyhedron pave; pave.push(f1); pave.push(f2); pave.push(f3); pave.push(f4); pave.push(f5); pave.push(f6); polyhedron[] parr={pave}; filldraw(parr,new pen[]{white},new pen[]{black},op=1); draw(som[0]--som[1],dashed); draw(som[1]--som[2],dashed); draw(som[2]--som[3],dashed); draw(som[3]--som[4],dashed); draw(som[4]--som[5],dashed); draw(som[5]--som[6],dashed); draw(som[6]--som[7],dashed); draw(som[7]--som[0],dashed); draw(som[5]--som[2],dashed); draw(som[7]--som[4],dashed); draw(som[6]--som[1],dashed); draw(som[0]--som[3],dashed); return som; } //trace un prisme de base ABC et de hauteur h //renvoie les sommets du prisme. triple[] prisme(triple A, triple B, triple C,real h,pen sty=currentpen){ triple[] som; triple n; n=cross(B-A,C-A)/abs(cross(B-A,C-A)); som[0]=A; som[1]=B; som[2]=C; som[3]=C+h*n; som[4]=B+h*n; som[5]=A+h*n; path3 f1=som[0]--som[1]--som[2]--cycle; path3 f2=som[3]--som[4]--som[5]--cycle; path3 f3=som[0]--som[2]--som[3]--som[5]--cycle; path3 f4=som[3]--som[4]--som[1]--som[2]--cycle; path3 f5=som[0]--som[1]--som[4]--som[5]--cycle; polyhedron faces; faces.push(f1); faces.push(f2); faces.push(f3); faces.push(f4); faces.push(f5); polyhedron[] parr={faces}; filldraw(parr,new pen[]{white},new pen[]{black},op=1); draw(som[0]--som[1],dashed); draw(som[1]--som[2],dashed); draw(som[2]--som[3],dashed); draw(som[3]--som[4],dashed); draw(som[4]--som[5],dashed); draw(som[5]--som[3],dashed); draw(som[5]--som[0],dashed); draw(som[0]--som[2],dashed); draw(som[1]--som[4],dashed); return som; } //trace un prisme de base ABCDE et de hauteur h //renvoie les sommets du prisme. triple[] prisme5(triple A, triple B, triple C, triple D, triple E,real h,pen sty=currentpen){ triple[] som; triple n; n=cross(B-A,E-A)/abs(cross(B-A,E-A)); som[0]=A; som[1]=B; som[2]=C; som[3]=D; som[4]=E; som[5]=E+h*n; som[6]=D+h*n; som[7]=C+h*n; som[8]=B+h*n; som[9]=A+h*n; path3 f1=som[0]--som[1]--som[2]--som[3]--som[4]--cycle; path3 f2=som[5]--som[6]--som[7]--som[8]--som[9]--cycle; path3 f3=som[0]--som[1]--som[8]--som[9]--cycle; path3 f4=som[1]--som[2]--som[7]--som[8]--cycle; path3 f5=som[2]--som[7]--som[6]--som[3]--cycle; path3 f6=som[4]--som[3]--som[6]--som[5]--cycle; path3 f7=som[0]--som[9]--som[5]--som[4]--cycle; polyhedron faces; faces.push(f1); faces.push(f2); faces.push(f3); faces.push(f4); faces.push(f5); faces.push(f6); faces.push(f7); polyhedron[] parr={faces}; filldraw(parr,new pen[]{white},new pen[]{black},op=1); draw(som[0]--som[1],dashed); draw(som[1]--som[2],dashed); draw(som[2]--som[3],dashed); draw(som[3]--som[4],dashed); draw(som[4]--som[5],dashed); draw(som[5]--som[6],dashed); draw(som[6]--som[7],dashed); draw(som[7]--som[8],dashed); draw(som[8]--som[9],dashed); draw(som[9]--som[5],dashed); draw(som[0]--som[4],dashed); draw(som[0]--som[9],dashed); draw(som[1]--som[8],dashed); draw(som[2]--som[7],dashed); draw(som[3]--som[6],dashed); return som; } //trace un prisme de base ABCD et de hauteur h //renvoie les sommets du prisme. triple[] prisme4(triple A, triple B, triple C, triple D,real h,pen sty=currentpen){ triple[] som; triple n; n=cross(B-A,D-A)/abs(cross(B-A,D-A)); som[0]=A; som[1]=B; som[2]=C; som[3]=D; som[4]=D+h*n; som[5]=C+h*n; som[6]=B+h*n; som[7]=A+h*n; path3 f1=som[0]--som[1]--som[2]--som[3]--cycle; path3 f2=som[4]--som[5]--som[6]--som[7]--cycle; path3 f3=som[0]--som[1]--som[6]--som[7]--cycle; path3 f4=som[1]--som[2]--som[5]--som[6]--cycle; path3 f5=som[2]--som[3]--som[4]--som[5]--cycle; path3 f6=som[3]--som[4]--som[7]--som[0]--cycle; polyhedron faces; faces.push(f1); faces.push(f2); faces.push(f3); faces.push(f4); faces.push(f5); faces.push(f6); polyhedron[] parr={faces}; filldraw(parr,new pen[]{white},new pen[]{black},op=1); draw(som[0]--som[1],dashed); draw(som[1]--som[2],dashed); draw(som[2]--som[3],dashed); draw(som[3]--som[4],dashed); draw(som[4]--som[5],dashed); draw(som[5]--som[6],dashed); draw(som[6]--som[7],dashed); draw(som[7]--som[4],dashed); draw(som[7]--som[0],dashed); draw(som[2]--som[5],dashed); draw(som[1]--som[6],dashed); draw(som[3]--som[0],dashed); return som; } //trace le cylindre de centre O, de rayon R, de hauteur h et d'axe axe Z par défaut; void cylindre(triple O, real r, real h,triple axe=Z, pen sty=currentpen){ revolution r=cylinder(O,r,h,axe); r.draw(sty); } //trace le cône de centre O, de rayon R, de hauteur h et d'axe axe Z par défaut; void conerevolution(triple O, real r, real h,triple axe=Z, pen sty=currentpen){ revolution r=cone(O,r,h,axe); r.draw(sty); } //remplis avec des hachures espacées de espace mm, avec un angle de angle ° le chemin fermé p void hachurage(path p,real espace, real angle, pen pen=currentpen){ add("hachure",hatch(espace,dir(angle),pen)); fill(p,pattern("hachure")); } //trace une flèche de cotation de A à B à d mm audessus du segment avec le texte au dessus. void cote(pair A,pair B, string texte, real d,pen sty=black){ draw(Label(texte,Rotate(-dir(B--A))),B+d/10*dir(degrees(B-A)+90)--A+d/10*dir(degrees(B-A)+90),Arrows(1.5mm),p=sty); } //trace une flèche de cotation de A à B à d mm audessus du segment avec le texte au milieu. void cotemilieu(pair A,pair B, string texte, real d,pen sty=black){ draw(Label(texte,align=Center,Rotate(-dir(B--A)),filltype=UnFill),B+d/10*dir(degrees(B-A)+90)--A+d/10*dir(degrees(B-A)+90),Arrows(1.5mm),p=sty); } //place le texte txt le long de p void etiquette(pair A, pair B, string txt,string direction="dessus",pen sty=currentpen){ if (direction=="dessus"){ label(rotate(degrees(B-A))*txt,0.5*B+0.5*A,dir(degrees(B-A)+90),sty); } else { label(rotate(degrees(B-A))*txt,0.5*B+0.5*A,dir(degrees(B-A)-90),sty); } } //retourne le segment [AB] qui peut dépasser de a cm path segment(pair A, pair B,real a=0){ path segment; segment=a*unit(A-B)+A--B+a*unit(B-A); return segment; } //retourne le milieu de [A,B]. triple milieu(triple A, triple B){ return 0.5(A+B); } //code le milieu du segment [A,B] void codemilieu(triple A, triple B, int trait){ if(trait < 4) { draw(A--milieu(A,B),StickIntervalMarker(1,n=trait,angle=-30,size=3mm,space=1mm)); draw(milieu(A,B)--B,StickIntervalMarker(1,n=trait,angle=-30,size=3mm,space=1mm)); } else {if(trait ==4) { draw(A--milieu(A,B),TildeIntervalMarker(i=1,size=3mm)); draw(milieu(A,B)--B,TildeIntervalMarker(i=1,size=3mm)); }else { draw(A--milieu(A,B),CircleBarIntervalMarker(1,n=0)); draw(milieu(A,B)--B,CircleBarIntervalMarker(1,n=0)); } } } //code les segments définis par le tableau triple[] K={A,B,C,...} avec trait traits void code(triple[] K,int trait){ if(trait < 4) { for(int i=0; i <=(K.length-2); i=i+2) { draw(K[i]--K[i+1],dashed,StickIntervalMarker(1,n=trait,angle=-30,size=3mm,space=1mm));} }else {if(trait ==4) { for(int i=0; i <=(K.length-2); i=i+2) { draw(K[i]--K[i+1],dashed,TildeIntervalMarker(i=1,size=3mm));} }else {for(int i=0; i <=(K.length-2); ++i) {draw(K[i]--K[i+1],dashed,CircleBarIntervalMarker(1,n=0));} } } } //code les angles avec des traits et un nombre nbarc d'arcs void codeangle(triple A,triple B, triple C,string txt="", int trait,int nbarc=1,pen sty=currentpen,real rayon=10mm ){ markangle(txt,n=nbarc,A,B,C,radius=rayon,marker(markinterval(stickframe(n=trait,p=sty),true)),p=sty); } //code les angles droits void angledroit(triple A,triple B, triple C,real taille=0.3, pen p=black){ triple u,v; u=unit(C-B); v=unit(A-B); if(dot(u,v)==0){ draw(B+taille*v--B+taille*(u+v)--B+taille*u,p); } } //renvoie le projeté de M orthogonal sur le plan passant par A,B et C triple projortho(triple M, triple A, triple B, triple C){ triple N,n,H; real a; n=cross(B-A,C-A); a=dot(n,A-M)/abs(n)^2; H=a*n+M; return H; } //renvoie l'intersection de de (MN) avec le plan passant par A,B et C triple intersectionDP(triple M,triple N, triple A, triple B, triple C){ triple n,d,I; real a; n=cross(B-A,C-A); d=N-M; a=dot(n,A-M)/dot(n,d); I=a*d+M; return I; } //renvoie l'intersection de (MN) avec le plan passant par A,B et C triple intersectionDD(triple M,triple N, triple A, triple B){ triple n,d,I; real a; n=cross(B-A,N-A); a=dot(n,M-B); if(a==0){ I=intersectionDP(M,N,A,B,B+n);} return I; } //retourne un point sur un chemin avec le paramètre r entre 0 et 1 triple pointsur(path3 chemin, real r) { return point(chemin,arctime(chemin,r*arclength(chemin))); } // renvoie un cercle de centre O et passant par A dans le plan EFG. path3 cercle(triple O, triple A, triple E, triple F, triple G){ triple n=cross(F-E,G-E); return circle(O,abs(A-O),n); } // renvoie un cercle de centre O et de rayon R le plan OAB. path3 cercleR(triple O, real R, triple A, triple B){ triple n=cross(A-O,B-O); return circle(O,R,n); }