Tracé d’une paramétrisation de la bouteille de Klein (mp-solid)

Auteur ou autrice : Christophe Poulain.

Mise en ligne le 20 janvier 2023

Image du résultat de l’exemple

Voici un tracé d’une paramétrisation de la bouteille de Klein (projection 3D de la surface 4D) (https://mathcurve.com/surfaces/klein/klein.shtml) avec le package mp-solid (https://syracuse.eu.org/syracuse/poulecl/mp-solid/).

L’exemple est extrait de la base MetaPost du site Syracuse : https://syracuse.eu.org/lab/bmp.

Code


input mp-solid

figureespace(-10u,-10u,10u,10u);
Initialisation(2000,-90,40,15);
incolor=0.5[bleu,white];
outcolor=0.5[orange,white];
draw Sparam("(6*cos(u)*(1+sin(u))+4*(1-cos(u)/2)*cos(v+pi),16*sin(u),4*(1-cos(u)/2)*sin(v))",0,2*pi,pi/24,0,2*pi,pi/24);
finespace;
end

Mots clés : 3Dmp-solidsyracusekleinsurface paramétrée

Cet exemple fait partie de la collection d’exemples Surfaces paramétrées (mp-solid).

Fichiers


klein-1.mp

277.00 B


klein-1.pdf

77.75 KB

Télécharger l’archive complète


klein-1.zip

850.82 KB

Fichiers auxiliaires

mp-solid.mp


%Le fichier spatial d'Anthony Phan m'a permis de mettre certaines choses au clair. ;-)
%v1
%14/08/2008
prologues:=2;

%Constantes
u:=1cm;
pi:=3.141592654;
c:=57.29578; % conversion d'un radian en degrs
color rouge,vert,bleu,jaune,noir,blanc,orange,rose,violet,ciel,cielfonce,orangevif,gris,marron;
rouge=(1,0,0);
bleu=(0,0,1);
noir=(0,0,0);
blanc=(1,1,1);
orange=(1,0.5,0);
violet=blanc-vert;
rose=(1,0.7,0.7);
cielfonce=0.9*(0.25,1,1);
ciel=bleu+vert;
orangevif=(1,0.25,0.1);
vert=(0,1,0);
jaune=blanc-bleu;
gris=0.8*white;

input format;
input marith;
input sarith;
%input donymodule;

input objets;

color Sommet[];

%Anthony Phan
vardef Norm primary z =
  abs (abs(Xpart z, Ypart z), Zpart z)
enddef;

let Xpart = redpart;
let Ypart = greenpart;
let Zpart = bluepart;
%

string typerepre,pointilles;
typerepre:="persp";

vardef Initialisation(expr r,t,p,d)=
  Rho:=r;
  Theta:=t;
  Phi:=p;
  DE:=d;
  Aux1:=sind(Theta);
  Aux2:=sind(Phi);
  Aux3:=cosd(Theta);
  Aux4:=cosd(Phi);
  Aux5:=Aux3*Aux2;
  Aux6:=Aux1*Aux2;
  Aux7:=Aux3*Aux4;
  Aux8:=Aux1*Aux4;
  pointilles:="oui";
  Lumiere:=Oeil;
enddef;

vardef Oeil=(Rho*Aux7,Rho*Aux8,Rho*Aux2)
enddef;

vardef sin(expr t) = sind(c*t) enddef;

vardef cos(expr t) = cosd(c*t) enddef;

vardef tan(expr t) = sin(t)/cos(t) enddef;

vardef exp(expr x) = mexp(256)**x enddef;

vardef Exp primary x = mexp(256)**x enddef;

vardef ln(expr t) = mlog(t)/256 enddef;

vardef log(expr t) = ln(t)/ln(10) enddef;

vardef ch(expr x)=(exp(x)+exp (-x))/2 enddef;

vardef sh(expr x)=(exp(x)-exp(-x))/2 enddef;

vardef th(expr x)=sh(x)/ch(x) enddef;

vardef arcsin(expr x)=%Dfinition mathmatique en radian
  pi*angle((sqrt(1-x**2),x))/180
enddef;

vardef arccos(expr x)=%Dfinition mathmatique en radian
  pi*angle((x,sqrt(1-x**2)))/180
enddef;

vardef arctan(expr x)=arcsin(x/(1++x))
enddef;

numeric satu,lum;
satu:=0.45;
lum:=1;

%Coordonnes dans le repre Oeil
vardef GCoord(expr N)=
  (-Xpart(N)*Aux1+Ypart(N)*Aux3,-Xpart(N)*Aux5-Ypart(N)*Aux6+Zpart(N)*Aux4,-Xpart(N)*Aux7-Ypart(N)*Aux8-Zpart(N)*Aux2+Rho)
enddef;

unit:=1;%pour les mises  l'chelle :) Merci pst-solides3d

vardef Projette(expr M)=
  %if typerepre="proj":
  %  unit*(DE*(Xpart(GCoord(M)/Zpart(GCoord(M))),(Ypart(GCoord(M))/Zpart(GCoord(M)))))
  %elseif typerepre="persp":
    unit*(DE*(Xpart(GCoord(M)),Ypart(GCoord(M))))
  %fi
enddef;

vardef TraceAxes=
  color Origine,Unitex,Unitey,Unitez;
  Origine=(0,0,0);
  Unitex=(5,0,0);
  Unitey=(0,5,0);
  Unitez=(0,0,5);
  drawoptions(dashed dashpattern(on 12bp off 6bp on 3bp off 6bp));
  drawarrow Projette(Origine)--Projette(Unitex) withcolor blue;
  drawarrow Projette(Origine)--Projette(Unitey) withcolor vert;
  drawarrow Projette(Origine)--Projette(Unitez);
  drawoptions();
enddef;

vardef TraceAxesD(expr xd,yd,zd)=
  drawoptions(dashed dashpattern(on12bp off6bp on3bp off6bp));;
  drawarrow Projette((0,0,0))--Projette((xd,0,0));
  drawarrow Projette((0,0,0))--Projette((0,yd,0));
  drawarrow Projette((0,0,0))--Projette((0,0,zd));
  drawoptions();
  label(btex $x$ etex,Projette((xd+0.3,0,0)));
  label(btex $y$ etex,Projette((0,yd+0.3,0)));
  label(btex $z$ etex,Projette((0,0,zd+0.3)));
enddef;

vardef TraceAxesDD(expr xd,yd,zd,xf,yf,zf)=
  drawoptions(dashed evenly);
  draw Projette((0,0,0))--Projette((xd,0,0));
  draw Projette((0,0,0))--Projette((0,yd,0));
  draw Projette((0,0,0))--Projette((0,0,zd));
  drawoptions();
  drawarrow Projette((xd,0,0))--Projette((xf,0,0));
  drawarrow Projette((0,yd,0))--Projette((0,yf,0));
  drawarrow Projette((0,0,zd))--Projette((0,0,zf));
  label(btex $x$ etex,Projette((xf+0.3,0,0)));
  label(btex $y$ etex,Projette((0,yf+0.3,0)));
  label(btex $z$ etex,Projette((0,0,zf+0.3)));
enddef;

vardef TraceGrille(expr NB)=
  color ppt[];
  for k=0 upto NB:
    ppt[k]:=(k,0,0);
    draw Projette(ppt[k]+(0,0,NB))--Projette(ppt[k])--Projette(ppt[k]+(0,NB,0));
    ppt[k]:=(0,k,0);
    draw Projette(ppt[k]+(NB,0,0))--Projette(ppt[k])--Projette(ppt[k]+(0,0,NB));
    ppt[k]:=(0,0,k);
    draw Projette(ppt[k]+(NB,0,0))--Projette(ppt[k])--Projette(ppt[k]+(0,NB,0));
  endfor;
enddef;

primarydef u Vectprod v =
  (Ypart u * Zpart v - Zpart u * Ypart v,
    Zpart u * Xpart v - Xpart u * Zpart v,
    Xpart u * Ypart v - Ypart u * Xpart v)
enddef;

vardef Normal(expr vecun,vecde,vectr)=
  save aa;
  color aa;
  P1:=redpart(vecde-vecun);
  P2:=greenpart(vecde-vecun);
  P3:=bluepart(vecde-vecun);
  Q1:=redpart(vectr-vecun);
  Q2:=greenpart(vectr-vecun);
  Q3:=bluepart(vectr-vecun);
  aa=(P2*Q3-Q2*P3,P3*Q1-Q3*P1,P1*Q2-Q1*P2);
  aa
enddef;

vardef ProduitScalaire(expr wec,mor)=
  %Mexp(Mlog redpart(wec) Mmul Mlog redpart(mor))+Mexp(Mlog greenpart(wec) Mmul Mlog greenpart(mor))+Mexp(Mlog bluepart(wec) Mmul Mlog bluepart(mor))
  Xpart(wec)*Xpart(mor)+Ypart(wec)*Ypart(mor)+Zpart(wec)*Zpart(mor)
enddef;
%pour les rotations et translations

vardef RotX(expr ptx)=
  (Xpart(ptx),Ypart(ptx)*cosd(angx)-Zpart(ptx)*sind(angx),Ypart(ptx)*sind(angx)+Zpart(ptx)*cosd(angx))
enddef;

vardef RotY(expr ptx)=
  (Xpart(ptx)*cosd(angy)+Zpart(ptx)*sind(angy),Ypart(ptx),-Xpart(ptx)*sind(angy)+Zpart(ptx)*cosd(angy))
enddef;

vardef RotZ(expr ptx)=
  (Xpart(ptx)*cosd(angz)-Ypart(ptx)*sind(angz),Xpart(ptx)*sind(angz)+Ypart(ptx)*cosd(angz),Zpart(ptx))
enddef;

vardef RotXYZ(expr ptx)=
  RotZ(RotY(RotX(ptx)))
enddef;

angx:=0;
angy:=0;
angz:=0;
color TR;
TR:=(0,0,0);
%pour les tubes
vardef VT(expr t)=Fp(t)/Norm(Fp(t))
enddef;

vardef VN(expr t)=Fd(t)/Norm(Fd(t))
enddef;

vardef VBN(expr t)=VT(t) Vectprod VN(t)
enddef;

path feuillet;
numeric _tfig,_nfig;
pair coinbg,coinbd,coinhd,coinhg;
_nfig:=0;

def feuille(expr xa,ya,xb,yb) =
  feuillet := (xa,ya)--(xa,yb)--(xb,yb)--(xb,ya)--cycle;
  coinbg := (xa,ya);
  coinbd := (xb,ya);
  coinhd := (xb,yb);
  coinhg := (xa,yb);
  %modifi le 29.09.04
  z.so=(xpart(coinbg/1cm),ypart(coinbg/1cm));
  z.ne=(xpart(coinhd/1cm),ypart(coinhd/1cm));
  %fin modification
  extra_endfig := "clip currentpicture to feuillet;" & extra_endfig;
enddef;

def figureespace(expr xa,ya,xb,yb) =
  _nfig:=_nfig+1;
  beginfig(_nfig);
    feuille(xa,ya,xb,yb);
    _tfig:= if (xb-xa)>(yb-ya): xb-xa else: yb-ya fi;
        _tfig:=2*_tfig;
enddef; 

def finespace=
endfig;
enddef;

def QS(expr ndeb,nfin)=
  begingroup
    save v,m,x;
    if ndeb<nfin:
      v:=ALT[cpt[ndeb]];
      m:=ndeb;
      for i=(ndeb+1) upto nfin:
	if ALT[cpt[i]]<v:
	  m:=m+1;
	  x:=cpt[m];cpt[m]:=cpt[i];cpt[i]:=x;
	fi
      endfor;
      x:=cpt[m];cpt[m]:=cpt[ndeb];cpt[ndeb]:=x;
      QS(ndeb,m-1);
      QS(m+1,nfin);
    fi
  endgroup
enddef;

boolean Pointilles;
Pointilles:=false;

boolean Vue[];
color Fc[].iso;
boolean Creux;
Creux:=false;

vardef DessineObjetNew=
  numeric ALT[];
  %on dtermine les zmax dans le repre spatial de l'cran
  for k=1 upto apj:
    Fc[k].iso:=(0,0,0) for l=1 upto ns[k][0]:
      +Fc[k][l]
    endfor;
    Fc[k].iso:=Fc[k].iso/ns[k][0];
  endfor;
  for k=1 upto apj:
    %ALT[k]=-Zpart(GCoord(Fc[k].iso));
    zmax:=infinity;
    for l=1 upto ns[k][0]:
      t:=-Zpart(GCoord(Fc[k][l]));
      if t<zmax:
	zmax:=t;
      fi;
    endfor;
    ALT[k]=zmax;
    cpt[k]:=k;
  endfor;
  %On trie suivant les zmax
  QS(1,apj);
  %On dessine
  if Pointilles:
    for k=1 upto apj:
      draw for l=1 upto ns[cpt[k]][0]:
	Projette(Fc[cpt[k]][l])--
      endfor
      cycle if Vue[cpt[k]]=false: dashed evenly fi;
    endfor;
  else:
    for k=1 upto apj:
      if Creux=false:
	if Vue[cpt[k]]:
	  fill for l=1 upto ns[cpt[k]][0]:
	    Projette(Fc[cpt[k]][l])--
	  endfor
	  cycle withcolor
	  if arcenciel:
	    lumin(cpt[k])*Hsvtorgb(((cpt[k]/apj)*360,satu,lum))
	  else:
	    lumin(cpt[k])*outcolor
	  fi;
	  if traits:
	    draw for l=1 upto ns[cpt[k]][0]:
	      Projette(Fc[cpt[k]][l])--
	    endfor
	    cycle;
	  fi;
	fi;
      else:
	fill for l=1 upto ns[cpt[k]][0]:
	  Projette(Fc[cpt[k]][l])--
	endfor
	cycle withcolor
	if Vue[cpt[k]]:
	  if arcenciel:
	    lumin(cpt[k])*Hsvtorgb(((cpt[k]/apj)*360,satu,lum))
	  else:
	    lumin(cpt[k])*outcolor
	  fi
	else:
	  lumin(cpt[k])*incolor
	fi;
	if traits:
	  draw for l=1 upto ns[cpt[k]][0]:
	    Projette(Fc[cpt[k]][l])--
	  endfor
	  cycle;
	fi;
      fi;
    endfor;
  fi;
enddef;

color Fc[][];%reprsente les sommets des diffrentes faces;

invnormale=1;%Parfois dans la lecture des fichiers OFF, il est ncessaire d'opposer la normale pour obtenir un bon intrieur-extrieur
boolean OFF,OBJ;%pour utiliser la lumire "correctement"
OFF:=false;
OBJ:=false;

