nurb_flat.c

Go to the documentation of this file.
00001 /*                     N U R B _ F L A T . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1990-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup nurb */
00023 /*@{*/
00024 /** @file nurb_flat.c
00025  *  Tests the NURB surface to see if its flat depending
00026  *  on the epsilon passed.
00027  *
00028  * Author -
00029  *     Paul R. Stay
00030  *
00031  * Source -
00032  *     SECAD/VLD Computing Consortium, Bldg 394
00033  *     The U.S. Army Ballistic Research Laboratory
00034  *     Aberdeen Proving Ground, Maryland 21005
00035  *
00036  */
00037 /*@}*/
00038 
00039 #include "common.h"
00040 
00041 
00042 
00043 #include <stdio.h>
00044 #include <math.h>
00045 #include "machine.h"
00046 #include "vmath.h"
00047 #include "raytrace.h"
00048 #include "nurb.h"
00049 
00050 int
00051 rt_nurb_s_flat(struct face_g_snurb *srf, fastf_t epsilon)
00052 
00053                                 /* Epsilon value for flatness testing */
00054 {
00055         register fastf_t        max_row_dist;
00056         register fastf_t        max_col_dist;
00057         register fastf_t        max_dist;
00058         int     dir;
00059         fastf_t        * mesh_ptr = srf->ctl_points;
00060         int     coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
00061         int     j, i, k;
00062         int     mesh_elt;
00063         vect_t          p1, p2, p3, p4, v1, v2, v3;
00064         vect_t          nrm;
00065         fastf_t         nrmln;
00066         fastf_t         dist;
00067         fastf_t        * crv;
00068         fastf_t         spl_crv_flat();
00069         int     otherdir;
00070 
00071         dir = srf->dir;
00072 
00073         otherdir = (dir == RT_NURB_SPLIT_ROW) ? RT_NURB_SPLIT_COL : RT_NURB_SPLIT_ROW;
00074 
00075         max_row_dist = max_col_dist = -INFINITY;
00076 
00077         crv = (fastf_t * ) bu_malloc( sizeof(fastf_t) *
00078             RT_NURB_EXTRACT_COORDS(srf->pt_type) * srf->s_size[1],
00079             "rt_nurb_s_flat: crv");
00080 
00081         /* Test Row and RT_NURB_SPLIT_COL curves for flatness,
00082          * If a curve is not flat than get distance to line */
00083 
00084         /* Test Row Curves */
00085 
00086         for (i = 0; i < (srf->s_size[0]); i++) {
00087                 fastf_t rdist;
00088                 for (j = 0;
00089                     j < (srf->s_size[1] *
00090                         RT_NURB_EXTRACT_COORDS(srf->pt_type));
00091                     j++)
00092                         crv[j] = *mesh_ptr++;
00093 
00094                 rdist = rt_nurb_crv_flat(crv, srf->s_size[1],
00095                     srf->pt_type);
00096                 max_row_dist = MAX(max_row_dist, rdist);
00097         }
00098 
00099         bu_free( (char *)crv, "rt_nurb_s_flat: crv" );
00100 
00101         crv = (fastf_t * ) bu_malloc(sizeof(fastf_t) *
00102             RT_NURB_EXTRACT_COORDS(srf->pt_type) *
00103             srf->s_size[0],     "rt_nurb_s_flat: crv");
00104 
00105         for (i = 0; i < (coords * srf->s_size[1]); i += coords) {
00106                 fastf_t rdist;
00107 
00108                 for (j = 0; j < (srf->s_size[0]); j++) {
00109                         mesh_elt =
00110                             (j * (srf->s_size[1] * coords)) + i;
00111 
00112                         for (k = 0; k < coords; k++)
00113                                 crv[j * coords + k] =
00114                                     srf->ctl_points[mesh_elt + k];
00115                 }
00116 
00117                 rdist = rt_nurb_crv_flat(crv,
00118                     srf->s_size[0], srf->pt_type);
00119 
00120                 max_col_dist = MAX( max_col_dist, rdist);
00121         }
00122 
00123         bu_free((char *)crv, "rt_nurb_s_flat: crv");
00124 
00125         max_dist = MAX( max_row_dist, max_col_dist);
00126 
00127         if ( max_dist > epsilon) {
00128                 if ( max_row_dist > max_col_dist )
00129                         return RT_NURB_SPLIT_ROW;
00130                 else
00131                         return RT_NURB_SPLIT_COL;
00132         }
00133 
00134         /* Test the corners to see if they lie in a plane. */
00135 
00136         /*
00137          * Extract the four corners and put a plane through three of them and
00138          * see how far the fourth is to the plane.
00139          */
00140 
00141         mesh_ptr = srf->ctl_points;
00142 
00143         if ( !RT_NURB_IS_PT_RATIONAL(srf->pt_type) ) {
00144 
00145                 VMOVE(p1, mesh_ptr);
00146                 VMOVE(p2,
00147                     (mesh_ptr + (srf->s_size[1] - 1) * coords));
00148                 VMOVE(p3,
00149                     (mesh_ptr +
00150                     ((srf->s_size[1] *
00151                     (srf->s_size[0] - 1)) +
00152                     (srf->s_size[1] - 1)) * coords));
00153 
00154                 VMOVE(p4,
00155                     (mesh_ptr +
00156                     (srf->s_size[1] *
00157                     (srf->s_size[0] - 1)) * coords));
00158         } else
00159          {
00160                 hvect_t h1, h2, h3, h4;
00161                 int     offset;
00162 
00163                 HMOVE(h1, mesh_ptr);
00164                 HDIVIDE( p1, h1 );
00165 
00166                 offset = (srf->s_size[1] - 1) * coords;
00167                 HMOVE(h2, mesh_ptr + offset);
00168                 HDIVIDE( p2, h2 );
00169 
00170                 offset =
00171                     ((srf->s_size[1] *
00172                     (srf->s_size[0] - 1)) +
00173                     (srf->s_size[1] - 1)) * coords;
00174                 HMOVE(h3, mesh_ptr + offset);
00175                 HDIVIDE( p3, h3 );
00176 
00177                 offset =
00178                     (srf->s_size[1] *
00179                     (srf->s_size[0] - 1)) * coords;
00180                 HMOVE(h4, mesh_ptr + offset);
00181                 HDIVIDE( p4, h4 );
00182         }
00183 
00184         VSUB2(v1, p2, p1);
00185         VSUB2(v2, p3, p1);
00186 
00187         VCROSS(nrm, v1, v2);
00188 
00189         nrmln = MAGNITUDE(nrm);
00190         if( nrmln < 0.0001 )                    /* XXX Why this constant? */
00191                 return RT_NURB_SPLIT_FLAT;
00192 
00193         VSUB2(v3, p4, p1);
00194 
00195         dist = fabs(VDOT( v3, nrm)) / nrmln;
00196 
00197         if (dist > epsilon)
00198                 return otherdir;
00199 
00200         return RT_NURB_SPLIT_FLAT;              /* Must be flat */
00201 
00202 }
00203 
00204 
00205 fastf_t
00206 rt_nurb_crv_flat(fastf_t *crv, int size, int pt_type)
00207 {
00208         point_t         p1, p2;
00209         vect_t          ln;
00210         int     i;
00211         fastf_t         dist;
00212         fastf_t         max_dist;
00213         fastf_t         length;
00214         fastf_t        * c_ptr;
00215         vect_t          testv, xp;
00216         hvect_t         h1, h2;
00217         int     coords;
00218         int     rational;
00219 
00220         coords = RT_NURB_EXTRACT_COORDS( pt_type);
00221         rational = RT_NURB_IS_PT_RATIONAL( pt_type);
00222         max_dist = -INFINITY;
00223 
00224         if ( !rational) {
00225                 VMOVE(p1, crv);
00226         } else   {
00227                 HMOVE( h1, crv);
00228                 HDIVIDE( p1, h1);
00229         }
00230 
00231         length = 0.0;
00232 
00233         /*
00234          * loop through all of the points until a line is found which may not
00235          * be the end pts of the curve if the endpoints are the same.
00236          */
00237         for (i = size - 1; (i > 0) && length < SQRT_SMALL_FASTF; i--) {
00238                 if ( !rational) {
00239                         VMOVE(p2, (crv + (i * coords)));
00240                 } else {
00241                         HMOVE( h2, (crv + ( i * coords)));
00242                         HDIVIDE( p2, h2 );
00243                 }
00244 
00245                 VSUB2(ln, p1, p2);
00246                 length = MAGNITUDE(ln);
00247         }
00248 
00249 
00250         if( length >= SQRT_SMALL_FASTF )  {
00251                 VSCALE(ln, ln, 1.0 / length);
00252                 c_ptr = crv + coords;
00253 
00254                 for (i = 1; i < size; i++) {
00255                         if ( !rational ) {
00256                                 VSUB2(testv, p1, c_ptr);
00257                         } else              {
00258                                 HDIVIDE(h2, c_ptr);
00259                                 VSUB2( testv, p1, h2);
00260                         }
00261 
00262                         VCROSS(xp, testv, ln);
00263                         dist = MAGNITUDE(xp);
00264                         max_dist = MAX( max_dist, dist);
00265                         c_ptr += coords;
00266                 }
00267         }
00268         return max_dist;
00269 }
00270 
00271 /*
00272  * Local Variables:
00273  * mode: C
00274  * tab-width: 8
00275  * c-basic-offset: 4
00276  * indent-tabs-mode: t
00277  * End:
00278  * ex: shiftwidth=4 tabstop=8
00279  */

Generated on Mon Sep 18 01:24:55 2006 for BRL-CAD by  doxygen 1.4.6