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_lod.h

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= terreno.cc                                                Mayo del 2000 =
00003 //=-------------------------------------------------------------------------=
00004 //= Definicion de la clase TERRENO_LOD                                      =
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_LOD 1
00036 
00037 #ifdef DEBUG_TERRENO_LOD
00038   #include "lista.cc"
00039 #endif
00040 
00041 class COORDENADA_2D
00042 {
00043   public:
00044     int x;
00045     int y;
00046 
00047     COORDENADA_2D operator + (COORDENADA_2D otro) {
00048         COORDENADA_2D r;
00049 
00050         r.x = x + otro.x;
00051         r.y = y + otro.y;
00052 
00053         return r;
00054     };
00055 
00056     COORDENADA_2D operator / (int otro) {
00057         COORDENADA_2D r;
00058 
00059         r.x = x/otro;
00060         r.y = y/otro;
00061 
00062         return r;
00063     };
00064 
00065     int operator == (COORDENADA_2D otro) {
00066         if ( x == otro.x && y == otro.y ) {
00067             return 1;
00068         }
00069         return 0;
00070     };
00071 };
00072 
00073 //===========================================================================
00074 //===========================================================================
00075 
00076 class _TERRENO_LOD_ATRIBUTO_VERTICE {
00077   private:
00078     BYTE data;
00079   public:
00080     inline _TERRENO_LOD_ATRIBUTO_VERTICE();
00081     inline ~_TERRENO_LOD_ATRIBUTO_VERTICE();
00082     inline BOOLEAN enabled(void);
00083     inline void set_enabled(BOOLEAN e);
00084     inline BOOLEAN activated(void);
00085     inline void set_activated(BOOLEAN e);
00086     inline BOOLEAN dependency(int i);
00087     inline void set_dependency(int i, BOOLEAN e);
00088 };
00089 
00090 //===========================================================================
00091 //= Metodos inline de _TERRENO_LOD_ATRIBUTO_VERTICE                                      =
00092 //===========================================================================
00093 
00094 _TERRENO_LOD_ATRIBUTO_VERTICE::_TERRENO_LOD_ATRIBUTO_VERTICE()
00095 {
00096     data = 0;
00097     set_enabled(FALSE);
00098     set_activated(FALSE);
00099     //set_locked(FALSE);
00100     set_dependency(0, FALSE);
00101     set_dependency(1, FALSE);
00102     set_dependency(2, FALSE);
00103     set_dependency(3, FALSE);
00104 }
00105 
00106 _TERRENO_LOD_ATRIBUTO_VERTICE::~_TERRENO_LOD_ATRIBUTO_VERTICE()
00107 {
00108     ;
00109 }
00110 
00111 BOOLEAN
00112 _TERRENO_LOD_ATRIBUTO_VERTICE::enabled(void)
00113 {
00114     return data & 0x01;
00115 }
00116 
00117 void
00118 _TERRENO_LOD_ATRIBUTO_VERTICE::set_enabled(BOOLEAN e)
00119 {
00120     if ( e ) {
00121         data |= 0x01;
00122       }
00123       else {
00124         data &= ~0x01;
00125     }
00126 }
00127 
00128 BOOLEAN
00129 _TERRENO_LOD_ATRIBUTO_VERTICE::activated(void)
00130 {
00131     return data & 0x02;
00132 }
00133 
00134 void
00135 _TERRENO_LOD_ATRIBUTO_VERTICE::set_activated(BOOLEAN e)
00136 {
00137     if ( e ) {
00138         data |= 0x02;
00139       }
00140       else {
00141         data &= ~0x02;
00142     }
00143 }
00144 
00145 BOOLEAN
00146 _TERRENO_LOD_ATRIBUTO_VERTICE::dependency(int i)
00147 {
00148     return data & (0x03<<i);
00149 }
00150 
00151 void
00152 _TERRENO_LOD_ATRIBUTO_VERTICE::set_dependency(int i, BOOLEAN e)
00153 {
00154     if ( e ) {
00155         data |= (0x03<<i);
00156       }
00157       else {
00158         data &= ~(0x03<<i);
00159     }
00160 }
00161 
00162 //===========================================================================
00163 //===========================================================================
00164 
00165 class TERRENO_LOD : public GEOMETRIA
00166 {
00167   private:
00168     //-----------------------------------------------------------------------
00169     COORDENADA_2D buffer[2];
00170     int nivel_anterior;
00171     int ptr;
00172     int dimension;
00173 
00174     //-----------------------------------------------------------------------
00175     IMAGEN *imagen;
00176     long int _x_tam;    // Tamanno del terreno en muestras
00177     long int _y_tam;
00178     long int vertices_tam; // Arreglo de vertices con la geometria del terreno
00179     VERTICE_GL *vertices_arr;
00180     _TERRENO_LOD_ATRIBUTO_VERTICE *atributos_arr;
00181 
00182     VECTOR _min;
00183     VECTOR _max;
00184     double _escala;
00185     double _factor_exageracion;
00186 
00187     //- Elementos de depuracion ---------------------------------------------
00188     LISTA <int> arr_debug_x;
00189     LISTA <int> arr_debug_y;
00190   #ifdef DEBUG_TERRENO_LOD
00191     COLOR color_debug;
00192   #endif
00193 
00194     //- Servicios privados --------------------------------------------------
00195 
00196     // Usados en la visualizacion
00197   #ifdef GL_ENABLED
00198     void pintar_tiras_gl(void);
00199     void pintar_tirasv_gl(void);
00200   #endif
00201 
00202     // Operaciones basicas
00203     VECTOR calcule_subnormal(int x1, int y1, int x2, int y2, int x3, int y3);
00204     VECTOR calcule_normal(int x, int y);
00205     double interseccion_celda(RAYO *Rayo, VECTOR &punto, VECTOR &normal,
00206                               int x, int y);
00207     int coord2index_x(double x_coord);
00208     int coord2index_y(double y_coord);
00209 
00210     // Usados por el algoritmo LOD
00211     void 
00212     pintar_cuadrante_gl(COORDENADA_2D l, COORDENADA_2D t, COORDENADA_2D r, 
00213                         int nivel);
00214     void toggle_ptr(void);
00215     BOOLEAN elem_buffer(COORDENADA_2D &o);
00216     void
00217     consultar_padres(COORDENADA_2D *h, COORDENADA_2D *p1, COORDENADA_2D *p2,
00218                      int *i1, int *i2, int nivel);
00219     void update_vertex(COORDENADA_2D *v);
00220     void notify(COORDENADA_2D *v, int child, BOOLEAN state);
00221 
00222   public:
00223     //- Operaciones standard de GEOMETRIA AQUYNZA ---------------------------
00224     TERRENO_LOD(GLOBAL_DEM *Fuente,
00225         long int origen_x, long int origen_y, long int xtam, long int ytam,
00226         double escala, double exageracion);
00227     virtual ~TERRENO_LOD();
00228 
00229     // Servicios para raytracers y algoritmos especiales de geometria
00230     double interseccion(RAYO *Rayo, VECTOR &punto, VECTOR &normal);
00231 
00232     // Otros
00233     void anexar_textura(IMAGEN *img);
00234     int clasificar_punto(VECTOR p);
00235     virtual GEOMETRIA *crear_copia(void);
00236 
00237     void minmax(VECTOR *min, VECTOR *max);
00238 
00239   #ifdef GL_ENABLED
00240     void
00241     pintar_gl(CALIDAD_VISUAL *Calidad, MATERIAL* Material, CAMARA *Camara);
00242   #endif
00243     void pintar_povray(FILE *fd);
00244     void pintar_aqz(FILE *fd);
00245 
00246     //- Operaciones particulares de la clase TERRENO_LOD --------------------
00247 //    double altura(double xx, double yy);
00248     BOOLEAN seleccionar(RAYO *Rayito, int *i, int *j);
00249     double index2coord_x(int i);
00250     double index2coord_y(int j);
00251 };
00252 
00253 inline int
00254 TERRENO_LOD::coord2index_x(double x_coord)
00260 {
00261     int i;
00262 
00263     i = (int)(x_coord / (1000*_escala)) - 1;
00264 
00265     return i;
00266 }
00267 
00268 inline int
00269 TERRENO_LOD::coord2index_y(double y_coord)
00275 {
00276     int j;
00277 
00278     // OJO: Ese -2 es machete!
00279     j = (int)(y_coord / (1000 * _escala)) + _y_tam - 1 - 2;
00280 
00281     return j;
00282 }
00283 
00284 inline double
00285 TERRENO_LOD::index2coord_x(int i)
00289 {
00290     double x;
00291 
00292     //x = (i+1) * 1000 * _escala;
00293     x = vertices_arr[i].x;
00294 
00295     return x;
00296 }
00297 
00298 inline double
00299 TERRENO_LOD::index2coord_y(int j)
00303 {
00304     double y;
00305 
00306     //y = 1000 * _escala * (j + 1 - _y_tam);
00307     y = vertices_arr[j*_x_tam].y;
00308 
00309     return y;
00310 }
00311 
00312 inline double
00313 TERRENO_LOD::interseccion_celda(RAYO *Rayo, VECTOR &punto, VECTOR &normal, 
00314                             int x, int y)
00328 {
00329     //- Determine los puntos extremos de los triangulos ---------------------
00330     VECTOR a, b, c, d;
00331 
00332     a.x = index2coord_x(x);
00333     a.y = index2coord_y(y);
00334     a.z = vertices_arr[y*_x_tam + x].z;
00335 
00336     b.x = index2coord_x(x);
00337     b.y = index2coord_y(y+1);
00338     b.z = vertices_arr[(y+1)*_x_tam + x].z;
00339 
00340     c.x = index2coord_x(x+1);
00341     c.y = index2coord_y(y);
00342     c.z = vertices_arr[y*_x_tam + x+1].z;
00343 
00344     d.x = index2coord_x(x+1);
00345     d.y = index2coord_y(y+1);
00346     d.z = vertices_arr[(y+1)*_x_tam + x+1].z;
00347 
00348     //- Preparativos con los planos de T1 y T2 ------------------------------
00349     VECTOR O = Rayo->origen;
00350     VECTOR l = Rayo->direccion;
00351     double T = 0;
00352     double pp, pq, m;
00353     double D;
00354 
00355     l.normalizar();
00356 
00357     //- Pruebo con T1 -------------------------------------------------------
00358     double t1 = INFINITO;
00359     VECTOR p1, n1;
00360 
00361     n1 = (a-b).producto_cruz(d-b);
00362     n1.normalizar();
00363     D = n1.x*d.x + n1.y*d.y + n1.z*d.z;  // Constante D de la ecuacion del
00364                                          // plano. 
00365     pp = n1.producto_punto(l);
00366     pq = n1.producto_punto(O-b);
00367     if ( pp < -EPSILON && pq > EPSILON ||
00368          pp > EPSILON && pq < -EPSILON ) { 
00369         //- 'n1' y 'l' estan "mirandose de frente", estamos en el plano -----
00370         // Pero tenemos que ver si esta en el triangulo en el plano XY...
00371         t1 = (-1) * (  (n1.x*O.x + n1.y*O.y + n1.z*O.z - D) / 
00372                       (n1.x*l.x + n1.y*l.y + n1.z*l.z)       );
00373         p1 = O + l * t1;
00374         m = (d.y - a.y)/(d.x - a.x);
00375         if ( p1.x >= a.x-EPSILON && p1.y <= d.y+EPSILON && 
00376              p1.y >= m*(p1.x - a.x) + a.y - EPSILON ) {
00377             //- Listo, si llegamos hasta aqui es porque aqui hay interseccion
00378             normal = n1;
00379             punto = p1;
00380             T = t1;
00381           }
00382           else {
00383             t1 = INFINITO;
00384         }
00385     }
00386 
00387     //- Pruebo con T2 -------------------------------------------------------
00388     double t2 = 0.0;
00389     VECTOR p2, n2;
00390 
00391     n2 = (d-c).producto_cruz(a-c);
00392     n2.normalizar();
00393     D = n2.x*d.x + n2.y*d.y + n2.z*d.z;  // Constante D de la ecuacion del
00394                                          // plano. 
00395     pp = n2.producto_punto(l);
00396     pq = n2.producto_punto(O-c);
00397     if ( pp < -EPSILON && pq > EPSILON ||
00398          pp > EPSILON && pq < -EPSILON ) { 
00399         //- 'n2' y 'l' estan "mirandose de frente", estamos en el plano -----
00400         // Pero tenemos que ver si esta en el triangulo en el plano XY...
00401         t2 = (-1) * (  (n2.x*O.x + n2.y*O.y + n2.z*O.z - D) / 
00402                       (n2.x*l.x + n2.y*l.y + n2.z*l.z)       );
00403         p2 = O + l * t2;
00404         m = (d.y - a.y)/(d.x - a.x);
00405         if ( p2.x <= d.x+EPSILON && p2.y >= c.y-EPSILON && 
00406              p2.y <= m*(p2.x - a.x) + a.y + EPSILON ) {
00407             //- Listo, si llegamos hasta aqui es porque aqui hay interseccion
00408             if ( t2 <= t1 + EPSILON ) {
00409                 normal = n2;
00410                 punto = p2;
00411                 T = t2;
00412             }
00413         }
00414     }
00415 
00416     //-----------------------------------------------------------------------
00417     return T;
00418 }
00419 
00420 inline double
00421 TERRENO_LOD::interseccion(RAYO *Rayo, VECTOR &punto, VECTOR &normal)
00432 {
00433     //= FASE 1 ==============================================================
00434 
00435     //- Determine la situacion actual y escoja el algoritmo de busqueda -----
00436     int tipo_situacion = 0; // 0: <N/A> 1: dz~=0 2: abs(m)<=1 3: abs(m)>1
00437     VECTOR r; // Proyeccion de Rayo->direccion en el plano <x, y>
00438     double m=0; // Pendiente de la recta definida por r
00439     double b=0; // La recta es f_de_y = m*x + b ... 
00440 
00441     arr_debug_x.elim();
00442     arr_debug_y.elim();
00443 
00444     //- Miro si la situacion es de tipo 1 -
00445     r = Rayo->direccion;
00446     r.normalizar();
00447     r.z = 0; // OJO: ESTA PROYECCION SUPONE QUE EL TERRENO_LOD ESTA EN XY...
00448              //      LO CUAL SIEMPRE ES CIERTO
00449     if ( r.norma() < 5*EPSILON ) {
00450         tipo_situacion = 1;
00451       #ifdef DEBUG_TERRENO_LOD
00452         color_debug.r = 1; color_debug.g = 0; color_debug.b = 0;
00453       #endif
00454     }
00455 
00456     //- Miro si la situacion es de tipo 2 o 3 -
00457     if ( !tipo_situacion ) {
00458         r.normalizar();
00459         if ( fabs(r.x) >= fabs(r.y) ) {
00460             tipo_situacion = 2;
00461           #ifdef DEBUG_TERRENO_LOD
00462             color_debug.r = 0; color_debug.g = 1; color_debug.b = 1;
00463           #endif
00464           }
00465           else {
00466             tipo_situacion = 3;
00467           #ifdef DEBUG_TERRENO_LOD
00468             color_debug.r = 1; color_debug.g = 0; color_debug.b = 1;
00469           #endif
00470         }
00471     }
00472 
00473     //- Ejecucion de las pruebas en casos de situacion 1 --------------------
00474     int x, y;
00475 
00476     if ( tipo_situacion == 1 ) {
00477         x = coord2index_x(Rayo->origen.x);
00478         y = coord2index_y(Rayo->origen.y);
00479         if ( x >= -1 && x <= _x_tam - 3 &&
00480              y > 0 && y <= _y_tam ) {
00481             arr_debug_x.anx(x+2); arr_debug_y.anx(y-1);
00482         }
00483     }
00484     //- Ejecucion de las pruebas en casos de situacion 2 --------------------
00485     double f_de_x;
00486 
00487     if ( tipo_situacion == 2 ) {
00488         m = r.y / r.x;
00489         b = Rayo->origen.y - m*Rayo->origen.x;
00490         for ( x = 1; x < _x_tam - 2; x++ ) {
00491             f_de_x = m * index2coord_x(x) + b;
00492             y = coord2index_y(f_de_x);
00493             if ( y >= 1 && y < _y_tam - 2 ) {
00494                 arr_debug_x.anx(x); arr_debug_y.anx(y);
00495             }
00496             if ( y >= 2 && y < _y_tam - 2 ) {
00497                 arr_debug_x.anx(x); arr_debug_y.anx(y-1);
00498             }
00499             if ( y >= 3 && y < _y_tam - 2 ) {
00500                 arr_debug_x.anx(x); arr_debug_y.anx(y-2);
00501             }
00502         }
00503     }
00504 
00505     //- Ejecucion de las pruebas en casos de situacion 3 --------------------
00506     double f_de_y;
00507 
00508     if ( tipo_situacion == 3 ) {
00509         m = r.x / r.y;
00510         b = Rayo->origen.x - m*Rayo->origen.y;
00511         for ( y = 1; y < _y_tam - 2; y++ ) {
00512             f_de_y = m * index2coord_y(y) + b;
00513             x = coord2index_x(f_de_y);
00514             if ( x >= 0 && x < _x_tam - 3 ) {
00515                 arr_debug_x.anx(x+1); arr_debug_y.anx(y);
00516             }
00517             if ( x >= -1 && x < _x_tam - 4 ) {
00518                 arr_debug_x.anx(x+2); arr_debug_y.anx(y);
00519             }
00520             if ( x >= -2 && x < _x_tam - 5 ) {
00521                 arr_debug_x.anx(x+3); arr_debug_y.anx(y);
00522             }
00523         }
00524     }
00525 
00526     //= FASE 2 ==============================================================
00527 
00528     //-----------------------------------------------------------------------
00529     double T = 0, distancia_minima = INFINITO, t;
00530     VECTOR p, n;
00531 
00532 #ifdef NONONO
00533     // OJO: La idea de la FASE 1 es no hacer esto asi de exhaustivo...
00534     for ( x = 1; x < _x_tam - 2; x++ ) {
00535         for ( y = 1; y < _y_tam - 2; y++ ) {
00536             t = interseccion_celda(Rayo, p, n, x, y);
00537             if ( (t > EPSILON) && (t < distancia_minima) ) {
00538                 distancia_minima = t;
00539                 T = t;
00540                 punto = p;
00541                 normal = n;
00542             }
00543         }
00544     }
00545 #endif
00546 //#ifdef NONONO
00547     // ... PERO DESAFORTUNADAMENTE TODAVIA NO FUNCIONA BIEN LA PRE-SELECCION,
00548     // REVISELO CON EL RAYTRACER SOBRE EL EJEMPLO raytrace3.aqz Y SE HARA
00549     // EVIDENTE...
00550     int i;
00551 
00552     for ( i = 0; i < arr_debug_x.tam(); i++ ) {
00553         x = arr_debug_x[i];
00554         y = arr_debug_y[i];
00555         t = interseccion_celda(Rayo, p, n, x, y);
00556         if ( (t > EPSILON) && (t < distancia_minima) ) {
00557             distancia_minima = t;
00558             T = t;
00559             punto = p;
00560             normal = n;
00561         }
00562     }
00563 //#endif
00564 
00565     return T;
00566 }
00567 
00568 //===========================================================================
00569 //= EOF                                                                     =
00570 //===========================================================================
00571 

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.