#include <QtGui>
#include <QtCore>
// #include <QGLWidget>
#include <QtOpenGL>
#include <QIODevice>
#include <math.h>
#include "surface3D.h"
#include "scene3D.h"

const static float R=0.85; // радиус сферы // глобальная переменная
const static float pi=3.141593, k=pi/180; // глобальная переменная
static int iteration_max=4; // число итераций 
static float eps=0.001; // величина приращения радиуса // глобальная переменная

static int num; // текущий номер треугольника
//static int num3; // номер узла
GLuint n_triangleList0; // хранит первый свободный номер для идентификации дисплейного списка

int Mvertex_Sph_size_1, Mvertex_Sph_size_2, Mtriangle_Sph_size, Mtriangle_Sph_size_1, Mtriangle_Sph_size_2;
int first_part1, last_part1, first_part2, last_part2, first_part3, last_part3; // первая и последняя точки 

QVector<int> Base; // основные параметры сферы
QVector<int> Base_v_r; // дискретные радиусы узлов
QVector<float> Base_v_a; // углы узлов
QVector<int> Base_t_v; // номера узлов треугольника 
QVector<int> Base_v_t; // номера треугольников узлов

void putbase() // загрузить базу
{
   // считываю информацию из бинарного файла
   QFile file1("base001.dat");
   file1.open(QIODevice::ReadOnly);   
   QDataStream in1(&file1);
   in1 >> Base; // вектор
    
   // считываю информацию из бинарного файла
   QFile file2("base002.dat"); // файл с дискретными радиусами
   file2.open(QIODevice::ReadOnly);   
   QDataStream in2(&file2);
   in2 >> Base_v_r; // вектор 
   
   int par_demo_relief; // демо-рельеф
   
   QFile fileP("demo.txt");
   fileP.open(QIODevice::ReadOnly);   
   QTextStream inP(&fileP);
   inP >> par_demo_relief;  
   
   if (par_demo_relief != 0)  
   {
      Base_v_r[0]=4;
      Base_v_r[1]=3;
      Base_v_r[2]=4; 
      Base_v_r[3]=7;
      Base_v_r[4]=4;
      Base_v_r[5]=3;
      Base_v_r[6]=3;
      Base_v_r[7]=3;
      Base_v_r[8]=3;
      Base_v_r[9]=3;
      Base_v_r[10]=4;
      Base_v_r[11]=4;
      Base_v_r[12]=4;
      Base_v_r[13]=3;
      Base_v_r[14]=3;
      Base_v_r[15]=4;
      Base_v_r[16]=2;
      Base_v_r[17]=3;
      Base_v_r[18]=3;
      Base_v_r[19]=2;
      Base_v_r[20]=3;
      Base_v_r[21]=3;
      Base_v_r[22]=3;
      Base_v_r[23]=3;
      Base_v_r[24]=4;
      Base_v_r[25]=5;
      Base_v_r[26]=3;
      Base_v_r[27]=2;
      Base_v_r[28]=2;
      Base_v_r[29]=3;
      Base_v_r[30]=3;
      Base_v_r[31]=2;
      Base_v_r[32]=2;
      Base_v_r[33]=2;
      Base_v_r[34]=2;
      Base_v_r[35]=1;
      Base_v_r[36]=2;
      Base_v_r[37]=3;
      Base_v_r[38]=2;
      Base_v_r[39]=2;
      Base_v_r[40]=2;
      Base_v_r[41]=2;
      Base_v_r[42]=3;
      Base_v_r[43]=3;
      Base_v_r[44]=3;
      Base_v_r[45]=2;
      Base_v_r[46]=1;
      Base_v_r[47]=1;
      Base_v_r[48]=2;
      Base_v_r[49]=2;
      Base_v_r[50]=2;
      Base_v_r[51]=1;
      Base_v_r[52]=1;
      Base_v_r[53]=2;
      Base_v_r[54]=1;
      Base_v_r[55]=1;
      Base_v_r[56]=1;
      Base_v_r[57]=1;
      Base_v_r[58]=2;
      Base_v_r[59]=2;
      Base_v_r[60]=1;
      Base_v_r[61]=1;
      Base_v_r[62]=1;
      Base_v_r[63]=1;
      Base_v_r[64]=2;
      Base_v_r[65]=2;
      Base_v_r[66]=2;
      Base_v_r[67]=2;
      Base_v_r[68]=2;
      Base_v_r[69]=1;
      Base_v_r[70]=1;
      Base_v_r[71]=1;
      Base_v_r[72]=1;
      Base_v_r[73]=1;
      Base_v_r[74]=1;
      Base_v_r[75]=2;
      Base_v_r[76]=0;
      Base_v_r[77]=1;
      Base_v_r[78]=1;
      Base_v_r[79]=1;
      Base_v_r[80]=1;
      Base_v_r[81]=0;
      Base_v_r[82]=1;
      Base_v_r[83]=0;
      Base_v_r[84]=1;
      Base_v_r[85]=1;
      Base_v_r[86]=1;
      Base_v_r[87]=0;
      Base_v_r[88]=1;
      Base_v_r[89]=1;
      Base_v_r[90]=0;
      Base_v_r[91]=1;
      Base_v_r[92]=1;
      Base_v_r[93]=2;
      Base_v_r[94]=1;
      Base_v_r[95]=1;
      Base_v_r[96]=1;
      Base_v_r[97]=1;
      Base_v_r[98]=0;
      Base_v_r[99]=1;
      Base_v_r[100]=0;
      Base_v_r[101]=1;
      Base_v_r[102]=1;
      Base_v_r[103]=0;
      Base_v_r[104]=1;
      Base_v_r[105]=1;
      Base_v_r[106]=1;
      Base_v_r[109]=1;
      Base_v_r[117]=1;
      Base_v_r[125]=1;
      Base_v_r[126]=1;
      Base_v_r[127]=1;   
      Base_v_r[142]=1;  
   }  
    
   // считываю информацию из бинарного файла
   QFile file3("base003.dat");
   file3.open(QIODevice::ReadOnly);   
   QDataStream in3(&file3);
   in3 >> Base_v_a; // вектор   
    
   // считываю информацию из бинарного файла
   QFile file4("base004.dat");
   file4.open(QIODevice::ReadOnly);   
   QDataStream in4(&file4);
   in4 >> Base_t_v; // вектор  
   
   // считываю информацию из бинарного файла
   QFile file5("base005.dat");
   file5.open(QIODevice::ReadOnly);   
   QDataStream in5(&file5);
   in5 >> Base_v_t; // вектор     
    
   //--
    
   iteration_max=Base[0]; // число итераций
   Mvertex_Sph_size_1=Base[1]; // число узлов в 1-ой части
   Mvertex_Sph_size_2=Base[2]; // число узлов во 2-ой части
   Mtriangle_Sph_size_1=Base[3]; // число треугольников в 1-ой части
   Mtriangle_Sph_size_2=Base[4]; // число треугольников во 2-ой части
   first_part1=Base[5]; // первая точка в 1-ой части
   last_part1=Base[6]; // последняя точка в 1-ой части
   first_part2=Base[7]; // первая точка во 2-ой части  
   last_part2=Base[8]; // последняя точка во 2-ой части    
   first_part3=Base[9]; // первая точка в 3-ей части  
   last_part3=Base[10]; // последняя точка в 3-ей части 
     
   Mtriangle_Sph_size=2*Mtriangle_Sph_size_1+Mtriangle_Sph_size_2;  
}

