#include<iostream>
#include<cstdlib>
#include<fstream>
#include<cmath>
#include<vector>
#include<algorithm>

using namespace std;

#include "postscript.h"


class tri {
    private:
     double x0, y0, z0;
     double x1, y1, z1;
     double x2, y2, z2;

    public:
     tri(double a0, double b0, double c0,
         double a1, double b1, double c1,
         double a2, double b2, double c2);

     void dib(PostScript& p);
     friend bool operator < (const tri&, const tri&);
};


tri::tri(double a0, double b0, double c0,
         double a1, double b1, double c1,
         double a2, double b2, double c2)

{
   x0= a0;  y0= b0; z0= c0;
   x1= a1;  y1= b1; z1= c1;
   x2= a2;  y2= b2; z2= c2;
}

void tri::dib(PostScript& p)
{
   p.setcolor(1,1,1);
   p.moveto(x0,y0,z0);
   p.lineto(x1,y1,z1);
   p.lineto(x2,y2,z2);
   p.lineto(x0,y0,z0);
   p.fill();
   p.setcolor(0,0,0);
   p.moveto(x0,y0,z0);
   p.lineto(x1,y1,z1);
   p.lineto(x2,y2,z2);
   p.lineto(x0,y0,z0);
}

bool operator < (const tri& a, const tri& b)
{
   return a.z0 <b.z0;
}

   
    
void torus(double th, double ph, double r, double R, 
                            double& x, double& y, double& z)
{
   x= (R+r*cos(ph))*sin(th);
   y= r*sin(ph);
   z= (R+r*cos(ph))*cos(th);
}


int main(int nargs, char* args[])
{
    PostScript p("torus.ps");
    p.pers32( 60, 20 );   // observador a 60 cm y plano a 40

    p.rotacion3('x', 30);

    int Np=12;
    int Nt=32;
    double R=5;
    double r=2;
    vector<tri> v;


    for (int i=0; i<Np; i++)
      {
       double ph0= 2*M_PI*  i  /Np;
       double ph1= 2*M_PI*(i+1)/Np;
       for (int j=0; j<Nt; j++)
          {
           double th0= 2*M_PI*  j  /Nt;
           double th1= 2*M_PI*(j+1)/Nt;
           double x0, y0, z0;
           double x1, y1, z1;
           double x2, y2, z2;
           double x3, y3, z3;
           torus(th0, ph0, r, R, x0, y0, z0);
           torus(th0, ph1, r, R, x1, y1, z1);
           torus(th1, ph0, r, R, x2, y2, z2);
           torus(th1, ph1, r, R, x3, y3, z3);

           v.push_back(tri(x0,y0,z0, x1,y1,z1, x2,y2,z2));
           v.push_back(tri(x2,y2,z2, x1,y1,z1, x3,y3,z3));
          }
      }

    sort(v.begin(), v.end());

    for (vector<tri>::iterator k= v.begin(); k!=v.end(); k++)
       k->dib(p);
  
    return EXIT_SUCCESS;
}