vardef LectureOFF(expr nomsolide)=
  OFF:=true;
  %Dtermination du nombre de sommets et de faces.
  string s_;
  s_=readfrom nomsolide;
  string ss[];
  if s_<>EOF:
    ss1 := loptok s_;
    t_ := if ss1="%": 0 else: 1 fi;
    forever:
      ss[incr t_] := loptok s_;
      exitif ss[t_]="";
    endfor
  else: false
  fi;
  NbS:=round(Mexp Mlog_str ss1);
  NF:=round(Mexp Mlog_str ss2);
  message("Il y a "&decimal(NbS)&" sommets.");
  message("Il y a "&decimal(NF)&" faces au total.");
  %Dtermination des coordonnes des sommets
  message("Cration des sommets.");
  s_:=readfrom nomsolide;
  if debut=0:
    for k=0 upto NbS-1:
      s_:=readfrom nomsolide;
      if s_<>EOF:
	ss1 := loptok s_;
	n_ := if ss1="%": 0 else: 1 fi;
	forever:
	  ss[incr n_] := loptok s_;
	  exitif ss[n_]="";
	endfor
      else: false
      fi;
      Sommet[k]:=(Mexp ((Mlog_str ss1) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss3) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss2) Mdiv (Mlog echelle)));
      %Sommet[k]:=(Mexp (Mlog_str ss1),Mexp (Mlog_str ss3),Mexp (Mlog_str ss2))/echelle;
      %Sommet[k]:=(Mexp (Mlog_str ss1)/echelle,Mexp (Mlog_str ss3)/echelle,Mexp (Mlog_str ss2)/echelle);
    endfor;
  else:
    for k=1 upto NbS:
      s_:=readfrom nomsolide;
      if s_<>EOF:
	ss1 := loptok s_;
	n_ := if ss1="%": 0 else: 1 fi;
	forever:
	  ss[incr n_] := loptok s_;
	  exitif ss[n_]="";
	endfor
      else: false
      fi;
      Sommet[k]:=(Mexp ((Mlog_str ss1) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss3) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss2) Mdiv (Mlog echelle)));
      %Sommet[k]:=(Mexp (Mlog_str ss1),Mexp (Mlog_str ss3),Mexp (Mlog_str ss2))/echelle;
      %Sommet[k]:=(Mexp (Mlog_str ss1)/echelle,Mexp (Mlog_str ss3)/echelle,Mexp (Mlog_str ss2)/echelle);
    endfor;
  fi;
  message("Cration des faces.");
  %Dtermination des faces
  apj:=0;color cc,dd;
  nbfvues:=0;
  for nf=-4000 upto (-4000+NF)-1:
    s_:=readfrom nomsolide;
     if s_<>EOF:
      ss1 := loptok s_;
      n_ := if ss1="%": 0 else: 1 fi;
      forever:
	ss[incr n_] := loptok s_;
	exitif ss[n_]="";
      endfor
    else: false
    fi;
    apj:=apj+1;
    ns[apj][0]:=Mexp Mlog_str ss1;%pour savoir le nb de sommets par face
    for nl=1 upto ns[apj][0]:
      Fc[apj][nl]:=Sommet[round(Mexp Mlog_str ss[nl+1])];
    endfor;
    dd:=Oeil-Fc[apj][1];
    cc:=invnormale*Normal(Fc[apj][1],Fc[apj][2],Fc[apj][3]);
    if (ProduitScalaire(dd,cc)>=0):
      Vue[apj]:=true;
      nbfvues:=nbfvues+1;
    else:
      if Creux=true:
	Vue[apj]:=false;
      else:
	apj:=apj-1;
      fi;
    fi;
  endfor;
  message("Faces vues dterminees : il y en a "&decimal(nbfvues)&".");
  closefrom nomsolide;
  DessineObjetNew;
enddef;

vardef LectureOBJ(expr nomfichier)=
  OBJ:=true;
  string s_;
  string ss[];
  nbss:=1;
  apj:=0;
  forever:
    s_:=readfrom nomfichier;
    if s_<>EOF:
      ss0 := loptok s_;
      if ss0="v":
	n_:=0;
	forever:
	  ss[incr n_] := loptok s_;
	  exitif ss[n_]="";
	endfor
	Sommet[nbss]:=(Mexp((Mlog_str ss1) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss3) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss2) Mdiv (Mlog echelle)));
	nbss:=incr nbss;
      elseif ss0="f":
	n_:=0;
	forever:
	  ss[incr n_] := loptok s_;
	  exitif ss[n_]="";
	endfor;
	ns[apj][0]:=n_-1;
	for k=1 upto ns[apj][0]:
	  if invnormale=1:
	    Fc[apj][ns[apj][0]-k+1] := Sommet[round(Mexp(Mlog_str ss[k]))]
	    %if unknown OTFc.@[apj][OTFc.@[apj].nb-k+1]:
	  %  show OTFc.@[apj][OTFc.@[apj].nb-k+1];
	  %fi;
	  else:
	    Fc[apj][k] := Sommet[round(Mexp(Mlog_str ss[k]))]
	    %if unknown OTFc.@[apj][k]:
	  %  show OTFc.@[apj][k];
	  %fi;
	  fi;
	endfor;
	if ProduitScalaire(Oeil-Fc[apj][1],Normal(Fc[apj][1],Fc[apj][2],Fc[apj][3]))>=0:
	  Vue[apj]:=true;
	  apj:=apj+1;
	else:
	  if Creux=true:
	    Vue[apj]:=false;
	    apj:=apj+1;
	  fi;
	fi;
      fi;
    fi;
    exitif s_=EOF;
  endfor;
  apj:=apj-1;
  closefrom nomfichier;
  DessineObjetNew
enddef;

nb:=8;

%tube
vardef Tube(expr Fn,dp,ds,rayon,tmin,nbp,pas)=%f,f',f'',rayon du tube,paramtre dpart,nb points, pas
  save _tube;
  picture _tube;
  scantokens("vardef F(expr t)="&Fn&" enddef;");
  scantokens("vardef Fp(expr t)="&dp&" enddef;");
  scantokens("vardef Fd(expr t)="&ds&" enddef;");
  color G[][];
%nb point sur le cercle
  NB:=nbp;%nb de pas
  for l=0 upto NB:
    for k=0 upto nb:
      G[l][k]=F(tmin+l*pas)+rayon*(cosd(k*(360/nb))*VN(tmin+l*pas)+sind(k*(360/nb))*VBN(tmin+l*pas));
    endfor;
  endfor;
  apj:=0;
  for l=0 upto (NB-1):
    for k=0 upto nb-1:
      apj:=apj+1;
      cpt[apj]:=apj;
      Fc[apj][1]:=G[l][k];
      Fc[apj][2]:=G[l][k+1];
      Fc[apj][3]:=G[l+1][k+1];
      Fc[apj][4]:=G[l+1][k];
      Fc[apj].iso:=(Fc[apj][1]+Fc[apj][2]+Fc[apj][3]+Fc[apj][4])/4;
      ALT[apj]:=-Zpart(GCoord(Fc[apj][1]));
    endfor;
  endfor;
  QS(1,apj);
  _tube=image(
    for k=1 upto apj:
      fill for l=1 upto 4:
	Projette(Fc[cpt[k]][l])--
      endfor
      cycle withcolor if arcenciel: lumin(cpt[k])*Hsvtorgb((floor((cpt[k]/apj)*360),satu,lum))
	else: lumin(cpt[k])*outcolor fi;
      draw for l=1 upto 4:
	Projette(Fc[cpt[k]][l])--
      endfor
      cycle withpen pencircle scaled0.25bp;
    endfor;
    );
  _tube
enddef;

%Tube new :)
%pour les tubes new :)
vardef T(expr t)=Fp(t)
enddef;

vardef VTn(expr t)=if Norm(T(t))=0:
    T(t)
  else:
    T(t)/Norm(T(t))
  fi
enddef;

vardef VNn(expr t)=
  save _VNBis,__VN;
  color _VNBis,__VN;
  __VN=T(t) Vectprod ((T(t+nn)-T(t-nn))/2);
  if __VN=(0,0,0):
    _VNBis=(0,0,1);
  else:
    __VN:=__VN/Norm(__VN);
    if ProduitScalaire(VNbisprec[t-nn],__VN)>0:
      _VNBis=__VN/Norm(__VN)
    else:
      _VNBis=-(__VN/Norm(__VN))
    fi;
  fi;
  VNbisprec[t]=_VNBis;
  _VNBis
enddef;

vardef VBNn(expr t)=VTn(t) Vectprod VNn(t)
enddef;

vardef Tuben(expr Fn,dp,rayon,tmin,nbp,pas)=%f,f',f'',rayon du tube,paramtre dpart,nb points, pas
  save _tuben;
  picture _tuben;
  scantokens("vardef F(expr t)="&Fn&" enddef;");
  scantokens("vardef Fp(expr t)="&dp&" enddef;");
  color G[][];
%nb point sur le cercle
  NB:=nbp;%nb de pas
  nn:=pas;
  %pour grer le "flip" aux points d'inflexion
  color VNbisprec[];
  VNbisprec[tmin-nn]=T(tmin-nn) Vectprod ((T(tmin)-T(tmin-2*nn))/2);
  %
  ang:=360/nb;
  for l=0 upto NB:
    for k=0 upto nb:
      G[l][k]=F(tmin+l*pas)+rayon*(cosd(k*ang)*VNn(tmin+l*pas)+sind(k*ang)*VBNn(tmin+l*pas));
    endfor;
  endfor;
  apj:=0;
  for l=0 upto (NB-1):
    for k=0 upto nb-1:
      apj:=apj+1;
      cpt[apj]:=apj;
      Fc[apj][1]:=G[l][k];
      Fc[apj][2]:=G[l][k+1];
      Fc[apj][3]:=G[l+1][k+1];
      Fc[apj][4]:=G[l+1][k];
      Fc[apj].iso:=(Fc[apj][1]+Fc[apj][2]+Fc[apj][3]+Fc[apj][4])/4;
      ALT[apj]:=-Zpart(GCoord(Fc[apj].iso));
    endfor;
  endfor;
  QS(1,apj);
  _tuben=image(
    for k=1 upto apj:
      fill for l=1 upto 4:
	Projette(Fc[cpt[k]][l])--
      endfor
      cycle withcolor if arcenciel: lumin(cpt[k])*Hsvtorgb((floor((cpt[k]/apj)*360),satu,lum))
	else: lumin(cpt[k])*outcolor fi;
      draw for l=1 upto 4:
	Projette(Fc[cpt[k]][l])--
      endfor
      cycle withpen pencircle scaled0.25bp;
    endfor;
    );
  _tuben
enddef;


vardef Fonction(expr fn,tmin,tmax,pas)=%fonction
  scantokens("vardef F(expr t)="&fn&" enddef;");
  save _f;
  path _f;
  _f=Projette(F(tmin))
  for k=tmin+pas step pas until tmax:
    --Projette(F(k))
  endfor;
  _f
enddef;

color outcolor,incolor,outcolorbis;

boolean Spar;
Spar:=false;

vardef Sparam(expr fn,umin,umax,upas,vmin,vmax,vpas)=%fonction
  Spar:=true;
  save _Sparam;
  scantokens("vardef Famille(expr u,v)="&fn&" enddef;");
  apj:=0;
  picture _Sparam;
  %On cre les facettes et on calcule la profondeur en Z.
  for k=umin step upas until umax:
    for l=vmin step vpas until vmax:
      apj:=apj+1;
      cpt[apj]:=apj;
      Fc[apj][1]:=Image(Famille(k+upas,l));
      Fc[apj][2]:=Image(Famille(k,l));
      Fc[apj][3]:=Image(Famille(k,l+vpas));
      Fc[apj][4]:=Image(Famille(k+upas,l+vpas));
      Fc[apj].iso:=(Fc[apj][1]+Fc[apj][3])/2;%(Fc[apj][1]+Fc[apj][2]+Fc[apj][3]+Fc[apj][4])/4;
      ALT[apj]:=-Zpart(GCoord(Fc[apj].iso));
      if ProduitScalaire(Oeil-Fc[apj].iso,invnormale*Normal(Fc[apj].iso,Fc[apj][1],Fc[apj][2]))>=0:
	Vue[apj]:=true
      else:
	Vue[apj]:=false
      fi;
    endfor;
  endfor;
  %On range les faces par un QS en fonction de leur profondeur
  QS(1,apj);
  %On affiche toutes les faces par ordre dcroissant de profondeur.
  _Sparam=image(
    for k=1 upto apj:
      fill for l=1 upto 4:
	Projette(Fc[cpt[k]][l])--
      endfor
      cycle withcolor if Vue[cpt[k]]:
	if arcenciel: lumin(cpt[k])*Hsvtorgb((floor((cpt[k]/apj)*360),satu,lum))
	else: lumin(cpt[k])*outcolor fi
      else:lumin(cpt[k])*incolor fi;
      if traits=true:
	draw for l=1 upto 4:
	    Projette(Fc[cpt[k]][l])--
	endfor
	cycle;
      else:
	draw for l=1 upto 4:
	    Projette(Fc[cpt[k]][l])--
	endfor
	cycle withcolor if Vue[cpt[k]]:
	    if arcenciel: lumin(cpt[k])*Hsvtorgb((floor((cpt[k]/apj)*360),satu,lum))
	  else: lumin(cpt[k])*outcolor fi
	else:lumin(cpt[k])*incolor fi;
      fi;
    endfor;
    );
  Spar:=false;
  _Sparam
enddef;

vardef Revolution(expr fn,umin,umax,upas,vmin,vmax,vpas)=
  Sparam("(xpart(point(u) of "&fn&")*cos(v),xpart(point(u) of "&fn&")*sin(v),ypart(point(u) of "&fn&"))",umin,umax,upas,vmin,vmax,vpas)
enddef;

boolean traits;%sur une ide d'Herbert Voss  propos de pst-solides :)
%sert  dsactiver le tracer des traits
%15/07/08:pour l'instant implanter uniquement pour les surfaces en z
traits=true;

boolean arcenciel;%pour essayer d'obtenir des dgrads tels que pst-solides :)
arcenciel=false;