//--

int putMtriangle_Sph_size()
{
   return Mtriangle_Sph_size;
}

int put_last_part3()
{
   return last_part3;
}

//--

Surface3D::Surface3D() // конструктор треугольников по умолчанию, с счетчиком num
{
   n0=Base_t_v[num*(3+1)+0]; // номер узла
   n1=Base_t_v[num*(3+1)+1];
   n2=Base_t_v[num*(3+1)+2];
      
   ps=Base_t_v[num*(3+1)+3]; // параметр построения сетки

   //--
      
   R0=   Base_v_r[n0]; // матрица дискретных радиусов 
   teta0=Base_v_a[n0*2+0]; // матрица углов тета и фи
   phi0= Base_v_a[n0*2+1]; // матрица углов тета и фи
      
   R1=   Base_v_r[n1];
   teta1=Base_v_a[n1*2+0];
   phi1= Base_v_a[n1*2+1];  
      
   R2=   Base_v_r[n2];
   teta2=Base_v_a[n2*2+0];
   phi2= Base_v_a[n2*2+1];
   
   //--
   
   GLfloat rR0, rR1, rR2; // реальные (недискретные) радиусы
   
   R_fun(R0, &rR0); // переход от дискретного радиуса к реальному радиусу     
   R_fun(R1, &rR1);       
   R_fun(R2, &rR2);   
   
   //--

   x0=rR0*sin(teta0)*sin(phi0);
   y0=rR0*sin(teta0)*cos(phi0);
   z0=rR0*cos(teta0);
      
   x1=rR1*sin(teta1)*sin(phi1);
   y1=rR1*sin(teta1)*cos(phi1);
   z1=rR1*cos(teta1);
      
   x2=rR2*sin(teta2)*sin(phi2);
   y2=rR2*sin(teta2)*cos(phi2);
   z2=rR2*cos(teta2);
   
   if (num==0)
   {
      // возвращает первый свободный номер для идентификации дисплейного списка (таблицы отображений)
      n_triangleList0 = glGenLists(Mtriangle_Sph_size); // OpenGL самостоятельно присваивает имя таблице   
   }
   n_triangleList = n_triangleList0+num; // идентификация дисплейного списка 
   
   this->create_triangleList(1.0f); // инициализация для таблицы отображений
   
   num++;
}

