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

cilindro.h

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= cilindro.h                                            Noviembre de 1999 =
00003 //=-------------------------------------------------------------------------=
00004 //= Definiciones de la clase CILINDRO.                                        =
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 cilindro.h, incluya a geometria.h!"
00028 #endif
00029 
00030 #ifdef VEL_ROSITA
00031     #include "toolkits/geom/geometria.h"
00032 #endif
00033 
00034 class CILINDRO : public PRIMITIVA_GEOMETRICA 
00035 {
00036   private:
00037     double _radio1;
00038     double _radio2;
00039     double _altura;
00040 #ifdef GL_ENABLED
00041     int paralelos;
00042     int meridianos;
00043     GLUquadricObj *Textura_glu; // OJO: No usar GLU, copy-pastear algo mejor...
00044 #endif
00045     IMAGEN *imagen;
00046 
00047     double interseccion_cono(const RAYO *in_Rayo, const double in_r, 
00048                              const double in_h,
00049                              VECTOR &out_punto, VECTOR &out_normal);
00050 
00051     double interseccion_cilindro(const RAYO *in_Rayo, const double in_r, 
00052                              const double in_h,
00053                              VECTOR &out_punto, VECTOR &out_normal);
00054 
00055     double interseccion_tapa(RAYO *in_Rayo, const double in_r, 
00056                              const double in_h,
00057                              VECTOR &out_punto, VECTOR &out_normal);
00058 
00059   public:
00060     CILINDRO(double r1, double r2, double h);
00061     virtual ~CILINDRO();
00062 
00063     // Servicios para raytracers y algoritmos especiales de geometria
00064     double interseccion(RAYO *Rayo, VECTOR &punto, VECTOR &normal);
00065 
00066     // Otros
00067     void valores(double *r1, double *r2, double *h);
00068     void set_valores(double r1, double r2, double h);
00069     void anexar_textura(IMAGEN *img);
00070     int clasificar_punto(VECTOR p);
00071     virtual GEOMETRIA *crear_copia(void);
00072 
00073     void minmax(VECTOR *min, VECTOR *max);
00074 
00075 #ifdef GL_ENABLED
00076     void
00077     pintar_gl(CALIDAD_VISUAL *Calidad, MATERIAL* Material, CAMARA *Camara);
00078 #endif
00079     void pintar_povray(FILE *fd);
00080     void pintar_aqz(FILE *fd);
00081 };
00082 
00083 //===========================================================================
00084 //= Metodos inline de la clase CILINDRO                                       =
00085 //===========================================================================
00086 
00087 inline double
00088 CILINDRO::interseccion_tapa(RAYO *in_Rayo, const double in_r, 
00089                             const double in_h,
00090                             VECTOR &out_punto, VECTOR &out_normal)
00108 {
00109     double t;
00110     VECTOR p;
00111     VECTOR proy;
00112     VECTOR o(0, 0, 0);
00113 
00114     if ( fabs(in_Rayo->direccion.z) > EPSILON ) {
00115         // El rayo no es paralelo al plano Z=in_h
00116         t = (in_h-in_Rayo->origen.z)/in_Rayo->direccion.z;
00117         if ( t > -EPSILON ) {
00118             p = in_Rayo->origen + in_Rayo->direccion * t;
00119             proy.x = p.x;
00120             proy.y = p.y;
00121             proy.z = 0;
00122             if ( DISTANCIA_V(proy, o) < in_r ) {
00123                 out_normal.x = out_normal.y = 0;
00124                 out_normal.z = 1;
00125                 out_punto = p;
00126                 return t;
00127             }
00128         }
00129     }
00130 
00131     return 0.0;
00132 }
00133 
00134 inline double
00135 CILINDRO::interseccion_cono(const RAYO *in_Rayo, const double in_r, 
00136                             const double in_h,
00137                             VECTOR &out_punto, VECTOR &out_normal)
00184 {
00185     double A, B, C, discriminante, t0 /*, t1*/;
00186 
00187     //- Translacion para concordar con la interpretacion AQUYNZA ------------
00188     RAYO r = (*in_Rayo);
00189     r.origen.z -= in_h/2;
00190     r.direccion.normalizar();
00191 
00192     //- Calcula el termino A ------------------------------------------------
00193     A = SQUARE(r.direccion.x) +
00194         SQUARE(r.direccion.y) -
00195         SQUARE(r.direccion.z * in_r / in_h);
00196 
00197     //- Calcula el termino B ------------------------------------------------
00198     B = 2 *
00199         ((r.direccion.x * r.origen.x) +
00200          (r.direccion.y * r.origen.y) -
00201          (r.direccion.z * r.origen.z * SQUARE(in_r)) / 
00202          SQUARE(in_h)
00203          );
00204 
00205     //- Calcula el termino C ------------------------------------------------
00206     C = SQUARE(r.origen.x) +
00207         SQUARE(r.origen.y) -
00208         SQUARE(r.origen.z * in_r / in_h);
00209 
00210     //- Calcula el discriminante. Si el discriminante no es positivo el -----
00211     //- rayo no intersecta la esfera. retorna t = 0                         -
00212     discriminante = SQUARE(B) - 4*A*C;
00213     if ( discriminante <= EPSILON ) return 0.0;
00214 
00215     //- Resuelve la ecuacion cuadratica para las raices de la ecuacion. -----
00216     //- (-B +/- sqrt(B^2 - 4*A*C)) / 2A.                                    -
00217     discriminante = sqrt(discriminante);
00218     t0 = (-B-discriminante) / (2 * A);
00219 
00220     //- Si t0 es > 0 listo. Si no debemos calcular la otra raiz t1. ---------
00221     if ( t0 > EPSILON ) {
00222         // OJO: Aqui va el calculo del punto y la normal!
00223         out_punto = r.origen + r.direccion * t0;
00224         if ( out_punto.z > 0 || out_punto.z < -in_h ) {
00225             return 0.0;
00226         }
00227 
00228         // Se calcula la normal como el gradiente de la formula del cono,
00229         // notese que aqui se obtiene un vector escalado en 1/2 respecto al
00230         // gradiente (para ahorrar multiplicaciones)
00231         out_normal.x = out_punto.x;
00232         out_normal.y = out_punto.y;
00233         out_normal.z = -out_punto.z * SQUARE(in_r/in_h);
00234         out_normal.normalizar();
00235 
00236         out_punto.z += in_h/2;
00237         return t0;
00238     }
00239 
00240 /*
00241     t1 = (-B+discriminante) / (2 * A);
00242     if ( t1 > EPSILON ) {
00243         // OJO: Aqui va el calculo del punto y la normal!
00244         out_punto = r.origen + r.direccion * t1;
00245         if ( out_punto.z > 0 || out_punto.z < -in_h ) {
00246             return 0.0;
00247         }
00248         out_punto.z += in_h/2;
00249         out_normal.normalizar();
00250         return t1;
00251     }
00252 */
00253     return 0.0;
00254 }
00255 
00256 inline double
00257 CILINDRO::interseccion_cilindro(const RAYO *in_Rayo, const double in_r, 
00258                             const double in_h,
00259                             VECTOR &out_punto, VECTOR &out_normal)
00294 {
00295     double A, B, C, discriminante, t0 /*, t1*/;
00296 
00297     //- Translacion para concordar con la interpretacion AQUYNZA ------------
00298     RAYO r = (*in_Rayo);
00299     r.direccion.normalizar();
00300 
00301     //- Calcula el termino A ------------------------------------------------
00302     A = SQUARE(r.direccion.x) +
00303         SQUARE(r.direccion.y);
00304 
00305     //- Calcula el termino B ------------------------------------------------
00306     B = 2 *
00307         ( (r.direccion.x * r.origen.x) +
00308           (r.direccion.y * r.origen.y) );
00309 
00310     //- Calcula el termino C ------------------------------------------------
00311     C = SQUARE(r.origen.x) +
00312         SQUARE(r.origen.y) -
00313         SQUARE(in_r);
00314 
00315     //- Calcula el discriminante. Si el discriminante no es positivo el -----
00316     //- rayo no intersecta la esfera. retorna t = 0                         -
00317     discriminante = SQUARE(B) - 4*A*C;
00318     if ( discriminante <= EPSILON ) return 0.0;
00319 
00320     //- Resuelve la ecuacion cuadratica para las raices de la ecuacion. -----
00321     //- (-B +/- sqrt(B^2 - 4*A*C)) / 2A.                                    -
00322     discriminante = sqrt(discriminante);
00323     t0 = (-B-discriminante) / (2 * A);
00324 
00325     //- Si t0 es > 0 listo. Si no debemos calcular la otra raiz t1. ---------
00326     if ( t0 > EPSILON ) {
00327         // OJO: Aqui va el calculo del punto y la normal!
00328         out_punto = r.origen + r.direccion * t0;
00329 
00330         if ( out_punto.z > in_h/2 || out_punto.z < -in_h/2 ) {
00331             return 0.0;
00332         }
00333 
00334         // Se calcula la normal como el gradiente de la formula del cono,
00335         // notese que aqui se obtiene un vector escalado en 1/2 respecto al
00336         // gradiente (para ahorrar multiplicaciones)
00337         out_normal.x = out_punto.x;
00338         out_normal.y = out_punto.y;
00339         out_normal.z = 0;
00340         out_normal.normalizar();
00341         return t0;
00342     }
00343 
00344     return 0.0;
00345 }
00346 
00347 inline double
00348 CILINDRO::interseccion(RAYO *Rayo, VECTOR &punto,
00349                        VECTOR &normal)
00356 {
00357     double t_body, t_tapa1, t_tapa2, t = 0;
00358     VECTOR p_body, p_tapa1, p_tapa2, n_body, n_tapa1, n_tapa2;
00359     int cercano = -1;
00360 
00361     //- Caso cono -----------------------------------------------------------
00362     if ( _radio2 < EPSILON && _radio1 > EPSILON ) {
00363         t_body = interseccion_cono(Rayo, _radio1, _altura, p_body, n_body);
00364         t_tapa1 = interseccion_tapa(Rayo, _radio1, -_altura/2, 
00365                                     p_tapa1, n_tapa1);
00366 
00367         if ( !IGUAL(t_body, 0.0) &&
00368              (IGUAL(t_tapa1, 0.0) || t_body < t_tapa1) ) {
00369             punto = p_body;
00370             normal = n_body;
00371             t = t_body;
00372           }
00373           else {
00374             punto = p_tapa1;
00375             normal = n_tapa1 * (-1);
00376             t = t_tapa1;
00377         }
00378     }
00379 
00380     //- Caso cilindro -------------------------------------------------------
00381     if ( IGUAL(_radio1, _radio2) ) {
00382         t_body = interseccion_cilindro(Rayo, _radio1, _altura, p_body, n_body);
00383         t_tapa1 = interseccion_tapa(Rayo, _radio1, -_altura/2, 
00384                                     p_tapa1, n_tapa1);
00385         t_tapa2 = interseccion_tapa(Rayo, _radio1, _altura/2, 
00386                                     p_tapa2, n_tapa2);
00387 
00388         if ( !IGUAL(t_body, 0.0) && 
00389              (!IGUAL(t_tapa1, 0) && t_body < t_tapa1 || IGUAL(t_tapa1, 0)) && 
00390              (!IGUAL(t_tapa2, 0) && t_body < t_tapa2 || IGUAL(t_tapa2, 0) ) ) {
00391             cercano = 1;
00392         }
00393         else if ( !IGUAL(t_tapa1, 0.0) && 
00394              (!IGUAL(t_body, 0) && t_tapa1 < t_body || IGUAL(t_body, 0)) && 
00395              (!IGUAL(t_tapa2, 0) && t_tapa1 < t_tapa2 || IGUAL(t_tapa2, 0)) ) {
00396             cercano = 3;
00397         }
00398         else {
00399             cercano = 2;
00400         }
00401 
00402         if ( cercano == 1 ) {
00403             punto = p_body;
00404             normal = n_body;
00405             t = t_body;
00406           }
00407           else if ( cercano == 2 )  {
00408             punto = p_tapa2;
00409             normal = n_tapa2;
00410             t = t_tapa2;
00411           }
00412         else if ( cercano == 3 ) {
00413             punto = p_tapa1;
00414             normal = n_tapa1 * (-1);
00415             t = t_tapa1;
00416         }
00417     }
00418 
00419     return t;
00420 }
00421 
00422 //===========================================================================
00423 //= EOF                                                                     =
00424 //===========================================================================
00425 

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.