boolean surfz;
surfz:=false;
boolean couleurz;
couleurz=false;
color cz[];
boolean Mcir;
Mcir:=false;
rayd:=0;%sauf si division par 0 :(
%ajout de angtotal et angd pour les cas dans les diffrents cadrans
angtotal:=360;
angd:=0;

vardef SurfZ(text t_)=
  surfz:=true;
  save _SurfZ;
  picture _SurfZ;
  color alt[];
  nbargument:=0;
  for p_=t_ :
    if string p_:
      scantokens("vardef Fz(expr X,Y)="&p_&" enddef;");
    else:
      nbargument:=nbargument+1;
      NN[nbargument]:=p_;
    fi;
  endfor;
  apj:=0;sign:=0;
  Zmax:=-infinity;
  Zmin:=infinity;
  if nbargument=6:
    xmin:=NN1;
    xmax:=NN2;
    ymin:=NN3;
    ymax:=NN4;
    nblignes:=NN5;
    nbpoints:=NN6;
    IncX:=(xmax-xmin)/nbpoints;
    IncY:=(ymax-ymin)/nblignes;
    color Yc[][],Xc[][],Fc[][];
    for ligne=0 upto nblignes:
      y:=ymax-ligne*IncY;
      x:=xmin;
      Yc[ligne][0]=(x,y,Fz(x,y));
      for k=1 upto nbpoints:
	Yc[ligne][k]=((xmin+k*IncX,y,Fz(xmin+k*IncX,y)));
      endfor;
    endfor;
    for k=0 upto (nblignes-1):
      for l=0 step 3 until (nbpoints-3):
	apj:=apj+1;
	cpt[apj]:=apj;
	Fc[apj][1]:=Yc[k][l];
	Fc[apj][2]:=Yc[k][l+3];
	Fc[apj][3]:=Yc[k+1][l+3];
	Fc[apj][4]:=Yc[k+1][l];
	Fc[apj].iso:=(Fc[apj][1]+Fc[apj][2]+Fc[apj][3]+Fc[apj][4])/4;
	ALT[apj]:=-Zpart(GCoord(Fc[apj].iso));
	if Zpart(Fc[apj].iso)>Zmax:
	  Zmax:=Zpart(Fc[apj].iso);
	fi;
	if Zpart(Fc[apj].iso)<Zmin:
	  Zmin:=Zpart(Fc[apj].iso);
	fi;
	if ProduitScalaire(Oeil-Fc[apj].iso,Normal(Fc[apj].iso,Fc[apj][2],Fc[apj][1]))>=0:
	  Vue[apj]:=true;
	else:
	  Vue[apj]:=false
	fi;
      endfor;
    endfor;
  else:
    raymax:=NN1;
    pray:=NN2;
    nblignes:=NN3;
      for r=rayd step pray until (raymax-pray):
      for y=0 step 1 until (nblignes-1):
	apj:=apj+1;
	cpt[apj]:=apj;
	Fc[apj][1]:=(r*cosd(angd+y*(angtotal/nblignes)),r*sind(angd+y*(angtotal/nblignes)),Fz(r*cosd(angd+y*(angtotal/nblignes)),r*sind(angd+y*(angtotal/nblignes))));
	Fc[apj][2]:=(r*cosd(angd+(y+1)*(angtotal/nblignes)),r*sind(angd+(y+1)*(angtotal/nblignes)),Fz(r*cosd(angd+(y+1)*(angtotal/nblignes)),r*sind(angd+(y+1)*(angtotal/nblignes))));
	Fc[apj][3]:=((r+pray)*cosd(angd+(y+1)*(angtotal/nblignes)),(r+pray)*sind(angd+(y+1)*(angtotal/nblignes)),Fz((r+pray)*cosd(angd+(y+1)*(angtotal/nblignes)),(r+pray)*sind(angd+(y+1)*(angtotal/nblignes))));
	Fc[apj][4]:=((r+pray)*cosd(angd+y*(angtotal/nblignes)),(r+pray)*sind(angd+y*(angtotal/nblignes)),Fz((r+pray)*cosd(angd+y*(angtotal/nblignes)),(r+pray)*sind(angd+y*(angtotal/nblignes))));
	Fc[apj].iso:=(Fc[apj][1]+Fc[apj][2]+Fc[apj][3]+Fc[apj][4])/4;
	if Zpart(Fc[apj].iso)>Zmax:
	  Zmax:=Zpart(Fc[apj].iso);
	fi;
	if Zpart(Fc[apj].iso)<Zmin:
	  Zmin:=Zpart(Fc[apj].iso);
	fi;
	ALT[apj]:=-Zpart(GCoord(Fc[apj].iso));
	if ProduitScalaire(Oeil-Fc[apj].iso,Normal(Fc[apj].iso,Fc[apj][2],Fc[apj][1]))>=0:
	  Vue[apj]:=true;
	else:
	  Vue[apj]:=false
	fi;
      endfor;
    endfor;
  fi;
  %On range les faces par un QS en fonction de leur profondeur
  QS(1,apj);
  %On affiche toutes les faces par ordre dcroissant de profondeur.
  _SurfZ=image(
    pickup pencircle scaled 0.25bp;
    for k=1 upto apj:
      fill for l=1 upto 4:
	Projette(Fc[cpt[k]][l])--
      endfor
      cycle withcolor if couleurz:
	  if unknown cz1:Hsvtorgb((floor(((Zpart(Fc[cpt[k]].iso)-Zmin)/(Zmax-Zmin))*360),satu,lum))
	else:
	  ((Zpart(Fc[cpt[k]].iso)-Zmin)/(Zmax-Zmin))[cz2,cz1]
	fi;
      else:
	if Vue[cpt[k]]:
	  if arcenciel: lumin(cpt[k])*Hsvtorgb((floor((cpt[k]/apj)*360),satu,lum))
	  else:lumin(cpt[k])*outcolor fi
	else: lumin(cpt[k])*incolor fi;
	if traits=true:
	  draw for l=1 upto 4:
	      Projette(Fc[cpt[k]][l])--
	  endfor
	  cycle;
	fi;
      fi;
      if traits=true:
	draw for l=1 upto 4:
	    Projette(Fc[cpt[k]][l])--
	endfor
	cycle;
      fi;
    endfor;
    );
  surfz:=false;
  _SurfZ
enddef;

%Objet prdfinis
vardef ObjetCube(expr ar)=
  NbS:=8;
  Sommet1:=(ar,0,0);
  Sommet2:=(ar,ar,0);
  Sommet3:=(0,ar,0);
  Sommet4:=(0,0,0);
  Sommet5:=(0,0,ar);
  Sommet6:=(ar,0,ar);
  Sommet7:=(ar,ar,ar);
  Sommet8:=(0,ar,ar);
%%Faces
  NF:=6;
  ns[1][0]:=4;Fc[1][1]:=Sommet1;Fc[1][2]:=Sommet2;Fc[1][3]:=Sommet3;Fc[1][4]:=Sommet4;
  ns[2][0]:=4;Fc[2][1]:=Sommet4;Fc[2][2]:=Sommet3;Fc[2][3]:=Sommet8;Fc[2][4]:=Sommet5;
  ns[3][0]:=4;Fc[3][1]:=Sommet1;Fc[3][2]:=Sommet4;Fc[3][3]:=Sommet5;Fc[3][4]:=Sommet6;
  ns[4][0]:=4;Fc[4][1]:=Sommet5;Fc[4][2]:=Sommet8;Fc[4][3]:=Sommet7;Fc[4][4]:=Sommet6;
  ns[5][0]:=4;Fc[5][1]:=Sommet2;Fc[5][2]:=Sommet7;Fc[5][3]:=Sommet8;Fc[5][4]:=Sommet3;
  ns[6][0]:=4;Fc[6][1]:=Sommet1;Fc[6][2]:=Sommet6;Fc[6][3]:=Sommet7;Fc[6][4]:=Sommet2;
  %
  %Dtermination des faces
  apj:=0;color cc,dd;
  for nf=1 upto NF:
    apj:=apj+1;
    dd:=Oeil-Fc[nf][1];
    cc:=invnormale*Normal(Fc[nf][1],Fc[nf][2],Fc[nf][3]);
    if (ProduitScalaire(dd,cc)>=0):
      Vue[apj]=true
    else:
      Vue[apj]=false;
    fi;
  endfor;
enddef;

%coloriage et lumire
vardef Hsvtorgb(expr CC)=%CC couleur donne en hsv d'aprs http://en.wikipedia.org/wiki/HSL_color_space
  save $;
  color $;
  SSw:=floor(Xpart(CC)/60);
  SSh:=SSw mod 6;
  SSf:=(Xpart(CC)/60)-floor(SSw);
  SSs:=Ypart((CC));
  SSv:=Zpart((CC));
  SSp:=SSv*(1-SSs);
  SSq:=SSv*(1-SSf*SSs);
  SSt:=SSv*(1-(1-SSf)*SSs);
  if SSh=0: $=(SSv,SSt,SSp) elseif SSh=1:$=(SSq,SSv,SSp) elseif SSh=2:$=(SSp,SSv,SSt) elseif SSh=3:$=(SSp,SSq,SSv) elseif SSh=4:$=(SSt,SSp,SSv) elseif SSh=5:$=(SSv,SSp,SSq) fi;
  $
enddef;

marron=Hsvtorgb((60,1,0.3));

intensite:=2;
boolean eclairage;
eclairage:=true;

color Lumiere;

invnormalelum:=1;

vardef lumin(expr nbt)=
  save $;
  numeric $;
  if eclairage=false:
    $=1;
  else:
    color uu,vv;
    uu=Lumiere-Fc[nbt].iso;
    uu:=uu/Norm(uu);
    vv=invnormalelum*Normal(Fc[nbt].iso,Fc[nbt][1],Fc[nbt][2]);
    if Norm(vv)<>0:
      vv:=vv/Norm(vv)
    fi;
    if (surfz) or (Spar) or (OFF) or (OBJ):
      $=intensite*abs(ProduitScalaire(vv,uu))
    else:
      $=intensite*(ProduitScalaire(vv,uu));
    fi;
    if $>1:
      $:=1;
    fi;
  fi;
  $
enddef;


%%sucre

%%Transparence fait par Anthony Phan
picture alphapict_; alphapict_=nullpicture;
color fillcolor; fillcolor=gris;
fgalpha := 0.5; % usual alpha parameter
bgalpha:= 1; % alpha parameter with respect to the background

vardef transparence expr c =
  alphapict_ := nullpicture;
  alphafill_(currentpicture, c);
  addto currentpicture also alphapict_;
enddef;

def alphafill_(expr p, c) =
  begingroup
    save p_, xmax_, xmin_, ymax_, ymin_; picture p_;
    p_ = nullpicture;
    (xmin_, ymin_) = llcorner c; (xmax_, ymax_) = urcorner c;
    addto p_ contour c withcolor bgalpha[background, fillcolor];
    for p__ within p:
      numeric xmin__, xmax__, ymin__, ymax__;
      (xmin__, ymin__) = llcorner p__; (xmax__, ymax__) = urcorner p__;
      if (xmax__<= xmin_) or (xmin__ >= xmax_):
      else:
        if (ymax__<= ymin_) or (ymin__ >= ymax_):
        else:
          if (not clipped p__) and (not bounded p__):
            addto p_ also p__ withcolor
            fgalpha[(redpart p__, greenpart p__, bluepart p__),
            fillcolor];
          else:
            begingroup save alphapict_;
              picture alphapict_; alphapict_ = nullpicture;
              alphafill_(p__, pathpart p__);
              addto p_ also alphapict_;
            endgroup;
          fi
        fi
      fi
    endfor
    clip p_ to c;
    addto alphapict_ also p_;
  endgroup;
enddef;

endinput;

objets.mp


%24/01/2011
%Gestion des couleurs dans l'objet Deplacement.

%27/11/2010
%Manque plusieurs : dans la dfinition de ObjetNew

%07/02/2009
color OTFc[][][];%pour mmoriser les diffrents sommets de chaque objet;
color OTFc[][].iso;
color coul[][];%pour memoriser la couleur de chacune des faces de l'objet;
color Outcolor[],Incolor[];%Permet de grer la gestion des couleurs d'un objet lors d'un dplacement de cet objet
boolean Vue[][];

boolean creux;  creux=false;%pour grer les solides creux
boolean transformation; transformation=false;%pour grer les transformations
boolean Ferme[];%pour grer les faces : si le solide est ferm, toutes les faces non vues ne sont pas intgres aux calculs
boolean perso[];%pour grer les gestions personnelles des couleurs
for k=0 upto 100:
  perso[k]=false;
endfor;
boolean numeroteface;
numeroteface:=false;

string couleurperso;

defaultfont:="cmr5";

vardef Image(expr dep)=
  if transformation:
    Transform(dep)
  else:
    RotXYZ(dep)
  fi
  +TR
enddef;

boolean Transparence;
Transparence:=false;

vardef AffichageObjet[]=
  save _affi;
  picture _affi;
  color Fc[][];color cou[];
  tapj:=0;
  for k=0 upto apj.@:
    cpt[tapj]:=tapj;
    Fc[tapj].nb:=OTFc.@[k].nb;
    for l=1 upto Fc[tapj].nb:
      Fc[tapj][l]:=OTFc.@[k][l];
    endfor;
    Fc[tapj].iso:=OTFc.@[k].iso;
    cou[tapj]:=if perso.@:scantokens(couleurperso) else: coul.@[k] fi;
    ALT[tapj]:=ALT.@[k];
    Vue[tapj]:=Vue.@[k];
    tapj:=tapj+1;
  endfor;
  tapj:=tapj-1;
  QS(0,tapj);
  if Transparence :
    for k=0 upto tapj:
      if Vue[cpt[k]]=false:
	fill for l=1 upto Fc[cpt[k]].nb:
	  Projette(Fc[cpt[k]][l])--
	endfor
	cycle withcolor abs(lumin(cpt[k]))*cou[cpt[k]];
	if traits=true:
	  draw for l=1 upto Fc[cpt[k]].nb:
	    Projette(Fc[cpt[k]][l])--
	  endfor
	  cycle dashed evenly withpen pencircle scaled0.25bp;
	fi;
      fi;
    endfor;
    for k=0 upto tapj:
      if Vue[cpt[k]]:
	transparence for l=1 upto Fc[cpt[k]].nb:
	  Projette(Fc[cpt[k]][l])--
	endfor
	cycle;
	if traits=true:
	  draw for l=1 upto Fc[cpt[k]].nb:
	    Projette(Fc[cpt[k]][l])--
	  endfor
	  cycle withpen pencircle scaled0.25bp;
	fi;
      fi;
    endfor;
  else:
    if Ferme.@:
      for k=0 upto tapj:
	if Vue[cpt[k]]=true:
	  fill for l=1 upto Fc[cpt[k]].nb:
	    Projette(Fc[cpt[k]][l])--
	  endfor
	  cycle withcolor
	  if arcenciel=true:
	    lumin(cpt[k])*Hsvtorgb(((cpt[k]/tapj)*360,satu,lum))
	  else:
	    lumin(cpt[k])*cou[cpt[k]]
	  fi;
	  if traits:
	    draw for l=1 upto Fc[cpt[k]].nb:
	      Projette(Fc[cpt[k]][l])--
	    endfor
	    cycle withpen pencircle scaled0.25bp;
	    %add by cp 01/08/11
	  else:
	    draw for l=1 upto Fc[cpt[k]].nb:
	      Projette(Fc[cpt[k]][l])--
	    endfor
	    cycle withcolor
	      if arcenciel=true:
	      lumin(cpt[k])*Hsvtorgb(((cpt[k]/tapj)*360,satu,lum))
	    else:
	      lumin(cpt[k])*cou[cpt[k]]
	    fi;
	    %fin add
	  fi;
	fi;
      endfor;
    else:
      for k=0 upto tapj:%apj downto 1:
	fill for l=1 upto Fc[cpt[k]].nb:
	  Projette(Fc[cpt[k]][l])--
	endfor
	cycle withcolor if Vue[cpt[k]]:
	  if arcenciel: lumin(cpt[k])*Hsvtorgb(((cpt[k]/tapj)*360,satu,lum))
	  else:lumin(cpt[k])*cou[cpt[k]] fi
	else: abs(lumin(cpt[k]))*cou[cpt[k]] fi;
	if traits:
	  draw for l=1 upto Fc[cpt[k]].nb:
	    Projette(Fc[cpt[k]][l])--
	  endfor
	  cycle withpen pencircle scaled0.25bp;
	  %add by cp 01/08/2011
	else:
	  draw for l=1 upto Fc[cpt[k]].nb:
	      Projette(Fc[cpt[k]][l])--
	  endfor
	  cycle withcolor if Vue[cpt[k]]:
	      if arcenciel: lumin(cpt[k])*Hsvtorgb(((cpt[k]/tapj)*360,satu,lum))
	    else:lumin(cpt[k])*cou[cpt[k]] fi
	  else: abs(lumin(cpt[k]))*cou[cpt[k]] fi;
	  %fin add
	fi;
      endfor;
    fi;
  fi;
  if numeroteface=true:
    for k=0 upto tapj:
      if Vue[k]:
	label(""&decimal(k)&"",Projette(Fc[k].iso));
      fi;
    endfor;
  fi;
enddef;


vardef AffichageObjetold[]=
  save _affi;
  picture _affi;
  color Fc[][];color cou[];
  tapj:=0;
  for k=0 upto apj.@:
    cpt[tapj]:=tapj;
    Fc[tapj].nb:=OTFc.@[k].nb;
    for l=1 upto Fc[tapj].nb:
      Fc[tapj][l]:=OTFc.@[k][l];
    endfor;
    Fc[tapj].iso:=OTFc.@[k].iso;
    cou[tapj]:=if perso.@:scantokens(couleurperso) else: coul.@[k] fi;
    ALT[tapj]:=ALT.@[k];
    Vue[tapj]:=Vue.@[k];
    tapj:=tapj+1;
  endfor;
  tapj:=tapj-1;
  QS(0,tapj);
  if Ferme.@:
    for k=0 upto tapj:
      if Vue[cpt[k]]=true:
	fill for l=1 upto Fc[cpt[k]].nb:
	  Projette(Fc[cpt[k]][l])--
	endfor
	cycle withcolor
	if arcenciel=true:
	  lumin(cpt[k])*Hsvtorgb(((cpt[k]/tapj)*360,satu,lum))
	else:
	  lumin(cpt[k])*cou[cpt[k]]
	fi;
	draw for l=1 upto Fc[cpt[k]].nb:
	  Projette(Fc[cpt[k]][l])--
	endfor
	cycle withpen pencircle scaled0.25bp;
      fi;
    endfor;
  else:
    for k=0 upto tapj:%apj downto 1:
      fill for l=1 upto Fc[cpt[k]].nb:
	Projette(Fc[cpt[k]][l])--
      endfor
      cycle withcolor if Vue[cpt[k]]:
	if arcenciel: lumin(cpt[k])*Hsvtorgb(((cpt[k]/tapj)*360,satu,lum))
	else:lumin(cpt[k])*cou[cpt[k]] fi
      else: abs(lumin(cpt[k]))*cou[cpt[k]] fi;
      draw for l=1 upto Fc[cpt[k]].nb:
	Projette(Fc[cpt[k]][l])--
      endfor
      cycle withpen pencircle scaled0.25bp;
    endfor;
  fi;
  if numeroteface=true:
    for k=0 upto tapj:
      if Vue[k]:
	label(""&decimal(k)&"",Projette(Fc[k].iso));
      fi;
    endfor;
  fi;
enddef;

vardef DessineFusion=
  save _fusion;
  picture _fusion;
  tapj:=0;
  color Fc[][];color cou[];
  for l=1 upto nbobj:
    for k=0 upto apj[l]:
      cpt[tapj]:=tapj;
      cou[tapj]:=if perso[l]:scantokens(couleurperso) else: coul[l][k] fi;
      Fc[tapj].nb:=OTFc[l][k].nb;
      for p=1 upto Fc[tapj].nb:
	Fc[tapj][p]:=OTFc[l][k][p];
      endfor;
      Fc[tapj].iso:=OTFc[l][k].iso;
      ALT[tapj]:=ALT[l][k];
      Vue[tapj]:=Vue[l][k];
      if Ferme[l]:
	if Vue[tapj]=false:
	  tapj:=tapj-1;
	fi;
      fi;
      tapj:=tapj+1;
    endfor;
  endfor;
  tapj:=tapj-1;
  QS(0,tapj);
  for k=0 upto tapj:
    fill for l=1 upto Fc[cpt[k]].nb:
      Projette(Fc[cpt[k]][l])--
    endfor
    cycle withcolor if Vue[cpt[k]]:
      if arcenciel: lumin(cpt[k])*Hsvtorgb(((cpt[k]/tapj)*360,satu,lum))
      else:lumin(cpt[k])*cou[cpt[k]] fi
    else: abs(lumin(cpt[k]))*cou[cpt[k]] fi;
    if traits:
      draw for l=1 upto Fc[cpt[k]].nb:
	Projette(Fc[cpt[k]][l])--
      endfor
      cycle withpen pencircle scaled0.25bp;
      %add by cp 22/08/2011
	else:
	  draw for l=1 upto Fc[cpt[k]].nb:
	      Projette(Fc[cpt[k]][l])--
	  endfor
	  cycle withcolor if Vue[cpt[k]]:
	      if arcenciel: lumin(cpt[k])*Hsvtorgb(((cpt[k]/tapj)*360,satu,lum))
	    else:lumin(cpt[k])*cou[cpt[k]] fi
	  else: abs(lumin(cpt[k]))*cou[cpt[k]] fi;
	  %fin add
    fi;
  endfor;
enddef;

vardef Objettore[](expr Rn,rn)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  if creux:
    Ferme.@:=false
  else:
    Ferme.@:=true;
  fi;
  scantokens("numeric "&substring(0,1) of rn&"; "&rn&";");
  scantokens("numeric "&substring(0,1) of Rn&"; "&Rn&";");
  vardef Famille(expr u,v)=((R+r*cos(u))*cos(v),(R+r*cos(u))*sin(v),r*sin(u)) enddef;
  umin:=-pi; umax:=pi; upas:=2*pi/nb;
  vmin:=-pi; vpas:=2*pi/subh; vmax:=pi;
  apj:=0;
  %On cre les facettes et on calcule la profondeur en Z.
  for k=0 upto (nb-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Famille(umin+(k+1)*upas,vmin+l*vpas));
      OTFc.@[apj][2]:=Image(Famille(umin+k*upas,vmin+l*vpas));
      OTFc.@[apj][3]:=Image(Famille(umin+k*upas,vmin+(l+1)*vpas));
      OTFc.@[apj][4]:=Image(Famille(umin+(k+1)*upas,vmin+(l+1)*vpas));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=outcolor;
      else:
	Vue.@[apj]:=false;coul.@[apj]:=incolor;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

vardef ObjetTube[](expr Fn,dp,rayon,tmin,nbp,pas)=%f,f',f'',rayon du tube,paramtre dpart,nb points, pas
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("vardef F(expr t)="&Fn&" enddef;");
  scantokens("vardef Fp(expr t)="&dp&" enddef;");
  color G[][];
  NB:=nbp;%nb de pas
  nn:=pas;
  %pour grer le "flip" aux points d'inflexion
  color VNbisprec[];
  VNbisprec[tmin-nn]=T(tmin-nn) Vectprod ((T(tmin)-T(tmin-2*nn))/2);
  %
  ang:=360/nb;
  for l=0 upto NB:
    for k=0 upto nb:
      G[l][k]=F(tmin+l*pas)+rayon*(cosd(k*ang)*VNn(tmin+l*pas)+sind(k*ang)*VBNn(tmin+l*pas));
    endfor;
  endfor;
  apj:=0;
  if creux=false:
    Ferme.@:=true;
    nbsp:=nb;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=nbsp;
    for k=1 upto nbsp:
      OTFc.@[apj][k]:=Image(G[0][nbsp+1-k]);
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nbsp:+OTFc.@[apj][k] endfor)/nbsp;
    apj:=apj+1;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=nbsp;
    for k=nbsp downto 1:
      OTFc.@[apj][k]:=Image(G[NB][k]);
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nbsp:+OTFc.@[apj][k] endfor)/nbsp;
    apj:=apj+1;
  else:
    Ferme.@:=false;
  fi;
  for l=0 upto (NB-1):
    for k=0 upto nb-1:
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(G[l][k]);
      OTFc.@[apj][2]:=Image(G[l][k+1]);
      OTFc.@[apj][3]:=Image(G[l+1][k+1]);
      OTFc.@[apj][4]:=Image(G[l+1][k]);
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      apj:=apj+1;
    endfor;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