//--

Surface3D::Surface3D(int num2) // конструктор треугольников с параметром
{
   n0=Base_t_v[num2*(3+1)+0]; // номер узла
   n1=Base_t_v[num2*(3+1)+1];
   n2=Base_t_v[num2*(3+1)+2];
      
   ps=Base_t_v[num2*(3+1)+3]; // параметр построения сетки 
   
   //--
      
   R0=   Base_v_r[n0]; // матрица дискретных радиусов 
   teta0=Base_v_a[n0*2+0]; // матрица углов тета и фи
   phi0= Base_v_a[n0*2+1]; // матрица углов тета и фи
      
   R1=   Base_v_r[n1];
   teta1=Base_v_a[n1*2+0];
   phi1= Base_v_a[n1*2+1];  
      
   R2=   Base_v_r[n2];
   teta2=Base_v_a[n2*2+0];
   phi2= Base_v_a[n2*2+1];
   
   //--
   
   GLfloat rR0, rR1, rR2; // реальные (недискретные) радиусы
   
   R_fun(R0, &rR0); // переход от дискретного радиуса к реальному радиусу     
   R_fun(R1, &rR1);       
   R_fun(R2, &rR2);   
   
   //--

   x0=rR0*sin(teta0)*sin(phi0);
   y0=rR0*sin(teta0)*cos(phi0);
   z0=rR0*cos(teta0);
      
   x1=rR1*sin(teta1)*sin(phi1);
   y1=rR1*sin(teta1)*cos(phi1);
   z1=rR1*cos(teta1);
      
   x2=rR2*sin(teta2)*sin(phi2);
   y2=rR2*sin(teta2)*cos(phi2);
   z2=rR2*cos(teta2);  
}

//--

Surface3D::~Surface3D() {} // деструктор

//--

