geo.c

Go to the documentation of this file.
00001 
00002 /*  Global variables and symbols                */
00003 
00004 #include <stdio.h>
00005 #include <math.h>
00006 #include "geo.h"
00007 
00008 #ifndef real
00009 #define real double
00010 #endif
00011 
00012 static real PFSGeoTolerance = 0.0001 ;
00013 
00014 #define RAD(x) ((x)*(acos(-1.0)/180.0))
00015 
00016 #define dsin(x) sin(RAD(x))
00017 #define dcos(x) cos(RAD(x))
00018 #define dtan(x) tan(RAD(x))
00019 
00020 
00021 /*      --------------------------------------------------------
00022 **      Private entry points
00023 */
00024 
00025     /*  --------------------------------------------------------
00026     **  PFSGeoIntscPolyLine - returns a flag (PFSGeoTrue of PFSGeoFalse) 
00027     **      indicating whether a horizontal scan line in 2D space 
00028     **      passing at the given 2D point intersects the given line 
00029     **      in 2D space from minus infinite to the given point.
00030     */
00031 
00032 PFSGeoPredicate PFSGeoIntscPolyLine( line, spar )
00033 
00034     PFSGeoSurfPar  line[] ;     /* given 2D line                    */
00035     PFSGeoSurfPar  *spar ;              /* 2D coordinates of pt location    */
00036 {
00037     real   u0,v0,u1,v1 ;   /* line endpoint 2D coords                       */
00038     real   ua,va,ub,vb ;   /* corrected line endpoint coordinates           */
00039     real   max_u,min_u ;   /* maximum and minimum u coordinates     */
00040     real   max_v,min_v ;   /* maximum and minimum v coordinates     */
00041 
00042     u0 = line[0].u ;
00043     v0 = line[0].v ;
00044     u1 = line[1].u ;
00045     v1 = line[1].v ;
00046 
00047     /*  find the max and min coordinates                        */
00048 
00049     max_u = (u0 > u1) ? u0 : u1 ;
00050     min_u = (u0 < u1) ? u0 : u1 ;
00051     max_v = (v0 > v1) ? v0 : v1 ;
00052     min_v = (v0 < v1) ? v0 : v1 ;
00053 
00054 /*
00055     the horizontal line does not intersect the line to the 
00056     left of location pt if:
00057 */
00058     /*  (1) if line is horizontal                                   */
00059 
00060     if( v0 == v1 ) return( PFSGeoFalse ) ;
00061 
00062     /*  (2) if the v coordinate of point is outside the range 
00063             max_v and min_v (but not including min_v)               */
00064 
00065     if( (spar->v < min_v) || (spar->v >= max_v) ) return( PFSGeoFalse ) ;
00066 
00067     /*  (3) if given line is vertical and u coordinate of point is 
00068             smaller than that of line                               */
00069 
00070     if( (u0 == u1) && (spar->u < u0) ) return( PFSGeoFalse ) ;
00071 
00072     /*  (4) if inclined line is located to the right of given point     */
00073     /*     (first reduce the problem to a case where vb >va, always)*/
00074 
00075     if( u0 != u1 ) {
00076         if( ((u1 > u0) && (v1 > v0)) || ((u1 < u0) && (v1 > v0)) ) {
00077             ua = u0 ;    va = v0 ;
00078             ub = u1 ;    vb = v1 ;
00079         }
00080         else {
00081             ua = u1 ;    va = v1 ;
00082             ub = u0 ;    vb = v0 ;
00083         }
00084 
00085         if( ((spar->v - va) * (ub - ua)) > ((spar->u - ua) * (vb - va)) ) {
00086             return( PFSGeoFalse ) ;
00087         }
00088     }
00089 
00090 /*
00091     if we get here that is because the horizontal line passing 
00092     at the location pt intersects the given line to the left of the pt
00093 */
00094 
00095 return( PFSGeoTrue ) ;
00096 }
00097 
00098 /*  --------------------------------------------------------------------
00099 **   The following two routines allow the user to get the current value
00100 **   of the tolerance being used in this module, and to change its value.
00101 **   -sss (27-Jan-90)
00102 */
00103 
00104 void PFSGeoSetTolerance( real tol )
00105 {
00106     PFSGeoTolerance = tol ;
00107 }
00108 
00109 real PFSGeoGetTolerance()
00110 {
00111     return( PFSGeoTolerance ) ;
00112 }
00113 
00114 
00115     /*  --------------------------------------------------------
00116     **  PFSGeoIsInsidePoly - returns a flag (PFSGeoTrue of PFSGeoFalse) 
00117     **      indicating whether a point lying on the plane of the 
00118     **      given polygon is inside it.
00119     **      A scan line algorithm in the parametric space of the 
00120     **      polygon plane is used to check whether the given point 
00121     **      is inside the polygon.  The algorith works as follows:
00122     **      It gets the projection of each polygon boundary edge onto 
00123     **      its plane and counts the number of intersections from 
00124     **      minus infinite in the u direction to the given point 
00125     **      of a horizontal scan line in the plane parametric space 
00126     **      with the boundary of the polygon.  If the number of 
00127     **      intersections is odd the point is inside, otherwise it 
00128     **      is outside.
00129     */
00130 
00131 PFSGeoPredicate PFSGeoIsInsidePoly( poly, spar )
00132 
00133     PFSGeoPoly  *poly ;         /* given polygon parametric rep.    */
00134     PFSGeoSurfPar  *spar ;              /* parametric values of pt location */
00135 {
00136     PFSGeoSurfPar  edge[2] ;    /* projection of a polygon edge on plane    */
00137     PFSGeoPoint local_pt ;      /* vector from origin of local plane system 
00138                                     to current vertex on polygon            */
00139     int         n_cross = 0 ;   /* counts the number of intersections       */
00140     int         i ;
00141 
00142     for( i = 0; i < poly->n_verts; i++ ) {
00143 
00144         local_pt.x = poly->verts[i].x - poly->nplane.a.x ;
00145         local_pt.y = poly->verts[i].y - poly->nplane.a.y ;
00146         local_pt.z = poly->verts[i].z - poly->nplane.a.z ;
00147         edge[0].u = PFSGeoDotProd( &local_pt, &poly->nplane.u ) ;
00148         edge[0].v = PFSGeoDotProd( &local_pt, &poly->nplane.v ) ;
00149 
00150         local_pt.x = poly->verts[(i+1) % poly->n_verts].x - poly->nplane.a.x ;
00151         local_pt.y = poly->verts[(i+1) % poly->n_verts].y - poly->nplane.a.y ;
00152         local_pt.z = poly->verts[(i+1) % poly->n_verts].z - poly->nplane.a.z ;
00153         edge[1].u = PFSGeoDotProd( &local_pt, &poly->nplane.u ) ;
00154         edge[1].v = PFSGeoDotProd( &local_pt, &poly->nplane.v ) ;
00155 
00156         if( PFSGeoIntscPolyLine( edge, spar ) == PFSGeoTrue ) n_cross++ ;
00157     }
00158 
00159     if( (n_cross % 2) == 0 ) return( PFSGeoFalse ) ;
00160     else                     return( PFSGeoTrue ) ;
00161 }
00162 
00163 
00164     /*  --------------------------------------------------------
00165     **  PFSGeoIsOnPolyBdry - returns a flag (PFSGeoTrue of PFSGeoFalse) 
00166     **      indicating whether a point in 3D space is close to 
00167     **      one of the edges of a given polygon.
00168     */
00169 
00170 PFSGeoPredicate PFSGeoIsOnPolyBdry( poly, pt )
00171 
00172     PFSGeoPoly  *poly ;         /* given polygon parametric rep.    */
00173     PFSGeoPoint *pt ;           /* given pt location                */
00174 {
00175     PFSGeoLine  edge ;          /* current polygon edge             */
00176     PFSGeoPoint clst ;          /* closest point on edge            */
00177     PFSGeoPointPar par ;                /* parametric value of point on edge*/
00178     int         is_on_bdry = 0 ;
00179     int         i ;
00180 
00181     for( i = 0; i < poly->n_verts; i++ ) {
00182         PFSGeoGenLine( &poly->verts[i], &poly->verts[(i+1) % poly->n_verts], 
00183                     &edge ) ;
00184         PFSGeoClstPtLine( &edge, pt, &clst, &par ) ;
00185         if( ( (real)par > - PFSGeoTolerance ) 
00186                     && ( (real)par < 1.0 + PFSGeoTolerance ) 
00187                     && ( PFSGeoDist( pt, &clst ) < PFSGeoTolerance ) ) {
00188             is_on_bdry = 1 ;
00189             break ;
00190         }
00191     }
00192 
00193     if( is_on_bdry == 0 ) return( PFSGeoFalse ) ;
00194     else                  return( PFSGeoTrue ) ;
00195 }
00196 
00197 
00198 
00199 /*      --------------------------------------------------------
00200 **      Public entry points
00201 */
00202 
00203 /*      --------------------------------------------------------
00204 **      Generation Routines:
00205 
00206         void PFSGeoGenLine( pt0, pt1, line ) 
00207             PFSGeoPoint *pt0, *pt1 ;
00208             PFSGeoLine  *line ;
00209 
00210         pt0     first input point on the line.
00211         pt1     second input point on the line.
00212         line    output parametric description of the line.
00213 
00214         given two input points, this function creates the parametric 
00215         description of the line  p = D + t*E where D = pt0 and
00216         E = pt1 - pt0.
00217 
00218 
00219         void PFSGeoGenPlane( pt0, pt1, pt2, plane ) 
00220             PFSGeoPoint *pt0, *pt1, *pt2 ; 
00221             PFSGeoPlane *plane ; 
00222 
00223         pt0     first input point on the plane.
00224         pt1     second input point on the plane.
00225         pt2     third input point on the plane.
00226         plane   output parametric description of the plane.
00227 
00228         given three input point, this function creates the parametric
00229         description of the plane  p = A + u*B + v*C where A = pt0,
00230         B = pt1 - pt0, and C = pt2 - pt0.
00231 
00232 
00233         void PFSGeoGenPlanEqn( pt0, pt1, pt2, plan_eqn ) 
00234             PFSGeoPoint *pt0, *pt1, *pt2 ; 
00235             PFSGeoPlanEqn       *plan_eqn ; 
00236 
00237         pt0     first input point on the plane.
00238         pt1     second input point on the plane.
00239         pt2     third input point on the plane.
00240         plane   output general (minimal) description of the plane
00241 
00242         given three input points, this function creates the general
00243         description of the plane such that the following eqn. is satisfied
00244         by any point (X,Y,Z) lying on the plane:  a*X + b*Y + c*Z + d = 0.
00245         The unit normal to the plane is given by (a,b,c) and points in
00246         direction defined by  {vec(0,1) cross vec(0,2)} (see below).
00247 
00248 
00249                      normal |  + pt2
00250                             | /
00251                             |/ 
00252                             + ------+
00253                          pt0        pt1
00254 
00255 
00256 
00257         PFSGeoStatus PFSGeoGenPoly( n_verts, verts, plane )
00258             int          *n_verts ;
00259             PFSGeoPoint  *verts ; 
00260             PFSGeoNormPlane *plane ;
00261 
00262         n_verts number of polygon vertices.
00263         verts   a list of the polygon vertices.
00264         plane   output parametric description of the normalized 
00265                 plane of the polygon.
00266 
00267         given a list of polygon vertex coordinates, this function creates
00268         the normalized parametric description of polygon plane, which 
00269         means that the two plane local directions are unit perpendicular 
00270         vectors and the unit normal vector is also contained in the 
00271         descriptor.
00272         The vertices are assumed given in clockwise direction around 
00273         the polygon.  If the computed normal vector is null, a PFSGeoInvalid 
00274         status is returned.  Otherwise a PFSGeoValid status is returned.
00275 */
00276 
00277 void PFSGeoGenLine( pt0, pt1, line ) 
00278     PFSGeoPoint *pt0, *pt1 ;
00279     PFSGeoLine  *line ;
00280 {                          
00281     line->d = *pt0 ;
00282     line->e.x = pt1->x - pt0->x ;
00283     line->e.y = pt1->y - pt0->y ;
00284     line->e.z = pt1->z - pt0->z ;
00285 }
00286 
00287 
00288 void PFSGeoGenPlane( pt0, pt1, pt2, plane ) 
00289     PFSGeoPoint *pt0, *pt1, *pt2 ; 
00290     PFSGeoPlane *plane ; 
00291 {
00292     plane->a = *pt0 ;
00293     plane->b.x = pt1->x - pt0->x ;
00294     plane->b.y = pt1->y - pt0->y ;
00295     plane->b.z = pt1->z - pt0->z ;
00296     plane->c.x = pt2->x - pt0->x ;
00297     plane->c.y = pt2->y - pt0->y ;
00298     plane->c.z = pt2->z - pt0->z ;
00299 }
00300 
00301 
00302 void PFSGeoGenPlanEqn( pt0, pt1, pt2, plan_eqn ) 
00303     PFSGeoPoint *pt0, *pt1, *pt2 ; 
00304     PFSGeoPlanEqn       *plan_eqn ; 
00305 {
00306     PFSGeoPoint vec1, vec2, normal ;
00307     real        length ;
00308 
00309     vec1.x =  pt1->x - pt0->x ;
00310     vec1.y =  pt1->y - pt0->y ;
00311     vec1.z =  pt1->z - pt0->z ;
00312     vec2.x =  pt2->x - pt0->x ;
00313     vec2.y =  pt2->y - pt0->y ;
00314     vec2.z =  pt2->z - pt0->z ;
00315  
00316     normal.x = (vec1.y * vec2.z) - (vec1.z * vec2.y) ; 
00317     normal.y = (vec1.z * vec2.x) - (vec1.x * vec2.z) ; 
00318     normal.z = (vec1.x * vec2.y) - (vec1.y * vec2.x) ; 
00319 
00320     length = sqrt(     normal.x*normal.x
00321                     +  normal.y*normal.y
00322                     +  normal.z*normal.z  ) ;
00323 
00324     plan_eqn->a = normal.x / length ;
00325     plan_eqn->b = normal.y / length ;
00326     plan_eqn->c = normal.z / length ;
00327     plan_eqn->d = (  - plan_eqn->a * pt0->x
00328                      - plan_eqn->b * pt0->y
00329                      - plan_eqn->c * pt0->z  ) ;
00330 
00331 return;
00332 }
00333 
00334 
00335 PFSGeoStatus PFSGeoGenPoly( n_verts, verts, plane )
00336     int          *n_verts ;
00337     PFSGeoPoint  *verts ; 
00338     PFSGeoNormPlane *plane ;
00339 {
00340     real  e_size ;                  /* length of last polygon edge  */
00341 
00342     if ( PFSGeoPolyNormal( n_verts, verts, &plane->n ) != PFSGeoValid )
00343         return( PFSGeoInvalid ) ;
00344 
00345     e_size = PFSGeoDist( &verts[0], &verts[*n_verts-1] ) ;
00346     plane->a = verts[0] ;
00347 
00348     plane->u.x = (verts[*n_verts-1].x - verts[0].x) / e_size ;
00349     plane->u.y = (verts[*n_verts-1].y - verts[0].y) / e_size ;
00350     plane->u.z = (verts[*n_verts-1].z - verts[0].z) / e_size ;
00351 
00352     PFSGeoCrossProd( &plane->n, &plane->u, &plane->v ) ;
00353     return( PFSGeoValid );
00354 }
00355 
00356 
00357 /*      --------------------------------------------------------
00358 **      Evaluation Routines:
00359 
00360         void PFSGeoEvalLine( par, line, pt ) 
00361             PFSGeoPointPar          *par ;
00362             PFSGeoLine      *line ;
00363             PFSGeoPoint     *pt ;
00364 
00365         par     input parametric value along the line.
00366         line    input parametric description of a line.
00367         pt      output evaluated cartesian point.
00368 
00369         given a parametric description of a line and a parameter
00370         value along the line, this routine generates the cartesian
00371         point coresponding to the given parametric value.
00372 
00373 
00374         void PFSGeoEvalPlane( par, plane, pt )  
00375             PFSGeoSurfPar       *par ;
00376             PFSGeoPlane *plane ;
00377             PFSGeoPoint *pt ;
00378 
00379         par     input parametric surface values.
00380         plane   input parametric representation of a plane.
00381         pt      output evaluated cartesian point.
00382 
00383         given a parametric description of a plane and surface
00384         parameter values (u and v), this routine generates the
00385         cartesian point coresponding to the given surface parameter.
00386 
00387 
00388 */
00389 
00390 void PFSGeoEvalLine( par, line, pt ) 
00391     PFSGeoPointPar          *par ;
00392     PFSGeoLine      *line ;
00393     PFSGeoPoint     *pt ;
00394 {
00395     pt->x = line->d.x + (*par * line->e.x) ;   
00396     pt->y = line->d.y + (*par * line->e.y) ;   
00397     pt->z = line->d.z + (*par * line->e.z) ;   
00398     return ;
00399 }
00400 
00401 
00402 void PFSGeoEvalPlane( par, plane, pt )  
00403     PFSGeoSurfPar       *par ;
00404     PFSGeoPlane *plane ;
00405     PFSGeoPoint *pt ;
00406 {
00407     pt->x = plane->a.x + (par->u * plane->b.x) + (par->v * plane->c.x) ;   
00408     pt->y = plane->a.y + (par->u * plane->b.y) + (par->v * plane->c.y) ;   
00409     pt->z = plane->a.z + (par->u * plane->b.z) + (par->v * plane->c.z) ;   
00410 }
00411 
00412 
00413 /*      --------------------------------------------------------
00414 **      Vector Routines:
00415 
00416 
00417         real PFSGeoDotProd( vec0, vec1 )        
00418             PFSGeoPoint *vec0, *vec1 ;
00419 
00420         vec0    first input vector.
00421         vec1    second input vector.
00422 
00423         The function value is the value of the dot product of
00424         the two three element input vectors.
00425 
00426 
00427         void PFSGeoCrossProd( in0, in1, out )
00428             PFSGeoPoint *in0, *in1, *out ;
00429 
00430         in0     first input vector.
00431         in1     second input vector.
00432         out     output cross product vector.
00433 
00434         This function computes the cross product of the two
00435         three element input vectors.  The cross product components
00436         are returned as the third argument.
00437 
00438 
00439         real PFSGeoTripleProd( vec0, vec1, vec2 ) 
00440             PFSGeoPoint    *vec0, *vec1, *vec2 ;
00441 
00442         vec0    first input vector.
00443         vec1    second input vector.
00444         vec2    third input vector.
00445         
00446         The returned function value is the value of the triple
00447         product of the three input vectors.
00448 
00449 
00450         PFSGeoPredicate PFSGeoNullVec( vec, tolerance )
00451             PFSGeoPoint *vec ;
00452             real        *tolerance ;
00453 
00454         vec             input vector.
00455         tolerance       check tolerance.
00456 
00457         This function return a value of PFSGeoTrue if all absolute values 
00458         of the three elements of vec are less the the value of tolerance.  
00459         Otherwise a value of PFSGeoFalse is returned.
00460 
00461 
00462         real PFSGeoVecLen( vec )
00463             PFSGeoPoint *vec ;
00464 
00465         vec     input vector.
00466 
00467         The value of this function is the length of the input
00468         vector.
00469 
00470 
00471         void PFSGeoVecNormalize( vec, n )
00472             PFSGeoPoint *vec ;
00473             PFSGeoPoint *n ;
00474 
00475         vec     input vector.
00476         n       normalized vector.
00477 
00478         This function normalizes a vector (i.e. finds a vector
00479         with the same direction but a magnitude of one).
00480 
00481 
00482         real    PFSGeoDist( in0, in1 )
00483             PFSGeoPoint *in0 ;
00484             PFSGeoPoint *in1 ;
00485 
00486         in0     input point0
00487         in1     input point1
00488 
00489         The value of this function is the distance between the
00490         two given points.
00491 
00492 
00493         void    PFSGeoDiffVec( in0, in1, out)
00494             PFSGeoPoint *in0, *in1, *out ;
00495 
00496         in0, in1 : input vectors
00497         out : output vector = in0 - in1 ;
00498 
00499         computes the difference between two vectors 
00500 
00501 
00502         void    PFSGeoSumVec( in0, in1, out)
00503             PFSGeoPoint    *in0, *in1, *out ;
00504 
00505         in0, in1 : input vectors
00506         out : output vector = in0 + in1 ;
00507 
00508         computes the sum of two vectors
00509 
00510  
00511         void PFSGeoProdScalVec ( in, scalar, out )
00512             PFSGeoPoint    *in, *out ;
00513             real       *csi ;
00514 
00515         in:     input vector
00516         out :   output vector = csi * in ;
00517 
00518         computes the product of a vector by a scalar
00519 
00520         void    PFSGeoLinCombVec( in0, csi0, in1, csi1, out )
00521             PFSGeoPoint    *in1, *in2, *out ; 
00522             real        *csi0, *csi1 ;
00523         in0, in1, :     input vectors ;
00524         csi0, csi1 :    coefficients corresponding to in0 and in1
00525         out :   output vector = csi0 * in0 + cs1 * in1 ;
00526 
00527         computes the linear combination of two vectors
00528 
00529 */
00530 
00531 real PFSGeoDotProd( vec0, vec1 )        
00532     PFSGeoPoint *vec0, *vec1 ;
00533 {
00534     return ( (vec0->x * vec1->x) + 
00535              (vec0->y * vec1->y) +
00536              (vec0->z * vec1->z) ) ;
00537 }    
00538 
00539 void PFSGeoCrossProd( in0, in1, out )
00540     PFSGeoPoint *in0, *in1, *out ;
00541 {
00542     out->x = (in0->y * in1->z) - (in0->z * in1->y) ; 
00543     out->y = (in0->z * in1->x) - (in0->x * in1->z) ; 
00544     out->z = (in0->x * in1->y) - (in0->y * in1->x) ; 
00545 }    
00546 
00547 real PFSGeoTripleProd( vec0, vec1, vec2 ) 
00548     PFSGeoPoint    *vec0, *vec1, *vec2 ;
00549 {
00550     PFSGeoPoint tmp ;
00551 
00552     PFSGeoCrossProd( vec0, vec1, &tmp ) ;
00553     return( PFSGeoDotProd( &tmp, vec2 ) ) ;
00554 }
00555 
00556 PFSGeoPredicate PFSGeoNullVec( vec, tolerance )
00557     PFSGeoPoint *vec ;
00558     real        *tolerance ;
00559 {
00560     if (( fabs( vec->x ) < *tolerance ) &&  
00561         ( fabs( vec->y ) < *tolerance ) &&  
00562         ( fabs( vec->z ) < *tolerance ))
00563         return( PFSGeoTrue ) ;
00564     else
00565         return( PFSGeoFalse );
00566 }
00567 
00568 real PFSGeoVecLen( vec )
00569     PFSGeoPoint *vec ;
00570 {
00571     return ( sqrt( (vec->x * vec->x) +
00572                    (vec->y * vec->y) +
00573                    (vec->z * vec->z) ) ) ;
00574 }
00575 
00576 
00577 void  PFSGeoVecNormalize( vec, n )
00578     PFSGeoPoint *vec ;
00579     PFSGeoPoint *n ;
00580 {
00581     real        len ;
00582 
00583     len = PFSGeoVecLen( vec ) ;
00584 
00585     n->x = vec->x / len ;
00586     n->y = vec->y / len ;
00587     n->z = vec->z / len ;
00588 }
00589 
00590 
00591 real    PFSGeoDist( in0,in1 )
00592     PFSGeoPoint *in0 ;
00593     PFSGeoPoint *in1 ;
00594 {
00595     PFSGeoPoint tmp ;
00596 
00597     tmp.x = in1->x - in0->x ;
00598     tmp.y = in1->y - in0->y ;
00599     tmp.z = in1->z - in0->z ;
00600 
00601     return( PFSGeoVecLen( &tmp ) ) ;
00602 }
00603 
00604 void    PFSGeoDiffVec( in0, in1, out)
00605     PFSGeoPoint *in0, *in1, *out ;
00606     
00607 {
00608     out->x = in0->x - in1->x ;
00609     out->y = in0->y - in1->y ;
00610     out->z = in0->z - in1->z ;
00611     return ;
00612 } 
00613 
00614 void    PFSGeoSumVec( in0, in1, out)
00615     PFSGeoPoint *in0, *in1, *out ;
00616     
00617 {
00618     out->x = in0->x + in1->x ;
00619     out->y = in0->y + in1->y ;
00620     out->z = in0->z + in1->z ;
00621     return ;
00622 } 
00623 
00624 
00625 void PFSGeoProdScalVec ( in, csi, out )
00626     PFSGeoPoint *in, *out ;
00627     real        *csi ;
00628 {
00629     out->x = in->x * (*csi) ;
00630     out->y = in->y * (*csi) ;
00631     out->z = in->z * (*csi) ;
00632     return ;
00633 }
00634 
00635 
00636 void    PFSGeoLinCombVec( in0, csi0, in1, csi1, out )
00637     PFSGeoPoint    *in0, *in1, *out ; 
00638     real        *csi0, *csi1 ;
00639 {
00640     out->x = in0->x * (*csi0) + in1->x * (*csi1) ;
00641     out->y = in0->y * (*csi0) + in1->y * (*csi1) ;
00642     out->z = in0->z * (*csi0) + in1->z * (*csi1) ;
00643 
00644     return ;
00645 
00646 }
00647 
00648 /*      --------------------------------------------------------
00649 **      Rotation Routines:
00650 
00651 
00652         void PFSGeoRotateX( angle, in, out ) 
00653             real        *angle ;
00654             PFSGeoPoint *in, *out ;
00655 
00656         angle   rotation angle (in degrees).
00657         in      input cartesian point.
00658         out     rotated cartesian point.
00659 
00660         This function takes an input and rotates it about the X
00661         axis by the number of degrees specified by angle.  The
00662         new point position is returned as the third argument.
00663 
00664 
00665         void PFSGeoRotateY( angle, in, out ) 
00666             real        *angle ;
00667             PFSGeoPoint *in, *out ;
00668 
00669         angle   rotation angle (in degrees).
00670         in      input cartesian point.
00671         out     rotated cartesian point.
00672 
00673         This function takes an input and rotates it about the Y
00674         axis by the number of degrees specified by angle.  The
00675         new point position is returned as the third argument.
00676 
00677 
00678         void PFSGeoRotateZ( angle, in, out ) 
00679             real        *angle ;
00680             PFSGeoPoint *in, *out ;
00681 
00682         angle   rotation angle (in degrees).
00683         in      input cartesian point.
00684         out     rotated cartesian point.
00685 
00686         This function takes an input and rotates it about the Z
00687         axis by the number of degrees specified by angle.  The
00688         new point position is returned as the third argument.
00689 
00690 
00691         void PFSGeoRotateAxis( axis, angle, in, out ) 
00692             PFSGeoPoint *axis ;
00693             real        *angle ;
00694             PFSGeoPoint *in, *out ;
00695 
00696         axis    asix about which to rotate.
00697         angle   rotation angle (in degrees).
00698         in      input cartesian point.
00699         out     rotated cartesian point.
00700 
00701         This function takes an input vector and rotates it about
00702         a given axis (passing through the origin) by the number 
00703         of degrees specified by angle.  The new point position
00704         is returned as the fourth argument.
00705 
00706 */
00707 
00708 void PFSGeoRotateX( angle, in, out ) 
00709     real        *angle ;
00710     PFSGeoPoint *in, *out ;
00711 {
00712     real        s, c ;
00713 
00714     s = dsin( *angle) ;   c = dcos( *angle ) ;
00715     out->x = in->x ;
00716     out->y = (in->y * c) - (in->z * s) ;
00717     out->z = (in->y * s) + (in->z * c) ;
00718 }
00719 
00720 
00721 void PFSGeoRotateY( angle, in, out ) 
00722     real        *angle ;
00723     PFSGeoPoint *in, *out ;
00724 {         
00725     real        s, c ;
00726 
00727     s = dsin( *angle) ;   c = dcos( *angle ) ;
00728     out->x = (in->x * c) - (in->z * s) ;
00729     out->y = in->y ;
00730     out->z = (in->x * s) + (in->z * c) ;
00731 }
00732 
00733 
00734 void PFSGeoRotateZ( angle, in, out ) 
00735     real        *angle ;
00736     PFSGeoPoint *in, *out ;
00737 {
00738     real        s, c ;
00739 
00740     s = dsin( *angle ) ;    c = dcos( *angle ) ;
00741     out->x = (in->x * c) - (in->y * s) ;
00742     out->y = (in->x * s) + (in->y * c) ;
00743     out->z = in->z ;
00744 }
00745 
00746 
00747 void PFSGeoRotateAxis( axis, angle, in, out ) 
00748     PFSGeoPoint *axis ;
00749     real        *angle ;
00750     PFSGeoPoint *in, *out ;
00751 {
00752     PFSGeoPoint u ;
00753     real        s, c ;
00754     real        r[3][3] ;
00755 
00756     s = dsin( *angle ) ;    c = dcos( *angle ) ;
00757 
00758     PFSGeoVecNormalize( axis, &u ) ;
00759 
00760     r[0][0] = u.x*u.x + c * (1.0 - u.x*u.x) ;
00761     r[0][1] = u.x*u.y*(1.0 - c) - u.z*s ;
00762     r[0][2] = u.z*u.x*(1.0 - c) + u.y*s ;
00763 
00764     r[1][0] = u.x*u.y*(1.0 - c) + u.z*s ;
00765     r[1][1] = u.y*u.y + c * (1.0 - u.y*u.y) ;
00766     r[1][2] = u.y*u.z*(1.0 - c) - u.x*s ;
00767 
00768     r[2][0] = u.z*u.x*(1.0 - c) - u.y*s ;
00769     r[2][1] = u.y*u.z*(1.0 - c) + u.x*s ;
00770     r[2][2] = u.z*u.z + c * (1.0 - u.z*u.z) ;
00771 
00772     out->x = r[0][0]*in->x + r[0][1]*in->y + r[0][2]*in->z ;
00773     out->y = r[1][0]*in->x + r[1][1]*in->y + r[1][2]*in->z ;
00774     out->z = r[2][0]*in->x + r[2][1]*in->y + r[2][2]*in->z ;
00775 }
00776 
00777 
00778 /*      --------------------------------------------------------
00779 **      Intersection Routines:
00780 
00781 
00782         PFSGeoStatus PFSGeoIntscLinePlane( line, plane, pt, ptpar, spar ) 
00783             PFSGeoLine  *line ;
00784             PFSGeoPlane *plane ;
00785             PFSGeoPoint *pt ;
00786             PFSGeoPointPar      *ptpar ;
00787             PFSGeoSurfPar  *spar ;
00788 
00789         line    input parametric description of a line.
00790         plane   input parametric description of a plane.
00791         pt      output intersection point.
00792         ptpar   output parametric value along the line.
00793         spar    output surface parameters for the plane.
00794 
00795         This function computes the intersection point of a line and a
00796         plane both given as parametric representations.  The parametric
00797         value of the intersection along the line as well as the 
00798         parametric values of the intersection point on the plane are
00799         also returned.
00800 
00801 
00802         PFSGeoStatus PFSGeoIntscLinePoly( line, poly, pt, ptpar, spar ) 
00803             PFSGeoLine  *line ;
00804             PFSGeoPoly  *poly ;
00805             PFSGeoPoint *pt ;
00806             PFSGeoPointPar      *ptpar ;
00807             PFSGeoSurfPar  *spar ;
00808 
00809         line    input parametric description of a line.
00810         poly    input parametric description of a polygon.
00811         pt      output intersection point.
00812         ptpar   output parametric value along the line.
00813         spar    output surface parameters for the plane.
00814 
00815         This function computes the intersection point of a line and a
00816         planar polygon both given as parametric representations.  The 
00817         parametric value of the intersection along the line as well as the 
00818         parametric values of the intersection point on the poly are
00819         also returned.
00820         First it is found whether the line intersects the plane which 
00821         contains the polygon, then, using a scan line algorithm in the 
00822         parametric space of that plane, it is checked whether the 
00823         intersection point is inside the polygon.
00824 */
00825 
00826 PFSGeoStatus PFSGeoIntscLinePlane( line, plane, pt, ptpar, spar ) 
00827     PFSGeoLine  *line ;
00828     PFSGeoPlane *plane ;
00829     PFSGeoPoint *pt ;
00830     PFSGeoPointPar      *ptpar ;
00831     PFSGeoSurfPar  *spar ;
00832 {
00833     real        size ;
00834     PFSGeoPoint b_cross_c, c_cross_e, b_cross_e ;
00835     real        b_x_c_dot_e, c_x_e_dot_b, b_x_e_dot_c ;
00836 
00837     size = PFSGeoVecLen( &plane->b ) ;
00838 
00839     PFSGeoCrossProd( &plane->b, &plane->c, &b_cross_c ) ;
00840     PFSGeoCrossProd( &plane->c, &line->e,  &c_cross_e ) ;
00841     PFSGeoCrossProd( &plane->b, &line->e,  &b_cross_e ) ;
00842          
00843     b_x_c_dot_e = PFSGeoDotProd( &b_cross_c, &line->e ) ;
00844     c_x_e_dot_b = PFSGeoDotProd( &c_cross_e, &plane->b ) ;
00845     b_x_e_dot_c = PFSGeoDotProd( &b_cross_e, &plane->c ) ;
00846 
00847     if (( fabs(b_x_c_dot_e) < PFSGeoTolerance*size ) || 
00848         ( fabs(c_x_e_dot_b) < PFSGeoTolerance*size ) || 
00849         ( fabs(b_x_e_dot_c) < PFSGeoTolerance*size )) 
00850         return( PFSGeoInvalid ) ;
00851     else {
00852         *ptpar = ( PFSGeoDotProd( &b_cross_c, &plane->a ) -
00853                    PFSGeoDotProd( &b_cross_c, &line->d ) ) /  
00854                    b_x_c_dot_e ;
00855         PFSGeoEvalLine( ptpar, line, pt ) ;
00856         spar->u = ( PFSGeoDotProd( &c_cross_e, &line->d ) -
00857                     PFSGeoDotProd( &c_cross_e, &plane->a ) ) /
00858                     c_x_e_dot_b ;
00859         spar->v = ( PFSGeoDotProd( &b_cross_e, &line->d ) -
00860                     PFSGeoDotProd( &b_cross_e, &plane->a ) ) /
00861                     b_x_e_dot_c ;
00862         return( PFSGeoValid ) ;
00863     }
00864 }
00865 
00866 
00867 
00868 PFSGeoStatus PFSGeoIntscLinePoly( line, poly, pt, ptpar, spar ) 
00869     PFSGeoLine  *line ;
00870     PFSGeoPoly  *poly ;
00871     PFSGeoPoint *pt ;
00872     PFSGeoPointPar      *ptpar ;
00873     PFSGeoSurfPar  *spar ;
00874 {
00875     PFSGeoPlane plane ;
00876 
00877     /*  first find if line intersects the plane which 
00878         contains the polygon                                            */
00879 
00880     plane.a = poly->nplane.a ;
00881     plane.b = poly->nplane.u ;
00882     plane.c = poly->nplane.v ;
00883     if( PFSGeoIntscLinePlane( line, &plane, pt, ptpar, spar ) == PFSGeoValid ) {
00884 
00885         /*  then check to see if intersection point is inside polygon
00886             or on the boundary of polygon                               */
00887 
00888         if( PFSGeoIsInsidePoly( poly, spar ) == PFSGeoTrue ) {
00889             return( PFSGeoValid ) ;
00890         }
00891         else {
00892             if( PFSGeoIsOnPolyBdry( poly, pt ) == PFSGeoTrue ) {
00893                 return( PFSGeoValid ) ;
00894             }
00895             else {
00896                 return( PFSGeoInvalid ) ;
00897             }
00898         }
00899     }
00900     else return( PFSGeoInvalid ) ;
00901 }
00902 
00903 
00904 
00905 /*      --------------------------------------------------------
00906 **      Find Normal Routines:
00907 
00908         PFSGeoStatus PFSGeoPolyNormal( n_verts, verts, n )
00909             int         *n_verts ; 
00910             PFSGeoPoint *verts ;
00911             PFSGeoPoint *n ;
00912 
00913         n_verts input number of polgon vertices.
00914         verts   input polygon vertices.
00915         n       ouput polygon normal.
00916 
00917         This function computes a unit vector normal of polygon given 
00918         by a list of vertex coordinates.  The vertices are assumed
00919         given in a clockwise order around the polygon.  If the computed
00920         normal vector is null, a PFSGeoInvalid status is returned. Otherwise
00921         a value of PFSGeoValid is returned.
00922 
00923         The algorithm for the routine is as follows:
00924             Traverse the loop of coordinates, assuming that it is in
00925             clockwise order, computing the components of the "area" of the
00926             enclosed polygon.  The total "area" components are computed by
00927             adding "area" components (cross product components) of
00928             triangles sides formed by the first, previous, and current
00929             vertices.  If the loop is not convex, some of the triangle
00930             areas might be negative, but those will be compensated by other
00931             positive triangle areas so that the final area is positive.
00932             (area here is actually twice the area).
00933             (positive here means in the direction of the face normal).
00934 
00935 
00936         PFSGeoStatus  PFSGeoLstSqrPlanEqn( num_pts, pts, plan_eqn ) 
00937             int         *num_pts ;
00938             PFSGeoPoint *pts ;
00939             PFSGeoPlanEqn       *plan_eqn ;
00940 
00941         num_pts     number of points
00942         pts         list of points
00943         plan_eqn    plane equation
00944 
00945         Given a list of points this function computes the equation 
00946         of the plane which correspond to the least square fit 
00947         through the points.
00948         The equation is given in the form:
00949             a * x  +  b * y  +  c * z  +  d  = 0
00950 
00951 */
00952 
00953 
00954 PFSGeoStatus PFSGeoPolyNormal( n_verts, verts, n )
00955     int         *n_verts ; 
00956     PFSGeoPoint *verts ;
00957     PFSGeoPoint *n ;
00958 {
00959     real        e_size;         /* length of first edge         */
00960     real        n_size;         /* normal length                */
00961     int         i;              /* loop counter                 */
00962 
00963     n->x = 0.0 ; n->y = 0.0 ; n->z = 0.0 ;
00964              
00965     for ( i=2 ; i < *n_verts ; i++ ) {
00966         n->x +=  (verts[i  ].y - verts[0].y) * 
00967                  (verts[i-1].z - verts[0].z) -
00968                  (verts[i  ].z - verts[0].z) * 
00969                  (verts[i-1].y - verts[0].y) ;
00970 
00971         n->y += -(verts[i  ].x - verts[0].x) * 
00972                  (verts[i-1].z - verts[0].z) +
00973                  (verts[i  ].z - verts[0].z) * 
00974                  (verts[i-1].x - verts[0].x) ;
00975 
00976         n->z +=  (verts[i  ].x - verts[0].x) * 
00977                  (verts[i-1].y - verts[0].y) -
00978                  (verts[i  ].y - verts[0].y) * 
00979                  (verts[i-1].x - verts[0].x) ;
00980     }
00981 
00982 /*  normalize                                                   */
00983 /*  get the length of the first edge (to compute ratio norm_size/edge_size) */
00984 
00985     e_size = PFSGeoDist( &verts[0], &verts[1] ) ;
00986     n_size = PFSGeoVecLen( n ) ;
00987 
00988     if (n_size/e_size > PFSGeoTolerance) {
00989         n->x /= n_size ;
00990         n->y /= n_size ;
00991         n->z /= n_size ;
00992         return( PFSGeoValid ) ;
00993     }
00994     else 
00995         return( PFSGeoInvalid );
00996 }
00997 
00998 
00999 PFSGeoStatus  PFSGeoLstSqrPlanEqn( num_pts, pts, plan_eqn ) 
01000     int         *num_pts ;      /* number of points     */
01001     PFSGeoPoint *pts ;          /* list of points       */
01002     PFSGeoPlanEqn       *plan_eqn ;     /* plane equation       */
01003 
01004 {
01005     real        a11,a12,a13,a22,a23,a33 ;       /* A matrix         */
01006     real        b11,b12,b13,b22,b23,b33 ;       /* A inverse matrix */
01007     real        sum_x,sum_y,sum_z ;             /* summed values    */
01008     real        div,norm ;                      /* auxiliar coeff.  */
01009     PFSGeoPoint    seg1, seg2, cross ;
01010     int         i ;                             /* counter          */
01011 
01012     /*  loop through the points and calculate the sums and products  */
01013 
01014     a11 = 0.0 ;     a12 = 0.0 ;     a13 = 0.0 ;
01015     a22 = 0.0 ;     a23 = 0.0 ;     a33 = 0.0 ;
01016 
01017     sum_x = 0.0 ;   sum_y = 0.0 ;   sum_z = 0.0 ;
01018 
01019     for ( i = 0; i < *num_pts; i++ ) {
01020         a11 = a11 + pts[i].x * pts[i].x ;
01021         a12 = a12 + pts[i].x * pts[i].y ;
01022         a13 = a13 + pts[i].x * pts[i].z ;
01023         a22 = a22 + pts[i].y * pts[i].y ;
01024         a23 = a23 + pts[i].y * pts[i].z ;
01025         a33 = a33 + pts[i].z * pts[i].z ;
01026 
01027         sum_x = sum_x + pts[i].x ;
01028         sum_y = sum_y + pts[i].y ;
01029         sum_z = sum_z + pts[i].z ;
01030     }
01031 
01032     /*  compute the inverse of A                            */
01033 
01034     div = a11 * ( a22*a33 - a23*a23 ) + a12 * ( a13*a23 - a12*a33 ) +
01035           a13 * ( a12*a23 - a13*a22 ) ;
01036 
01037     /* Check for possible trouble.  Either colinear points or
01038        all pts. lie near to a plane which passes through origin resulting
01039        in the A matrix to be singular, e.g., if only three pts. then
01040        third row is linear combo. of top two rows.
01041     */
01042 
01043     if ( fabs(div) < PFSGeoTolerance ) {
01044 
01045         /* Find first two segments which are non-colinear.
01046            Use these to form the plane eqn.
01047         */
01048         for( i = 0; i < *num_pts - 2; i++ ) {
01049             PFSGeoDiffVec( &pts[i+1], &pts[i], &seg1 ) ;
01050             PFSGeoDiffVec( &pts[i+2], &pts[i+1], &seg2 ) ;
01051             PFSGeoCrossProd( &seg1, &seg2, &cross ) ;
01052             if( PFSGeoNullVec( &cross, &PFSGeoTolerance ) == PFSGeoFalse ) {
01053                 PFSGeoGenPlanEqn( &pts[i], &pts[i+1], &pts[i+2], plan_eqn ) ;
01054                 return( PFSGeoValid ) ;
01055             }
01056         }
01057 
01058         return( PFSGeoInvalid ) ;
01059     }
01060     else {
01061     /*  compute the inverse of A coefficients               */
01062 
01063         b11 = ( a22*a33 - a23*a23 ) / div ;
01064         b12 = ( a13*a23 - a12*a33 ) / div ;
01065         b13 = ( a12*a23 - a13*a22 ) / div ;
01066         b22 = ( a11*a33 - a13*a13 ) / div ;
01067         b23 = ( a12*a13 - a11*a23 ) / div ;
01068         b33 = ( a11*a22 - a12*a12 ) / div ;
01069 
01070     /*  compute the equation coefficients                   */
01071 
01072         plan_eqn->a = b11*sum_x + b12*sum_y + b13*sum_z ;
01073         plan_eqn->b = b12*sum_x + b22*sum_y + b23*sum_z ;
01074         plan_eqn->c = b13*sum_x + b23*sum_y + b33*sum_z ;
01075 
01076     /*  normalize the equation coefficients                 */
01077 
01078         norm = sqrt( plan_eqn->a * plan_eqn->a + plan_eqn->b * plan_eqn->b + 
01079                      plan_eqn->c * plan_eqn->c ) ;
01080 
01081         plan_eqn->a /= norm ;
01082         plan_eqn->b /= norm ;
01083         plan_eqn->c /= norm ;
01084         plan_eqn->d = - 1.0 / norm ;
01085     }
01086 
01087 return( PFSGeoValid ) ;
01088 }
01089 
01090 
01091 
01092 /*      --------------------------------------------------------
01093 **      Closest Point Routines:
01094 
01095         void PFSGeoClstPtLine( line, pt, clst, par ) 
01096             PFSGeoLine   *line ;
01097             PFSGeoPoint  *pt, *clst ;
01098             PFSGeoPointPar  *par ;
01099 
01100         line    input parametric description of a line.
01101         pt      input cartesian point.
01102         clst    output closest point.
01103         par     parametric value of the point.
01104 
01105         Given the parametric description of a line, and a cartesian
01106         point not on the line, this function computes the cartesian
01107         coordinates of a point on the line which is closest to the
01108         input point.  The function also returns the parametric value
01109         of this point along the input line.
01110 
01111 
01112         void PFSGeoClstPtNormPlane( plane, pt, clst, spar ) 
01113             PFSGeoNormPlane *plane ;
01114             PFSGeoPoint  *pt, *clst ;
01115             PFSGeoSurfPar   *spar ;
01116 
01117         plane   input normalized parametric description of a plane.
01118         pt      input cartesian point.
01119         clst    output closest point.
01120         spar    parametric value of the point.
01121 
01122         Given the normalized parametric description of a plane, and a 
01123         cartesian point not necessarely on the plane, this function 
01124         computes the cartesian coordinates of a point on the plane 
01125         which is closest to the input point.  
01126         The function also returns the parametric values of this point on 
01127         the plane.  
01128         It is assumed that the two local vectors on the plane, 
01129         "u" and "v", are perpendicular-to-each-other unit vectors.
01130 
01131 
01132         PFSGeoStatus PFSGeoClstPtPoly( poly, pt, clst, spar ) 
01133             PFSGeoPoly  *poly ;
01134             PFSGeoPoint *pt ;
01135             PFSGeoPoint *clst ;
01136             PFSGeoSurfPar  *spar ;
01137 
01138         poly    input parametric description of a polygon.
01139         pt      input cartesian point.
01140         clst    output closest point.
01141         spar    parametric value of the point.
01142 
01143         Given the normalized parametric description of a polygon, and a 
01144         cartesian point not necessarely on its plane, this function 
01145         computes the cartesian coordinates of a point on the plane 
01146         which is closest to the input point.  
01147         The function also returns the parametric values of this point on 
01148         the plane.  
01149         First it is obtained the closest point on the plane which
01150         contains the polygon, then, using a scan line algorithm in the 
01151         parametric space of that plane, it is checked whether the 
01152         closest point is inside the polygon.  If the point is inside 
01153         the polygon, the function returns a PFSGeoValid status, otherwise 
01154         it returns PFSGeoInvalid.
01155         It is assumed that the two local vectors on the polygon plane, 
01156         "u" and "v", are perpendicular-to-each-other unit vectors.
01157 
01158 
01159         PFSGeoPredicate PFSGeoIsOnPlane( PFSGeoPoint  *pt, PFSGeoNormPlane  *pla )
01160 
01161         This function determines if the given point, pt,  lies on the
01162         given plane, pla. THE PLANE SHOULD BE GIVEN AS A POINTER 
01163         TO A PLANE NORMALIZED DESCRIPTION.
01164 */
01165 
01166 
01167 void PFSGeoClstPtLine( line, pt, clst, par ) 
01168     PFSGeoLine  *line ;
01169     PFSGeoPoint *pt, *clst ;
01170     PFSGeoPointPar *par ;
01171 {
01172     PFSGeoPoint local_pt  ;
01173 
01174     local_pt.x = pt->x - line->d.x ;
01175     local_pt.y = pt->y - line->d.y ;
01176     local_pt.z = pt->z - line->d.z ;
01177 
01178     *par = PFSGeoDotProd( &local_pt, &line->e ) / 
01179            PFSGeoDotProd( &line->e,  &line->e ) ;
01180 
01181     PFSGeoEvalLine( par, line, clst ) ;
01182 }
01183 
01184 
01185 void PFSGeoClstPtNormPlane( plane, pt, clst, spar ) 
01186     PFSGeoNormPlane *plane ;
01187     PFSGeoPoint  *pt, *clst ;
01188     PFSGeoSurfPar   *spar ;
01189 {
01190     PFSGeoPoint local_pt ;
01191 
01192     local_pt.x = pt->x - plane->a.x ;
01193     local_pt.y = pt->y - plane->a.y ;
01194     local_pt.z = pt->z - plane->a.z ;
01195 
01196     spar->u = - PFSGeoTripleProd( &local_pt, &plane->n, &plane->v ) ;
01197     spar->v =   PFSGeoTripleProd( &local_pt, &plane->n, &plane->u ) ;
01198 
01199     PFSGeoEvalPlane( spar, (PFSGeoPlane *)plane, clst ) ;
01200 }
01201 
01202 
01203 
01204 PFSGeoStatus PFSGeoClstPtPoly( poly, pt, clst, spar ) 
01205     PFSGeoPoly  *poly ;
01206     PFSGeoPoint *pt, *clst ;
01207     PFSGeoSurfPar  *spar ;
01208 {
01209     /*  first get the closest point on the plane which 
01210         contains the polygon                                    */
01211 
01212     PFSGeoClstPtNormPlane( &(poly->nplane), pt, clst, spar ) ;
01213 
01214     /*  then check to see if closest point is inside polygon 
01215         or on the boundary of polygon                           */
01216 
01217     if( PFSGeoIsInsidePoly( poly, spar ) == PFSGeoTrue ) {
01218         return( PFSGeoValid ) ;
01219     }
01220     else {
01221         if( PFSGeoIsOnPolyBdry( poly, pt ) == PFSGeoTrue ) {
01222             return( PFSGeoValid ) ;
01223         }
01224         else {
01225             return( PFSGeoInvalid ) ;
01226         }
01227     }
01228 }
01229 
01230 
01231 
01232 PFSGeoPredicate PFSGeoIsOnPlane( pt, pla )
01233 
01234 PFSGeoPoint     *pt ;
01235 PFSGeoNormPlane *pla ;
01236 
01237 {
01238 PFSGeoLine              line ;          /* line from "pt" to origin of "pla"        */
01239 real            proj ;          /* projection of above line on plane normal */
01240 real            toler ;         /* tolerance for closeness of point on plane*/
01241 real            line_len ;      /* length of line                           */
01242 
01243     /*  Generate a line connecting the given point to the  
01244         origin of the given normalized plane.                   */
01245 
01246     PFSGeoGenLine( pt, &pla->a, &line ) ;
01247 
01248     line_len = PFSGeoVecLen( &line.e ) ;
01249 
01250     /*  Get the projection of this line in the direction of the unit 
01251         normal of the given plane. (take the dot product of the two 
01252         vectors).  The division by line_len is to normalize the vector 
01253         line.e to unit size.                                    */
01254 
01255     if( fabs( line_len ) < PFSGeoTolerance ) return( PFSGeoTrue ) ;
01256     proj = fabs( PFSGeoDotProd( &pla->n, &line.e ) / line_len ) ;
01257 
01258     /*  If the projection is smaller than an arbitrary value,
01259         the point can be assumed to be on the plane.            */
01260 
01261     toler = 0.01 ;      /* 0.01 ~= cos(1.56 radians) == cos(89.4 degrees) */
01262     if( proj < toler ) {
01263         return( PFSGeoTrue ) ;
01264     }
01265     else {
01266         return( PFSGeoFalse ) ;
01267     }
01268 }
01269 
01270 
01271 /*      --------------------------------------------------------
01272 **      Misc Routines:
01273 
01274         PFSGeoStatus  PFSGeoInvert2x2( a, b ) 
01275             real        a[2][2] ;
01276             real        b[2][2] ;
01277 
01278         a       input 2 x 2 array of floats.
01279         b       output 2 x 2 inverse of a.
01280 
01281         This function computes the inverse of a 2 x 2 array.
01282         If the matrix is singular a value of PFSGeoInvalid is
01283         returned.  Otherwise a value of PFSGeoValid is returned
01284 
01285 
01286         PFSGeoStatus  PFSGeoInvert3x3( a, b ) 
01287             real        a[3][3] ;
01288             real        b[3][3] ;
01289 
01290         a       input 3 x 3 array of real.
01291         b       output 3 x 3 inverse of a.
01292 
01293         This function computes the inverse of a 3 x 3 array.
01294         If the matrix is singular a value of PFSGeoInvalid is
01295         returned.  Otherwise a value of PFSGeoValid is returned
01296 
01297 
01298         PFSGeoStatus  PFSGeodInvert3x3( a, b ) 
01299             double      a[3][3] ;
01300             double      b[3][3] ;
01301 
01302         a       input 3 x 3 array of doubles.
01303         b       output 3 x 3 inverse of a.
01304 
01305         This function computes the inverse of a 3 x 3 array
01306         in double precision.
01307         If the matrix is singular a value of PFSGeoInvalid is
01308         returned.  Otherwise a value of PFSGeoValid is returned
01309 
01310 
01311         void    PFSGeoCentroid( num_pts, pts, cntrd )
01312             int         *num_pts ;
01313             PFSGeoPoint pts[*num_pts] ;
01314             PFSGeoPoint *cntrd ;
01315 
01316         num_pts - number of points input
01317         pts     - coordinates of the points
01318         cntrd   - returned value of the centroid of the given list of points
01319 
01320         This function calculates the centroid of the given list of points
01321         such that cntrd->k =  sum{ pts[j]->k } / num_pts.
01322 
01323 
01324         PFSGeoStatus PFSGeoPerpLine( pl1, pl2, pl3, u, v, w ) 
01325             PFSGeoLine  *pl1, *pl2, *pl3 ; 
01326             PFSGeoPointPar *u, *v, *w ;
01327 
01328         pl1     first input parametric line.
01329         pl2     second input parametric line.
01330         pl3     output parametric line.
01331         u       output parametric value along pl1
01332         v       output parametric value along pl2
01333         w       output parametric value along pl3
01334 
01335         Given the parametric description of two input lines
01336         this function computes the parametric description of the
01337         line which is perpendicular to the two given lines.
01338         It also returns the parametric values for the intersection
01339         points along the three lines.  The w paramenter is the 
01340         parametric value of the intersection point of pl3 and pl2
01341         along pl3.  The parametric value of the intersection point
01342         of pl3 and pl1 measured along pl3 is always 0.0.
01343 
01344 
01345         void    PFSGeoPtNormToParPlan( pt, normal, plane ) 
01346             PFSGeoPoint  *pt, *normal ;
01347             PFSGeoNormPlane *plane ;
01348 
01349         pt          point on plane
01350         normal      normal to plane
01351         plane       normalized plane parametric description
01352 
01353         Given a point on a plane and the plane normal direction, 
01354         this function finds a parametric representation of the plane.
01355         The representation is given as a PFSGeoNormPlane structure, which 
01356         means that the two plane local directions are unit perpendicular 
01357         vectors and the unit normal vector is also contained in the 
01358         descriptor.
01359         The origin of the plane local system is the given point, and the 
01360         two unit directions on the plane are arbitrarely chosen.
01361 
01362         void    PFSGeoPlanToNormPlan( plane, normplane )
01363             PFSGeoPlane     *plane ;
01364             PFSGeoNormPlane    *normplane ;
01365             
01366         plane       PFSGeoPlane description of plane             (in)
01367         normplane   retrieved PFSGeoNormPlane description of plane (out)
01368 
01369         converts plane description from PFSGeoPlane to PFSGeoNormPlane. 
01370         The vector normplane->u is plane->d normalized and normplane->v
01371         is the normalized difference between plane.e and its projection
01372         onto the direction of normplane->u.  
01373 
01374 
01375         PFSGeoStatus   PFSGeo3PointsToNormPlane( in0, in1, in2, plane )
01376             PFSGeoPoint    *in0 ;
01377             PFSGeoPoint    *in1 ;
01378             PFSGeoPoint    *in2 ;
01379             PFSGeoNormPlane *plane ;
01380 
01381         in0     input point0
01382         in1     input point1
01383         in2     input point2
01384         plane   output normalized plane
01385 
01386         given 3 points, if they are not colinear, determine a normalized 
01387         description for the plane containing them and return a PFSGeoValid 
01388         status, othewise return PFSGeoInvalid. 
01389 
01390         void    PFSGeoPlanEqnToParPlan( plan_eqn, plane ) 
01391             PFSGeoPlanEqn        *plan_eqn ;
01392             PFSGeoNormPlane *plane ;
01393 
01394         plan_eqn    plane equation
01395         plane       normalized plane parametric description
01396 
01397         Given a plane equation in the form:
01398             a * x  +  b * y  +  c * z  +  d  = 0
01399         this function finds a parametric representation of the plane.
01400         The representation is given as a PFSGeoNormPlane structure, which 
01401         means that the two plane local directions are unit perpendicular 
01402         vectors and the unit normal vector is also contained in the 
01403         descriptor.
01404         The origin of the plane local system and the two unit directions 
01405         on the plane are arbitrarely chosen.
01406 
01407 
01408         PFSGeoPtTest   PFSGeoSideofPlan( plan_eqn, pt )
01409             PFSGeoPlanEqn       *plan_eqn ;
01410             PFSGeoPoint *pt ;
01411 
01412         Given a plane equation of the form:  a*x + b*y + c*z + d = 0
01413         (which was created via call to PFSGeoGenPlanEqn), whose top side
01414         is taken to be that side in which the normal vector points;
01415         this function will return one of three values.
01416                 PFSGeoAbove -- given pt. is above the plane
01417                 PFSGeoBelow -- given pt. is below the plane
01418                 PFSGeoOn         -- given pt. is on (within PFSGeoTolerance) the plane
01419 
01420 
01421         void    PFSGeoSurfInterp( num_pts, map_func, pts_val, interp_val ) 
01422             int         *num_pts ;
01423             real        map_func[*num_pts] ;
01424             PFSGeoSurfPar       pts_val[*num_pts] ;
01425             PFSGeoSurfPar       *interp_val ;
01426 
01427         num_pts     number of points which describe the mapping
01428         map_func[]  mapping function evaluated at target point
01429         pts_val[]   known surface values at interpolation points
01430         interp_val  returned surface values at target point
01431 
01432         This function interpolates a set of known surface values.
01433         The mapping function is given evaluated at the target point.
01434         Basically this function performs the dot product of the 
01435         given mapping function with the known interpolation point surface 
01436         values, which results in the target interpolated values.
01437 
01438 
01439         void    PFSGeoSurfJacob( num_pts, map_deriv_s, map_deriv_t, 
01440                                         pts_val, jac ) 
01441             int         *num_pts ;
01442             real        map_deriv_s[*num_pts] ;
01443             real        map_deriv_t[*num_pts] ;
01444             PFSGeoSurfPar       pts_val[*num_pts] ;
01445             real        jac[2][2] ;
01446 
01447         num_pts         number of points which describe the mapping
01448         map_deriv_s[]   mapping derivative wrt s evaluated at target point
01449         map_deriv_t[]   mapping derivative wrt t evaluated at target point
01450         pts_val[]       known surface values at interpolation points
01451         jac[2][2]       returned mapping jacobian evaluated at target point
01452 
01453         This function computes the jacobian matrix of a surface mapping at 
01454         a target point.
01455         The partial derivatives of the mapping function are given evaluated at 
01456         a the target point.
01457         Basically this function performs the dot product of the given mapping 
01458         function derivatives with the known interpolation point surface 
01459         values, which results in jacobian matrix.
01460 
01461 
01462         real    PFSGeoAngVecAboutLine( l, v0, v1 ) 
01463             PFSGeoLine  *l ;
01464             PFSGeoPoint *v0, *v1 ;
01465 
01466         l               given line
01467         v0, v1          reference and angle vectors normal to line
01468 
01469         This function determines the angle about a given line between two 
01470         planes that meet at this line and contain the two given vectors
01471         (presumed normal to line).
01472         The angle is measured in clockwise order going from the plane passing 
01473         at the second (angle) vector to the first (reference) plane.
01474         Clockwise is given by the right hand rule with the thumb 
01475         pointing in the direction of the line.
01476 
01477 
01478         real    PFSGeoAngPtAboutLine( l, p0, p1 ) 
01479             PFSGeoLine  *l ;
01480             PFSGeoPoint *p0, *p1 ;
01481 
01482         l               given line
01483         p0, p1          reference and angle points
01484 
01485         This function determines the angle about a given line between two 
01486         planes that meet at this line and pass at two given points 
01487         (presumed not on the line).
01488         The angle is measured in clockwise order going from the plane passing 
01489         at the second (angle) point to the first (reference) plane.
01490         Clockwise is given by the right hand rule with the thumb 
01491         pointing in the direction of the line.
01492 
01493 
01494         real    PFSGeoAngPtAboutPt( pivot, p0, p1 ) 
01495             PFSGeoPoint *pivot ;
01496             PFSGeoPoint *p0, *p1 ;
01497 
01498         pivot           pivot point
01499         p0, p1          reference and angle points
01500 
01501         This function determines the angle about a given pivot point 
01502         between two given points.
01503         The angle is measured in clockwise order going from the second 
01504         (angle) point to the first (reference) point.
01505 
01506 
01507         PFSGeoStatus PFSGeoProjVecPlane( vec, plane, proj )
01508             PFSGeoPoint *vec ; 
01509             PFSGeoPlane *plane ;
01510             PFSGeoPoint *proj ; 
01511 
01512         vec     vector direction
01513         plane   given plane
01514         proj    projection of vector direction onto plane
01515 
01516         given a vector direction and a plane, this function finds the 
01517         vector direction which corresponds to the projection of the 
01518         vector onto the plane.
01519         If the given vector is normal to the plane, a PFSGeoInvalid 
01520         status is returned.  Otherwise a PFSGeoValid status is returned.
01521 
01522 
01523         real PFSGeoDistPtNormPlane( plane, pt )
01524             PFSGeoNormPlane    *plane ;
01525             PFSGeoPoint     *pt ;
01526 
01527         plane   input normalized parametric description of a plane.
01528         pt      input cartesian point.
01529 
01530         returns the distance from the point to the plane
01531 
01532 
01533         void PFSGeoDyadProd( vec0, vec1, matr )
01534 
01535             PFSGeoPoint *vec0, *vec1 ;
01536             real        matr[3][3] ;
01537 
01538         vec0, vec1  input vectors
01539         matr        output matrix, dyadic product  matr = v1 @ v2
01540 
01541         performs tensorial, or dyadic, product of two vectors
01542 
01543 
01544         void PFSGeoProdMatrVec( matr, vec0, vec1 ) 
01545 
01546         real        matr[3][3] ;
01547         PFSGeoPoint    *vec0 ;
01548         PFSGeoPoint    *vec1 ;
01549         
01550         matr    input matrix
01551         vec0    input vector
01552         vec1    output vector   v1 = matr x v0
01553 
01554 */
01555 
01556 PFSGeoStatus  PFSGeoInvert2x2( a, b ) 
01557     real        a[2][2] ;       /* matrix to invert     */
01558     real        b[2][2] ;       /* inverse matrix       */
01559 {
01560     real        det ;       /* determinant of given matrix  */
01561     int         i,j ;       /* counters                     */
01562 
01563 /*  clear inverse matrix                        */
01564 
01565     for( i = 0; i < 2; i++) 
01566         for( j = 0; j < 2; j++) b[i][j] = 0.0 ;
01567 
01568 /*  compute matrix determinant                  */
01569 
01570     det = a[0][0] * a[1][1] - a[0][1] * a[1][0] ;
01571 
01572     if (det == 0.0) 
01573         return( PFSGeoInvalid ) ;
01574     else {
01575         b[0][0] =  a[1][1] / det ;
01576         b[0][1] = -a[0][1] / det ;
01577         b[1][0] = -a[1][0] / det ;
01578         b[1][1] =  a[0][0] / det ;
01579         return( PFSGeoValid );
01580     }
01581 }
01582 
01583 
01584 PFSGeoStatus  PFSGeoInvert3x3( a, b ) 
01585     real        a[3][3] ;       /* matrix to invert     */
01586     real        b[3][3] ;       /* inverse matrix       */
01587 {
01588     real        det ;       /* determinant of given matrix  */
01589     int         i,j ;       /* counters                     */
01590 
01591 /*  clear inverse matrix                        */
01592 
01593     for( i = 0; i < 3; i++) 
01594         for( j = 0; j < 3; j++) b[i][j] = 0.0 ;
01595 
01596 /*  compute matrix determinant                  */
01597 
01598     det = a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) - 
01599           a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0]) + 
01600           a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]) ;
01601 
01602     if (det == 0.0) 
01603         return( PFSGeoInvalid ) ;
01604     else {
01605         b[0][0] =  (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det ;
01606         b[0][1] = -(a[0][1] * a[2][2] - a[0][2] * a[2][1]) / det ;
01607         b[0][2] =  (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det ;
01608         b[1][0] = -(a[1][0] * a[2][2] - a[1][2] * a[2][0]) / det ;
01609         b[1][1] =  (a[0][0] * a[2][2] - a[0][2] * a[2][0]) / det ;
01610         b[1][2] = -(a[0][0] * a[1][2] - a[0][2] * a[1][0]) / det ;
01611         b[2][0] =  (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det ;
01612         b[2][1] = -(a[0][0] * a[2][1] - a[0][1] * a[2][0]) / det ;
01613         b[2][2] =  (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det ;
01614         return( PFSGeoValid );
01615     }
01616 }
01617 
01618 
01619 PFSGeoStatus  PFSGeodInvert3x3( a, b ) 
01620     double      a[3][3] ;       /* matrix to invert     */
01621     double      b[3][3] ;       /* inverse matrix       */
01622 {
01623     double      det ;       /* determinant of given matrix  */
01624     int         i,j ;       /* counters                     */
01625 
01626 /*  clear inverse matrix                        */
01627 
01628     for( i = 0; i < 3; i++) 
01629         for( j = 0; j < 3; j++) b[i][j] = 0.0 ;
01630 
01631 /*  compute matrix determinant                  */
01632 
01633     det = a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) - 
01634           a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0]) + 
01635           a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]) ;
01636 
01637     if (det == 0.0) 
01638         return( PFSGeoInvalid ) ;
01639     else {
01640         b[0][0] =  (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det ;
01641         b[0][1] = -(a[0][1] * a[2][2] - a[0][2] * a[2][1]) / det ;
01642         b[0][2] =  (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det ;
01643         b[1][0] = -(a[1][0] * a[2][2] - a[1][2] * a[2][0]) / det ;
01644         b[1][1] =  (a[0][0] * a[2][2] - a[0][2] * a[2][0]) / det ;
01645         b[1][2] = -(a[0][0] * a[1][2] - a[0][2] * a[1][0]) / det ;
01646         b[2][0] =  (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det ;
01647         b[2][1] = -(a[0][0] * a[2][1] - a[0][1] * a[2][0]) / det ;
01648         b[2][2] =  (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det ;
01649         return( PFSGeoValid );
01650     }
01651 }
01652 
01653 
01654 void    PFSGeoCentroid( num_pts, pts, cntrd )
01655             int         *num_pts ;   /* number of points            */
01656             PFSGeoPoint pts[] ;     /* list of points       */
01657             PFSGeoPoint *cntrd ;    /* returned centroid    */
01658 
01659 {
01660     PFSGeoPoint sum ;
01661     int         i ;
01662 
01663     sum.x = sum.y = sum.z = 0.0 ;
01664     for( i=0; i<(*num_pts); i++ ) {
01665 
01666         sum.x += pts[i].x ;
01667         sum.y += pts[i].y ;
01668         sum.z += pts[i].z ;
01669     }
01670 
01671     cntrd->x = sum.x / *num_pts ;
01672     cntrd->y = sum.y / *num_pts ;
01673     cntrd->z = sum.z / *num_pts ;
01674 
01675 return ;
01676 }
01677 
01678 
01679 PFSGeoStatus PFSGeoPerpLine( pl1, pl2, pl3, u, v, w ) 
01680     PFSGeoLine  *pl1, *pl2, *pl3 ; 
01681     PFSGeoPointPar *u, *v, *w ;
01682 {
01683     real        coef[3][3], cinv[3][3];
01684     PFSGeoPoint dvec ;
01685 
01686     /* comput the direction of the perpendicular line   */
01687 
01688     PFSGeoCrossProd( &pl1->e, &pl2->e, &pl3->e ) ;
01689 
01690     /* build and invert the coef matrix */
01691 
01692     coef[0][0] = pl1->e.x ; coef[0][1] = pl2->e.x ; coef[0][2] = pl3->e.x ;
01693     coef[1][0] = pl1->e.y ; coef[1][1] = pl2->e.y ; coef[1][2] = pl3->e.y ;
01694     coef[2][0] = pl1->e.z ; coef[2][1] = pl2->e.z ; coef[2][2] = pl3->e.z ;
01695 
01696     if ( PFSGeoInvert3x3( coef, cinv ) != PFSGeoValid ) 
01697         return( PFSGeoInvalid ) ;
01698     else {
01699         /* find the scale factors */
01700 
01701         dvec.x = pl2->d.x - pl1->d.x ;
01702         dvec.y = pl2->d.y - pl1->d.y ;
01703         dvec.z = pl2->d.z - pl1->d.z ;
01704 
01705         *u = cinv[0][0]*dvec.x + cinv[0][1]*dvec.y + cinv[0][2]*dvec.z ;
01706         *v = cinv[1][0]*dvec.x + cinv[1][1]*dvec.y + cinv[1][2]*dvec.z ;
01707         *w = cinv[2][0]*dvec.x + cinv[2][1]*dvec.y + cinv[2][2]*dvec.z ;
01708         *v = -*v ;
01709 
01710         PFSGeoEvalLine( u, pl1, &pl3->d ) ;
01711         return(PFSGeoValid) ;
01712     }
01713 }
01714 
01715 
01716 void    PFSGeoPtNormToParPlan( pt, normal, plane ) 
01717     PFSGeoPoint  *pt, *normal ; /* point on plane and normal    */
01718     PFSGeoNormPlane *plane ;    /* plane parametric description */
01719 
01720 {
01721     PFSGeoPoint    x_dir ;                      /* x direction              */
01722     PFSGeoPoint    y_dir ;                      /* y direction              */
01723     PFSGeoPoint    z_dir ;                      /* z direction              */
01724     real        size ;                  /* size of a vector         */
01725     real        tolerance ;             /* tolerance for checking   */
01726 
01727     x_dir.x = 1.0 ;     x_dir.y = 0.0 ;     x_dir.z = 0.0 ;
01728     y_dir.x = 0.0 ;     y_dir.y = 1.0 ;     y_dir.z = 0.0 ;
01729     z_dir.x = 0.0 ;     z_dir.y = 0.0 ;     z_dir.z = 1.0 ;
01730 
01731     /*  normalize given normal                          */
01732 
01733     size = PFSGeoVecLen( normal ) ;
01734 
01735     plane->n.x = normal->x / size ;
01736     plane->n.y = normal->y / size ;
01737     plane->n.z = normal->z / size ;
01738 
01739     /*  choose the given point as an origin for the local system on plane */
01740 
01741     plane->a = *pt ;
01742 
01743     /*  arbitrarely choose two unit directions for the local system on plane */
01744 
01745     tolerance = PFSGeoTolerance ;
01746     PFSGeoCrossProd( &plane->n, &x_dir, &plane->u ) ;
01747     if (PFSGeoNullVec( &plane->u, &tolerance ) == PFSGeoTrue) {
01748         PFSGeoCrossProd( &plane->n, &y_dir, &plane->u ) ;
01749         if (PFSGeoNullVec( &plane->u, &tolerance ) == PFSGeoTrue) {
01750             PFSGeoCrossProd( &plane->n, &z_dir, &plane->u ) ;
01751         }
01752     }
01753     size = PFSGeoVecLen( &plane->u ) ;
01754     plane->u.x /= size ;    plane->u.y /= size ;    plane->u.z /= size ;
01755     PFSGeoCrossProd( &plane->n, &plane->u, &plane->v ) ;
01756 
01757 return ;
01758 }
01759 
01760 void    PFSGeoPlanToNormPlan( plane, normplane )
01761     PFSGeoPlane     *plane ;
01762     PFSGeoNormPlane    *normplane ;
01763 
01764 
01765 {
01766     normplane->a = plane->a ;
01767     PFSGeoVecNormalize( &plane->b, &normplane->u ) ;
01768     PFSGeoCrossProd( &normplane->u, &plane->c, &normplane->n ) ;
01769     PFSGeoVecNormalize( &normplane->n, &normplane->n) ;
01770     PFSGeoCrossProd( &normplane->n, &normplane->u, &normplane->v ) ;
01771 }
01772 
01773 PFSGeoStatus  PFSGeo3PointsToNormPlane( in0, in1, in2, plane )
01774     PFSGeoPoint    *in0 ;
01775     PFSGeoPoint    *in1 ;
01776     PFSGeoPoint    *in2 ;
01777     PFSGeoNormPlane *plane ;
01778 
01779 {
01780     plane->a = *in0 ;
01781     PFSGeoDiffVec( in1, in0, &plane->u ) ;
01782     PFSGeoDiffVec( in2, in0, &plane->v ) ;
01783     
01784     PFSGeoCrossProd( &plane->u, &plane->v, &plane->n ) ;
01785 
01786     if (PFSGeoNullVec( &plane->n, &PFSGeoTolerance ) ) return(PFSGeoInvalid) ;
01787     
01788     PFSGeoPlanToNormPlan( (PFSGeoPlane *)plane, plane ) ;    
01789 
01790     return(PFSGeoValid) ;
01791 }
01792         
01793 
01794 
01795 void    PFSGeoPlanEqnToParPlan( plan_eqn, plane ) 
01796     PFSGeoPlanEqn        *plan_eqn ;    /* plane equation               */
01797     PFSGeoNormPlane *plane ;    /* plane parametric description */
01798 
01799 {
01800     PFSGeoPoint    x_dir ;                      /* x direction              */
01801     PFSGeoPoint    y_dir ;                      /* y direction              */
01802     PFSGeoPoint    z_dir ;                      /* z direction              */
01803     real        tolerance ;             /* tolerance for checking   */
01804     real        size ;                  /* size of a vector         */
01805 
01806     x_dir.x = 1.0 ;     x_dir.y = 0.0 ;     x_dir.z = 0.0 ;
01807     y_dir.x = 0.0 ;     y_dir.y = 1.0 ;     y_dir.z = 0.0 ;
01808     z_dir.x = 0.0 ;     z_dir.y = 0.0 ;     z_dir.z = 1.0 ;
01809 
01810     /*  normal to plane is obtained directly from its equation  */
01811 
01812     size = sqrt( plan_eqn->a * plan_eqn->a + plan_eqn->b * plan_eqn->b + 
01813                  plan_eqn->c * plan_eqn->c ) ;
01814 
01815     plane->n.x = plan_eqn->a /size ;
01816     plane->n.y = plan_eqn->b /size ;
01817     plane->n.z = plan_eqn->c /size ;
01818 
01819     /*  arbitrarely choose an origin for the local system on plane */
01820 
01821     if (fabs(plan_eqn->a) > PFSGeoTolerance) {
01822         plane->a.x = - plan_eqn->d / plan_eqn->a ;
01823         plane->a.y = 0.0 ;
01824         plane->a.z = 0.0 ;
01825     }
01826     else if (fabs(plan_eqn->b) > PFSGeoTolerance) {
01827         plane->a.x = 0.0 ;
01828         plane->a.y = - plan_eqn->d / plan_eqn->b ;
01829         plane->a.z = 0.0 ;
01830     }
01831     else {
01832         plane->a.x = 0.0 ;
01833         plane->a.y = 0.0 ;
01834         plane->a.z = - plan_eqn->d / plan_eqn->c ;
01835     }
01836 
01837     /*  arbitrarely choose two unit directions for the local system on plane */
01838 
01839     if (fabs( plan_eqn->d ) == 0.0) tolerance = PFSGeoTolerance ;
01840     else                        tolerance = PFSGeoTolerance * fabs( plan_eqn->d ) ;
01841     PFSGeoCrossProd( &plane->n, &x_dir, &plane->u ) ;
01842     if (PFSGeoNullVec( &plane->u, &tolerance ) == PFSGeoTrue) {
01843         PFSGeoCrossProd( &plane->n, &y_dir, &plane->u ) ;
01844         if (PFSGeoNullVec( &plane->u, &tolerance ) == PFSGeoTrue) {
01845             PFSGeoCrossProd( &plane->n, &z_dir, &plane->u ) ;
01846         }
01847     }
01848     size = PFSGeoVecLen( &plane->u ) ;
01849     plane->u.x /= size ;    plane->u.y /= size ;    plane->u.z /= size ;
01850     PFSGeoCrossProd( &plane->n, &plane->u, &plane->v ) ;
01851 
01852 return ;
01853 }
01854 
01855 
01856 PFSGeoPtTest  PFSGeoSideofPlan( plan_eqn, pt )
01857     PFSGeoPlanEqn       *plan_eqn ;
01858     PFSGeoPoint *pt ;
01859 
01860 {
01861     real  result ;
01862 
01863     result =  (     plan_eqn->a * pt->x
01864                  +  plan_eqn->b * pt->y
01865                  +  plan_eqn->c * pt->z
01866                  +  plan_eqn->d          ) ;
01867 
01868     if( result > PFSGeoTolerance )
01869         return( PFSGeoAbove ) ;
01870     else if( result < -PFSGeoTolerance )
01871         return( PFSGeoBelow ) ;
01872     else
01873         return( PFSGeoOn ) ;
01874 }
01875 
01876 
01877 void    PFSGeoSurfInterp( num_pts, map_func, pts_val, interp_val ) 
01878     int         *num_pts ;      /* number of points which describe the mapping*/
01879     real        map_func[] ;    /* mapping function evaluated at target point */
01880     PFSGeoSurfPar       pts_val[] ;     /* known surface values at interpolation pts  */
01881     PFSGeoSurfPar       *interp_val ;   /* returned surface values at target point    */
01882 
01883 {
01884     int     i;
01885 
01886     interp_val->u = 0.0 ;
01887     interp_val->v = 0.0 ;
01888 
01889     for( i = 0; i < *num_pts; i++ ) {
01890         interp_val->u += map_func[i] * pts_val[i].u ;
01891         interp_val->v += map_func[i] * pts_val[i].v ;
01892     }
01893 
01894 return ;
01895 }
01896 
01897 
01898 void    PFSGeoSurfJacob( num_pts, map_deriv_s, map_deriv_t, pts_val, jac ) 
01899     int         *num_pts ;      /* number of points which describe the mapping*/
01900     real        map_deriv_s[] ; /* mapping deriv. wrt s evaluated at target pt*/
01901     real        map_deriv_t[] ; /* mapping deriv. wrt t evaluated at target pt*/
01902     PFSGeoSurfPar       pts_val[] ;     /* known surface values at interpolation pts  */
01903     real        jac[2][2] ;     /* mapping jacobian evaluated at target point */
01904 
01905 {
01906     int     i;
01907 
01908     jac[0][0] = 0.0 ;       jac[0][1] = 0.0 ;
01909     jac[1][0] = 0.0 ;       jac[1][1] = 0.0 ;
01910 
01911     for( i = 0; i < *num_pts; i++ ) {
01912         jac[0][0] += map_deriv_s[i] * pts_val[i].u ;
01913         jac[0][1] += map_deriv_s[i] * pts_val[i].v ;
01914         jac[1][0] += map_deriv_t[i] * pts_val[i].u ;
01915         jac[1][1] += map_deriv_t[i] * pts_val[i].v ;
01916     }
01917 
01918 return ;
01919 }
01920 
01921 
01922 real    PFSGeoAngVecAboutLine( l, v0, v1 ) 
01923     PFSGeoLine  *l ;            /* given line                                */
01924     PFSGeoPoint *v0, *v1 ;      /* reference and angle vectors normal to line*/
01925 {
01926     real        cosang ;            /* cosine of target angle           */
01927     PFSGeoPoint cross ;             /* cross product of normal vectors  */
01928     real        pi = fabs( acos(-1.0) ) ;
01929     real        len, toler ;
01930 
01931     /* normalize the given vectors                          */
01932 
01933     len = PFSGeoVecLen ( v0 ) ;
01934     if( len == 0.0 ) return( 0.0 ) ;
01935     v0->x /= len ;   v0->y /= len ;   v0->z /= len ;
01936     len = PFSGeoVecLen ( v1 ) ;
01937     if( len == 0.0 ) return( 0.0 ) ;
01938     v1->x /= len ;   v1->y /= len ;   v1->z /= len ;
01939 
01940     /* cosine of angle between two vectors is obtained from dot product */
01941 
01942     cosang = PFSGeoDotProd( v1, v0 ) ;
01943 
01944     /* get the cross product of these vectors.  if the cross product vector 
01945        has the same direction as the given line, then desired angle is 
01946        in the range [0 .. pi], otherwise it is in the range [pi .. 2pi] */
01947 
01948     PFSGeoCrossProd( v1, v0, &cross ) ;
01949 
01950     toler = PFSGeoTolerance ;
01951     if( PFSGeoNullVec( &cross, &toler ) == PFSGeoFalse ) {
01952         if( PFSGeoDotProd( &l->e, &cross ) > 0.0 ) {
01953             return( acos( cosang ) ) ;
01954         }
01955         else {
01956             return( 2.0 * pi - acos( cosang ) ) ;
01957         }
01958     }
01959     else {
01960         if( cosang > 0.0 ) {
01961             return( 0.0 ) ;
01962         }
01963         else {
01964             return( pi ) ;
01965         }
01966     }
01967 }
01968 
01969 
01970 real    PFSGeoAngPtAboutLine( l, p0, p1 ) 
01971     PFSGeoLine  *l ;            /* given line                   */
01972     PFSGeoPoint *p0, *p1 ;      /* reference and angle points   */
01973 {
01974     PFSGeoPoint clstp0, clstp1 ;    /* points on line which are closest 
01975                                        to given points respectively     */
01976     PFSGeoPoint v0, v1 ;            /* vectors normal to given line 
01977                                        passing on p0 and p1 respectively*/
01978     PFSGeoPointPar dum_par ;
01979 
01980     /* get the two points on line which are closest to given points */
01981 
01982     PFSGeoClstPtLine  ( l, p0, &clstp0, &dum_par ) ;
01983     PFSGeoClstPtLine  ( l, p1, &clstp1, &dum_par ) ;
01984 
01985     /* generate two vectors normal to line passing at the given points  */
01986 
01987     v0.x = p0->x - clstp0.x ;
01988     v0.y = p0->y - clstp0.y ;
01989     v0.z = p0->z - clstp0.z ;
01990     v1.x = p1->x - clstp1.x ;
01991     v1.y = p1->y - clstp1.y ;
01992     v1.z = p1->z - clstp1.z ;
01993 
01994     return( PFSGeoAngVecAboutLine( l, &v0, &v1 ) ) ;
01995 }
01996 
01997 
01998 real    PFSGeoAngPtAboutPt( pivot, p0, p1 ) 
01999     PFSGeoPoint *pivot ;        /* pivot point                  */
02000     PFSGeoPoint *p0, *p1 ;      /* reference and angle points   */
02001 {
02002     PFSGeoLine  l ;              /* line normal to plane formed by 3 points*/
02003     PFSGeoPoint v0, v1 ;         /* vectors from pivot to given points  */
02004     real        pi = fabs( acos(-1.0) ) ;
02005     real        toler ;
02006 
02007     /* first the vectors from the pivot to the two other points.
02008        get the cross product of these vectors.                              */
02009 
02010     v0.x = p0->x - pivot->x; v0.y = p0->y - pivot->y; v0.z = p0->z - pivot->z;
02011     v1.x = p1->x - pivot->x; v1.y = p1->y - pivot->y; v1.z = p1->z - pivot->z;
02012 
02013     /* get a line which is normal to the three points.
02014        if the cross product vector is null, the angle is either 0 or pi.    */
02015 
02016     l.d = *pivot ;
02017     PFSGeoCrossProd( &v1, &v0, &l.e ) ;
02018 
02019     toler = PFSGeoTolerance ;
02020     if( PFSGeoNullVec( &l.e, &toler ) == PFSGeoTrue ) {
02021         if( PFSGeoDotProd( &v0, &v1 ) > 0.0 ) {
02022             return( 0.0 ) ;
02023         }
02024         else {
02025             return( pi ) ;
02026         }
02027     }
02028     else {
02029 
02030     /* return angle between two vectors             */
02031 
02032         return( PFSGeoAngVecAboutLine( &l, &v0, &v1 ) ) ;
02033     }
02034 }
02035 
02036 
02037 PFSGeoStatus PFSGeoProjVecPlane( vec, plane, proj )
02038     PFSGeoPoint *vec ; 
02039     PFSGeoPlane *plane ;
02040     PFSGeoPoint *proj ; 
02041 {
02042     real        vec_dot_b, vec_dot_c ;
02043 
02044     vec_dot_b = PFSGeoDotProd( vec, &plane->b ) ;
02045     vec_dot_c = PFSGeoDotProd( vec, &plane->c ) ;
02046 
02047     proj->x = vec_dot_b * plane->b.x + vec_dot_c * plane->c.x ;
02048     proj->y = vec_dot_b * plane->b.y + vec_dot_c * plane->c.y ;
02049     proj->z = vec_dot_b * plane->b.z + vec_dot_c * plane->c.z ;
02050 
02051     if( (fabs(vec_dot_b) < PFSGeoTolerance) && (fabs(vec_dot_c) < PFSGeoTolerance) ) {
02052         return( PFSGeoInvalid ) ;
02053     }
02054     else {
02055         return( PFSGeoValid ) ;
02056     }
02057 }
02058 
02059 real PFSGeoDistPtNormPlane( plane, pt )
02060     PFSGeoNormPlane    *plane ;
02061     PFSGeoPoint     *pt ;
02062 
02063 {
02064     PFSGeoPoint    clst ;
02065     PFSGeoSurfPar  spar ;
02066 
02067     PFSGeoClstPtNormPlane( plane, pt, &clst, &spar ) ;
02068 
02069     return( PFSGeoDist( pt, &clst ) ) ;
02070 }
02071 
02072 void PFSGeoDyadProd( vec0, vec1, matr )
02073 
02074     PFSGeoPoint *vec0, *vec1 ;
02075     real        matr[3][3] ;
02076 {
02077 
02078     matr[0][0] = vec0->x * vec1->x ;
02079     matr[0][1] = vec0->x * vec1->y ;
02080     matr[0][2] = vec0->x * vec1->z ;
02081     matr[1][0] = vec0->y * vec1->x ;
02082     matr[1][1] = vec0->y * vec1->y ;
02083     matr[1][2] = vec0->y * vec1->z ;
02084     matr[2][0] = vec0->z * vec1->x ;
02085     matr[2][1] = vec0->z * vec1->y ;
02086     matr[2][2] = vec0->z * vec1->z ;
02087 
02088     return ;
02089 }
02090 
02091 void PFSGeoProdMatrVec( matr, vec0, vec1 ) 
02092     real        matr[3][3] ;
02093     PFSGeoPoint *vec0 ;
02094     PFSGeoPoint *vec1 ;
02095 
02096 {
02097     vec1->x = matr[0][0] * vec0->x + matr[0][1] * vec0->y + 
02098                                      matr[0][2] * vec0->z ;
02099     vec1->y = matr[1][0] * vec0->x + matr[1][1] * vec0->y + 
02100                                      matr[1][2] * vec0->z ;
02101     vec1->z = matr[2][0] * vec0->x + matr[2][1] * vec0->y + 
02102                                      matr[2][2] * vec0->z ;
02103     return ;
02104 }
02105 
02106 
02107 
02108 

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