vardef ObjetCylindre[](expr fn,umin,umax,vmin,vmax)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("vardef Famille(expr u,v)="&fn&" enddef;");
  apj:=0;
  upas:=(umax-umin)/nb;vpas:=(vmax-vmin)/subh;
  %On cre les facettes et on calcule la profondeur en Z.
  %for k=umin step upas until umax:
  %  for l=vmin step vpas until vmax:
  for k=0 upto (nb-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Famille(umin+(k+1)*upas,vmin+l*vpas));
      OTFc.@[apj][2]:=Image(Famille(umin+k*upas,vmin+l*vpas));
      OTFc.@[apj][3]:=Image(Famille(umin+k*upas,vmin+(l+1)*vpas));
      OTFc.@[apj][4]:=Image(Famille(umin+(k+1)*upas,vmin+(l+1)*vpas));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=outcolor;
      else:
	Vue.@[apj]:=false;coul.@[apj]:=incolor;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

vardef Objetcylindre[](expr rn,hn)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("numeric "&substring(0,1) of rn&"; "&rn&";");
  scantokens("numeric "&substring(0,1) of hn&"; "&hn&";");
  vardef Famille(expr u,v)=(r*cos(u),r*sin(u),v) enddef;
  umin:=pi; umax:=-pi; upas:=-2*pi/nb;
  vmin:=0; vmax:=h; vpas:=h/subh;
  nbsp:=nb;
  apj:=0;
  if creux=false:
    Ferme.@:=true;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=nbsp;
    for k=1 upto nb:
      OTFc.@[apj][k]:=Image(Famille(umin+k*upas,vmin));
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nbsp:+OTFc.@[apj][k] endfor)/nbsp;
    apj:=apj+1;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=nbsp;
    for k=1 upto nbsp:
      OTFc.@[apj][k]:=Image(Famille(umin+(nbsp-k)*upas,vmax));
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nbsp:+OTFc.@[apj][k] endfor)/nbsp;
    apj:=apj+1;
  else:
    Ferme.@:=false;
  fi;
  %On cre les facettes et on calcule la profondeur en Z.
  for k=0 upto (nb-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Famille(umin+(k+1)*upas,vmin+l*vpas));
      OTFc.@[apj][2]:=Image((Famille(umin+k*upas,vmin+l*vpas)));
      OTFc.@[apj][3]:=Image((Famille(umin+k*upas,vmin+(l+1)*vpas)));
      OTFc.@[apj][4]:=Image(Famille(umin+(k+1)*upas,vmin+(l+1)*vpas));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      apj:=apj+1;
    endfor;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

vardef ObjetCone[](expr fn,umin,umax,zbas,orign)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("vardef Famille(expr u)="&fn&" enddef;");
  scantokens("color "&substring(0,4) of orign&"; "&orign&";");
  apj:=0;
  upas:=(umax-umin)/nb;vpas:=2*abs(zbas)/subh;
  %On cre les facettes et on calcule la profondeur en Z.
  for k=0 upto (nb-1):
    for l=0 upto (2*subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Famille(umin+(k+1)*upas)+(l/subh)[Famille(umin+(k+1)*upas),orig]-Famille(umin+(k+1)*upas));
      OTFc.@[apj][4]:=Image(Famille(umin+k*upas)+(l/subh)[Famille(umin+k*upas),orig]-Famille(umin+k*upas));
      OTFc.@[apj][3]:=Image(Famille(umin+k*upas)+((l+1)/subh)[Famille(umin+k*upas),orig]-Famille(umin+k*upas));
      OTFc.@[apj][2]:=Image(Famille(umin+(k+1)*upas)+((l+1)/subh)[Famille(umin+(k+1)*upas),orig]-Famille(umin+(k+1)*upas));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=outcolor;
      else:
	Vue.@[apj]:=false;coul.@[apj]:=incolor;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

subh:=12;

vardef Objetcone[](expr rn,hn)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("numeric "&substring(0,1) of rn&"; "&rn&";");
  scantokens("numeric "&substring(0,1) of hn&"; "&hn&";");
  vardef Famille(expr u,v)=(r*(1-(v/h))*cos(u),r*(1-(v/h))*sin(u),v) enddef;
  umin:=pi; umax:=-pi; upas:=-2*pi/nb;
  vmin:=0; vpas:=h/subh; vmax:=h-vpas;
  apj:=0;
  if creux=false:
    Ferme.@:=true;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=nb;
    for k=0 upto nb:
      OTFc.@[apj][k]:=Image(Famille(umin+k*upas,vmin));
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nb:+OTFc.@[apj][k] endfor)/nb;
    apj:=apj+1;
  else:
    Ferme.@:=false;
  fi;
  %On cre les facettes et on calcule la profondeur en Z.
  for k=0 upto (nb-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Famille(umin+(k+1)*upas,vmin+l*vpas));
      OTFc.@[apj][2]:=Image(Famille(umin+k*upas,vmin+l*vpas));
      OTFc.@[apj][3]:=Image(Famille(umin+k*upas,vmin+(l+1)*vpas));
      OTFc.@[apj][4]:=Image(Famille(umin+(k+1)*upas,vmin+(l+1)*vpas));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      apj:=apj+1;
    endfor;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

vardef Objettronccone[](expr rn,hn,Hn)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("numeric "&substring(0,1) of rn&"; "&rn&";");
  scantokens("numeric "&substring(0,1) of hn&"; "&hn&";");
  scantokens("numeric "&substring(0,1) of Hn&"; "&Hn&";");
  vardef Famille(expr u,v)=(r*(1-v/H)*cos(u),r*(1-v/H)*sin(u),v) enddef;
  umin:=pi; umax:=-pi; upas:=-2*pi/nb;
  vmin:=0; vpas:=h/subh; vmax:=h;
  apj:=0;
  if creux=false:
    Ferme.@:=true;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=nb;
    for k=0 upto nb:
      OTFc.@[apj][k]:=Image(Famille(umin+k*upas,vmin));
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nb:+OTFc.@[apj][k] endfor)/nb;
    apj:=apj+1;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=nb;
    for k=0 upto nb:
      OTFc.@[apj][nb-k]:=Image(Famille(umin+k*upas,vmax));
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nb:+OTFc.@[apj][k] endfor)/nb;
        apj:=apj+1;
  else:
    Ferme.@:=false;
  fi;
  %On cre les facettes et on calcule la profondeur en Z.
  for k=0 upto (nb-1):%umin step upas until umax-upas:
    for l=0 upto (subh-1):
       tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Famille(umin+(k+1)*upas,vmin+l*vpas));
      OTFc.@[apj][2]:=Image(Famille(umin+k*upas,vmin+l*vpas));
      OTFc.@[apj][3]:=Image(Famille(umin+k*upas,vmin+(l+1)*vpas));
      OTFc.@[apj][4]:=Image(Famille(umin+(k+1)*upas,vmin+(l+1)*vpas));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      apj:=apj+1;
    endfor;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

vardef Objetsphere[](expr Rn)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  if creux:Ferme.@:=false else: Ferme.@:=true fi;
  scantokens("numeric "&substring(0,1) of Rn&"; "&Rn&";");
  vardef Famille(expr u,v)=(R*(cos(u)*cos(v),cos(u)*sin(v),sin(u))) enddef;
  umin:=-pi/2; umax:=pi/2; upas:=pi/nb;
  vmin:=-pi; vpas:=2*pi/subh; vmax:=pi;
  apj:=0;
  %On cre les facettes et on calcule la profondeur en Z.
  for k=0 upto (nb-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Famille(umin+(k+1)*upas,vmin+l*vpas));
      OTFc.@[apj][2]:=Image(Famille(umin+k*upas,vmin+l*vpas));
      OTFc.@[apj][3]:=Image(Famille(umin+k*upas,vmin+(l+1)*vpas));
      OTFc.@[apj][4]:=Image(Famille(umin+(k+1)*upas,vmin+(l+1)*vpas));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=outcolor;
      else:
	Vue.@[apj]:=false;coul.@[apj]:=incolor;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

vardef Objetcalotte[](expr Rn,Phib,Phih)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("numeric "&substring(0,1) of Rn&"; "&Rn&";");
  scantokens("numeric "&substring(0,4) of Phib&"; "&Phib&";");
  scantokens("numeric "&substring(0,4) of Phih&"; "&Phih&";");
  vardef Famille(expr u,v)=(R*(cos(u)*cos(v),cos(u)*sin(v),sin(u))) enddef;
  umin:=phib; umax:=phih; upas:=(phih-phib)/nb;
  vmin:=-pi; vpas:=2*pi/subh; vmax:=pi;
  apj:=0;
  nbsp:=subh;
  if creux=false:
    Ferme.@:=true;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=nbsp;
    for l=1 upto nbsp:
      OTFc.@[apj][l]:=Image(Famille(umin,vmax-l*vpas));
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nbsp:+OTFc.@[apj][k] endfor)/nbsp;
    apj:=apj+1;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=subh;
    for l=1 upto nbsp:
      OTFc.@[apj][l]:=Image(Famille(umax,vmin+l*vpas));
     endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nbsp:+OTFc.@[apj][k] endfor)/nbsp;
    apj:=apj+1;
  else:
    Ferme.@:=false;
  fi;
  %On cre les facettes et on calcule la profondeur en Z.
  %for k=umin step upas until umax-upas:
  for k=0 upto (nb-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Famille(umin+(k+1)*upas,vmin+l*vpas));
      OTFc.@[apj][2]:=Image(Famille(umin+k*upas,vmin+l*vpas));
      OTFc.@[apj][3]:=Image(Famille(umin+k*upas,vmin+(l+1)*vpas));
      OTFc.@[apj][4]:=Image(Famille(umin+(k+1)*upas,vmin+(l+1)*vpas));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      apj:=apj+1;
    endfor;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