// рельефная радиус-функция
void Surface3D::R_fun(GLint x, GLfloat *y) 
{
   // 1/pow(4,iteration_max-4) - пропорциональный коэффицент, зависящий от числа итераций   
 
   switch(x)
   {
      case 0: *y=R; break; // 0 м
      case 1: *y=R*(1+0.005/pow(4,iteration_max-4)); break; // 100 м
      case 2: *y=R*(1+0.010/pow(4,iteration_max-4)); break; // 200 м
      case 3: *y=R*(1+0.020/pow(4,iteration_max-4)); break; // 500 м
      case 4: *y=R*(1+0.035/pow(4,iteration_max-4)); break; // 1000 м
      case 5: *y=R*(1+0.050/pow(4,iteration_max-4)); break; // 2000 м
      case 6: *y=R*(1+0.060/pow(4,iteration_max-4)); break; // 3000 м
      case 7: *y=R*(1+0.065/pow(4,iteration_max-4)); break; // 4000 м
      case 8: *y=R*(1+0.070/pow(4,iteration_max-4)); break; // 5000 м
      case 9: *y=R*(1+0.075/pow(4,iteration_max-4)); break; // выше 5000 м (условно 5500 м)
      
      default: *y=R;       
   }
}

// цветовая радиус-функция
void Surface3D::C_fun(GLint x, GLfloat *c1, GLfloat *c2, GLfloat *c3) 
{ 
   switch(x)
   {
      case 0: *c1=0.5098; *c2=0.7608; *c3=0.9647; break; // 0 м
      case 1: *c1=0.3098; *c2=0.9686; *c3=0.5294; break; // 100 м
      case 2: *c1=0.6000; *c2=1.0000; *c3=0.6628; break; // 200 м
      case 3: *c1=0.9216; *c2=0.8235; *c3=0.5529; break; // 500 м
      case 4: *c1=0.8863; *c2=0.6745; *c3=0.3922; break; // 1000 м
      case 5: *c1=0.8431; *c2=0.5647; *c3=0.2549; break; // 2000 м
      case 6: *c1=0.8392; *c2=0.4980; *c3=0.2902; break; // 3000 м
      case 7: *c1=0.8235; *c2=0.4431; *c3=0.2118; break; // 4000 м
      case 8: *c1=0.7059; *c2=0.3804; *c3=0.1804; break; // 5000 м
      case 9: *c1=0.5843; *c2=0.2863; *c3=0.1529; break; // выше 5000 м (условно 5500 м)
      
      default: *c1=0; *c2=0; *c3=0;       
   }
}

void Surface3D::paint() // изобразить треугольник
{  
   GLfloat rR0, rR1, rR2; // реальные (недискретные) радиусы
   
   R_fun(R0, &rR0); // переход от дискретного радиуса к реальному радиусу     
   R_fun(R1, &rR1);       
   R_fun(R2, &rR2);    
       
   GLfloat color1, color2, color3; // хранят цвет, для Cfun() 
   
   // треугольник
   glBegin(GL_TRIANGLES);
      C_fun(R0, &color1, &color2, &color3);
      glColor4f(color1, color2, color3, 1.0f);
      glVertex3f( x0, y0 , z0 );
         
      C_fun(R1, &color1, &color2, &color3);
      glColor4f(color1, color2, color3, 1.0f);
      glVertex3f( x1, y1 , z1 );
         
      C_fun(R2, &color1, &color2, &color3);
      glColor4f(color1, color2, color3, 1.0f);
      glVertex3f( x2, y2 , z2 );
   glEnd();      
}

void Surface3D::paint_no_color() // изобразить треугольник без цветовой функции
{     
   // треугольник
   glBegin(GL_TRIANGLES);
      glVertex3f( x0, y0 , z0 );
      glVertex3f( x1, y1 , z1 );
      glVertex3f( x2, y2 , z2 );
   glEnd();      
}

