constcurve.c

Go to the documentation of this file.
00001 /*
00002  * $Id: constcurve.c,v 1.4 2004/06/24 18:32:35 joaoluiz Exp $
00003  * (C) COPYRIGHT 2004, Joao Luiz Elias Campos.
00004  * All Rights Reserved
00005  * Duplication of this program or any part thereof without the express
00006  * written consent of the author is prohibited
00007  *
00008  *   Modified:    01-Aug-05    Alexandre A. Del Savio
00009  *     Modificada a funcao CheckPoint e criada a funcao LineBounds.
00010  *     Criada as definicoes: ZERO, MIN e MAX.
00011  *
00012  *   Modified:    03-Aug-05    Alexandre A. Del Savio
00013  *     Criada as funcoes VecLen, Dist, PolySurf e PolyInvSurf.
00014  *
00015  *   Modified:    18-Aug-05    Alexandre A. Del Savio
00016  *     Modificada as funcoes CurveToGlobal e CurveToLocal para usarem 
00017  *     diretamente o inverso do jacobiano e o jacobiano, respectivamente, 
00018  *     do elemento e nao mais a combinacao destes dos nos.
00019  *
00020  *   Modified:    25-Aug-05    Alexandre A. Del Savio
00021  *     Modificada a funcao ConstCurveInit e criada as funcoes 
00022  *     ConstCurveGlobalParametric e CurveToGlobalParametric. 
00023  *
00024  *   Modified:    01-Sep-05    Alexandre A. Del Savio
00025  *     Modificada as funcoes ConstCurveNew e ConstCurveRead de modo
00026  *     que as restricoes sejam estendidas. 
00027  *
00028  *   Modified:    25-Oct-05    Alexandre A. Del Savio
00029  *     Implementada uma tolerância adaptativa que se modifica em
00030  *     função das geometrias das curvas lidas por este pacote.
00031  *     Para tanto, criou-se uma função para calcular esta tolerância, 
00032  *     EvaluateTolerance, e adicionou-se uma chamada a esta função na
00033  *     função que efetua a leitura das curvas, ConstCurveRead.
00034  *
00035  *   Modified:    23-Fev-06    Juan Pablo Ibañez
00036  *     modificada a funcões CurveToLocal, ConstCurveLocal, CurveToGlobal, 
00037  *     CurveToGlobalParametric, ConstCurveGlobalParametric, ConstCurveGlobal,
00038  *     que passam a retornar 0 ou 1 em caso de falha ou sucesso respectivamente.
00039  *
00040  *  Modified:    29-Mar-06    Juan Pablo Ibañez
00041  *     Modificada a funcão ConstCurveNew que passa a receber mais um
00042  *     parâmetro, "i".
00043  *
00044  *   Modified:    11-Apr-06    Alexandre A. Del Savio
00045  *     Adicionada as funcoes: DiffVector, CrossProd e Invert3x3.
00046  *     Re-organizada as funcoes: EvaluateTolerance, CurveToLocal e 
00047  *     CurveToGlobal.
00048  *     Modificada as funcoes: LineBounds, VecLen, Dist, VecNormalize,
00049  *     DirNormalize, CheckPoint, PolySurf e ConstCurveRead.
00050  *     Estas modificacoes e novas funcoes tem como objetivo habilitar estas
00051  *     restricoes no espaco 3D. Ou seja, a partir de agora as restricoes de 
00052  *     linha podem ser dadas em qualquer posicao do espaco.
00053  *     Além disso, compatibilizou-se este arquivo com a versao do Juan Pablo.
00054  *     Funcoes compatibilizadas: CurveToLocal, ConstCurveLocal, CurveToGlobal, 
00055  *     CurveToGlobalParametric, ConstCurveGlobalParametric e ConstCurveGlobal.
00056  *
00057  *   Modified:    24-Mai-06    Juan Pablo Ibañez
00058  *     Modificada a funcão CurveToGlobalParametric, onde corrigui-se o 
00059  *     controle para saber se delta é negativo ou positivo.
00060  *
00061  *   Modified:    21-Jun-06    Alexandre A. Del Savio
00062  *     Modified the ConstCurveNew function when it was removed the first 
00063  *     parameter "int i" and it started to use the ContNumConstrainRead
00064  *     variable.
00065  *
00066  *    Modified:    12-Jul-06    Juan Pablo Iba
00067  *     Modificadas as funcoes PolySurf e PolyInvSurf onde foram definidas
00068  *     tolerancias para o cálculo.
00069  *
00070  *    Modified:    12-Ago-06    Juan Pablo Iba
00071  *     Criadas as funcoes ConstShotNew e ConstShotRead para o caso de constrain
00072  *     tipo SHOT (apoio inclinado).
00073  *
00074  *    Modified     14-Set-2006  Juan Pablo Ibanez
00075  *     Foram removidas as funcoes ConstShotNew e ConstShotRead que passaram
00076  *     ao modulo constshot.c
00077  *
00078  *    Modified     14-Dec-2006  Juan Pablo Ibanez
00079  *     Modificada a função _curveSlide que deixou de calcular o
00080  *     sinal do deslocamento porque o vetor de deslocamento 
00081  *     recebido já está no sistema local do elemento da curva.
00082  *
00083  *    Modified     02-Apr-2007  Gisele Holtz
00084  *     Modificada as funções _curvePolySlide, PolyInvSurf, _curveToLocal, 
00085  *     _curveToGlocal para prolongar o primeiro e o último
00086  *     segmento da curva, permitindo projetar sobre a curva um comprimento maior
00087  *     que o comprimento da curva.  
00088  *     Criada a função _checkPointInExtrem para verificar se um pto está sobre 
00089  *     os segmentos extremos da curva.
00090  *     
00091  */
00092 
00099 /*
00100  * Global variables and symbols:
00101  */
00102 #include <stdlib.h>
00103 #include <math.h>
00104 #include "constrain.h"
00105 #include "rio.h"
00106 
00107 typedef struct _curvedata 
00108 {
00109   double jac[3][3];
00110   double ijac[3][3];
00111 } sCCurveData;
00112 
00113 
00114 /*
00115 ** ------------------------------------------------------------------------
00116 ** Local variables and symbols:
00117 */
00118 
00119 /*
00120 %K Tolerance definition
00121 */
00122 static double Tolerance = 1.0e+10;
00123 
00124 /*
00125 %K Zero definition
00126 */
00127 #ifndef ZERO
00128 #define ZERO(v)     ((fabs(v)<Tolerance)?1:0) 
00129 #endif
00130 
00131 /*
00132 %K Minimum definition
00133 */
00134 #ifndef MIN
00135 #define MIN(a,b)    ((a<b)?a:b)
00136 #endif
00137 
00138 /*
00139 %K Maximum definition
00140 */
00141 #ifndef MAX
00142 #define MAX(a,b)    ((a>b)?a:b)
00143 #endif
00144 
00145 
00146 /*
00147 ** ------------------------------------------------------------------------
00148 ** Local functions:
00149 */
00150 
00157 static void     DiffVec( sCoord *in0, sCoord *in1, sCoord *out )    
00158 {
00159   out->x = in0->x - in1->x;
00160   out->y = in0->y - in1->y;
00161   out->z = in0->z - in1->z;
00162 } 
00163 
00170 static double ProdEscalar( sCoord *in0, sCoord* in1 )
00171 {
00172   double prod;
00173   prod = (in0->x)*(in1->x) + (in0->y)*(in1->y) + (in0->z)*(in1->z);
00174 
00175   return (prod);
00176 }
00177 
00184 static void CrossProd( sCoord *in0, sCoord *in1, sCoord *out )
00185 {
00186   out->x = (in0->y * in1->z) - (in0->z * in1->y); 
00187   out->y = (in0->z * in1->x) - (in0->x * in1->z); 
00188   out->z = (in0->x * in1->y) - (in0->y * in1->x); 
00189 }  
00190 
00194 static double VecLen( sCoord *vec )
00195 {
00196   return(sqrt((vec->x * vec->x) + (vec->y * vec->y) + (vec->z * vec->z)));
00197 }
00198 
00202 static double Dist( sCoord *in0, sCoord *in1 )
00203 {
00204   sCoord tmp;
00205 
00206   DiffVec(in1, in0, &tmp);
00207   
00208   return(VecLen(&tmp));
00209 }
00210 
00215 static void  VecNormalize( sCoord *vec, sCoord *n )
00216 {
00217   double      len;
00218 
00219   len = VecLen(vec);
00220 
00221   n->x = vec->x / len;
00222   n->y = vec->y / len;
00223   n->z = vec->z / len;
00224 }
00225 
00230 static sCoord DirNormalize( sCoord* p1, sCoord* p2 )
00231 {
00232   sCoord  dr;    /* Vetor direção da reta (p1,p2). */
00233   sCoord  nrm;
00234 
00235   dr.x = p2->x - p1->x;
00236   dr.y = p2->y - p1->y;
00237   dr.z = p2->z - p1->z;
00238 
00239   VecNormalize(&dr,&nrm);
00240 
00241   return nrm;
00242 }
00243 
00253 static int LineBounds( sCoord *c, sCoord *pi, sCoord *pf )
00254 {
00255   double aux;
00256 
00257   aux = MIN(pi->x, pf->x);
00258   if(c->x < aux) if(!ZERO(c->x - aux)) return(0);
00259   aux = MAX(pi->x, pf->x);
00260   if(c->x > aux) if(!ZERO(c->x - aux)) return(0);
00261 
00262   aux = MIN(pi->y, pf->y);
00263   if(c->y < aux) if(!ZERO(c->y - aux)) return(0);
00264   aux = MAX(pi->y, pf->y);
00265   if(c->y > aux) if(!ZERO(c->y - aux)) return(0);
00266 
00267   aux = MIN(pi->z, pf->z);
00268   if(c->z < aux) if(!ZERO(c->z - aux)) return(0);
00269   aux = MAX(pi->z, pf->z);
00270   if(c->z > aux) if(!ZERO(c->z - aux)) return(0);
00271 
00272   return(1);
00273 }
00274 
00282 static int Invert3x3( double a[3][3], double b[3][3] )
00283 {
00284   double det;
00285   int    i, j;
00286         
00287   /* Limpa a matriz inversa. */
00288   for(i = 0; i < 3; i++)
00289     for(j = 0; j < 3; j++) 
00290       b[i][j] = 0.0 ;
00291 
00292   /* Calcula o determinante da matriz. */
00293   det = a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) -
00294         a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0]) +
00295         a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]) ;
00296 
00297   /* Se não foi possível inverter a matriz retorna 0. */
00298   if(ZERO(det)) 
00299     return 0;
00300 
00301   /* Calcula os coeficientes da matriz inversa. */
00302   b[0][0] =  (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det ;
00303   b[0][1] = -(a[0][1] * a[2][2] - a[0][2] * a[2][1]) / det ;
00304   b[0][2] =  (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det ;
00305   b[1][0] = -(a[1][0] * a[2][2] - a[1][2] * a[2][0]) / det ;
00306   b[1][1] =  (a[0][0] * a[2][2] - a[0][2] * a[2][0]) / det ;
00307   b[1][2] = -(a[0][0] * a[1][2] - a[0][2] * a[1][0]) / det ;
00308   b[2][0] =  (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det ;
00309   b[2][1] = -(a[0][0] * a[2][1] - a[0][1] * a[2][0]) / det ;
00310   b[2][2] =  (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det ;
00311 
00312   return 1;
00313 }
00314 
00324 static int CheckPoint( sCoord *c, sCoord *pi, sCoord *pf )
00325 {
00326   sCoord du, dv, dw;
00327   double coef[3][3];
00328   double cinv[3][3];
00329 
00330   /* Direções. */
00331   DiffVec(pf, pi, &du);
00332   DiffVec(c,  pi, &dv);
00333 
00334   /* Direção da linha perpendicular. */
00335   CrossProd(&du, &dv, &dw);
00336 
00337   /* Constroi os coeficientes da matriz. */
00338   coef[0][0] = du.x;  coef[0][1] = dv.x;  coef[0][2] = dw.x;
00339   coef[1][0] = du.y;  coef[1][1] = dv.y;  coef[1][2] = dw.y;
00340   coef[2][0] = du.z;  coef[2][1] = dv.z;  coef[2][2] = dw.z;
00341  
00342   /* Inverte a matriz dos coeficientes. */
00343   if(!Invert3x3(coef, cinv)) 
00344   {
00345     /* Como nao foi possível inverter a matriz significa que o determinante é
00346      * nulo. Ou seja, os vetores sao paralelos ou colineares. Desta forma,
00347      * basta testar se o ponto está sobre a reta testando a sua bounding box.
00348      */
00349     /*printf("lineBounds...\n");*/
00350     if(!LineBounds(c, pi, pf))
00351       return(0);
00352     else
00353       return(1);
00354   }
00355 
00356   return(0);
00357 }
00358 
00359 
00360 static int _checkPointInExtrem(sConstrain *c, sCoord *p, int *id )
00361 {
00362   sCoord d, dp, n;
00363   double area;
00364   sCoord *pi;
00365   sCoord *pf;
00366   int    inc[2];
00367   double TOL = 0.001;
00368   
00369   /* Verifica primeiro segmento  da curva
00370    *
00371    *          d                           
00372    *      i  <--   f                     
00373    *      .----------.       .........    . ----------. 
00374    */
00375   ElmConnect(c->elems[0], inc);
00376   pi = &c->nodes[inc[0]-1].coord;
00377   pf = &c->nodes[inc[1]-1].coord;
00378   d = DirNormalize(pi, pf);
00379   dp = DirNormalize( p, pf );
00380   
00381   /* Verifica se o ponto está na direção do segmento */
00382   CrossProd(&d, &dp, &n);
00383   area = VecLen( &n );
00384   
00385   /* Verifica se o pto está no mesmo sentido do segmento */
00386   if( area < TOL )
00387   {
00388         if( ProdEscalar( &d, &dp ) > 0 )
00389         {
00390          /* ponto está antes do primeiro ponto da curva */
00391     *id = 0;
00392     return( 1 );
00393    }
00394   }
00395   
00396    /* Verifica último segmento  da curva   
00397    *                                             d
00398    *                                        i    -->   f
00399    *      .----------.       .........      . ----------.
00400    */
00401   ElmConnect(c->elems[c->numElems-1], inc);
00402   pi = &c->nodes[inc[0]-1].coord;
00403   pf = &c->nodes[inc[1]-1].coord;
00404   d = DirNormalize(pf, pi);
00405   dp = DirNormalize( p, pi );
00406 
00407   /* Direção da linha perpendicular. */
00408   CrossProd(&d, &dp, &n);
00409   area = VecLen( &n );
00410 
00411   if( area < TOL )
00412   {
00413         /* Ponto está na mesma direção do último segmento */
00414         if( ProdEscalar( &d, &dp ) > 0 )
00415         {
00416          /* ponto está depois do último ponto da curva */
00417     *id = c->numElems-1;
00418     return( 1 );
00419    }
00420   }
00421   return( 0 );
00422 }
00423 
00431 static int PolyInvSurf( sConstrain *c, sCoord *p, double *dist )
00432 {
00433   int  flag = 0;
00434   int  e;
00435   int  inc[2];
00436   int  id;
00437   double tol = 0.000001;
00438   
00439   /* Inicializa a distancia.
00440    */
00441   *dist = 0.0;
00442 
00443   /* Testa se o ponto p é o primeiro ponto inicial da curva (poligonal).
00444    */
00445   ElmConnect(c->elems[0], inc);
00446   
00447   if((Dist(&c->nodes[inc[0]-1].coord, p)) < tol)
00448   {
00449     id = 0;
00450     *dist = 0.0;
00451     return(id);
00452   }
00453 
00454   /* Encontra o segmento onde esta o ponto p, acumulando a distancia
00455    * ate chegar a ele.
00456    */
00457   for(e = 0; e < c->numElems; e++)
00458   {
00459     ElmConnect(c->elems[e], inc);
00460     if(CheckPoint(p, &c->nodes[inc[0]-1].coord, &c->nodes[inc[1]-1].coord))
00461     {
00462       id = e;
00463       flag = 1;
00464       *dist += Dist(&c->nodes[inc[0]-1].coord, p);
00465       break;
00466     }
00467     *dist += Dist(&c->nodes[inc[0]-1].coord, &c->nodes[inc[1]-1].coord);
00468   }
00469 
00470   /* O ponto p não está sobre a poligonal.
00471   */
00472   if(!flag)
00473   {
00474     flag = _checkPointInExtrem(c, p, &id );
00475     
00476     if( !flag )
00477     {
00478      id = -1;
00479      *dist = 0.0;
00480      return(id);
00481     }
00482     ElmConnect(c->elems[id], inc);
00483     
00484     if( id == 0 )
00485         *dist = 0.0;
00486     else 
00487       *dist += Dist(&c->nodes[inc[1]-1].coord, p);
00488   }
00489    
00490   return(id);
00491 }
00492 
00500 static int _curvePolySlide( sConstrain *c, double dist, void **elm, sCoord *p )
00501 {
00502   double  dist_pol = 0.0;
00503   int     flag     = 0;
00504   double  D, Dx, Dy, Dz, d;
00505   int     e;
00506   int     inc[2];
00507   double tol = 0.000001;
00508   int     first = 0; /* flag q indica q o pto está sobre a prolongação do primeiro
00509                       * segmento */
00510 
00511   /* A distância passada como parâmetro é negativa.
00512   */
00513   if(dist < 0.0)
00514   {
00515     /* printf( "_curvePolySlide: distância negativa\n" ); */
00516     /* mantains current element node constrain */
00517     ElmConnect(c->elems[0], inc);
00518     *elm = c->elems[0];
00519     first = 1;
00520     dist_pol = Dist(&c->nodes[inc[1]-1].coord, &c->nodes[inc[0]-1].coord);
00521   }
00522 
00523   /* Distância passada como parâmetro igual a zero.
00524   ** Retorna o primeiro ponto da curva (poligonal).
00525   */
00526   if(fabs( dist ) < tol)
00527   {
00528    /* printf("_curvePolySlide: distancia nula\n");*/
00529     ElmConnect(c->elems[0], inc);
00530     p->x = c->nodes[inc[0]-1].coord.x;
00531     p->y = c->nodes[inc[0]-1].coord.y;
00532     p->z = c->nodes[inc[0]-1].coord.z;
00533     *elm = c->elems[0];
00534 
00535     return(0);
00536   }
00537   if( !first )
00538   {
00539     /* Encontra o segmento onde esta o ponto p.
00540      */
00541     for(e = 0; e < c->numElems; e++)
00542     {
00543       ElmConnect(c->elems[e], inc);
00544       dist_pol += Dist(&c->nodes[inc[0]-1].coord, &c->nodes[inc[1]-1].coord);
00545       if((dist_pol > dist) || (fabs(dist_pol - dist)<0.00001))
00546       {
00547         /*printf("distancia achada\n");*/
00548         flag = 1;
00549         *elm = c->elems[e];   
00550         break;
00551       }
00552     }
00553   }
00554 
00555   /* A distância passada como parâmetro é maior que o comprimento
00556   ** de toda a curva (polyline).
00557   */
00558   if( !first && !flag )
00559   {
00560     /*printf("_curvePolySlide: distancia maior do que a curva\n");*/
00561     /* mantains current element node constrain */
00562     *elm = c->elems[c->numElems-1];
00563     ElmConnect(c->elems[c->numElems-1], inc);
00564   }
00565   
00566   D  = Dist(&c->nodes[inc[1]-1].coord, &c->nodes[inc[0]-1].coord);
00567   Dx = c->nodes[inc[1]-1].coord.x - c->nodes[inc[0]-1].coord.x;
00568   Dy = c->nodes[inc[1]-1].coord.y - c->nodes[inc[0]-1].coord.y;
00569   Dz = c->nodes[inc[1]-1].coord.z - c->nodes[inc[0]-1].coord.z;
00570   d  = dist - dist_pol;
00571   
00572   p->x = c->nodes[inc[1]-1].coord.x + (d * Dx) / D;
00573   p->y = c->nodes[inc[1]-1].coord.y + (d * Dy) / D;
00574   p->z = c->nodes[inc[1]-1].coord.z + (d * Dz) / D;
00575   
00576   return(1);
00577 }
00578 
00583 static void EvaluateTolerance( sConstrain *c )
00584 {
00585   int inc[3];
00586   double dist = 0.0;
00587   double auxTol = 0.0;
00588   int i;
00589 
00590   for(i = 0; i < c->numElems; i++)
00591   {
00592     ElmConnect(c->elems[i],inc);
00593     dist = Dist(&c->nodes[inc[1]-1].coord, &c->nodes[inc[0]-1].coord);
00594     auxTol = dist * 0.1;
00595     if(auxTol < Tolerance)
00596       Tolerance = auxTol;
00597   }
00598 
00599 } /* End of EvaluateTolerance */
00600 
00604 static int _curveToLocal(sConstrain *c, sCoord *p, void **elm, double jac[3][3])
00605 {
00606   int    e, i, j;
00607   int    inc[2];
00608   double jace[3][3], ijace[3][3];
00609   int    found = 0;
00610 
00611   if( !(*elm) )
00612   {
00613     for(e = 0; e < c->numElems; e++) 
00614     {
00615       ElmConnect(c->elems[e],inc);
00616       if(CheckPoint(p, &c->nodes[inc[0]-1].coord, &c->nodes[inc[1]-1].coord)) 
00617       {
00618         ElmJacobian(c->elems[e],jace,ijace);
00619         *elm = c->elems[e];
00620         found = 1;
00621         break;
00622       }
00623     }
00624 
00625     if(!found)
00626     {
00627       found = _checkPointInExtrem(c, p, &e );
00628 
00629       if( !found )
00630       {
00631         fprintf(stderr, "Could not find element(1).\n\n");
00632         *elm = NULL; /* not necessary */
00633         return 0;
00634       }
00635       ElmJacobian(c->elems[e],jace,ijace);
00636       *elm = c->elems[e];
00637     }
00638   }
00639   else
00640   {
00641     sElement *_elm = (sElement*)(*elm);
00642 
00643     ElmJacobian( _elm, jace, ijace );
00644   }
00645 
00646   for( i = 0; i < 3; i++ ) 
00647     for( j = 0; j < 3; j++ ) 
00648       jac[i][j] = jace[i][j];
00649 
00650   return 1;
00651 
00652 } /* End of _curveToLocal */
00653 
00657 static int _curveToGlobal( sConstrain *c, sCoord *p, 
00658                            void **elm, double ijac[3][3] )
00659 { 
00660   int    i, j;
00661   int    inc[2];
00662   double jace[3][3], ijace[3][3]; 
00663   int    found = 0;
00664 
00665   if( !(*elm) )
00666   {
00667     for(i = 0; i < c->numElems; i++) 
00668     {
00669       ElmConnect(c->elems[i],inc);
00670       if(CheckPoint(p, &c->nodes[inc[0]-1].coord, &c->nodes[inc[1]-1].coord))
00671       {
00672         ElmJacobian(c->elems[i],jace,ijace);
00673         *elm = c->elems[i];
00674         found = 1;
00675         break;
00676       } 
00677     }
00678 
00679     if(!found)
00680     {
00681       found = _checkPointInExtrem(c, p, &i );
00682 
00683       if( !found )
00684       {
00685         fprintf(stderr, "Could not find element(2).\n\n");
00686         *elm = NULL; 
00687         return 0;
00688       }
00689       ElmJacobian(c->elems[i],jace,ijace);
00690       *elm = c->elems[i];
00691     }
00692   }
00693   else
00694   {
00695     sElement *_elm = ((sElement*)(*elm));
00696 
00697     ElmJacobian( _elm, jace, ijace );
00698   }
00699 
00700   for( i = 0; i < 3; i++ )
00701     for( j = 0; j < 3; j++ ) 
00702       ijac[i][j] = ijace[i][j];
00703 
00704   return 1;
00705 
00706 } /* End of _curveToGlobal */
00707 
00711 static int _curveSlide( sConstrain *c, sCoord *p, void **elm, sCoord *d,
00712                         double ijac[3][3], sCoord *pl )
00713 {
00714   int    i, j;
00715   int    inc[2];
00716   double jace[3][3], ijace[3][3];
00717   double dist_p;  /* Distancia do inicio da curva ate o ponto p.            */
00718   double dist_pl; /* Distancia do inicio da curva ate o ponto pl.           */
00719   int    id_p;    /* Identificacao do segmento onde encontra-se o ponto p.  */
00720   int    status;  /* buleano: encontrou o  ponto pl em algum elemento?     */
00721 
00722   /* Calcula as distancias. */
00723   id_p = PolyInvSurf(c, p, &dist_p);
00724   if(id_p == -1)
00725   {
00726     fprintf(stderr, "Could not find element(3).\n\n");
00727     return 0;
00728   }
00729 
00730   /* calcula distância no espaço da restrição */
00731   dist_pl = dist_p + d->x;
00732 
00733   /* Encontra o segmento em funcao da distancia ate o ponto pl e
00734    * encontra o ponto correspondente percorrendo o espaco da restricao.
00735    */
00736   status = _curvePolySlide(c, dist_pl, elm, pl);
00737   if(!status)
00738   { 
00739     pl->x = p->x;
00740     pl->y = p->y;
00741     pl->z = p->z;
00742   }
00743 
00744   /* Calcula os parametros em funcao do segmento encontrado. */
00745   {
00746     sElement *_elm = (sElement*)(*elm);
00747 
00748     ElmConnect( _elm, inc );
00749     ElmJacobian( _elm, jace, ijace );
00750   }
00751  
00752   for(i = 0; i < 3; i++)
00753     for(j = 0; j < 3; j++) 
00754       ijac[i][j] = ijace[i][j];
00755 
00756   return 1;
00757 
00758 } /* End of _curveSlide */
00759 
00760 /*
00761 **--------------------------------------------------------------------------
00762 */
00763 
00764 /*
00765  * Subclass methods:
00766  */
00767 static void ConstCurveNew(int, int, int, sConstrain **, sConstrain **);
00768 static void ConstCurveFree(sConstrain *);
00769 static void ConstCurveRead(sConstrain *);
00770 static void ConstCurveBuild(sConstrain *);
00771 
00775 static void ConstCurveNew( int label, int num_nodes, int num_elems,
00776                            sConstrain **c, sConstrain **clst )
00777 {
00778  sCCurveData *data = NULL;
00779 
00780  /* A partir de agora sera adicionado a curva de restricao mais dois
00781   * segmentos que correspondem a extensao do primeiro e do ultimo
00782   * segmento da restricao, na direcao dada pelos proprios segmentos que
00783   * estao sendo estendidos.
00784   */
00785  num_nodes += 2;
00786  num_elems += 2;
00787 
00788  data = (sCCurveData *)calloc(num_nodes, sizeof(sCCurveData));
00789 
00790  (*c) = (sConstrain *)malloc(sizeof(sConstrain));
00791  (*c)->type = CURVE;
00792  (*c)->label = label;
00793  (*c)->numNodes = num_nodes;
00794  (*c)->numElems = num_elems;
00795  (*c)->nodes = (sNode *)calloc(num_nodes, sizeof(sNode));
00796  (*c)->elems = (sElement **)calloc(num_elems, sizeof(sElement *));
00797  (*c)->data = data;
00798  
00799  clst[ContNumConstrainRead] = (*c);
00800  ContNumConstrainRead++;
00801 
00802 } /* End of ConstCurveNew */
00803 
00807 static void ConstCurveFree(sConstrain *c)
00808 {
00809  int i;
00810 
00811  if( c->data ) {
00812   free(c->data);
00813  }
00814 
00815  if( c->numNodes != 0 ) {
00816   free(c->nodes);
00817  }
00818 
00819  if( c->numElems != 0 ) {
00820   for( i = 0; i < c->numElems; i++ ) {
00821    ElmFree(c->elems[i]);
00822   }
00823   free(c->elems);
00824  }
00825  c->numNodes = 0;
00826  c->numElems = 0;
00827  c->nodes = NULL;
00828  c->elems = NULL;
00829  c->data = NULL;
00830 
00831 } /* End of ConstCurveFree */
00832 
00836 static void ConstCurveRead(sConstrain *c)
00837 {
00838  int i, id;
00839  double x, y, z;
00840  int matid, tckid, ordid;
00841  sElement *elm = NULL;
00842 
00843 #if 0
00844  static int first = 0;
00845  if(!first)
00846  {
00847   for( i = 0; i < c->numNodes; i++ ) 
00848   {
00849     fscanf(nf, "%d %lf %lf %lf", &id, &x, &y, &z);
00850     c->nodes[i].id = id;
00851     c->nodes[i].coord.x = x;
00852     c->nodes[i].coord.y = y;
00853     c->nodes[i].coord.z = z;
00854     c->nodes[i].dof.x = FORCE;
00855     c->nodes[i].dof.y = FORCE;
00856     c->nodes[i].dof.z = FORCE;
00857     c->nodes[i].dof.psi = 0.0;
00858     c->nodes[i].rezone = NONE;
00859     c->nodes[i].curve = 0;
00860     c->nodes[i].dspIteration = DSP_NO;
00861     c->nodes[i].dspTime = DSP_NO;
00862   }
00863 
00864   for( i = 0; i < c->numElems; i++ ) 
00865   {
00866     fscanf(nf, "%d%d%d%d", &id, &matid, &tckid, &ordid);
00867     ElmNew(LINE2,id,matid,ordid,tckid,&elm,c->elems,c->nodes);
00868     ElmRead(elm);
00869   }
00870   first = 1;
00871  }
00872  else
00873  {
00874 #else
00875   /* A partir de agora sera adicionado a curva de restricao mais dois
00876    * segmentos que correspondem a extensao do primeiro e do ultimo
00877    * segmento da restricao, na direcao dada pelos proprios segmentos que
00878    * estao sendo estendidos.
00879    */
00880 
00881   /* Le as coordenadas dos nos "internos".
00882    */ 
00883   for(i = 1; i < c->numNodes - 1; i++) 
00884   {
00885     fscanf(nf, "%d %lf %lf %lf", &id, &x, &y, &z);
00886     c->nodes[i].id = id+1;
00887     c->nodes[i].coord.x = x;
00888     c->nodes[i].coord.y = y;
00889     c->nodes[i].coord.z = z;
00890     c->nodes[i].dof.x = FORCE;
00891     c->nodes[i].dof.y = FORCE;
00892     c->nodes[i].dof.z = FORCE;
00893     c->nodes[i].dof.psi = 0.0;
00894     c->nodes[i].rezone = NONE;
00895     c->nodes[i].curve = 0;
00896     c->nodes[i].dspIteration = DSP_NO;
00897     c->nodes[i].dspTime = DSP_NO;
00898   }  
00899  
00900   /* Le os segmentos "internos".
00901    */ 
00902   for(i = 1; i < c->numElems - 1; i++) 
00903   {
00904     fscanf(nf, "%d%d%d%d", &id, &matid, &tckid, &ordid);
00905     ElmNew(LINE2, id+1, matid, ordid, tckid, &elm, c->elems, c->nodes);
00906     ElmRead(elm);
00907   }
00908 
00909   /* Corrige as incidencias dos elementos para permitir a adicao de um
00910    * novo segmento no inicio e no fim.
00911    */
00912   for(i = 1; i < c->numElems - 1; i++) 
00913   {
00914     ElmUpdateConnect(c->elems[i]);
00915   }
00916 
00917   /* Calcula a extensao do primeiro e do ultimo segmento,
00918    * consequentemente ocorre a criacao de mais dois nos e dois
00919    * segmentos.
00920    */
00921   {
00922     sCoord dirn;   /* Direcao normalizada do vetor dado pelo segmento. */
00923     int    inc[2]; /* Vetor auxiliar para capturar a incidencia do segmento. */
00924     sCoord pe;     /* Ponto estendido. */
00925     double extension = 10.0; /* Fator de extensao. */
00926     int    lastElem;         /* Ultimo segmento.   */
00927     int    lastNode;         /* Ultimo no.         */
00928    
00929     /* Primeiro segmento. 
00930      */ 
00931     ElmConnect(c->elems[1], inc);
00932     dirn = DirNormalize(&c->nodes[inc[1]-1].coord, &c->nodes[inc[0]-1].coord);
00933     pe.x = c->nodes[inc[0]-1].coord.x + extension * dirn.x;
00934     pe.y = c->nodes[inc[0]-1].coord.y + extension * dirn.y;
00935     pe.z = c->nodes[inc[0]-1].coord.z + extension * dirn.z;
00936     c->nodes[0].id = 1;
00937     c->nodes[0].coord.x = pe.x;
00938     c->nodes[0].coord.y = pe.y;
00939     c->nodes[0].coord.z = pe.z;
00940     c->nodes[0].dof.x = FORCE;
00941     c->nodes[0].dof.y = FORCE;
00942     c->nodes[0].dof.z = FORCE;
00943     c->nodes[0].dof.psi = 0.0;
00944     c->nodes[0].rezone = NONE;
00945     c->nodes[0].curve = 0;
00946     c->nodes[0].dspIteration = DSP_NO;
00947     c->nodes[0].dspTime = DSP_NO;
00948     ElmNew(LINE2, 1, 1, 1, 1, &elm, c->elems, c->nodes);
00949     inc[0] = 1;
00950     inc[1] = 2;
00951     ElmSetConnect(elm, inc);
00952 
00953     /* Ultimo segmento. 
00954      */
00955     lastElem = c->numElems - 1;
00956     lastNode = c->numNodes - 1;
00957     ElmConnect(c->elems[lastElem-1], inc);
00958     dirn = DirNormalize(&c->nodes[inc[0]-1].coord, &c->nodes[inc[1]-1].coord);
00959     pe.x = c->nodes[inc[1]-1].coord.x + extension * dirn.x;
00960     pe.y = c->nodes[inc[1]-1].coord.y + extension * dirn.y;
00961     pe.z = c->nodes[inc[1]-1].coord.z + extension * dirn.z;
00962     c->nodes[lastNode].id = c->numNodes;
00963     c->nodes[lastNode].coord.x = pe.x;
00964     c->nodes[lastNode].coord.y = pe.y;
00965     c->nodes[lastNode].coord.z = pe.z;
00966     c->nodes[lastNode].dof.x = FORCE;
00967     c->nodes[lastNode].dof.y = FORCE;
00968     c->nodes[lastNode].dof.z = FORCE;
00969     c->nodes[lastNode].dof.psi = 0.0;
00970     c->nodes[lastNode].rezone = NONE;
00971     c->nodes[lastNode].curve = 0;
00972     c->nodes[lastNode].dspIteration = DSP_NO;
00973     c->nodes[lastNode].dspTime = DSP_NO;
00974     ElmNew(LINE2, c->numElems, 1, 1, 1, &elm, c->elems, c->nodes);
00975     inc[0] = inc[0] + 1;
00976     inc[1] = inc[1] + 1;
00977     ElmSetConnect(elm, inc); 
00978  }
00979 #endif
00980 
00981  EvaluateTolerance(c);
00982 
00983 } /* End of ConstCurveRead */
00984 
00988 static void ConstCurveBuild(sConstrain *c)
00989 {
00990  int i, j, n, k, l;
00991  int inc[3];
00992  double jac[3][3], ijac[3][3];
00993  int *count = NULL;
00994  sCCurveData *data = NULL;
00995 
00996  count = (int *)calloc(c->numNodes, sizeof(int));
00997  data = (sCCurveData *)c->data;
00998 
00999  for( i = 0; i < c->numElems; i++ ) {
01000   ElmNumNodes(c->elems[i],&n);
01001   ElmConnect(c->elems[i],inc);
01002   ElmJacobian(c->elems[i],jac,ijac);
01003   for( j = 0; j < n; j++ ) {
01004    for( k = 0; k < 3; k++ ) {
01005     for( l = 0; l < 3; l++ ) {
01006      data[inc[j]-1].jac[k][l] += jac[k][l];
01007      data[inc[j]-1].ijac[k][l] += ijac[k][l];
01008     }
01009    }
01010    count[inc[j]-1]++;
01011   }
01012  }
01013 
01014  for( i = 0; i < c->numNodes; i++ ) {
01015   for( k = 0; k < 3; k++ ) {
01016    for( l = 0; l < 3; l++ ) {
01017     data[i].jac[k][l] /= count[i];
01018     data[i].ijac[k][l] /= count[i];
01019    }
01020   }
01021  }
01022  
01023  free(count);
01024 
01025 } /* End of ConstCurveBuild */
01026 
01030 static int ConstCurveLocal(sConstrain *c, sCoord *p, void **elm,
01031                            double *g, double *l)
01032 {
01033   int i, j;
01034   double jac[3][3];
01035 
01036   if(!_curveToLocal(c, p, elm, jac)) 
01037     return 0;
01038 
01039   for(i = 0; i < NDof; i++) 
01040   {
01041     l[i] = 0.0;
01042     for(j = 0; j < NDof; j++) 
01043       l[i] += jac[i][j] * g[j];
01044   }
01045 
01046   return 1;
01047 
01048 } /* End of ConstCurveLocal */
01049 
01053 static int ConstCurveGlobal(sConstrain *c, sCoord *p, void **elm, 
01054                             double *l, double *g)
01055 {
01056   int i, j;
01057   double ijac[3][3];
01058 
01059   if(!_curveToGlobal(c, p, elm, ijac)) 
01060     return 0;
01061 
01062   for(i = 0; i < NDof; i++) 
01063   {
01064     g[i] = 0.0;
01065     for( j = 0; j < NDof; j++ )
01066       g[i] += ijac[i][j] * l[j];
01067   }
01068 
01069   return 1;
01070 
01071 } /* End of ConstCurveGlobal */
01072 
01076 static int ConstCurveSlide( sConstrain *c, sCoord *p, void **elm, sCoord *d,
01077                             double *l, double *g, sCoord *pl )
01078 {
01079   int i, j;
01080   double ijac[3][3];
01081 
01082   if(!_curveSlide(c, p, elm, d, ijac, pl)) 
01083     return 0;
01084 
01085   for(i = 0; i < NDof; i++)
01086   {
01087     g[i] = 0.0;
01088     for(j = 0; j < NDof; j++)
01089       g[i] += ijac[i][j] * l[j];
01090   }
01091 
01092   return 1;
01093 
01094 } /* End of ConstCurveSlide */
01095 
01096 /*
01097  * Public functions:
01098  */
01099 
01103 void ConstCurveInit(void);
01104 void ConstCurveInit(void)
01105 {
01106   ConstClass[CURVE].new    = ConstCurveNew;
01107   ConstClass[CURVE].free   = ConstCurveFree;
01108   ConstClass[CURVE].read   = ConstCurveRead;
01109   ConstClass[CURVE].build  = ConstCurveBuild;
01110   ConstClass[CURVE].local  = ConstCurveLocal;
01111   ConstClass[CURVE].global = ConstCurveGlobal;
01112   ConstClass[CURVE].slide  = ConstCurveSlide;
01113 
01114   Tolerance = 1.0e+10;
01115 
01116 } /* End of ConstCurveInit */
01117 
01118 /*
01119  * End of File.
01120  */
01121 
01122 

Generated on Tue Oct 23 11:23:29 2007 for Relax by  doxygen 1.5.3