vardef Objetanneau[](expr Rn,rn,hn)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  if creux:Ferme.@:=false else:Ferme.@:=true fi;
  scantokens("numeric "&substring(0,1) of Rn&"; "&Rn&";");
  scantokens("numeric "&substring(0,1) of rn&"; "&rn&";");
  scantokens("numeric "&substring(0,1) of hn&"; "&hn&";");
  path sectionanneau;
  sectionanneau=(R,0)--(R,h)--(r,h)--(r,0)--cycle;
  vardef Famille(expr u,v)=((xpart(point(u) of sectionanneau)*cos(v),xpart(point(u) of sectionanneau)*sin(v),ypart(point(u) of sectionanneau))) enddef;
  umin:=0; umax:=4; upas:=4/nb;
  vmin:=-pi; vpas:=2*pi/subh; vmax:=2*pi;
  apj:=0;
  %On cre les facettes et on calcule la profondeur en Z.
  for k=0 upto (nb-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Famille(umin+(k+1)*upas,vmin+l*vpas));
      OTFc.@[apj][2]:=Image(Famille(umin+k*upas,vmin+l*vpas));
      OTFc.@[apj][3]:=Image(Famille(umin+k*upas,vmin+(l+1)*vpas));
      OTFc.@[apj][4]:=Image(Famille(umin+(k+1)*upas,vmin+(l+1)*vpas));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=outcolor;
      else:
	Vue.@[apj]:=false;coul.@[apj]:=incolor;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

vardef ObjetAnneau[](expr nbpn,sectionanneau)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("numeric "&substring(0,3) of nbpn&"; "&nbpn&";");
  vardef Famille(expr u,v)=((xpart(point(u) of sectionanneau)*cos(v),xpart(point(u) of sectionanneau)*sin(v),ypart(point(u) of sectionanneau))) enddef;
  umin:=0; umax:=nbp; upas:=1;
  vmin:=-pi; vpas:=2*pi/subh; vmax:=pi;
  apj:=0;
  %On cre les facettes et on calcule la profondeur en Z.
  for k=0 upto (nbp-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Famille(umin+(k+1)*upas,vmin+l*vpas));
      OTFc.@[apj][2]:=Image(Famille(umin+k*upas,vmin+l*vpas));
      OTFc.@[apj][3]:=Image(Famille(umin+k*upas,vmin+(l+1)*vpas));
      OTFc.@[apj][4]:=Image(Famille(umin+(k+1)*upas,vmin+(l+1)*vpas));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=outcolor;
      else:
	Vue.@[apj]:=false;coul.@[apj]:=incolor;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

vardef ObjetPrisme[](expr axen,hn)(text tn)=%pb avec certaines positions de l'observateur.->maillage vertical
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("numeric "&substring(0,1) of hn&"; "&hn&";");
  scantokens("color "&substring(0,3) of axen&"; "&axen&";");
  nbsn:=0;%nb sommets total pour la base
  for _p=tn:
    Sommet[nbsn]:=_p;
    nbsn:=nbsn+1;
  endfor;
  apj:=0;
  if creux=false:
    Ferme.@:=true;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=nbsn;
    for k=1 upto nbsn:
      OTFc.@[apj][k]:=Image(Sommet[nbsn-k]);
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nbsn:+OTFc.@[apj][k] endfor)/nbsn;
    apj:=apj+1;
    tcpt.@[apj]:=apj;
    OTFc.@[apj].nb:=nbsn;
    for k=1 upto nbsn:
      OTFc.@[apj][k]:=Image(Sommet[k-1]+h*axe);
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nbsn:+OTFc.@[apj][k] endfor)/nbsn;
    apj:=apj+1;
  else:
    Ferme.@:=false;
  fi;
  for k=1 upto nbsn:
    for l=0 upto (subh-1):
      for p=0 upto (nb-1):
	tcpt.@[apj]:=apj;
	OTFc.@[apj].nb:=4;
	OTFc.@[apj][1]:=Image((p/nb)[Sommet[(k-1) mod nbsn],Sommet[k mod nbsn]]+(l/subh)*(h*axe));
	OTFc.@[apj][2]:=Image(((p+1)/nb)[Sommet[(k-1) mod nbsn],Sommet[k mod nbsn]]+(l/subh)*(h*axe));
	OTFc.@[apj][3]:=Image(((p+1)/nb)[Sommet[(k-1) mod nbsn],Sommet[k mod nbsn]]+((l+1)/subh)*(h*axe));
	OTFc.@[apj][4]:=Image((p/nb)[Sommet[(k-1) mod nbsn],Sommet[k mod nbsn]]+((l+1)/subh)*(h*axe));
	OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
	apj:=apj+1;
      endfor;
    endfor;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

vardef Objetcube[](expr ar)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  if creux=true:Ferme.@:=false else: Ferme.@:=true fi;
  scantokens("numeric "&substring(0,1) of ar&"; "&ar&";");
  Sommet1:=(a/2,-a/2,-a/2);
  Sommet2:=(a/2,a/2,-a/2);
  Sommet3:=(-a/2,a/2,-a/2);
  Sommet4:=(-a/2,-a/2,-a/2);
  Sommet5:=(-a/2,-a/2,a/2);
  Sommet6:=(a/2,-a/2,a/2);
  Sommet7:=(a/2,a/2,a/2);
  Sommet8:=(-a/2,a/2,a/2);
%%Faces
  apj:=0;
  for p=1 upto 4:
    for l=0 upto (subh-1):
      for k=0 upto (subh-1):
	OTFc.@[apj][1]:=Image((l/subh)[Sommet[p],Sommet[(p mod 4)+1]]+(k/subh)*(Sommet[(p mod 4)+5]-Sommet[p]));
	OTFc.@[apj][2]:=Image(((l+1)/subh)[Sommet[p],Sommet[(p mod 4)+1]]+(k/subh)*(Sommet[(p mod 4)+5]-Sommet[p]));
	OTFc.@[apj][3]:=Image(((l+1)/subh)[Sommet[p],Sommet[(p mod 4)+1]]+((k+1)/subh)*(Sommet[(p mod 4)+5]-Sommet[p]));
	OTFc.@[apj][4]:=Image((l/subh)[Sommet[p],Sommet[(p mod 4)+1]]+((k+1)/subh)*(Sommet[(p mod 4)+5]-Sommet[p]));
	OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
	apj:=apj+1;
      endfor;
    endfor;
  endfor;
  %face du dessous
  for l=0 upto (subh-1):
    for k=0 upto (subh-1):
      OTFc.@[apj][1]:=Image((l/subh)[Sommet1,Sommet4]+(k/subh)*(Sommet2-Sommet1));
      OTFc.@[apj][2]:=Image(((l+1)/subh)[Sommet1,Sommet4]+(k/subh)*(Sommet2-Sommet1));
      OTFc.@[apj][3]:=Image(((l+1)/subh)[Sommet1,Sommet4]+((k+1)/subh)*(Sommet2-Sommet1));
      OTFc.@[apj][4]:=Image((l/subh)[Sommet1,Sommet4]+((k+1)/subh)*(Sommet2-Sommet1));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      apj:=apj+1;
    endfor;
  endfor;
  %face du dessus
  for l=0 upto (subh-1):
    for k=0 upto (subh-1):
      OTFc.@[apj][1]:=Image((l/subh)[Sommet6,Sommet7]+(k/subh)*(Sommet5-Sommet6));
      OTFc.@[apj][2]:=Image(((l+1)/subh)[Sommet6,Sommet7]+(k/subh)*(Sommet5-Sommet6));
      OTFc.@[apj][3]:=Image(((l+1)/subh)[Sommet6,Sommet7]+((k+1)/subh)*(Sommet5-Sommet6));
      OTFc.@[apj][4]:=Image((l/subh)[Sommet6,Sommet7]+((k+1)/subh)*(Sommet5-Sommet6));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      apj:=apj+1;
    endfor;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    OTFc.@[k].nb:=4;
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

vardef Objetpave[](expr Lln,Hhn,Ppn)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  if creux=true: Ferme.@:=true else: Ferme.@:=false fi;
  scantokens("numeric "&substring(0,1) of Lln&"; "&Lln&";");
  scantokens("numeric "&substring(0,1) of Hhn&"; "&Hhn&";");
  scantokens("numeric "&substring(0,1) of Ppn&"; "&Ppn&";");
  NbS:=8;
  Sommet1:=(P/2,-L/2,-H/2);
  Sommet2:=(P/2,L/2,-H/2);
  Sommet3:=(-P/2,L/2,-H/2);
  Sommet4:=(-P/2,-L/2,-H/2);
  Sommet5:=(-P/2,-L/2,H/2);
  Sommet6:=(P/2,-L/2,H/2);
  Sommet7:=(P/2,L/2,H/2);
  Sommet8:=(-P/2,L/2,H/2);
%%Faces
  apj:=0;
  for p=1 upto 4:
    for l=0 upto (subh-1):
      for k=0 upto (subh-1):
	OTFc.@[apj][1]:=Image((l/subh)[Sommet[p],Sommet[(p mod 4)+1]]+(k/subh)*(Sommet[(p mod 4)+5]-Sommet[p]));
	OTFc.@[apj][2]:=Image(((l+1)/subh)[Sommet[p],Sommet[(p mod 4)+1]]+(k/subh)*(Sommet[(p mod 4)+5]-Sommet[p]));
	OTFc.@[apj][3]:=Image(((l+1)/subh)[Sommet[p],Sommet[(p mod 4)+1]]+((k+1)/subh)*(Sommet[(p mod 4)+5]-Sommet[p]));
	OTFc.@[apj][4]:=Image((l/subh)[Sommet[p],Sommet[(p mod 4)+1]]+((k+1)/subh)*(Sommet[(p mod 4)+5]-Sommet[p]));
	OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
	apj:=apj+1;
      endfor;
    endfor;
  endfor;
  %face du dessous
  for l=0 upto (subh-1):
    for k=0 upto (subh-1):
      OTFc.@[apj][1]:=Image((l/subh)[Sommet1,Sommet4]+(k/subh)*(Sommet2-Sommet1));
      OTFc.@[apj][2]:=Image(((l+1)/subh)[Sommet1,Sommet4]+(k/subh)*(Sommet2-Sommet1));
      OTFc.@[apj][3]:=Image(((l+1)/subh)[Sommet1,Sommet4]+((k+1)/subh)*(Sommet2-Sommet1));
      OTFc.@[apj][4]:=Image((l/subh)[Sommet1,Sommet4]+((k+1)/subh)*(Sommet2-Sommet1));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      apj:=apj+1;
    endfor;
  endfor;
  %face du dessus
  for l=0 upto (subh-1):
    for k=0 upto (subh-1):
      OTFc.@[apj][1]:=Image((l/subh)[Sommet6,Sommet7]+(k/subh)*(Sommet5-Sommet6));
      OTFc.@[apj][2]:=Image(((l+1)/subh)[Sommet6,Sommet7]+(k/subh)*(Sommet5-Sommet6));
      OTFc.@[apj][3]:=Image(((l+1)/subh)[Sommet6,Sommet7]+((k+1)/subh)*(Sommet5-Sommet6));
      OTFc.@[apj][4]:=Image((l/subh)[Sommet6,Sommet7]+((k+1)/subh)*(Sommet5-Sommet6));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      apj:=apj+1;
    endfor;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    OTFc.@[k].nb:=4;
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