void Surface3D::netpaint() // построить сетку
{  
   GLfloat rR0, rR1, rR2; // реальные (недискретные) радиусы
   
   R_fun(R0, &rR0); // переход от дискретного радиуса к реальному радиусу     
   R_fun(R1, &rR1);       
   R_fun(R2, &rR2);    
   
   GLfloat xtemp0, ytemp0, ztemp0, xtemp1, ytemp1, ztemp1, xtemp2, ytemp2, ztemp2;    

   // построение сетки
   xtemp0=(rR0+eps)*sin(teta0)*sin(phi0);
   ytemp0=(rR0+eps)*sin(teta0)*cos(phi0);
   ztemp0=(rR0+eps)*cos(teta0);
      
   xtemp1=(rR1+eps)*sin(teta1)*sin(phi1);
   ytemp1=(rR1+eps)*sin(teta1)*cos(phi1);
   ztemp1=(rR1+eps)*cos(teta1);
      
   xtemp2=(rR2+eps)*sin(teta2)*sin(phi2);
   ytemp2=(rR2+eps)*sin(teta2)*cos(phi2);
   ztemp2=(rR2+eps)*cos(teta2);      
   
   // сетка
   glLineWidth(1);
   glColor4f(0.50f, 0.50f, 0.50f, 1.0f);           
   if (ps==0)
   {
      glBegin(GL_LINES); // 3 линия
         glVertex3f( xtemp2, ytemp2 , ztemp2 );
         glVertex3f( xtemp0, ytemp0 , ztemp0 );
      glEnd();       
      glBegin(GL_LINES); // 2 линия
         glVertex3f( xtemp1, ytemp1 , ztemp1 );
         glVertex3f( xtemp2, ytemp2 , ztemp2 );
      glEnd();   
   }
   else
   {
      glBegin(GL_LINES); // 1 линия
         glVertex3f( xtemp0, ytemp0 , ztemp0 );
         glVertex3f( xtemp1, ytemp1 , ztemp1 );
      glEnd();  
   }  
}

void Surface3D::create_triangleList(GLfloat fSize/*=1.0f*/) // создание таблиц отображений
{                                                                   
   glNewList(n_triangleList, GL_COMPILE); // начало таблицы отображений  
      this->paint();
      this->netpaint();
   glEndList(); // конец таблицы отображений 
} 

GLuint Surface3D::put_n_triangleList()
{
   return n_triangleList;
}

void Surface3D::redefine(int newR0, int newR1, int newR2) // переопределение радиусов
{
   R0=   newR0;    
   R1=   newR1;
   R2=   newR2;
   
   //--
   
   GLfloat rR0, rR1, rR2; // реальные (недискретные) радиусы
   
   R_fun(R0, &rR0); // переход от дискретного радиуса к реальному радиусу     
   R_fun(R1, &rR1);       
   R_fun(R2, &rR2);   
   
   //--

   x0=rR0*sin(teta0)*sin(phi0);
   y0=rR0*sin(teta0)*cos(phi0);
   z0=rR0*cos(teta0);
      
   x1=rR1*sin(teta1)*sin(phi1);
   y1=rR1*sin(teta1)*cos(phi1);
   z1=rR1*cos(teta1);
      
   x2=rR2*sin(teta2)*sin(phi2);
   y2=rR2*sin(teta2)*cos(phi2);
   z2=rR2*cos(teta2);
}

void Surface3D::single_out() //  выделить треугольник
{  
   GLfloat rR0, rR1, rR2; // реальные (недискретные) радиусы
   
   R_fun(R0, &rR0); // переход от дискретного радиуса к реальному радиусу     
   R_fun(R1, &rR1);       
   R_fun(R2, &rR2);    
   
   GLfloat xtemp0, ytemp0, ztemp0, xtemp1, ytemp1, ztemp1, xtemp2, ytemp2, ztemp2;    

   // построение треугольников 
   xtemp0=(rR0+eps)*sin(teta0)*sin(phi0);
   ytemp0=(rR0+eps)*sin(teta0)*cos(phi0);
   ztemp0=(rR0+eps)*cos(teta0);
      
   xtemp1=(rR1+eps)*sin(teta1)*sin(phi1);
   ytemp1=(rR1+eps)*sin(teta1)*cos(phi1);
   ztemp1=(rR1+eps)*cos(teta1);
      
   xtemp2=(rR2+eps)*sin(teta2)*sin(phi2);
   ytemp2=(rR2+eps)*sin(teta2)*cos(phi2);
   ztemp2=(rR2+eps)*cos(teta2); 
   
   glColor4f(1.00f, 0.00f, 0.00f, 1.0f);
   // треугольник
   glBegin(GL_TRIANGLES);
      glVertex3f( xtemp0, ytemp0 , ztemp0 );
      glVertex3f( xtemp1, ytemp1 , ztemp1 );
      glVertex3f( xtemp2, ytemp2 , ztemp2 );
   glEnd();      
}

