Página principal | Jerarquía de la clase | Lista alfabética | Lista de componentes | Lista de archivos | Miembros de las clases | Archivos de los miembros | Páginas relacionadas

terreno.h

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= terreno.cc                                              Octubre de 1999 =
00003 //=-------------------------------------------------------------------------=
00004 //= Definicion de la clase TERRENO                                          =
00005 //= NOTA: No incluya este encabezado en los modulos.  Incluya a             =
00006 //=       geometria.h.                                                      =
00007 //=-------------------------------------------------------------------------=
00008 //= ADVERTENCIA: ESTE SOFTWARE NO ESTA CONCEBIDO NI DISENNADO PARA EL USO   =
00009 //= EN EQUIPO DE CONTROL EN LINEA EN ENTORNOS PELIGROSOS QUE REQUIERAN UN   =
00010 //= DESEMPENNO LIBRE DE FALLAS, COMO LA OPERACION DE PLANTAS NUCLEARES,     = 
00011 //= SISTEMAS DE NAVEGACION O COMUNICACION EN AVIONES, TRAFICO AEREO,        =
00012 //= EQUIPO MEDICO DEL CUAL DEPENDAN VIDAS HUMANAS O SISTEMAS DE ARMAMENTO,  =
00013 //= EN LOS CUALES UNA FALLA EN EL SOFTWARE PUEDA IMPLICAR DIRECTAMENTE LA   =
00014 //= MUERTE, DANNOS PERSONALES O DANNOS FISICOS Y/O AMBIENTALES GRAVES       =
00015 //= ("ACTIVIDADES DE ALGO RIESGO").                                         =
00016 //=-------------------------------------------------------------------------=
00017 //= Autor original: Oscar J. Chavarro G.  A.K.A. JEDILINK. Copyright (c),   =
00018 //= 1997 - 2003, oscarchavarro@hotmail.com                                  =
00019 //= AQUYNZA es software libre, y se rige bajo los terminos de la licencia   =
00020 //= LGPL de GNU (http://www.gnu.org). Para mayor informacion respecto a la  =
00021 //= licencia de uso, consulte el archivo ./doc/LICENCIA en la distribucion. =
00022 //===========================================================================
00023 
00024 #include "jed_defs.h"
00025 
00026 #ifndef __GEOMETRIA__
00027     #error "No incluya a terreno.h, incluya a geometria.h!"
00028 #endif
00029 
00030 #ifdef VEL_ROSITA
00031     #include "toolkits/geom/geometria.h"
00032 #endif
00033 #include "toolkits/util/dem.h"
00034 
00035 //#define DEBUG_TERRENO 1
00036 
00037 #ifdef DEBUG_TERRENO
00038   #include "lista.cc"
00039 #endif
00040 
00041 class TERRENO : public GEOMETRIA
00042 {
00043   private:
00044     //-----------------------------------------------------------------------
00045     PALETA *Paleta;
00046     IMAGEN *imagen;
00047     long int _x_tam;    // Tamanno del terreno en muestras
00048     long int _y_tam;
00049     long int vertices_tam; // Arreglo de vertices con la geometria del terreno
00050     VERTICE_GL *vertices_arr;
00051     GLubyte *colores_arr;
00052     GLuint **TIras_arr; // Arreglo dinamico de tiras (c/u es un arreglo)
00053 
00054     VECTOR _min;
00055     VECTOR _max;
00056     double _escala;
00057     double _factor_exageracion;
00058 
00059     //- Elementos de depuracion ---------------------------------------------
00060     LISTA <int> arr_debug_x;
00061     LISTA <int> arr_debug_y;
00062   #ifdef DEBUG_TERRENO
00063     COLOR color_debug;
00064   #endif
00065 
00066     //- Servicios privados --------------------------------------------------
00067 
00068     // Usados en la visualizacion
00069   #ifdef GL_ENABLED
00070     void pintar_tiras_gl(void);
00071     void pintar_tirasv_gl(void);
00072   #endif
00073 
00074     // Operaciones basicas
00075     void calcular_color(float z, float *r, float *g, float *b);
00076     VECTOR calcule_subnormal(int x1, int y1, int x2, int y2, int x3, int y3);
00077     VECTOR calcule_normal(int x, int y);
00078     double interseccion_celda(RAYO *Rayo, VECTOR &punto, VECTOR &normal,
00079                               int x, int y);
00080     int coord2index_x(double x_coord);
00081     int coord2index_y(double y_coord);
00082 
00083   public:
00084     //- Operaciones standard de GEOMETRIA AQUYNZA ---------------------------
00085     TERRENO(GLOBAL_DEM *Fuente,
00086         long int origen_x, long int origen_y, long int xtam, long int ytam,
00087         double escala, double exageracion);
00088     virtual ~TERRENO();
00089 
00090     // Servicios para raytracers y algoritmos especiales de geometria
00091     double interseccion(RAYO *Rayo, VECTOR &punto, VECTOR &normal);
00092 
00093     // Otros
00094     void anexar_textura(IMAGEN *img);
00095     int clasificar_punto(VECTOR p);
00096     virtual GEOMETRIA *crear_copia(void);
00097 
00098     void minmax(VECTOR *min, VECTOR *max);
00099 
00100   #ifdef GL_ENABLED
00101     void
00102     pintar_gl(CALIDAD_VISUAL *Calidad, MATERIAL* Material, CAMARA *Camara);
00103   #endif
00104     void pintar_povray(FILE *fd);
00105     void pintar_aqz(FILE *fd);
00106 
00107     //- Operaciones particulares de la clase TERRENO ------------------------
00108     void set_paleta(PALETA *P);
00109 //    double altura(double xx, double yy);
00110     BOOLEAN seleccionar(RAYO *Rayito, int *i, int *j);
00111     double index2coord_x(int i);
00112     double index2coord_y(int j);
00113     void elim(void);
00114 };
00115 
00116 inline int
00117 TERRENO::coord2index_x(double x_coord)
00123 {
00124     int i;
00125 
00126     i = (int)(x_coord / (1000*_escala)) - 1;
00127 
00128     return i;
00129 }
00130 
00131 inline int
00132 TERRENO::coord2index_y(double y_coord)
00138 {
00139     int j;
00140 
00141     // OJO: Ese -2 es machete!
00142     j = (int)(y_coord / (1000 * _escala)) + _y_tam - 1 - 2;
00143 
00144     return j;
00145 }
00146 
00147 inline double
00148 TERRENO::index2coord_x(int i)
00152 {
00153     double x;
00154 
00155     //x = (i+1) * 1000 * _escala;
00156     x = vertices_arr[i].x;
00157 
00158     return x;
00159 }
00160 
00161 inline double
00162 TERRENO::index2coord_y(int j)
00166 {
00167     double y;
00168 
00169     //y = 1000 * _escala * (j + 1 - _y_tam);
00170     y = vertices_arr[j*_x_tam].y;
00171 
00172     return y;
00173 }
00174 
00175 inline double
00176 TERRENO::interseccion_celda(RAYO *Rayo, VECTOR &punto, VECTOR &normal, 
00177                             int x, int y)
00191 {
00192     //- Determine los puntos extremos de los triangulos ---------------------
00193     VECTOR a, b, c, d;
00194 
00195     a.x = index2coord_x(x);
00196     a.y = index2coord_y(y);
00197     a.z = vertices_arr[y*_x_tam + x].z;
00198 
00199     b.x = index2coord_x(x);
00200     b.y = index2coord_y(y+1);
00201     b.z = vertices_arr[(y+1)*_x_tam + x].z;
00202 
00203     c.x = index2coord_x(x+1);
00204     c.y = index2coord_y(y);
00205     c.z = vertices_arr[y*_x_tam + x+1].z;
00206 
00207     d.x = index2coord_x(x+1);
00208     d.y = index2coord_y(y+1);
00209     d.z = vertices_arr[(y+1)*_x_tam + x+1].z;
00210 
00211     //- Preparativos con los planos de T1 y T2 ------------------------------
00212     VECTOR O = Rayo->origen;
00213     VECTOR l = Rayo->direccion;
00214     double T = 0;
00215     double pp, pq, m;
00216     double D;
00217 
00218     l.normalizar();
00219 
00220     //- Pruebo con T1 -------------------------------------------------------
00221     double t1 = INFINITO;
00222     VECTOR p1, n1;
00223 
00224     n1 = (a-b).producto_cruz(d-b);
00225     n1.normalizar();
00226     D = n1.x*d.x + n1.y*d.y + n1.z*d.z;  // Constante D de la ecuacion del
00227                                          // plano. 
00228     pp = n1.producto_punto(l);
00229     pq = n1.producto_punto(O-b);
00230     if ( pp < -EPSILON && pq > EPSILON ||
00231          pp > EPSILON && pq < -EPSILON ) { 
00232         //- 'n1' y 'l' estan "mirandose de frente", estamos en el plano -----
00233         // Pero tenemos que ver si esta en el triangulo en el plano XY...
00234         t1 = (-1) * (  (n1.x*O.x + n1.y*O.y + n1.z*O.z - D) / 
00235                       (n1.x*l.x + n1.y*l.y + n1.z*l.z)       );
00236         p1 = O + l * t1;
00237         m = (d.y - a.y)/(d.x - a.x);
00238         if ( p1.x >= a.x-EPSILON && p1.y <= d.y+EPSILON && 
00239              p1.y >= m*(p1.x - a.x) + a.y - EPSILON ) {
00240             //- Listo, si llegamos hasta aqui es porque aqui hay interseccion
00241             normal = n1;
00242             punto = p1;
00243             T = t1;
00244           }
00245           else {
00246             t1 = INFINITO;
00247         }
00248     }
00249 
00250     //- Pruebo con T2 -------------------------------------------------------
00251     double t2 = 0.0;
00252     VECTOR p2, n2;
00253 
00254     n2 = (d-c).producto_cruz(a-c);
00255     n2.normalizar();
00256     D = n2.x*d.x + n2.y*d.y + n2.z*d.z;  // Constante D de la ecuacion del
00257                                          // plano. 
00258     pp = n2.producto_punto(l);
00259     pq = n2.producto_punto(O-c);
00260     if ( pp < -EPSILON && pq > EPSILON ||
00261          pp > EPSILON && pq < -EPSILON ) { 
00262         //- 'n2' y 'l' estan "mirandose de frente", estamos en el plano -----
00263         // Pero tenemos que ver si esta en el triangulo en el plano XY...
00264         t2 = (-1) * (  (n2.x*O.x + n2.y*O.y + n2.z*O.z - D) / 
00265                       (n2.x*l.x + n2.y*l.y + n2.z*l.z)       );
00266         p2 = O + l * t2;
00267         m = (d.y - a.y)/(d.x - a.x);
00268         if ( p2.x <= d.x+EPSILON && p2.y >= c.y-EPSILON && 
00269              p2.y <= m*(p2.x - a.x) + a.y + EPSILON ) {
00270             //- Listo, si llegamos hasta aqui es porque aqui hay interseccion
00271             if ( t2 <= t1 + EPSILON ) {
00272                 normal = n2;
00273                 punto = p2;
00274                 T = t2;
00275             }
00276         }
00277     }
00278 
00279     //-----------------------------------------------------------------------
00280     return T;
00281 }
00282 
00283 inline double
00284 TERRENO::interseccion(RAYO *Rayo, VECTOR &punto, VECTOR &normal)
00295 {
00296     //= FASE 1 ==============================================================
00297 
00298     //- Determine la situacion actual y escoja el algoritmo de busqueda -----
00299     int tipo_situacion = 0; // 0: <N/A> 1: dz~=0 2: abs(m)<=1 3: abs(m)>1
00300     VECTOR r; // Proyeccion de Rayo->direccion en el plano <x, y>
00301     double m=0; // Pendiente de la recta definida por r
00302     double b=0; // La recta es f_de_y = m*x + b ... 
00303 
00304     arr_debug_x.elim();
00305     arr_debug_y.elim();
00306 
00307     //- Miro si la situacion es de tipo 1 -
00308     r = Rayo->direccion;
00309     r.normalizar();
00310     r.z = 0; // OJO: ESTA PROYECCION SUPONE QUE EL TERRENO ESTA EN XY...
00311              //      LO CUAL SIEMPRE ES CIERTO
00312     if ( r.norma() < 5*EPSILON ) {
00313         tipo_situacion = 1;
00314       #ifdef DEBUG_TERRENO
00315         color_debug.r = 1; color_debug.g = 0; color_debug.b = 0;
00316       #endif
00317     }
00318 
00319     //- Miro si la situacion es de tipo 2 o 3 -
00320     if ( !tipo_situacion ) {
00321         r.normalizar();
00322         if ( fabs(r.x) >= fabs(r.y) ) {
00323             tipo_situacion = 2;
00324           #ifdef DEBUG_TERRENO
00325             color_debug.r = 0; color_debug.g = 1; color_debug.b = 1;
00326           #endif
00327           }
00328           else {
00329             tipo_situacion = 3;
00330           #ifdef DEBUG_TERRENO
00331             color_debug.r = 1; color_debug.g = 0; color_debug.b = 1;
00332           #endif
00333         }
00334     }
00335 
00336     //- Ejecucion de las pruebas en casos de situacion 1 --------------------
00337     int x, y;
00338 
00339     if ( tipo_situacion == 1 ) {
00340         x = coord2index_x(Rayo->origen.x);
00341         y = coord2index_y(Rayo->origen.y);
00342         if ( x >= -1 && x <= _x_tam - 3 &&
00343              y > 0 && y <= _y_tam ) {
00344             arr_debug_x.anx(x+2); arr_debug_y.anx(y-1);
00345         }
00346     }
00347     //- Ejecucion de las pruebas en casos de situacion 2 --------------------
00348     double f_de_x;
00349 
00350     if ( tipo_situacion == 2 ) {
00351         m = r.y / r.x;
00352         b = Rayo->origen.y - m*Rayo->origen.x;
00353         for ( x = 1; x < _x_tam - 2; x++ ) {
00354             f_de_x = m * index2coord_x(x) + b;
00355             y = coord2index_y(f_de_x);
00356             if ( y >= 1 && y < _y_tam - 2 ) {
00357                 arr_debug_x.anx(x); arr_debug_y.anx(y);
00358             }
00359             if ( y >= 2 && y < _y_tam - 2 ) {
00360                 arr_debug_x.anx(x); arr_debug_y.anx(y-1);
00361             }
00362             if ( y >= 3 && y < _y_tam - 2 ) {
00363                 arr_debug_x.anx(x); arr_debug_y.anx(y-2);
00364             }
00365         }
00366     }
00367 
00368     //- Ejecucion de las pruebas en casos de situacion 3 --------------------
00369     double f_de_y;
00370 
00371     if ( tipo_situacion == 3 ) {
00372         m = r.x / r.y;
00373         b = Rayo->origen.x - m*Rayo->origen.y;
00374         for ( y = 1; y < _y_tam - 2; y++ ) {
00375             f_de_y = m * index2coord_y(y) + b;
00376             x = coord2index_x(f_de_y);
00377             if ( x >= 0 && x < _x_tam - 3 ) {
00378                 arr_debug_x.anx(x+1); arr_debug_y.anx(y);
00379             }
00380             if ( x >= -1 && x < _x_tam - 4 ) {
00381                 arr_debug_x.anx(x+2); arr_debug_y.anx(y);
00382             }
00383             if ( x >= -2 && x < _x_tam - 5 ) {
00384                 arr_debug_x.anx(x+3); arr_debug_y.anx(y);
00385             }
00386         }
00387     }
00388 
00389     //= FASE 2 ==============================================================
00390 
00391     //-----------------------------------------------------------------------
00392     double T = 0, distancia_minima = INFINITO, t;
00393     VECTOR p, n;
00394 
00395 #ifdef NONONO
00396     // OJO: La idea de la FASE 1 es no hacer esto asi de exhaustivo...
00397     for ( x = 1; x < _x_tam - 2; x++ ) {
00398         for ( y = 1; y < _y_tam - 2; y++ ) {
00399             t = interseccion_celda(Rayo, p, n, x, y);
00400             if ( (t > EPSILON) && (t < distancia_minima) ) {
00401                 distancia_minima = t;
00402                 T = t;
00403                 punto = p;
00404                 normal = n;
00405             }
00406         }
00407     }
00408 #endif
00409 //#ifdef NONONO
00410     // ... PERO DESAFORTUNADAMENTE TODAVIA NO FUNCIONA BIEN LA PRE-SELECCION,
00411     // REVISELO CON EL RAYTRACER SOBRE EL EJEMPLO raytrace3.aqz Y SE HARA
00412     // EVIDENTE...
00413     int i;
00414 
00415     for ( i = 0; i < arr_debug_x.tam(); i++ ) {
00416         x = arr_debug_x[i];
00417         y = arr_debug_y[i];
00418         t = interseccion_celda(Rayo, p, n, x, y);
00419         if ( (t > EPSILON) && (t < distancia_minima) ) {
00420             distancia_minima = t;
00421             T = t;
00422             punto = p;
00423             normal = n;
00424         }
00425     }
00426 //#endif
00427 
00428     return T;
00429 }
00430 
00431 //===========================================================================
00432 //= EOF                                                                     =
00433 //===========================================================================
00434 

Este archivo HTML ha sido generado automáticamente a partir del código fuente AQUYNZA. NO LO EDITE. Para mayor información contacte al autor.