vardef Objetgrille[](expr amn,ann,bmn,bnn)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  Ferme.@:=false;
  scantokens("numeric "&substring(0,2) of amn&"; "&amn&";");
  scantokens("numeric "&substring(0,2) of ann&"; "&ann&";");
  scantokens("numeric "&substring(0,2) of bmn&"; "&bmn&";");
  scantokens("numeric "&substring(0,2) of bnn&"; "&bnn&";");
  apj:=0;
  upas:=(an-am)/nb;
  vpas:=(bn-bm)/subh;
  for k=0 upto (nb-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image((am+k*upas,bm+l*vpas,0));
      OTFc.@[apj][2]:=Image((am+(k+1)*upas,bm+l*vpas,0));
      OTFc.@[apj][3]:=Image((am+(k+1)*upas,bm+(l+1)*vpas,0));
      OTFc.@[apj][4]:=Image((am+k*upas,bm+(l+1)*vpas,0));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=outcolor;
      else:
	Vue.@[apj]:=false;coul.@[apj]:=incolor;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

vardef ObjetRuban[](expr hn)(text tn)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("numeric "&substring(0,1) of hn&"; "&hn&";");
  nbsn:=0;%nb sommets total pour la base
  for _p=tn:
    Sommet[nbsn]:=_p;
    nbsn:=nbsn+1;
  endfor;
  Ferme.@:=false;
  apj:=0;
  for k=1 upto (nbsn-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image(Sommet[k-1]+(l/subh)*(h*(0,0,1)));
      OTFc.@[apj][2]:=Image(Sommet[k]+(l/subh)*(h*(0,0,1)));
      OTFc.@[apj][3]:=Image(Sommet[k]+((l+1)/subh)*(h*(0,0,1)));
      OTFc.@[apj][4]:=Image(Sommet[k-1]+((l+1)/subh)*(h*(0,0,1)));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      apj:=apj+1;
    endfor;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

vardef ObjetBiface[](text tn)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  nbsn:=0;%nb sommets total pour la base
  for _p=tn:
    nbsn:=nbsn+1;
    Sommet[nbsn]:=_p;
  endfor;
  Ferme.@:=true;
  apj:=0;
  tcpt.@[apj]:=apj;
  OTFc.@[apj].nb:=nbsn;
  for k=1 upto nbsn:
    OTFc.@[apj][k]:=Image(Sommet[nbsn+1-k]);
  endfor;
  OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nbsn:+OTFc.@[apj][k] endfor)/nbsn;
  apj:=apj+1;
  tcpt.@[apj]:=apj;
  OTFc.@[apj].nb:=nbsn;
  for k=1 upto nbsn:
    OTFc.@[apj][k]:=Image(Sommet[k]);
  endfor;
  OTFc.@[apj].iso:=(OTFc.@[apj][1] for k=2 upto nbsn:+OTFc.@[apj][k] endfor)/nbsn;
  for k=0 upto apj:
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

lambda:=3;
mu:=2;

vardef Objetplan[](expr Ann,Bnn,Cnn)=% modifier mais pour l'instant a marche pour les intersections;
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  Ferme.@:=false;
  color PPP[];
  scantokens("color "&substring(0,2) of Ann&"; "&Ann&";");
  scantokens("color "&substring(0,2) of Bnn&"; "&Bnn&";");
  scantokens("color "&substring(0,2) of Cnn&"; "&Cnn&";");
  apj:=0;
  PPP[0]=Image(An-lambda*(Bn-An)-mu*(Cn-An));
  PPP[1]=Image(An+lambda*(Bn-An)-mu*(Cn-An));
  PPP[2]=Image(An+lambda*(Bn-An)+mu*(Cn-An));
  PPP[3]=Image(An-lambda*(Bn-An)+mu*(Cn-An));
  for k=0 upto (nb-1):
    for l=0 upto (subh-1):
      tcpt.@[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Image((k/subh)[PPP0,PPP1]+(l/subh)*(PPP3-PPP0));
      OTFc.@[apj][2]:=Image(((k+1)/subh)[PPP0,PPP1]+(l/subh)*(PPP3-PPP0));
      OTFc.@[apj][3]:=Image(((k+1)/subh)[PPP0,PPP1]+((l+1)/subh)*(PPP3-PPP0));
      OTFc.@[apj][4]:=Image((k/subh)[PPP0,PPP1]+((l+1)/subh)*(PPP3-PPP0));
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=outcolor;
      else:
	Vue.@[apj]:=false;coul.@[apj]:=incolor;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

vardef Objettetraedre[](expr ar)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  if creux=true:Ferme.@:=false else: Ferme.@:=true fi;
  scantokens("numeric "&substring(0,1) of ar&"; "&ar&";");
  Sommet0:=a*(-0.81650,-0.47140,-1/3);
  Sommet1:=a*(0.81650,-0.471402,-1/3);
  Sommet2:=a*(0,0.94281,-1/3);
  Sommet3:=a*(0,0,1);
  tcpt.@[0]:=0;
  OTFc.@[0].nb:=3;
  OTFc.@[0][1]:=Image(Sommet0);
  OTFc.@[0][2]:=Image(Sommet2);
  OTFc.@[0][3]:=Image(Sommet1);
  OTFc.@[0].iso:=(OTFc.@[0][1]+OTFc.@[0][2]+OTFc.@[0][3])/3;
  tcpt.@[1]:=1;
  OTFc.@[1].nb:=3;
  OTFc.@[1][1]:=Image(Sommet0);
  OTFc.@[1][2]:=Image(Sommet1);
  OTFc.@[1][3]:=Image(Sommet3);
  OTFc.@[1].iso:=(OTFc.@[1][1]+OTFc.@[1][2]+OTFc.@[1][3])/3;
  tcpt.@[2]:=2;
  OTFc.@[2].nb:=3;
  OTFc.@[2][1]:=Image(Sommet1);
  OTFc.@[2][2]:=Image(Sommet2);
  OTFc.@[2][3]:=Image(Sommet3);
  OTFc.@[2].iso:=(OTFc.@[2][1]+OTFc.@[2][2]+OTFc.@[2][3])/3;
  tcpt.@[3]:=3;
  OTFc.@[3].nb:=3;
  OTFc.@[3][1]:=Image(Sommet2);
  OTFc.@[3][2]:=Image(Sommet0);
  OTFc.@[3][3]:=Image(Sommet3);
  OTFc.@[3].iso:=(OTFc.@[3][1]+OTFc.@[3][2]+OTFc.@[3][3])/3;
  for k=0 upto 3:
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=3;
enddef;

vardef Objetoctaedre[](expr ar)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  if creux=true:Ferme.@:=false else: Ferme.@:=true fi;
  scantokens("numeric "&substring(0,1) of ar&"; "&ar&";");
  AA=a*sqrt(2)/2;
  ObjetNew.@((0,0,-a),(-AA,-AA,0),(AA,-AA,0),(AA,AA,0),(-AA,AA,0),(0,0,a))(%
    3,0,2,1,%
    3,0,3,2,%
    3,0,4,3,%
    3,0,1,4,%
    3,5,1,2,%
    3,5,2,3,%
    3,5,3,4,%
    3,5,4,1%
    );
enddef;

vardef Objeticosaedre[](expr ar)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  if creux=true:Ferme.@:=false else: Ferme.@:=true fi;
  scantokens("numeric "&substring(0,1) of ar&"; "&ar&";");
  aplus=sqrt((5+sqrt(5))/10);
  amoins=sqrt((5-sqrt(5))/10);
  bplus=(5+sqrt(5))/10;
  bmoins=(5-sqrt(5))/10;
  Cmp=sqrt(5)/5;
  ObjetNew.@(a*(0,1,0),a*(amoins,Cmp,-bplus),a*(-amoins,Cmp,-bplus),a*(-aplus,Cmp,bmoins),a*(0,Cmp,2*Cmp),a*(aplus,Cmp,bmoins),a*(amoins,-Cmp,bplus),a*(-amoins,-Cmp,bplus),a*(-aplus,-Cmp,-bmoins),a*(0,-Cmp,-2*Cmp),a*(aplus,-Cmp,-bmoins),a*(0,-1,0))(%
    3,1,5,6,%
    3,1,4,5,%
    3,1,3,4,%
    3,1,2,3,%
    3,1,6,2,%
    3,7,6,5,%
    3,8,5,4,%
    3,9,4,3,%
    3,10,3,2,%
    3,11,2,6,%
    3,6,7,11,%
    3,5,8,7,%
    3,4,9,8,%
    3,3,10,9,%
    3,2,11,10,%
    3,12,10,11,%
    3,12,9,10,%
    3,12,8,9,%
    3,12,7,8,%
    3,12,11,7);
enddef;

vardef Objetdodecaedre[](expr ar)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  if creux=true:Ferme.@:=false else: Ferme.@:=true fi;
  scantokens("numeric "&substring(0,1) of ar&"; "&ar&";");
  Ap=a*sqrt((5+2*sqrt(5))/15);
  Bp=a*sqrt((10+2*sqrt(5))/15);
  Cp=a*sqrt((5+sqrt(5))/30);
  Dp=a*(sqrt(15)+sqrt(3))/6;
  Am=a*sqrt((5-2*sqrt(5))/15);
  Bm=a*sqrt((10-2*sqrt(5))/15);
  Cm=a*sqrt((5-sqrt(5))/30);
  Dm=a*(sqrt(15)-sqrt(3))/6;
  Ee:=a*sqrt(3)/3;
  ObjetNew.@((0,Ap,-Bm),(-Ee,Ap,-Am),(-Dm,Ap,Cp),(Dm,Ap,Cp),(Ee,Ap,-Am),(0,Am,-Bp),(-Dp,Am,-Cm),(-Ee,Am,Ap),(Ee,Am,Ap),(Dp,Am,-Cm),(0,-Am,Bp),(Dp,-Am,Cm),(Ee,-Am,-Ap),(-Ee,-Am,-Ap),(-Dp,-Am,Cm),(0,-Ap,Bm),(Ee,-Ap,Am),(Dm,-Ap,-Cp),(-Dm,-Ap,-Cp),(-Ee,-Ap,Am))(%
    5,5,1,2,3,4,%
    5,1,5,10,13,6,%
    5,2,1,6,14,7,%
    5,3,2,7,15,8,%
    5,4,3,8,11,9,%
    5,5,4,9,12,10,%
    5,6,13,18,19,14,%
    5,7,14,19,20,15,%
    5,8,15,20,16,11,%
    5,9,11,16,17,12,%
    5,10,12,17,18,13,%
    5,16,20,19,18,17%
    );
enddef;

vardef ObjetNew[](text listesommets)(text listefaces)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  color Sommet[];
  nbs:=0;
  mini:=min(listefaces);
  if mini=0:
    for _p=listesommets:
      Sommet[nbs]:=_p;
      nbs:=nbs+1;
    endfor;
  elseif mini=1:
    for _p=listesommets:
      nbs:=nbs+1;
      Sommet[nbs]:=_p;
    endfor;
  fi;
  apj:=0;
  j:=0;%pour compter le nombre de sommets  conserver
  for p_=listefaces:
    if j=0:
      OTFc.@[apj].nb:=p_;
      j:=1;
      k:=0;
    else:
      k:=k+1;
      if k<>OTFc.@[apj].nb:
	OTFc.@[apj][k]:=Image(Sommet[p_]);
      else:
	OTFc.@[apj][k]:=Image(Sommet[p_]);
	j:=0;
	apj:=apj+1;
      fi;
    fi;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    OTFc.@[k].iso:=(OTFc.@[k][1] for l=2 upto OTFc.@[k].nb:+OTFc.@[k][l] endfor)/OTFc.@[k].nb;
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
enddef;

%Objet lecture externe

vardef ObjetOFF[](expr nomfichier)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  OFF:=true;
  string s_;
  s_=readfrom nomfichier;
  string ss[];
  if s_<>EOF:
    ss1 := loptok s_;
    t_ := if ss1="%": 0 else: 1 fi;
    forever:
      ss[incr t_] := loptok s_;
      exitif ss[t_]="";
    endfor
  else: false
  fi;
  NbS:=round(Mexp Mlog_str ss1);
  NF:=round(Mexp Mlog_str ss2);
  s_:=readfrom nomfichier;
  if debut=0:
    for k=0 upto NbS-1:
      s_:=readfrom nomfichier;
      if s_<>EOF:
	ss1 := loptok s_;
	n_ := if ss1="%": 0 else: 1 fi;
	forever:
	  ss[incr n_] := loptok s_;
	  exitif ss[n_]="";
	endfor
      else: false
      fi;
      Sommet[k]:=(Mexp ((Mlog_str ss1) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss3) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss2) Mdiv (Mlog echelle)));
     endfor;
  else:
    for k=1 upto NbS:
      s_:=readfrom nomfichier;
      if s_<>EOF:
	ss1 := loptok s_;
	n_ := if ss1="%": 0 else: 1 fi;
	forever:
	  ss[incr n_] := loptok s_;
	  exitif ss[n_]="";
	endfor
      else: false
      fi;
      Sommet[k]:=(Mexp ((Mlog_str ss1) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss3) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss2) Mdiv (Mlog echelle)));
    endfor;
  fi;
  apj:=0;
  for nf=-4000 upto (-4000+NF)-1:
    s_:=readfrom nomfichier;
     if s_<>EOF:
      ss1 := loptok s_;
      n_ := if ss1="%": 0 else: 1 fi;
      forever:
	ss[incr n_] := loptok s_;
	exitif ss[n_]="";
      endfor
    else: false
    fi;
    OTFc.@[apj].nb:=Mexp Mlog_str ss1;%pour savoir le nb de sommets par face
    for nl=1 upto OTFc.@[apj].nb:
      if invnormale=1:
	OTFc.@[apj][nl]:=Image(Sommet[round(Mexp Mlog_str ss[nl+1])]);
      else:
	OTFc.@[apj][OTFc.@[apj].nb+1-nl]:=Image(Sommet[round(Mexp Mlog_str ss[nl+1])]);
      fi;
    endfor;
    OTFc.@[apj].iso:=(OTFc.@[apj][1] for l=2 upto OTFc.@[apj].nb:+OTFc.@[apj][l] endfor)/OTFc.@[apj].nb;
    ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
    if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
      Vue.@[apj]:=true;coul.@[apj]:=outcolor;
    else:
      Vue.@[apj]:=false;coul.@[apj]:=incolor;
    fi;
    apj:=apj+1;
  endfor;
  apj.@:=apj-1;
  closefrom nomfichier;
enddef;

vardef ObjetOBJ[](expr nomfichier)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  string s_;
  string ss[];
  nbss:=1;
  apj:=0;
  forever:
    s_:=readfrom nomfichier;
    if s_<>EOF:
      ss0 := loptok s_;
      if ss0="v":
	n_:=0;
	forever:
	  ss[incr n_] := loptok s_;
	  exitif ss[n_]="";
	endfor
	Sommet[nbss]:=(Mexp((Mlog_str ss1) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss3) Mdiv (Mlog echelle)),Mexp ((Mlog_str ss2) Mdiv (Mlog echelle)));
	nbss:=incr nbss;
      elseif ss0="f":
	n_:=0;
	forever:
	  ss[incr n_] := loptok s_;
	  exitif ss[n_]="";
	endfor;
	OTFc.@[apj].nb:=n_-1;
	for k=1 upto OTFc.@[apj].nb:
	  if invnormale=1:
	    OTFc.@[apj][OTFc.@[apj].nb-k+1] := Image(Sommet[round(Mexp(Mlog_str ss[k]))])
	    %if unknown OTFc.@[apj][OTFc.@[apj].nb-k+1]:
	  %  show OTFc.@[apj][OTFc.@[apj].nb-k+1];
	  %fi;
	  else:
	    OTFc.@[apj][k] := Image(Sommet[round(Mexp(Mlog_str ss[k]))])
	    %if unknown OTFc.@[apj][k]:
	  %  show OTFc.@[apj][k];
	  %fi;
	  fi;
	  
	endfor;
	apj:=apj+1;
      fi;
    fi;
    exitif s_=EOF;
  endfor;
  apj:=apj-1;
  for k=0 upto apj:
    OTFc.@[k].iso:=(OTFc.@[k][1] for l=2 upto OTFc.@[k].nb:+OTFc.@[k][l] endfor)/OTFc.@[k].nb;
    ALT.@[k]:=-Zpart(GCoord(OTFc.@[k].iso));
    if ProduitScalaire(Oeil-OTFc.@[k].iso,Normal(OTFc.@[k].iso,OTFc.@[k][1],OTFc.@[k][2]))>=0:
      Vue.@[k]:=true;coul.@[k]:=outcolor;
    else:
      Vue.@[k]:=false;coul.@[k]:=incolor;
    fi;
  endfor;
  apj.@:=apj;
  closefrom nomfichier;
enddef;


%%%%%%%Objets travaills

vardef ObjetEnleve[](text t)=%les numros des faces sont donnes par ordre croissant.
  numeric numface[];
  nface:=0;
  numface[0]:=0;
  %rcuprer les numros des faces.
  forsuffixes _p=t:
    nface:=nface+1;
    numface[nface]=_p-(nface-1);%marchait :)
  endfor;
  numface[nface+1]:=apj.@-nface+1;
  %Mettre dans l'ordre ces numros.<-dj fait par l'utilisateur
  %enlever les numros des faces
  apj:=0;
  for k=0 upto nface:
    for l=numface[k] upto (numface[k+1]-1):
      tcpt.@[apj]:=tcpt.@[apj+k];
      OTFc.@[apj].nb:=OTFc.@[apj+k].nb;
      for p=1 upto OTFc.@[apj].nb:
	OTFc.@[apj][p]:=OTFc.@[apj+k][p];
      endfor;
      OTFc.@[apj].iso:=OTFc.@[apj+k].iso;
      ALT.@[apj]:=ALT.@[apj+k];
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=outcolor;
      else:
	Vue.@[apj]:=false;coul.@[apj]:=incolor;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

vardef ObjetDeplacement[](text t)=
  %permet de dplacer un objet en donnant au pralable les angles de rotations et la translation. On peut galement appliquer une transformation.
    Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  apj:=0;
  forsuffixes p_=t:
    Ferme.@:=Ferme[p_];
    for k=0 upto apj[p_]:
      cpt.@[apj]:=cpt[p_][k];
      OTFc.@[apj].nb:=OTFc[p_][k].nb;
      for l=1 upto OTFc.@[apj].nb:
	OTFc.@[apj][l]:=Image(OTFc[p_][k][l]);
      endfor;
      OTFc.@[apj].iso:=Image(OTFc[p_][k].iso);
      ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=Outcolor[p_];
      else:
	if Ferme.@=false:
	  Vue.@[apj]:=false;coul.@[apj]:=Incolor[p_];
	else:
	  apj:=apj-1;
	fi;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

vardef ObjetFusion[](text t)=
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  tapj:=0;
  Nbobj:=0;
  forsuffixes p_=t:
    for k=0 upto apj[p_]:
      cpt.@[tapj]:=tapj;
      OTFc.@[tapj].nb:=OTFc[p_][k].nb;
      for p=1 upto OTFc.@[tapj].nb:
	OTFc.@[tapj][p]:=OTFc[p_][k][p];
      endfor;
      OTFc.@[tapj].iso:=OTFc[p_][k].iso;
      ALT.@[tapj]:=-Zpart(GCoord(OTFc.@[tapj].iso));
      Vue.@[tapj]:=Vue[p_][k];
      coul.@[tapj]:=coul[p_][k];
      tapj:=tapj+1;
    endfor;
  endfor;
  apj.@:=tapj-1;