void Surface3D::single_out_line(int i) // выделить линию, противолежащию узлу
{
   GLfloat rR0, rR1, rR2; // реальные (недискретные) радиусы
   
   R_fun(R0, &rR0); // переход от дискретного радиуса к реальному радиусу     
   R_fun(R1, &rR1);       
   R_fun(R2, &rR2);    
   
   GLfloat xtemp0, ytemp0, ztemp0, xtemp1, ytemp1, ztemp1, xtemp2, ytemp2, ztemp2;    

   // построение точек
   xtemp0=(rR0+1.5*eps)*sin(teta0)*sin(phi0);
   ytemp0=(rR0+1.5*eps)*sin(teta0)*cos(phi0);
   ztemp0=(rR0+1.5*eps)*cos(teta0);
      
   xtemp1=(rR1+1.5*eps)*sin(teta1)*sin(phi1);
   ytemp1=(rR1+1.5*eps)*sin(teta1)*cos(phi1);
   ztemp1=(rR1+1.5*eps)*cos(teta1);
      
   xtemp2=(rR2+1.5*eps)*sin(teta2)*sin(phi2);
   ytemp2=(rR2+1.5*eps)*sin(teta2)*cos(phi2);
   ztemp2=(rR2+1.5*eps)*cos(teta2); 
      
   glLineWidth(2);
   glColor4f(1.00f, 0.00f, 0.00f, 1.0f);
   if (i==n0)
   {
      glBegin(GL_LINES);
         glVertex3f( xtemp1, ytemp1 , ztemp1 );
         glVertex3f( xtemp2, ytemp2 , ztemp2 );
      glEnd();
   } 
   else if (i==n1) 
        {
           glBegin(GL_LINES);
              glVertex3f( xtemp0, ytemp0 , ztemp0 );
              glVertex3f( xtemp2, ytemp2 , ztemp2 );
           glEnd();   
        }
        else /* i==n2 */ 
        {
           glBegin(GL_LINES);
              glVertex3f( xtemp0, ytemp0 , ztemp0 );
              glVertex3f( xtemp1, ytemp1 , ztemp1 );
           glEnd();         
        }      
}

void Surface3D::single_out_point(int i) // выделить узел точкой
{
   GLfloat xtemp, ytemp, ztemp;
   
   if (i==n0) 
      {
         xtemp=x0;
         ytemp=y0;
         ztemp=z0;
      }
   else if (i==n1) 
           {
              xtemp=x1;
              ytemp=y1;
              ztemp=z1;
           } 
        else /* i==n2 */ 
           {
              xtemp=x2;
              ytemp=y2;
              ztemp=z2;  
           }
   
           
   glPointSize(5);
   glColor4f(1.00f, 0.00f, 1.00f, 1.0f);
   glBegin(GL_POINTS);
      glVertex3f( xtemp, ytemp , ztemp );
   glEnd();                      
}

//--

void R_save(Surface3D* tr) // записать радиусы
{     
   for (int i=0; i<Mtriangle_Sph_size; i++)
   {     
      Base_v_r[tr[i].putn0()]=tr[i].putR0();
      Base_v_r[tr[i].putn1()]=tr[i].putR1();
      Base_v_r[tr[i].putn2()]=tr[i].putR2();  
   }
      
   // записываю в файл  
   QFile file_R_save("save.dat");
   file_R_save.open(QIODevice::WriteOnly);
   QDataStream out_R_save(&file_R_save);
   out_R_save << Base_v_r;
   file_R_save.close(); // файл можно и не закрывать, если он дальше не используется снова       
}

