Tracé de la surface « breather » (mp-solid)

Auteur ou autrice : Christophe Poulain.

Mise en ligne le 20 janvier 2023

Image du résultat de l’exemple

Voici un tracé de la surface « breather » (https://en.wikipedia.org/wiki/Breather) 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(1500,60,30,50);
incolor:=gris;
arcenciel:=true;
b:=0.4;
r:=1-(0.4**2);
w:=sqrt(r);
draw Sparam("(-u+(2*r*ch(b*u)*sh(b*u))/(b*(((w*ch(b*u))**2)+(b*sin(w*v))**2)),(2*w*ch(b*u)*(-(w*cos(v)*cos(w*v))-sin(v)*sin(w*v)))/(b*(((w*ch(b*u))**2)+(b*sin(w*v))**2)),(2*w*ch(b*u)*(-(w*sin(v)*cos(w*v))+cos(v)*sin(w*v)))/(b*(((w*ch(b*u))**2)+(b*sin(w*v))**2)))",-9.9,9.9,0.66,-37.4,37.4,0.748);finespace;
end

Mots clés : 3Dmp-solidsurface paramétréesyracuse

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

Fichiers

Télécharger l’archive complète

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;