enddef;

%les intersections d'objets

vardef ProjectionsurPlan(expr aa,bb,cc,dd)=%Projection du point aa sur le plan (bbccdd)
  save di,vc;
  color va,vb,vc,vd;
  vd=Normal(bb,cc,dd);
  va=vd/Norm(vd);
  vb=aa-bb;
  di=-ProduitScalaire(vb,va);
  va:=di*va;
  vb:=vb+va;
  vc=bb+vb;
  vc
enddef;

%%denis Roegel----------
vardef IntersectionPlandroite(expr aa,bb,cc,dd,ee)=%pour les aretes :)
  save Int;
  boolean Int;
  color gg,caaa[],Caaa[];
  caaa3=Normal(aa,bb,cc)/Norm(Normal(aa,bb,cc));
  caaa1=aa-dd;if Norm(caaa1)<>0:Caaa1=caaa1/Norm(caaa1) else:Caaa1=caaa1 fi;
  caaa2=ee-dd;if Norm(caaa2)<>0:Caaa2=caaa2/Norm(caaa2) else:Caaa2=caaa2 fi;
  ww:=ProduitScalaire(caaa2,caaa3);
  if ww<>0:
    %if (ProduitScalaire(caaa1,caaa3)*ww>0) and (ProduitScalaire(caaa1,caaa3)/ww<1):
      caaa4=caaa2*(ProduitScalaire(caaa1,caaa3)/ww);
      Int:=true;
    %else:
    %  Int:=false;
    %fi;
  else: % the line is parallel to the plane
    Int:=false;
  fi;
  Int
enddef;

vardef Intersectionplandroite(expr aa,bb,cc,dd,ee)=%pour les aretes :)
  save Int;
  boolean Int;
  color gg,caaa[],Caaa[];
  caaa3=Normal(aa,bb,cc)/Norm(Normal(aa,bb,cc));
  caaa1=aa-dd;if Norm(caaa1)<>0:Caaa1=caaa1/Norm(caaa1) else:Caaa1=caaa1 fi;
  caaa2=ee-dd;if Norm(caaa2)<>0:Caaa2=caaa2/Norm(caaa2) else:Caaa2=caaa2 fi;
  ww:=ProduitScalaire(caaa2,caaa3);
  if ww<>0:
    if (ProduitScalaire(caaa1,caaa3)*ww>0) and (ProduitScalaire(caaa1,caaa3)/ww<1):
      %message("ww"&decimal(ww)&" PS"&decimal(ProduitScalaire(caaa1,caaa3))&"");      
      caaa4=caaa2*(ProduitScalaire(caaa1,caaa3)/ww);
      Int:=true;
    else:
      Int:=false;
    fi;
  else: % the line is parallel to the plane
    Int:=false;
  fi;
  Int
enddef;

vardef IntersectionPlanDroite(expr aa,bb,cc,dd,ee)=%plan (aa,bb,cc) droite(dd,ee)
  if Intersectionplandroite(aa,bb,cc,dd,ee):
    gg=dd+caaa4;
  fi;
  gg
enddef;

vardef IPP(expr aa,bb,cc,dd,ee,ff)=
  %a vrifier
  %save da,db,dc;
  boolean int;
  da:=Norm(aa-ProjectionsurPlan(aa,dd,ee,ff));
  db:=Norm(bb-ProjectionsurPlan(bb,dd,ee,ff));
  dc:=Norm(cc-ProjectionsurPlan(cc,dd,ee,ff));
  if (da=db) and (db=dc): % the two planes are parallel
    int:=false;
  else:
    int:=true;
    nbi:=nbi+1;
  fi;
enddef;
%%---------------------

vardef ObjetIntersection[](text t)=%plan n1 solide n2
  color INTER[][][];%pour avoir les points d'intersection
  nbsol:=1;
  forsuffixes p_=t:
    pp_[nbsol]:=p_;
    nbsol:=nbsol+1;
  endfor;
  nbi:=0;
  for k=0 upto apj[pp_[2]]:
      IPP(OTFc[pp_[2]][k][1],OTFc[pp_[2]][k][2],OTFc[pp_[2]][k][3],PPP0,PPP1,PPP2);
      if int=true:
	nbint:=0;
	OTFc[pp_[2]][k][OTFc[pp_[2]][k].nb+1]=OTFc[pp_[2]][k][1];
      	for l=1 upto (OTFc[pp_[2]][k].nb):
	  if Intersectionplandroite(PPP0,PPP1,PPP2,OTFc[pp_[2]][k][l],OTFc[pp_[2]][k][l+1]):
	    nbint:=nbint+1;
	    INTER[pp_2][k][nbint]=IntersectionPlanDroite(PPP0,PPP1,PPP2,OTFc[pp_[2]][k][l],OTFc[pp_[2]][k][l+1]);
	  fi;
	endfor;
	%%%Pas satisfaisant ->  travailler
	%show nbint;
	if nbint=2:
	  draw Projette(INTER[pp_2][k][1])--Projette(INTER[pp_2][k][2]) withpen pencircle scaled2bp withcolor violet;
	fi;
      fi;
  endfor;
enddef;
  