void R_load() // загрузить радиусы 
{
   // загружаю из файла
   QFile file_R_load("save.dat"); // файл с дискретными радиусами
   file_R_load.open(QIODevice::ReadOnly);   
   QDataStream in_R_load(&file_R_load);
   in_R_load >> Base_v_r; // вектор 
   file_R_load.close(); // файл можно и не закрывать, если он дальше не используется снова 
}

void R_new() // загрузить радиусы 
{
   // загружаю из файла
   QFile file_R_load("base002.dat"); // файл с дискретными радиусами
   file_R_load.open(QIODevice::ReadOnly);   
   QDataStream in_R_load(&file_R_load);
   in_R_load >> Base_v_r; // вектор 
   file_R_load.close(); // файл можно и не закрывать, если он дальше не используется снова 
}

//--

int Surface3D::putn0() // вернуть n0
{
   return n0;
}

int Surface3D::putn1() // вернуть n1
{
   return n1;
}

int Surface3D::putn2() // вернуть n2
{
   return n2;
}

//--

int Surface3D::putR0() // вернуть R0
{
   return R0;
}

int Surface3D::putR1() // вернуть R1
{
   return R1;
}

int Surface3D::putR2() // вернуть R2
{
   return R2;
}

//--



//--

void set_num(int num2) // установить счетчик
{
   num=num2;
}

void single_out_v(int i, Surface3D *t) // выделить узел
{
   int tri0, tri1, tri2, tri3, tri4, tri5;
   
   tri0=Base_v_t[i*6+0];
   tri1=Base_v_t[i*6+1];
   tri2=Base_v_t[i*6+2];
   tri3=Base_v_t[i*6+3];
   tri4=Base_v_t[i*6+4];
   tri5=Base_v_t[i*6+5];
   
   t[tri0].single_out();
   t[tri1].single_out();
   t[tri2].single_out();
   t[tri3].single_out();   
   t[tri4].single_out();    

   if (tri4 != tri5) // определяю: шестиугольник или пятиугольник
   {
      t[tri5].single_out();
   }
      
}

void single_out_v_contour(int i, Surface3D *t) // выделить узел по контору всех треугольников
{
   int tri0, tri1, tri2, tri3, tri4, tri5;
   
   tri0=Base_v_t[i*6+0];
   tri1=Base_v_t[i*6+1];
   tri2=Base_v_t[i*6+2];
   tri3=Base_v_t[i*6+3];
   tri4=Base_v_t[i*6+4];
   tri5=Base_v_t[i*6+5];
   
   t[tri0].single_out_point(i);
   
   t[tri0].single_out_line(i);
   t[tri1].single_out_line(i);
   t[tri2].single_out_line(i);
   t[tri3].single_out_line(i);   
   t[tri4].single_out_line(i);    

   if (tri4 != tri5) // определяю: шестиугольник или пятиугольник
   {
      t[tri5].single_out_line(i);
   }
}

//--

int put_R(int i, Surface3D *t) // возвращает радиус узла для элемента массива объектов
{
   int y, tri0;
   
   tri0=Base_v_t[i*6+0];
   
   if (i==t[tri0].putn0()) 
      y=t[tri0].putR0();
   else if (i==t[tri0].putn1()) 
           y=t[tri0].putR1();
        else /* i==t[tri0].putn2() */ 
           y=t[tri0].putR2(); 
           
   return y;  
}