vardef ObjetSepare[](expr nbd,nbD)=%nbd pour l'objet du dessous, nbD pour l'objet du dessus.
  Ferme[nbd]:=Ferme.@;
  Ferme[nbD]:=Ferme.@;
  Outcolor[nbd]:=outcolor;
  Incolor[nbd]:=incolor;
  Outcolor[nbD]:=outcolor;
  Incolor[nbD]:=incolor;
  color INTER[][][];
  color Nn;color PPP.iso;
  Nn=Normal(PPP0,PPP1,PPP3);
  PPP.iso=(PPP0+PPP1+PPP2)/3;
  apj:=0;bpj:=0;%bpj pour le 2eme solide
  for k=0 upto apj.@:
    if ProduitScalaire(Nn,OTFc.@[k].iso-PPP.iso)<=0:
      nbint:=0;
      OTFc.@[k][OTFc.@[k].nb+1]:=OTFc.@[k][1];
      for l=1 upto OTFc.@[k].nb:
	if Intersectionplandroite(PPP0,PPP1,PPP3,OTFc.@[k][l],OTFc.@[k][l+1]):
	  nbint:=nbint+1;
	  INTER.@[k][nbint]=IntersectionPlanDroite(PPP0,PPP1,PPP3,OTFc.@[k][l],OTFc.@[k][l+1]);
	  prec.@[k][nbint]:=l;
	  suiv.@[k][nbint]:=l+1;
	fi;
      endfor;
      if nbint=0:
	tcpt[nbd][apj]:=apj; OTFc[nbd][apj].nb:=OTFc.@[k].nb;
	for l=1 upto OTFc[nbd][apj].nb:
	  OTFc[nbd][apj][l]:=Image(OTFc.@[k][l]);
	endfor;
	OTFc[nbd][apj].iso:=(OTFc[nbd][apj][1]+for l=2 upto OTFc[nbd][apj].nb:+OTFc[nbd][apj][l] endfor)/OTFc[nbd][apj].nb;
	ALT[nbd][apj]:=-Zpart(GCoord(OTFc[nbd][apj].iso));
	if ProduitScalaire(Oeil-OTFc[nbd][apj].iso,Normal(OTFc[nbd][apj].iso,OTFc[nbd][apj][1],OTFc[nbd][apj][2]))>=0:
	  Vue[nbd][apj]:=true;coul[nbd][apj]:=outcolor;
	else:
	  Vue[nbd][apj]:=false;coul[nbd][apj]:=incolor;
	fi;
	apj:=apj+1;
      fi;
      if nbint=2:
	tcpt[nbd][apj]:=apj;
	if ProduitScalaire(Nn,OTFc.@[k][prec.@[k][1]]-PPP.iso)<=0:
	  compt:=0;
	  for l=1 upto prec.@[k][1]:
	    compt:=compt+1;
	    OTFc[nbd][apj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  OTFc[nbd][apj][compt+1]:=Image(INTER.@[k][1]);
	  OTFc[nbd][apj][compt+2]:=Image(INTER.@[k][2]);
	  compt:=compt+2;
	  for l=suiv.@[k][2] upto OTFc.@[k].nb:
	    compt:=compt+1;
	    OTFc[nbd][apj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  OTFc[nbd][apj].nb:=compt;
	  OTFc[nbd][apj].iso:=(OTFc[nbd][apj][1]+for l=2 upto OTFc[nbd][apj].nb:+OTFc[nbd][apj][l] endfor)/OTFc[nbd][apj].nb;
	  ALT[nbd][apj]:=-Zpart(GCoord(OTFc[nbd][apj].iso));
	  if ProduitScalaire(Oeil-OTFc[nbd][apj].iso,Normal(OTFc[nbd][apj].iso,OTFc[nbd][apj][1],OTFc[nbd][apj][2]))>=0:
	    Vue[nbd][apj]:=true;coul[nbd][apj]:=outcolor;
	  else:
	    Vue[nbd][apj]:=false;coul[nbd][apj]:=incolor;
	  fi;
	  apj:=apj+1;
	  %2eme solide
	  compt:=1;
	  OTFc[nbD][bpj][1]:=Image(INTER.@[k][1]);
	  for l=suiv.@[k][1] upto prec.@[k][2]:
	    compt:=compt+1;
	    OTFc[nbD][bpj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  compt:=compt+1;
	  OTFc[nbD][bpj][compt]:=Image(INTER.@[k][2]);
	  OTFc[nbD][bpj].nb:=compt;
	  OTFc[nbD][bpj].iso:=(OTFc[nbD][bpj][1]+for l=2 upto OTFc[nbD][bpj].nb:+OTFc[nbD][bpj][l] endfor)/OTFc[nbD][bpj].nb;
	  ALT[nbD][bpj]:=-Zpart(GCoord(OTFc[nbD][bpj].iso));
	  if ProduitScalaire(Oeil-OTFc[nbD][bpj].iso,Normal(OTFc[nbD][bpj].iso,OTFc[nbD][bpj][1],OTFc[nbD][bpj][2]))>=0:
	    Vue[nbD][bpj]:=true;coul[nbD][bpj]:=outcolor;
	  else:
	    Vue[nbD][bpj]:=false;coul[nbD][bpj]:=incolor;
	  fi;
	  bpj:=bpj+1;
	  %fin 2eme solide
	else:
	  compt:=1;
	  OTFc[nbd][apj][1]:=Image(INTER.@[k][1]);
	  for l=suiv.@[k][1] upto prec.@[k][2]:
	    compt:=compt+1;
	    OTFc[nbd][apj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  compt:=compt+1;
	  OTFc[nbd][apj][compt]:=Image(INTER.@[k][2]);
	  OTFc[nbd][apj].nb:=compt;
	  OTFc[nbd][apj].iso:=(OTFc[nbd][apj][1]+for l=2 upto OTFc[nbd][apj].nb:+OTFc[nbd][apj][l] endfor)/OTFc[nbd][apj].nb;
	  ALT[nbd][apj]:=-Zpart(GCoord(OTFc[nbd][apj].iso));
	  if ProduitScalaire(Oeil-OTFc[nbd][apj].iso,Normal(OTFc[nbd][apj].iso,OTFc[nbd][apj][1],OTFc[nbd][apj][2]))>=0:
	    Vue[nbd][apj]:=true;coul[nbd][apj]:=outcolor;
	  else:
	    Vue[nbd][apj]:=false;coul[nbd][apj]:=incolor;
	  fi;
	  apj:=apj+1;
	  %2eme solide
	  compt:=0;
	  for l=1 upto prec.@[k][1]:
	    compt:=compt+1;
	    OTFc[nbD][bpj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  OTFc[nbD][bpj][compt+1]:=Image(INTER.@[k][1]);
	  OTFc[nbD][bpj][compt+2]:=Image(INTER.@[k][2]);
	  compt:=compt+2;
	  for l=suiv.@[k][2] upto OTFc.@[k].nb:
	    compt:=compt+1;
	    OTFc[nbD][bpj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  OTFc[nbD][bpj].nb:=compt;
	  OTFc[nbD][bpj].iso:=(OTFc[nbD][bpj][1]+for l=2 upto OTFc[nbD][bpj].nb:+OTFc[nbD][bpj][l] endfor)/OTFc[nbD][bpj].nb;
	  ALT[nbD][bpj]:=-Zpart(GCoord(OTFc[nbD][bpj].iso));
	  if ProduitScalaire(Oeil-OTFc[nbD][bpj].iso,Normal(OTFc[nbD][bpj].iso,OTFc[nbD][bpj][1],OTFc[nbD][bpj][2]))>=0:
	    Vue[nbD][bpj]:=true;coul[nbD][bpj]:=outcolor;
	  else:
	    Vue[nbD][bpj]:=false;coul[nbD][bpj]:=incolor;
	  fi;
	  bpj:=bpj+1;
	  %fin 2eme solide
	fi;
      fi;
      if nbint=1:
	compt:=0;%compteur pour le nb de sommets
	comp:=0;%pour savoir o se situe le point  enlever
	for l=1 upto OTFc.@[k].nb:
	  if ProduitScalaire(Nn,OTFc.@[k][l]-PPP.iso)>0:
	    comp:=comp+1;
	  fi;
	endfor;
	if comp=1:
	  tcpt[nbd][apj]:=apj;
	  for l=1 upto prec.@[k][1]-1:
	    compt:=compt+1;
	    OTFc[nbd][apj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  compt:=compt+1;
	  OTFc[nbd][apj][compt]:=Image(INTER.@[k][1]);
	  for l=suiv.@[k][1] upto OTFc.@[k].nb:
	    compt:=compt+1;
	    OTFc[nbd][apj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  OTFc[nbd][apj].nb:=compt;
	  OTFc[nbd][apj].iso:=(OTFc[nbd][apj][1]+for l=2 upto OTFc[nbd][apj].nb:+OTFc[nbd][apj][l] endfor)/OTFc[nbd][apj].nb;
	  ALT[nbd][apj]:=-Zpart(GCoord(OTFc[nbd][apj].iso));
	  if ProduitScalaire(Oeil-OTFc[nbd][apj].iso,Normal(OTFc[nbd][apj].iso,OTFc[nbd][apj][1],OTFc[nbd][apj][2]))>=0:
	    Vue[nbd][apj]:=true;coul[nbd][apj]:=outcolor;
	  else:
	    Vue[nbd][apj]:=false;coul[nbd][apj]:=incolor;
	  fi;
	  apj:=apj+1;
	else:
	  tcpt[nbd][apj]:=apj; OTFc[nbd][apj].nb:=OTFc.@[k].nb;
	  for l=1 upto OTFc[nbd][apj].nb:
	    OTFc[nbd][apj][l]:=Image(OTFc.@[k][l]);
	  endfor;
	  OTFc[nbd][apj].iso:=(OTFc[nbd][apj][1]+for l=2 upto OTFc[nbd][apj].nb:+OTFc[nbd][apj][l] endfor)/OTFc[nbd][apj].nb;
	  ALT[nbd][apj]:=-Zpart(GCoord(OTFc[nbd][apj].iso));
	  if ProduitScalaire(Oeil-OTFc[nbd][apj].iso,Normal(OTFc[nbd][apj].iso,OTFc[nbd][apj][1],OTFc[nbd][apj][2]))>=0:
	    Vue[nbd][apj]:=true;coul[nbd][apj]:=outcolor;
	  else:
	    Vue[nbd][apj]:=false;coul[nbd][apj]:=incolor;
	  fi;
	  apj:=apj+1;
	fi;
      fi;
    fi;
    if ProduitScalaire(Nn,OTFc.@[k].iso-PPP.iso)>0:
      nbint:=0;
      OTFc.@[k][OTFc.@[k].nb+1]:=OTFc.@[k][1];
      for l=1 upto OTFc.@[k].nb:
	if Intersectionplandroite(PPP0,PPP1,PPP3,OTFc.@[k][l],OTFc.@[k][l+1]):
	  nbint:=nbint+1;
	  INTER.@[k][nbint]=IntersectionPlanDroite(PPP0,PPP1,PPP3,OTFc.@[k][l],OTFc.@[k][l+1]);
	  prec.@[k][nbint]:=l;
	  suiv.@[k][nbint]:=l+1;
	fi;
      endfor;
      %2eme solide sans intersection
      if nbint=0:
	tcpt[nbD][bpj]:=bpj; OTFc[nbD][bpj].nb:=OTFc.@[k].nb;
	for l=1 upto OTFc[nbD][bpj].nb:
	  OTFc[nbD][bpj][l]:=Image(OTFc.@[k][l]);
	endfor;
	OTFc[nbD][bpj].iso:=(OTFc[nbD][bpj][1]+for l=2 upto OTFc[nbD][bpj].nb:+OTFc[nbD][bpj][l] endfor)/OTFc[nbD][bpj].nb;
	ALT[nbD][bpj]:=-Zpart(GCoord(OTFc[nbD][bpj].iso));
	if ProduitScalaire(Oeil-OTFc[nbD][bpj].iso,Normal(OTFc[nbD][bpj].iso,OTFc[nbD][bpj][1],OTFc[nbD][bpj][2]))>=0:
	  Vue[nbD][bpj]:=true;coul[nbD][bpj]:=outcolor;
	else:
	  Vue[nbD][bpj]:=false;coul[nbD][bpj]:=incolor;
	fi;
	bpj:=bpj+1;
      fi;
      %fin 2eme solide
      if nbint=2:
	tcpt[nbd][apj]:=apj;
	if ProduitScalaire(Nn,OTFc.@[k][prec.@[k][1]]-PPP.iso)<=0:
	  compt:=0;
	  for l=1 upto prec.@[k][1]:
	    compt:=compt+1;
	    OTFc[nbd][apj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  OTFc[nbd][apj][compt+1]:=Image(INTER.@[k][1]);
	  OTFc[nbd][apj][compt+2]:=Image(INTER.@[k][2]);
	  compt:=compt+2;
	  for l=suiv.@[k][2] upto OTFc.@[k].nb:
	    compt:=compt+1;
	    OTFc[nbd][apj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  OTFc[nbd][apj].nb:=compt;
	  OTFc[nbd][apj].iso:=(OTFc[nbd][apj][1]+for l=2 upto OTFc[nbd][apj].nb:+OTFc[nbd][apj][l] endfor)/OTFc[nbd][apj].nb;
	  ALT[nbd][apj]:=-Zpart(GCoord(OTFc[nbd][apj].iso));
	  if ProduitScalaire(Oeil-OTFc[nbd][apj].iso,Normal(OTFc[nbd][apj].iso,OTFc[nbd][apj][1],OTFc[nbd][apj][2]))>=0:
	    Vue[nbd][apj]:=true;coul[nbd][apj]:=outcolor;
	  else:
	    Vue[nbd][apj]:=false;coul[nbd][apj]:=incolor;
	  fi;
	  apj:=apj+1;
	  %2eme solide
	  compt:=1;
	  OTFc[nbD][bpj][1]:=Image(INTER.@[k][1]);
	  for l=suiv.@[k][1] upto prec.@[k][2]:
	    compt:=compt+1;
	    OTFc[nbD][bpj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  compt:=compt+1;
	  OTFc[nbD][bpj][compt]:=Image(INTER.@[k][2]);
	  OTFc[nbD][bpj].nb:=compt;
	  OTFc[nbD][bpj].iso:=(OTFc[nbD][bpj][1]+for l=2 upto OTFc[nbD][bpj].nb:+OTFc[nbD][bpj][l] endfor)/OTFc[nbD][bpj].nb;
	  ALT[nbD][bpj]:=-Zpart(GCoord(OTFc[nbD][bpj].iso));
	  if ProduitScalaire(Oeil-OTFc[nbD][bpj].iso,Normal(OTFc[nbD][bpj].iso,OTFc[nbD][bpj][1],OTFc[nbD][bpj][2]))>=0:
	    Vue[nbD][bpj]:=true;coul[nbD][bpj]:=outcolor;
	  else:
	    Vue[nbD][bpj]:=false;coul[nbD][bpj]:=incolor;
	  fi;
	  bpj:=bpj+1;
	  %fin 2eme solide
	else:
	  compt:=1;
	  OTFc[nbd][apj][1]:=Image(INTER.@[k][1]);
	  for l=suiv.@[k][1] upto prec.@[k][2]:
	    compt:=compt+1;
	    OTFc[nbd][apj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  compt:=compt+1;
	  OTFc[nbd][apj][compt]:=Image(INTER.@[k][2]);
	  OTFc[nbd][apj].nb:=compt;
	  OTFc[nbd][apj].iso:=(OTFc[nbd][apj][1]+for l=2 upto OTFc[nbd][apj].nb:+OTFc[nbd][apj][l] endfor)/OTFc[nbd][apj].nb;
	  ALT[nbd][apj]:=-Zpart(GCoord(OTFc[nbd][apj].iso));
	  if ProduitScalaire(Oeil-OTFc[nbd][apj].iso,Normal(OTFc[nbd][apj].iso,OTFc[nbd][apj][1],OTFc[nbd][apj][2]))>=0:
	    Vue[nbd][apj]:=true;coul[nbd][apj]:=outcolor;
	  else:
	    Vue[nbd][apj]:=false;coul[nbd][apj]:=incolor;
	  fi;
	  apj:=apj+1;
	  %2eme solide
	  compt:=0;
	  for l=1 upto prec.@[k][1]:
	    compt:=compt+1;
	    OTFc[nbD][bpj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  OTFc[nbD][bpj][compt+1]:=Image(INTER.@[k][1]);
	  OTFc[nbD][bpj][compt+2]:=Image(INTER.@[k][2]);
	  compt:=compt+2;
	  for l=suiv.@[k][2] upto OTFc.@[k].nb:
	    compt:=compt+1;
	    OTFc[nbD][bpj][compt]:=Image(OTFc.@[k][l]);
	  endfor;
	  OTFc[nbD][bpj].nb:=compt;
	  OTFc[nbD][bpj].iso:=(OTFc[nbD][bpj][1]+for l=2 upto OTFc[nbD][bpj].nb:+OTFc[nbD][bpj][l] endfor)/OTFc[nbD][bpj].nb;
	  ALT[nbD][bpj]:=-Zpart(GCoord(OTFc[nbD][bpj].iso));
	  if ProduitScalaire(Oeil-OTFc[nbD][bpj].iso,Normal(OTFc[nbD][bpj].iso,OTFc[nbD][bpj][1],OTFc[nbD][bpj][2]))>=0:
	    Vue[nbD][bpj]:=true;coul[nbD][bpj]:=outcolor;
	  else:
	    Vue[nbD][bpj]:=false;coul[nbD][bpj]:=incolor;
	  fi;
	  bpj:=bpj+1;
	  %fin 2eme solide
	fi;
      fi;
    fi;
  endfor;
  apj[nbd]:=apj-1;
  apj[nbD]:=bpj-1;
enddef;

%pour les lignes de niveaux.
vardef ObjetSurfaceZ[](expr fn,xmin,xmax,ymin,ymax,nblignes,nbpoints)=
  surfz:=true;
  Outcolor.@:=outcolor;
  Incolor.@:=incolor;
  scantokens("vardef Fz(expr X,Y)="&fn&" enddef;");
  apj:=0;
  IncX:=(xmax-xmin)/nbpoints;
  IncY:=(ymax-ymin)/nblignes;
  color Yc[][],Xc[][],Fc[][];
  for ligne=0 upto nblignes:
    y:=ymax-ligne*IncY;
    x:=xmin;
    Yc[ligne][0]=(x,y,Fz(x,y));
    for k=1 upto nbpoints:
      Yc[ligne][k]=((xmin+k*IncX,y,Fz(xmin+k*IncX,y)));
    endfor;
  endfor;
  for k=(nblignes-1) downto 0:
    for l=(nbpoints-3) step -3 until 0: 
      cpt[apj]:=apj;
      OTFc.@[apj].nb:=4;
      OTFc.@[apj][1]:=Yc[k][l];
      OTFc.@[apj][2]:=Yc[k+1][l];
      OTFc.@[apj][3]:=Yc[k+1][l+3];
      OTFc.@[apj][4]:=Yc[k][l+3];
      OTFc.@[apj].iso:=(OTFc.@[apj][1]+OTFc.@[apj][2]+OTFc.@[apj][3]+OTFc.@[apj][4])/4;
      ALT.@[apj]:=-Zpart(GCoord(OTFc.@[apj].iso));
      if ProduitScalaire(Oeil-OTFc.@[apj].iso,Normal(OTFc.@[apj].iso,OTFc.@[apj][1],OTFc.@[apj][2]))>=0:
	Vue.@[apj]:=true;coul.@[apj]:=outcolor;
      else:
	Vue.@[apj]:=false;coul.@[apj]:=incolor;
      fi;
      apj:=apj+1;
    endfor;
  endfor;
  apj.@:=apj-1;
enddef;

vardef GrilleSurfZ(expr xmin,xmax,xpas,ymin,ymax,ypas,zmin,zmax,zpas,zechelle)=
  drawoptions(withcolor gris);
  for k=zmin upto zmax:
    draw Projette((-xmin,ymin,k))--Projette((-xmax,ymin,k))--Projette((-xmax,ymax,k));
  endfor;
  for k=ymin upto ymax:
    draw Projette((-xmin,k,zmin))--Projette((-xmax,k,zmin))--Projette((-xmax,k,zmax));
  endfor;
  for k=xmin upto xmax:
    draw Projette((-k,ymax,zmin))--Projette((-k,ymin,zmin))--Projette((-k,ymin,zmax));
  endfor;
  drawoptions();
  if Phi<>90:
    for k=zmin step zpas until zmax:
      label.lft(""&decimal(zechelle*k)&"",Projette((-xmin,ymin,k)));
    endfor;
    for k=ymin step ypas until ymax:
      label.bot(""&decimal(k)&"",Projette((-xmin,k,zmin)));
    endfor;
    for k=xmin step xpas until xmax:
      label.rt(""&decimal(k)&"",Projette((-k,ymax,zmin)));
    endfor;
    labeloffset:=8*labeloffset;
    label.bot(btex $y$ etex,Projette((-xmin,(ymin+ymax)/2,zmin)));
    label.lft(btex $z$ etex,Projette((-xmin,ymin,(zmin+zmax)/2)));
    label.rt(btex $x$ etex,Projette((-(xmin+xmax)/2,ymax,zmin)));
    labeloffset:=labeloffset/8;
  else:
    for k=ymin step ypas until ymax:
      label.bot(""&decimal(k)&"",Projette((-xmin,k,zmin)));
    endfor;
    for k=xmin step xpas until xmax:
      label.rt(""&decimal(k)&"",Projette((-k,ymax,zmin)));
    endfor;
    labeloffset:=8*labeloffset;
    label.bot(btex $y$ etex,Projette((-xmin,(ymin+ymax)/2,zmin)));
    label.rt(btex $x$ etex,Projette((-(xmin+xmax)/2,ymax,zmin)));
    labeloffset:=labeloffset/8;
  fi;
enddef;

vardef GrilleSurfZZ(expr xmin,xmax,xpas,ymin,ymax,ypas,zmin,zmax,zpas,zechelle)=
  drawoptions(withcolor gris);
  for k=zmin upto zmax:
    draw Projette((xmin,ymin,k))--Projette((xmin,ymax,k))--Projette((xmax,ymax,k));
  endfor;
  for k=ymin upto ymax:
    draw Projette((xmax,k,zmin))--Projette((xmin,k,zmin))--Projette((xmin,k,zmax));
  endfor;
  for k=xmin upto xmax:
    draw Projette((k,ymin,zmin))--Projette((k,ymax,zmin))--Projette((k,ymax,zmax));
  endfor;
  drawoptions();
  if Phi<>90:
    for k=zmin step zpas until zmax:
      label.lft(""&decimal(zechelle*k)&"",Projette((xmin,ymin,k)));
    endfor;
    for k=ymin step ypas until ymax:
      label.rt(""&decimal(k)&"",Projette((xmax,k,zmin)));
    endfor;
    for k=xmin step xpas until xmax:
      label.bot(""&decimal(k)&"",Projette((k,ymin,zmin)));
    endfor;
    labeloffset:=8*labeloffset;
    label.rt(btex $y$ etex,Projette((xmax,(ymin+ymax)/2,zmin)));
    label.lft(btex $z$ etex,Projette((xmin,ymin,(zmin+zmax)/2)));
    label.bot(btex $x$ etex,Projette(((xmin+xmax)/2,ymin,zmin)));
    labeloffset:=labeloffset/8;
  else:
    for k=ymin step ypas until ymax:
      label.bot(""&decimal(k)&"",Projette((xmin,k,zmin)));
    endfor;
    for k=xmin step xpas until xmax:
      label.rt(""&decimal(k)&"",Projette((k,ymax,zmin)));
    endfor;
    labeloffset:=8*labeloffset;
    label.bot(btex $y$ etex,Projette((xmin,(ymin+ymax)/2,zmin)));
    label.rt(btex $x$ etex,Projette(((xmin+xmax)/2,ymax,zmin)));
    labeloffset:=labeloffset/8;
  fi;
enddef;

vardef Legende(expr xmax,ymax,nbplan,zechelle)=
  path legende[];
  for k=1 upto nbplan+1:
    legende[k]=Projette((-xmax,ymax+1,k-0.5))--Projette((-xmax,ymax+1,k))--Projette((-xmax,ymax+2,k))--Projette((-xmax,ymax+2,k-0.5))--cycle;
  endfor;
  for k=1 upto nbplan+1:
    fill legende[k] withcolor Outcolor[k];
    draw legende[k];
    label.rt(""&decimal(zechelle*(k-1))&" - "&decimal(zechelle*k)&"",Projette((-xmax,ymax+2,k-0.25)));
  endfor;
enddef;

vardef MaillageZ(expr fn,xmin,xmax,ymin,ymax,nblignes,nbpoints)=
  traits:=true;
  scantokens("vardef Fz(expr X,Y)="&fn&" enddef;");
  IncX:=(xmax-xmin)/nbpoints;
  IncY:=(ymax-ymin)/nblignes;
  color Yc[][],Xc[][];
  for ligne=0 upto nblignes:
    y:=ymax-ligne*IncY;
    x:=xmin;
    Yc[ligne][0]=(x,y,Fz(x,y));
    for k=1 upto nbpoints:
      Yc[ligne][k]=((xmin+k*IncX,y,Fz(xmin+k*IncX,y)));
    endfor;
  endfor;
  for l=0 upto nbpoints:
    x:=xmax-l*IncX;
    y:=ymin;
    Xc[l][0]:=(x,y,Fz(x,y));
    for k=1 upto nblignes:
      Xc[l][k]=(x,ymin+k*IncY,Fz(x,ymin+k*IncY));
    endfor;
  endfor;
  for k=nblignes downto 0:
    draw Projette(Yc[k][nbpoints])
    for l=(nbpoints-1) downto 0:
      ..Projette(Yc[k][l])
    endfor;
  endfor;
  for l=nbpoints downto 0:
    draw Projette(Xc[l][nblignes])
    for k=nblignes-1 downto 0:
      ..Projette(Xc[l][k])
    endfor;
  endfor;
enddef;

endinput;