// переопределить радиус узла и вернуть номера треугольников
void redefine_v(int i, int newR, Surface3D *t, int *ntr0, int *ntr1, int *ntr2, int *ntr3, int *ntr4, int *ntr5)
{ // номер узла, новый радиус, указатель на массив объектов, указатели на номера треугольников 
   int tri0, tri1, tri2, tri3, tri4, tri5;
      
   tri0=Base_v_t[i*6+0];
   tri1=Base_v_t[i*6+1];
   tri2=Base_v_t[i*6+2];
   tri3=Base_v_t[i*6+3];
   tri4=Base_v_t[i*6+4];
   tri5=Base_v_t[i*6+5];
      
   *ntr0=tri0;
   *ntr1=tri1; 
   *ntr2=tri2;
   *ntr3=tri3; 
   *ntr4=tri4;
   *ntr5=tri5; 
   
   if (newR > 9) newR=9;
   if (newR < 0) newR=0;                               

   if (i==t[tri0].putn0()) 
      t[tri0].redefine(newR, t[tri0].putR1(), t[tri0].putR2());
   else if (i==t[tri0].putn1()) 
           t[tri0].redefine(t[tri0].putR0(), newR, t[tri0].putR2());
        else /* i==t[tri0].putn2() */ 
           t[tri0].redefine(t[tri0].putR0(), t[tri0].putR1(), newR);
   
   if (i==t[tri1].putn0()) 
      t[tri1].redefine(newR, t[tri1].putR1(), t[tri1].putR2());
   else if (i==t[tri1].putn1()) 
           t[tri1].redefine(t[tri1].putR0(), newR, t[tri1].putR2());
        else /* i==t[tri1].putn2() */ 
           t[tri1].redefine(t[tri1].putR0(), t[tri1].putR1(), newR);   
         
   if (i==t[tri2].putn0()) 
      t[tri2].redefine(newR, t[tri2].putR1(), t[tri2].putR2());
   else if (i==t[tri2].putn1()) 
           t[tri2].redefine(t[tri2].putR0(), newR, t[tri2].putR2());
        else /* i==t[tri2].putn2() */ 
           t[tri2].redefine(t[tri2].putR0(), t[tri2].putR1(), newR);   
           
   if (i==t[tri3].putn0()) 
      t[tri3].redefine(newR, t[tri3].putR1(), t[tri3].putR2());
   else if (i==t[tri3].putn1()) 
           t[tri3].redefine(t[tri3].putR0(), newR, t[tri3].putR2());
        else /* i==triangle[tri3].putn2() */ 
           t[tri3].redefine(t[tri3].putR0(), t[tri3].putR1(), newR);  
           
   if (i==t[tri4].putn0()) 
      t[tri4].redefine(newR, t[tri4].putR1(), t[tri4].putR2());
   else if (i==t[tri4].putn1()) 
           t[tri4].redefine(t[tri4].putR0(), newR, t[tri4].putR2());
        else /* i==t[tri4].putn2() */ 
           t[tri4].redefine(t[tri4].putR0(), t[tri4].putR1(), newR);       
           
   if (i==t[tri5].putn0()) 
      t[tri5].redefine(newR, t[tri5].putR1(), t[tri5].putR2());
   else if (i==t[tri5].putn1()) 
           t[tri5].redefine(t[tri5].putR0(), newR, t[tri5].putR2());
        else /* i==t[tri5].putn2() */ 
           t[tri5].redefine(t[tri5].putR0(), t[tri5].putR1(), newR);                     
}

//--

GLfloat Surface3D::putx0() // вернуть x0
{
   return x0;
}

GLfloat Surface3D::puty0() // вернуть y0
{
   return y0;
}

GLfloat Surface3D::putz0() // вернуть z0
{
   return z0;
}

GLfloat Surface3D::putx1() // вернуть x1
{
   return x1;
}

GLfloat Surface3D::puty1() // вернуть y1
{
   return y1;
}

GLfloat Surface3D::putz1() // вернуть z1
{
   return z1;
}

GLfloat Surface3D::putx2() // вернуть x2
{
   return x2;
}

GLfloat Surface3D::puty2() // вернуть y2
{
   return y2;
}

GLfloat Surface3D::putz2() // вернуть z2
{
   return z2;
}

GLfloat Surface3D::putteta0() // вернуть teta0
{
   return teta0;
}

GLfloat Surface3D::putteta1() // вернуть teta1
{
   return teta1;
}

GLfloat Surface3D::putteta2() // вернуть teta0
{
   return teta2;
}

GLfloat Surface3D::putphi0() // вернуть phi0
{
   return phi0;
}

GLfloat Surface3D::putphi1() // вернуть phi1
{
   return phi1;
}

GLfloat Surface3D::putphi2() // вернуть phi2
{
   return phi2;
}