g_nurb.c

Go to the documentation of this file.
00001 /*                        G _ N U R B . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1991-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 /** @addtogroup g_  */
00022 
00023 /*@{*/
00024 /** @file g_nurb.c
00025  *      Intersect a ray with a Non Uniform Rational B-Spline.
00026  *
00027  *  Authors -
00028  *      Paul R. Stay
00029  *
00030  *  Source -
00031  *      SECAD/VLD Computing Consortium, Bldg 394
00032  *      The U. S. Army Ballistic Research Laboratory
00033  *      Aberdeen Proving Ground, Maryland  21005-5066
00034  *
00035  */
00036 /*@}*/
00037 
00038 #ifndef lint
00039 static const char RCSnurb[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_nurb.c,v 14.15 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00040 #endif
00041 
00042 #include "common.h"
00043 
00044 #include <stdlib.h>
00045 #include <stdio.h>
00046 #ifdef HAVE_STRING_H
00047 #  include <string.h>
00048 #else
00049 #  include <strings.h>
00050 #endif
00051 #include <math.h>
00052 
00053 #include "machine.h"
00054 #include "vmath.h"
00055 #include "db.h"
00056 #include "raytrace.h"
00057 #include "nurb.h"               /* before nmg.h */
00058 #include "nmg.h"
00059 #include "rtgeom.h"
00060 #include "./debug.h"
00061 
00062 
00063 #ifndef M_SQRT1_2
00064 #       define M_SQRT1_2       0.70710678118654752440
00065 #endif /* M_SQRT1_2 */
00066 
00067 struct nurb_specific {
00068         struct nurb_specific *  next;   /* next surface in the the solid */
00069         struct face_g_snurb *   srf;    /* Original surface description */
00070         struct bu_list          bez_hd; /* List of Bezier face_g_snurbs */
00071 };
00072 
00073 struct nurb_hit {
00074         struct nurb_hit * next;
00075         struct nurb_hit * prev;
00076         fastf_t         hit_dist;       /* Distance from the r_pt to surface */
00077         point_t         hit_point;      /* intersection point */
00078         vect_t          hit_normal;     /* Surface normal */
00079         fastf_t         hit_uv[2];      /* Surface parametric u,v */
00080         char *          hit_private;    /* Store current nurb root */
00081 };
00082 
00083 #define NULL_HIT  (struct nurb_hit *)0
00084 
00085 BU_EXTERN(int rt_nurb_grans, (struct face_g_snurb * srf));
00086 BU_EXTERN(struct nurb_hit *rt_conv_uv, (struct nurb_specific *n,
00087         struct xray *r, struct rt_nurb_uv_hit *h));
00088 BU_EXTERN(struct nurb_hit *rt_return_nurb_hit, (struct nurb_hit * head));
00089 BU_EXTERN(void          rt_nurb_add_hit, (struct nurb_hit *head,
00090                         struct nurb_hit * hit, const struct bn_tol *tol));
00091 
00092 
00093 /**
00094  *                      R T _ N U R B _ P R E P
00095  *
00096  *  Given a pointer of a GED database record, and a transformation matrix,
00097  *  determine if this is a valid NURB, and if so, prepare the surface
00098  *  so the intersections will work.
00099  */
00100 
00101 int
00102 rt_nurb_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00103 {
00104         struct rt_nurb_internal *sip;
00105         struct nurb_specific    *nurbs;
00106         int                     i;
00107 
00108         nurbs = (struct nurb_specific *) 0;
00109 
00110         sip = (struct rt_nurb_internal *) ip->idb_ptr;
00111         RT_NURB_CK_MAGIC(sip);
00112 
00113         for( i = 0; i < sip->nsrf; i++)
00114         {
00115                 struct face_g_snurb * s;
00116                 struct nurb_specific * n;
00117 
00118                 BU_GETSTRUCT( n, nurb_specific);
00119 
00120                 /* Store off the original face_g_snurb */
00121                 s = rt_nurb_scopy (sip->srfs[i], (struct resource *)NULL);
00122                 NMG_CK_SNURB(s);
00123                 rt_nurb_s_bound(s, s->min_pt, s->max_pt);
00124 
00125                 n->srf = s;
00126                 BU_LIST_INIT( &n->bez_hd );
00127 
00128                 /* Grind up the original surf into a list of Bezier face_g_snurbs */
00129                 (void)rt_nurb_bezier( &n->bez_hd, sip->srfs[i], (struct resource *)NULL );
00130 
00131                 /* Compute bounds of each Bezier face_g_snurb */
00132                 for( BU_LIST_FOR( s, face_g_snurb, &n->bez_hd ) )  {
00133                         NMG_CK_SNURB(s);
00134                         rt_nurb_s_bound( s, s->min_pt, s->max_pt );
00135                         VMINMAX( stp->st_min, stp->st_max, s->min_pt);
00136                         VMINMAX( stp->st_min, stp->st_max, s->max_pt);
00137                 }
00138 
00139                 n->next = nurbs;
00140                 nurbs = n;
00141         }
00142 
00143         stp->st_specific = (genptr_t)nurbs;
00144 
00145         VADD2SCALE( stp->st_center, stp->st_max, stp->st_min, 0.5 );
00146         {
00147                 fastf_t f, dx, dy, dz;
00148                 dx = (stp->st_max[0] - stp->st_min[0])/2;
00149                 f = dx;
00150                 dy = (stp->st_max[1] - stp->st_min[1])/2;
00151                 if( dy > f )  f = dy;
00152                 dz = (stp->st_max[2] - stp->st_min[2])/2;
00153                 if( dz > f )  f = dz;
00154                 stp->st_aradius = f;
00155                 stp->st_bradius = sqrt(dx*dx + dy*dy + dz*dz);
00156         }
00157 
00158         return 0;
00159 }
00160 
00161 /**
00162  *                      R T _ N U R B _ P R I N T
00163  */
00164 void
00165 rt_nurb_print(register const struct soltab *stp)
00166 {
00167         register struct nurb_specific *nurb =
00168                 (struct nurb_specific *)stp->st_specific;
00169 
00170         if( nurb == (struct nurb_specific *)0)
00171         {
00172                 bu_log("rt_nurb_print: no surfaces\n");
00173                 return;
00174         }
00175 
00176         for( ; nurb != (struct nurb_specific *)0; nurb = nurb->next)
00177         {
00178                 /* XXX There is a linked list of Bezier surfaces to print here too */
00179                 rt_nurb_s_print("NURB", nurb->srf);
00180         }
00181 }
00182 
00183 /**
00184  *                      R T _ N U R B _ S H O T
00185  *
00186  *  Intersect a ray with a nurb.
00187  *  If an intersection occurs, a struct seg will be acquired
00188  *  and filled in.
00189  *
00190  *  Returns -
00191  *      0       MISS
00192  *      >0      HIT
00193  */
00194 
00195 int
00196 rt_nurb_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00197 {
00198         register struct nurb_specific * nurb =
00199                 (struct nurb_specific *)stp->st_specific;
00200         register struct seg *segp;
00201         const struct bn_tol     *tol = &ap->a_rt_i->rti_tol;
00202         point_t p1, p2, p3, p4;
00203         vect_t dir1, dir2;
00204         plane_t plane1, plane2;
00205         struct nurb_hit * hit;
00206         struct nurb_hit hit_list;
00207         vect_t invdir;
00208         int hit_num;
00209 
00210         invdir[0] = invdir[1] = invdir[2] = INFINITY;
00211         if(!NEAR_ZERO(rp->r_dir[0], SQRT_SMALL_FASTF))
00212                 invdir[0] = 1.0 / rp->r_dir[0];
00213         if(!NEAR_ZERO(rp->r_dir[1], SQRT_SMALL_FASTF))
00214                 invdir[1] = 1.0 / rp->r_dir[1];
00215         if(!NEAR_ZERO(rp->r_dir[2], SQRT_SMALL_FASTF))
00216                 invdir[2] = 1.0 / rp->r_dir[2];
00217 
00218         /* Create two orthogonal Planes their intersection contains the ray
00219          * so we can project the surface into a 2 dimensional problem
00220          */
00221 
00222         bn_vec_ortho(dir1, rp->r_dir);
00223         VCROSS( dir2, rp->r_dir, dir1);
00224 
00225         VMOVE(p1, rp->r_pt);
00226         VADD2(p2, rp->r_pt, rp->r_dir);
00227         VADD2(p3, rp->r_pt, dir1);
00228         VADD2(p4, rp->r_pt, dir2);
00229 
00230         /* Note: the equation of the plane in BRL-CAD is
00231          * Ax + By + Cz = D represented by [A B C D]
00232          */
00233         bn_mk_plane_3pts( plane1, p1, p3, p2, tol );
00234         bn_mk_plane_3pts( plane2, p1, p2, p4, tol );
00235 
00236         /* make sure that the hit_list is zero */
00237 
00238         hit_list.next = (struct nurb_hit *)0;
00239         hit_list.prev = (struct nurb_hit *)0;
00240         hit_list.hit_dist = 0;
00241         VSET(hit_list.hit_point, 0.0, 0.0, 0.0);
00242         VSET(hit_list.hit_normal, 0.0, 0.0, 0.0);
00243         hit_list.hit_uv[0] =    hit_list.hit_uv[1] = 0.0;
00244         hit_list.hit_private = (char *)0;
00245 
00246         while( nurb != (struct nurb_specific *) 0 )
00247         {
00248                 struct face_g_snurb * s;
00249                 struct rt_nurb_uv_hit *hp;
00250 
00251                 for( BU_LIST_FOR( s, face_g_snurb, &nurb->bez_hd ) )  {
00252                         if( !rt_in_rpp( rp, invdir, s->min_pt, s->max_pt))
00253                                 continue;
00254 
00255 #define UV_TOL  1.0e-6  /* Paper says 1.0e-4 is reasonable for 1k images, not close up */
00256                         hp = rt_nurb_intersect(
00257                                 s, plane1, plane2, UV_TOL, (struct resource *)ap->a_resource );
00258                         while( hp != (struct rt_nurb_uv_hit *)0)
00259                         {
00260                                 struct rt_nurb_uv_hit * o;
00261 
00262                                 if( RT_G_DEBUG & DEBUG_SPLINE )
00263                                         bu_log("hit at %d %d sub = %d u = %f v = %f\n",
00264                                                 ap->a_x, ap->a_y, hp->sub, hp->u, hp->v);
00265 
00266                                 hit = (struct nurb_hit *)
00267                                         rt_conv_uv(nurb, rp, hp);
00268 
00269                                 o = hp;
00270                                 hp = hp->next;
00271                                 bu_free( (char *)o,
00272                                         "rt_nurb_shot:rt_nurb_uv_hit structure");
00273 
00274                                 rt_nurb_add_hit( &hit_list, hit, tol );
00275                         }
00276                 }
00277                 nurb = nurb->next;
00278                 /* Insert Trimming routines here */
00279         }
00280 
00281         /* Convert hits to segments for rt */
00282 
00283         hit_num = 0;
00284 
00285         while( hit_list.next != NULL_HIT )
00286         {
00287                 struct nurb_hit * h1, * h2;
00288 
00289                 RT_GET_SEG( segp, ap->a_resource);
00290 
00291                 h1 = (struct nurb_hit *) rt_return_nurb_hit( &hit_list );
00292                 h2 = (struct nurb_hit *) rt_return_nurb_hit( &hit_list );
00293 
00294                 segp->seg_stp = stp;
00295                 segp->seg_in.hit_dist = h1->hit_dist;
00296                 VMOVE(segp->seg_in.hit_point, h1->hit_point);
00297                 segp->seg_in.hit_vpriv[0] = h1->hit_uv[0];
00298                 segp->seg_in.hit_vpriv[1] = h1->hit_uv[1];
00299                 segp->seg_in.hit_private = h1->hit_private;
00300                 segp->seg_in.hit_vpriv[2] = 0;
00301                 hit_num++;
00302 
00303 
00304                 if( h2 != NULL_HIT)
00305                 {
00306                         segp->seg_out.hit_dist = h2->hit_dist;
00307                         VMOVE(segp->seg_out.hit_point, h2->hit_point);
00308                         segp->seg_out.hit_vpriv[0] = h2->hit_uv[0];
00309                         segp->seg_out.hit_vpriv[1] = h2->hit_uv[1];
00310                         segp->seg_out.hit_private = h2->hit_private;
00311                         bu_free( (char *)h2,"rt_nurb_shot: nurb hit");
00312                         hit_num++;
00313                 }
00314                 else
00315                 {
00316                         segp->seg_out.hit_dist = h1->hit_dist + .01;
00317                         VJOIN1(segp->seg_out.hit_point,
00318                                 rp->r_pt, segp->seg_out.hit_dist, rp->r_dir);
00319                         segp->seg_out.hit_vpriv[0] = h1->hit_uv[0];
00320                         segp->seg_out.hit_vpriv[1] = h1->hit_uv[1];
00321                         segp->seg_out.hit_vpriv[2] = 1;
00322                         segp->seg_out.hit_private = h1->hit_private;
00323                 }
00324 
00325                 bu_free( (char *)h1, "rt_nurb_shot:nurb hit");
00326 
00327                 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00328         }
00329 
00330         return(hit_num);        /* not hit */
00331 }
00332 
00333 #define SEG_MISS(SEG)           (SEG).seg_stp=(struct soltab *) 0;
00334 
00335 /**
00336  *                      R T _ N U R B _ V S H O T
00337  *
00338  *  Vectorized version.
00339  */
00340 void
00341 rt_nurb_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
00342                                /* An array of solid pointers */
00343                                /* An array of ray pointers */
00344                                /* array of segs (results returned) */
00345                                /* Number of ray/object pairs */
00346 
00347 {
00348         rt_vstub( stp, rp, segp, n, ap );
00349 }
00350 
00351 /**
00352  *                      R T _ N U R B _ N O R M
00353  *
00354  *  Given ONE ray distance, return the normal and entry/exit point.
00355  */
00356 void
00357 rt_nurb_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00358 {
00359 /*      register struct nurb_specific *nurb =
00360                 (struct nurb_specific *)stp->st_specific; */
00361 
00362         struct face_g_snurb * n  = (struct face_g_snurb *) hitp->hit_private;
00363         fastf_t u = hitp->hit_vpriv[0];
00364         fastf_t v = hitp->hit_vpriv[1];
00365         fastf_t norm[4];
00366 
00367         rt_nurb_s_norm( n, u, v, norm);
00368 
00369         VMOVE( hitp->hit_normal, norm);
00370 
00371         if ( hitp->hit_vpriv[2] == 1)
00372         {
00373                 VREVERSE( hitp->hit_normal, norm );
00374         }
00375 
00376         return;
00377 }
00378 
00379 /**
00380  *                      R T _ N U R B _ C U R V E
00381  *
00382  *  Return the curvature of the nurb.
00383  */
00384 void
00385 rt_nurb_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00386 {
00387 /*      register struct nurb_specific *nurb =
00388                 (struct nurb_specific *)stp->st_specific; */
00389         struct face_g_snurb * srf = (struct face_g_snurb *) hitp->hit_private;
00390         fastf_t         u, v;
00391 
00392         if( srf->order[0] <= 2 && srf->order[1] <= 2)
00393         {
00394                 cvp->crv_c1 = cvp->crv_c2 = 0;
00395 
00396                 /* any tangent direction */
00397                 bn_vec_ortho( cvp->crv_pdir, hitp->hit_normal );
00398                 return;
00399         }
00400 
00401         u = hitp->hit_vpriv[0];
00402         v = hitp->hit_vpriv[1];
00403 
00404         rt_nurb_curvature( cvp, srf, u, v );
00405 }
00406 
00407 /**
00408  *                      R T _ N U R B _ U V
00409  *
00410  *  For a hit on the surface of an nurb, return the (u,v) coordinates
00411  *  of the hit point, 0 <= u,v <= 1.
00412  *  u = azimuth
00413  *  v = elevation
00414  */
00415 void
00416 rt_nurb_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00417 {
00418 /*      register struct nurb_specific *nurb =
00419                 (struct nurb_specific *)stp->st_specific; */
00420         uvp->uv_u = hitp->hit_vpriv[0];
00421         uvp->uv_v = hitp->hit_vpriv[1];
00422         return;
00423 }
00424 
00425 /**
00426  *              R T _ N U R B _ F R E E
00427  */
00428 void
00429 rt_nurb_free(register struct soltab *stp)
00430 {
00431         register struct nurb_specific *nurb =
00432                 (struct nurb_specific *)stp->st_specific;
00433         register struct nurb_specific *next;
00434 
00435         if( nurb == (struct nurb_specific *)0)
00436                 rt_bomb("rt_nurb_free: no surfaces\n");
00437 
00438         for( ; nurb != (struct nurb_specific *)0; nurb = next)  {
00439                 register struct face_g_snurb    *s;
00440 
00441                 next = nurb->next;
00442 
00443                 /* There is a linked list of surfaces to free for each nurb */
00444                 while( BU_LIST_WHILE( s, face_g_snurb, &nurb->bez_hd ) )  {
00445                         NMG_CK_SNURB( s );
00446                         BU_LIST_DEQUEUE( &(s->l) );
00447                         rt_nurb_free_snurb( s, (struct resource *)NULL );
00448                 }
00449                 rt_nurb_free_snurb( nurb->srf, (struct resource *)NULL );       /* original surf */
00450                 bu_free( (char *)nurb, "nurb_specific" );
00451         }
00452 }
00453 
00454 /**
00455  *                      R T _ N U R B _ C L A S S
00456  */
00457 int
00458 rt_nurb_class(void)
00459 {
00460         return(0);
00461 }
00462 
00463 /**
00464  *                      R T _ N U R B _ P L O T
00465  */
00466 int
00467 rt_nurb_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00468 {
00469         struct rt_nurb_internal *sip;
00470         register int            i;
00471         register int            j;
00472         register fastf_t        * vp;
00473         int                     s;
00474 
00475 
00476         RT_CK_DB_INTERNAL(ip);
00477         sip = (struct rt_nurb_internal *) ip->idb_ptr;
00478         RT_NURB_CK_MAGIC(sip);
00479 
00480         for( s=0; s < sip->nsrf; s++)
00481         {
00482                 struct face_g_snurb     * n, *r, *c;
00483                 int             coords;
00484                 fastf_t         bound;
00485                 point_t         tmp_pt;
00486                 fastf_t         rel;
00487                 struct knot_vector      tkv1,
00488                                         tkv2;
00489                 fastf_t         tess;
00490                 int             num_knots;
00491                 fastf_t         rt_nurb_par_edge(const struct face_g_snurb *srf, fastf_t epsilon);
00492 
00493                 n = (struct face_g_snurb *) sip->srfs[s];
00494 
00495                 VSUB2(tmp_pt, n->min_pt, n->max_pt);
00496                 bound =         MAGNITUDE( tmp_pt)/ 2.0;
00497                 /*
00498                  *  Establish tolerances
00499                  */
00500                 if( ttol->rel <= 0.0 || ttol->rel >= 1.0 )  {
00501                         rel = 0.0;              /* none */
00502                 } else {
00503                         /* Convert rel to absolute by scaling by diameter */
00504                         rel = ttol->rel * 2 * bound;
00505                 }
00506                 if( ttol->abs <= 0.0 )  {
00507                         if( rel <= 0.0 )  {
00508                                 /* No tolerance given, use a default */
00509                                 rel = 2 * 0.10 * bound;        /* 10% */
00510                         } else {
00511                                 /* Use absolute-ized relative tolerance */
00512                         }
00513                 } else {
00514                         /* Absolute tolerance was given, pick smaller */
00515                         if( ttol->rel <= 0.0 || rel > ttol->abs )
00516                                 rel = ttol->abs;
00517                 }
00518 
00519                 if( n->order[0] < 3 || n->order[1] < 3 ) {
00520                         /* cannot use rt_nurb_par_edge() in this case */
00521                         tess = 0.25; /* hack for now */
00522                 } else
00523                         tess = (fastf_t) rt_nurb_par_edge(n, rel);
00524 
00525                 num_knots = (int)floor(1.0/((M_SQRT1_2 / 2.0) * tess));
00526 
00527                 if( num_knots < 2) num_knots = 2;
00528 
00529                 rt_nurb_kvknot( &tkv1, n->order[0],
00530                         n->u.knots[0],
00531                         n->u.knots[n->u.k_size-1], num_knots, (struct resource *)NULL);
00532 
00533                 rt_nurb_kvknot( &tkv2, n->order[1],
00534                         n->v.knots[0],
00535                         n->v.knots[n->v.k_size-1], num_knots, (struct resource *)NULL);
00536 
00537 
00538                 r = (struct face_g_snurb *) rt_nurb_s_refine( n, RT_NURB_SPLIT_COL, &tkv2, (struct resource *)NULL);
00539                 c = (struct face_g_snurb *) rt_nurb_s_refine( r, RT_NURB_SPLIT_ROW, &tkv1, (struct resource *)NULL);
00540 
00541                 coords = RT_NURB_EXTRACT_COORDS(n->pt_type);
00542 
00543                 if( RT_NURB_IS_PT_RATIONAL(n->pt_type))
00544                 {
00545                         vp = c->ctl_points;
00546                         for(i= 0;
00547                                 i < c->s_size[0] * c->s_size[1];
00548                                 i++)
00549                         {
00550                                 vp[0] /= vp[3];
00551                                 vp[1] /= vp[3];
00552                                 vp[2] /= vp[3];
00553                                 vp[3] /= vp[3];
00554                                 vp += coords;
00555                         }
00556                 }
00557 
00558 
00559                 vp = c->ctl_points;
00560                 for( i = 0; i < c->s_size[0]; i++)
00561                 {
00562                         RT_ADD_VLIST( vhead, vp, BN_VLIST_LINE_MOVE );
00563                         vp += coords;
00564                         for( j = 1; j < c->s_size[1]; j++)
00565                         {
00566                                 RT_ADD_VLIST( vhead, vp, BN_VLIST_LINE_DRAW );
00567                                 vp += coords;
00568                         }
00569                 }
00570 
00571                 for( j = 0; j < c->s_size[1]; j++)
00572                 {
00573                         int stride;
00574 
00575                         stride = c->s_size[1] * coords;
00576                         vp = &c->ctl_points[j * coords];
00577                         RT_ADD_VLIST( vhead, vp, BN_VLIST_LINE_MOVE );
00578                         for( i = 0; i < c->s_size[0]; i++)
00579                         {
00580                                 RT_ADD_VLIST( vhead, vp, BN_VLIST_LINE_DRAW );
00581                                 vp += stride;
00582                         }
00583                 }
00584                 rt_nurb_free_snurb(c, (struct resource *)NULL);
00585                 rt_nurb_free_snurb(r, (struct resource *)NULL);
00586 
00587                 bu_free( (char *) tkv1.knots, "rt_nurb_plot:tkv1>knots");
00588                 bu_free( (char *) tkv2.knots, "rt_nurb_plot:tkv2.knots");
00589         }
00590         return(0);
00591 }
00592 
00593 /**
00594  *                      R T _ N U R B _ T E S S
00595  */
00596 int
00597 rt_nurb_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00598 {
00599         return(-1);
00600 }
00601 
00602 /**
00603  *                      R T _ N U R B _ I M P O R T
00604  */
00605 int
00606 rt_nurb_import(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
00607 {
00608 
00609         struct rt_nurb_internal * sip;
00610         union record            *rp;
00611         register int            i;
00612         int                     s;
00613 
00614         BU_CK_EXTERNAL( ep );
00615         rp = (union record *)ep->ext_buf;
00616         if( rp->u_id != ID_BSOLID )
00617         {
00618                 bu_log("rt_nurb_import: defective header record");
00619                 return (-1);
00620         }
00621 
00622         RT_CK_DB_INTERNAL( ip );
00623         ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00624         ip->idb_type = ID_BSPLINE;
00625         ip->idb_meth = &rt_functab[ID_BSPLINE];
00626         ip->idb_ptr = bu_malloc( sizeof(struct rt_nurb_internal), "rt_nurb_internal");
00627         sip = (struct rt_nurb_internal *)ip->idb_ptr;
00628         sip->magic = RT_NURB_INTERNAL_MAGIC;
00629 
00630 
00631         sip->nsrf = rp->B.B_nsurf;
00632         sip->srfs = (struct face_g_snurb **) bu_malloc(
00633                 sip->nsrf * sizeof( struct face_g_snurb), "nurb srfs[]");
00634         rp++;
00635 
00636         for( s = 0; s < sip->nsrf; s++)
00637         {
00638                 register fastf_t        * m;
00639                 int                     coords;
00640                 register dbfloat_t      *vp;
00641                 int                     pt_type;
00642 
00643                 if( rp->d.d_id != ID_BSURF )  {
00644                         bu_log("rt_nurb_import() surf %d bad ID\n", s);
00645                         return -1;
00646                 }
00647 
00648                 if( rp->d.d_geom_type == 3)
00649                         pt_type = RT_NURB_MAKE_PT_TYPE(3,RT_NURB_PT_XYZ,RT_NURB_PT_NONRAT);
00650                 else
00651                         pt_type = RT_NURB_MAKE_PT_TYPE(4,RT_NURB_PT_XYZ,RT_NURB_PT_RATIONAL);
00652 
00653                 sip->srfs[s] = (struct face_g_snurb *) rt_nurb_new_snurb(
00654                         rp->d.d_order[0],rp->d.d_order[1],
00655                         rp->d.d_kv_size[0],rp->d.d_kv_size[1],
00656                         rp->d.d_ctl_size[0],rp->d.d_ctl_size[1],
00657                         pt_type, (struct resource *)NULL);
00658 
00659                 vp = (dbfloat_t *) &rp[1];
00660 
00661                 for( i = 0; i < rp->d.d_kv_size[0]; i++)
00662                         sip->srfs[s]->u.knots[i] = (fastf_t) *vp++;
00663 
00664                 for( i = 0; i < rp->d.d_kv_size[1]; i++)
00665                         sip->srfs[s]->v.knots[i] = (fastf_t) *vp++;
00666 
00667                 rt_nurb_kvnorm( &sip->srfs[s]->u);
00668                 rt_nurb_kvnorm( &sip->srfs[s]->v);
00669 
00670                 vp = (dbfloat_t *) &rp[rp->d.d_nknots+1];
00671                 m = sip->srfs[s]->ctl_points;
00672                 coords = rp->d.d_geom_type;
00673                 i = (rp->d.d_ctl_size[0] *rp->d.d_ctl_size[1]);
00674                 if( coords == 3)
00675                 {
00676                         for( ; i> 0; i--)
00677                         {
00678                                 MAT4X3PNT( m, mat, vp);
00679                                 m += 3;
00680                                 vp += 3;
00681                         }
00682                 } else if( coords == 4)
00683                 {
00684                         for( ; i> 0; i--)
00685                         {
00686                                 MAT4X4PNT( m, mat, vp);
00687                                 m += 4;
00688                                 vp += 4;
00689                         }
00690                 } else {
00691                         bu_log("rt_nurb_internal: %d invalid elements per vect\n", rp->d.d_geom_type);
00692                         return (-1);
00693                 }
00694 
00695                 /* bound the surface for tolerancing and other bounding box tests */
00696                 rt_nurb_s_bound( sip->srfs[s], sip->srfs[s]->min_pt,
00697                         sip->srfs[s]->max_pt);
00698 
00699                 rp += 1 + rp->d.d_nknots + rp->d.d_nctls;
00700         }
00701         return (0);
00702 }
00703 
00704 struct nurb_hit *
00705 rt_conv_uv(struct nurb_specific *n, struct xray *r, struct rt_nurb_uv_hit *h)
00706 {
00707         struct nurb_hit * hit;
00708         fastf_t pt[4];
00709         point_t vecsub;
00710 
00711         hit = (struct nurb_hit *) bu_malloc( sizeof (struct nurb_hit),
00712                 "rt_conv_uv:nurb hit");
00713 
00714         hit->prev = hit->next = (struct nurb_hit *)0;
00715         VSET(hit->hit_normal, 0.0, 0.0, 0.0);
00716 
00717         rt_nurb_s_eval(n->srf, h->u, h->v, pt);
00718 
00719         if( RT_NURB_IS_PT_RATIONAL(n->srf->pt_type) )
00720         {
00721                 hit->hit_point[0] = pt[0] / pt[3];
00722                 hit->hit_point[1] = pt[1] / pt[3];
00723                 hit->hit_point[2] = pt[2] / pt[3];
00724         } else
00725         {
00726                 hit->hit_point[0] = pt[0];
00727                 hit->hit_point[1] = pt[1];
00728                 hit->hit_point[2] = pt[2];
00729         }
00730 
00731         VSUB2( vecsub, hit->hit_point, r->r_pt);
00732         hit->hit_dist = VDOT( vecsub, r->r_dir);
00733         hit->hit_uv[0] = h->u;
00734         hit->hit_uv[1] = h->v;
00735         hit->hit_private = (char *) n->srf;
00736 
00737         return (struct nurb_hit *) hit;
00738 }
00739 
00740 void
00741 rt_nurb_add_hit(struct nurb_hit *head, struct nurb_hit *hit, const struct bn_tol *tol)
00742 {
00743         register struct nurb_hit * h_ptr;
00744 
00745         BN_CK_TOL(tol);
00746 #if 0
00747         /* Shouldn't be discarded, because shootray moves start pt around */
00748         if( hit->hit_dist < .001)
00749         {
00750 
00751                 bu_free( (char *) hit, "internal_add_hit: hit");
00752                 return;
00753         }
00754 #endif
00755 
00756         /* If this is the only one, nothing to check against */
00757         if( head->next == (struct nurb_hit *) 0)
00758         {
00759                 head->next = hit;
00760                 hit->prev = head;
00761                 return;
00762         }
00763 
00764         /* Check for duplicates */
00765         for( h_ptr = head->next; h_ptr != (struct nurb_hit *)0; h_ptr = h_ptr->next)
00766         {
00767                 register fastf_t        f;
00768 
00769                 /* This test a distance in model units (mm) */
00770                 f = hit->hit_dist - h_ptr->hit_dist;
00771                 if( NEAR_ZERO( f, tol->dist ) )  goto duplicate;
00772 
00773                 /* These tests are in parameter space, 0..1 */
00774                 f = hit->hit_uv[0] - h_ptr->hit_uv[0];
00775                 if( NEAR_ZERO( f, 0.0001 ) )  goto duplicate;
00776                 f = hit->hit_uv[1] - h_ptr->hit_uv[1];
00777                 if( NEAR_ZERO( f, 0.0001 ) )  goto duplicate;
00778         }
00779 
00780         hit->prev = head;
00781         hit->next = head->next;
00782         hit->next->prev = hit;
00783         head->next = hit;
00784         return;
00785 duplicate:
00786         bu_free( (char *) hit, "add hit: hit");
00787         return;
00788 }
00789 
00790 struct nurb_hit *
00791 rt_return_nurb_hit(struct nurb_hit *head)
00792 {
00793 
00794         register struct nurb_hit * h, * ret;
00795         fastf_t dist;
00796 
00797         if( head->next == NULL_HIT)
00798                 return NULL_HIT;
00799 
00800         dist = INFINITY;
00801         ret = NULL_HIT;
00802 
00803         for( h = head->next; h != NULL_HIT; h = h->next)
00804         {
00805                 if( h->hit_dist < dist )
00806                 {
00807                         ret = h;
00808                         dist = ret->hit_dist;
00809                 }
00810         }
00811 
00812         if( ret != NULL_HIT)
00813         {
00814                 if( ret->prev != NULL_HIT) ret->prev->next = ret->next;
00815                 if( ret->next != NULL_HIT) ret->next->prev = ret->prev;
00816                 ret->next = ret->prev = NULL_HIT;
00817         }
00818         return (struct nurb_hit *) ret;
00819 }
00820 
00821 /**
00822  *                      R T _ N U R B _ E X P O R T
00823  */
00824 int
00825 rt_nurb_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00826 {
00827         register int            rec_ptr;
00828         struct rt_nurb_internal * sip;
00829         union record            * rec;
00830         int                     s;
00831         int                     grans;
00832         int                     total_grans;
00833         dbfloat_t               * vp;
00834         int                     n;
00835 
00836         RT_CK_DB_INTERNAL(ip);
00837         if( ip->idb_type != ID_BSPLINE) return(-1);
00838         sip = (struct rt_nurb_internal *) ip->idb_ptr;
00839         RT_NURB_CK_MAGIC(sip);
00840 
00841         /* Figure out how many recs to buffer by
00842          * walking through the surfaces and
00843          * calculating the number of granuels
00844          * needed for storage and add it to the total
00845          */
00846         total_grans = 1;        /* First gran for BSOLID record */
00847         for( s = 0; s < sip->nsrf; s++)
00848         {
00849                 total_grans += rt_nurb_grans(sip->srfs[s]);
00850         }
00851 
00852         BU_CK_EXTERNAL(ep);
00853         ep->ext_nbytes = total_grans * sizeof(union record);
00854         ep->ext_buf = (genptr_t)bu_calloc(1,ep->ext_nbytes,"nurb external");
00855         rec = (union record *)ep->ext_buf;
00856 
00857         rec[0].B.B_id = ID_BSOLID;
00858         rec[0].B.B_nsurf = sip->nsrf;
00859 
00860         rec_ptr = 1;
00861 
00862         for( s = 0; s < sip->nsrf; s++)
00863         {
00864                 register struct face_g_snurb    *srf = sip->srfs[s];
00865                 NMG_CK_SNURB(srf);
00866 
00867                 grans = rt_nurb_grans( srf);
00868 
00869                 rec[rec_ptr].d.d_id = ID_BSURF;
00870                 rec[rec_ptr].d.d_nknots = (((srf->u.k_size + srf->v.k_size)
00871                         * sizeof(dbfloat_t)) + sizeof(union record)-1)/ sizeof(union record);
00872                 rec[rec_ptr].d.d_nctls = ((
00873                         RT_NURB_EXTRACT_COORDS(srf->pt_type)
00874                         * (srf->s_size[0] * srf->s_size[1])
00875                         * sizeof(dbfloat_t)) + sizeof(union record)-1 )
00876                         / sizeof(union record);
00877 
00878                 rec[rec_ptr].d.d_order[0] = srf->order[0];
00879                 rec[rec_ptr].d.d_order[1] = srf->order[1];
00880                 rec[rec_ptr].d.d_kv_size[0] = srf->u.k_size;
00881                 rec[rec_ptr].d.d_kv_size[1] = srf->v.k_size;
00882                 rec[rec_ptr].d.d_ctl_size[0] =  srf->s_size[0];
00883                 rec[rec_ptr].d.d_ctl_size[1] =  srf->s_size[1];
00884                 rec[rec_ptr].d.d_geom_type =
00885                         RT_NURB_EXTRACT_COORDS(srf->pt_type);
00886 
00887                 vp = (dbfloat_t *) &rec[rec_ptr +1];
00888                 for(n = 0; n < rec[rec_ptr].d.d_kv_size[0]; n++)
00889                 {
00890                         *vp++ = srf->u.knots[n];
00891                 }
00892 
00893                 for(n = 0; n < rec[rec_ptr].d.d_kv_size[1]; n++)
00894                 {
00895                         *vp++ = srf->v.knots[n];
00896                 }
00897 
00898                 vp = (dbfloat_t *) &rec[rec_ptr + 1 +
00899                         rec[rec_ptr].d.d_nknots];
00900 
00901                 for( n = 0; n < (srf->s_size[0] * srf->s_size[1]) *
00902                         rec[rec_ptr].d.d_geom_type; n++)
00903                         *vp++ = srf->ctl_points[n];
00904 
00905                 rec_ptr += grans;
00906                 total_grans -= grans;
00907         }
00908         return(0);
00909 }
00910 
00911 int
00912 rt_nurb_bytes(struct face_g_snurb *srf)
00913 {
00914         int     total_bytes=0;
00915 
00916         total_bytes = 3 * SIZEOF_NETWORK_LONG           /* num_coords and order */
00917                 + 2 * SIZEOF_NETWORK_LONG               /* k_size in both knot vectors */
00918                 + srf->u.k_size * SIZEOF_NETWORK_DOUBLE /* u knot vector knots */
00919                 + srf->v.k_size * SIZEOF_NETWORK_DOUBLE /* v knot vector knots */
00920                 + 2 * SIZEOF_NETWORK_LONG               /* mesh size */
00921                 + RT_NURB_EXTRACT_COORDS(srf->pt_type) *
00922                         (srf->s_size[0] * srf->s_size[1]) * SIZEOF_NETWORK_DOUBLE;      /* control point mesh */
00923 
00924         return total_bytes;
00925 }
00926 
00927 /**
00928  *                      R T _ N U R B _ E X P O R T 5
00929  */
00930 int
00931 rt_nurb_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00932 {
00933         struct rt_nurb_internal * sip;
00934         int                     s;
00935         unsigned char           *cp;
00936         int                     coords;
00937 
00938         RT_CK_DB_INTERNAL(ip);
00939         if( ip->idb_type != ID_BSPLINE) return(-1);
00940         sip = (struct rt_nurb_internal *) ip->idb_ptr;
00941         RT_NURB_CK_MAGIC(sip);
00942 
00943         /* Figure out how many bytes are needed by
00944          * walking through the surfaces and
00945          * calculating the number of bytes
00946          * needed for storage and add it to the total
00947          */
00948         BU_INIT_EXTERNAL(ep);
00949         ep->ext_nbytes = SIZEOF_NETWORK_LONG;   /* number of surfaces */
00950         for( s = 0; s < sip->nsrf; s++)
00951         {
00952                 ep->ext_nbytes += rt_nurb_bytes(sip->srfs[s]);
00953         }
00954 
00955         ep->ext_buf = (genptr_t)bu_malloc(ep->ext_nbytes,"nurb external");
00956         cp = (unsigned char *)ep->ext_buf;
00957 
00958         (void)bu_plong( cp, sip->nsrf );
00959         cp += SIZEOF_NETWORK_LONG;
00960 
00961         for( s = 0; s < sip->nsrf; s++)
00962         {
00963                 register struct face_g_snurb    *srf = sip->srfs[s];
00964 
00965                 NMG_CK_SNURB(srf);
00966 
00967                 coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
00968                 (void)bu_plong( cp, coords );
00969                 cp += SIZEOF_NETWORK_LONG;
00970                 (void)bu_plong( cp, srf->order[0] );
00971                 cp += SIZEOF_NETWORK_LONG;
00972                 (void)bu_plong( cp, srf->order[1] );
00973                 cp += SIZEOF_NETWORK_LONG;
00974                 (void)bu_plong( cp, srf->u.k_size );
00975                 cp += SIZEOF_NETWORK_LONG;
00976                 (void)bu_plong( cp, srf->v.k_size );
00977                 cp += SIZEOF_NETWORK_LONG;
00978                 (void)bu_plong( cp, srf->s_size[0] );
00979                 cp += SIZEOF_NETWORK_LONG;
00980                 (void)bu_plong( cp, srf->s_size[1] );
00981                 cp += SIZEOF_NETWORK_LONG;
00982                 htond( cp, (unsigned char *)srf->u.knots, srf->u.k_size );
00983                 cp += srf->u.k_size * SIZEOF_NETWORK_DOUBLE;
00984                 htond( cp, (unsigned char *)srf->v.knots, srf->v.k_size );
00985                 cp += srf->v.k_size * SIZEOF_NETWORK_DOUBLE;
00986 
00987                 htond( cp, (unsigned char *)srf->ctl_points,
00988                         coords * srf->s_size[0] * srf->s_size[1] );
00989                 cp += coords * srf->s_size[0] * srf->s_size[1] * SIZEOF_NETWORK_DOUBLE;
00990         }
00991 
00992         return(0);
00993 }
00994 
00995 
00996 /**
00997  *                      R T _ N U R B _ I M P O R T 5
00998  */
00999 int
01000 rt_nurb_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
01001 {
01002 
01003         struct rt_nurb_internal * sip;
01004         register int            i;
01005         int                     s;
01006         unsigned char           *cp;
01007         fastf_t                 tmp_vec[4];
01008 
01009         BU_CK_EXTERNAL( ep );
01010 
01011         RT_CK_DB_INTERNAL( ip );
01012         ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01013         ip->idb_type = ID_BSPLINE;
01014         ip->idb_meth = &rt_functab[ID_BSPLINE];
01015         ip->idb_ptr = bu_malloc( sizeof(struct rt_nurb_internal), "rt_nurb_internal");
01016         sip = (struct rt_nurb_internal *)ip->idb_ptr;
01017         sip->magic = RT_NURB_INTERNAL_MAGIC;
01018 
01019         cp = ep->ext_buf;
01020 
01021         sip->nsrf = bu_glong( cp );
01022         cp += SIZEOF_NETWORK_LONG;
01023         sip->srfs = (struct face_g_snurb **) bu_calloc(
01024                 sip->nsrf, sizeof( struct face_g_snurb *), "nurb srfs[]");
01025 
01026         for( s = 0; s < sip->nsrf; s++)
01027         {
01028                 register struct face_g_snurb    *srf;
01029                 int                     coords;
01030                 int                     pt_type;
01031                 int                     order[2], u_size, v_size;
01032                 int                     s_size[2];
01033 
01034                 pt_type = bu_glong( cp );
01035                 cp += SIZEOF_NETWORK_LONG;
01036                 order[0] = bu_glong( cp );
01037                 cp += SIZEOF_NETWORK_LONG;
01038                 order[1] = bu_glong( cp );
01039                 cp += SIZEOF_NETWORK_LONG;
01040                 u_size = bu_glong( cp );
01041                 cp += SIZEOF_NETWORK_LONG;
01042                 v_size = bu_glong( cp );
01043                 cp += SIZEOF_NETWORK_LONG;
01044                 s_size[0] = bu_glong( cp );
01045                 cp += SIZEOF_NETWORK_LONG;
01046                 s_size[1] = bu_glong( cp );
01047                 cp += SIZEOF_NETWORK_LONG;
01048                 if( pt_type == 3)
01049                         pt_type = RT_NURB_MAKE_PT_TYPE(3,RT_NURB_PT_XYZ,RT_NURB_PT_NONRAT);
01050                 else
01051                         pt_type = RT_NURB_MAKE_PT_TYPE(4,RT_NURB_PT_XYZ,RT_NURB_PT_RATIONAL);
01052 
01053                 sip->srfs[s] = (struct face_g_snurb *) rt_nurb_new_snurb(
01054                         order[0],order[1],
01055                         u_size,v_size,
01056                         s_size[0],s_size[1],
01057                         pt_type, (struct resource *)NULL);
01058 
01059                 srf = sip->srfs[s];
01060                 coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
01061 
01062                 ntohd( (unsigned char *)srf->u.knots, cp, srf->u.k_size );
01063                 cp += srf->u.k_size * SIZEOF_NETWORK_DOUBLE;
01064                 ntohd( (unsigned char *)srf->v.knots, cp, srf->v.k_size );
01065                 cp += srf->v.k_size * SIZEOF_NETWORK_DOUBLE;
01066 
01067                 rt_nurb_kvnorm( &srf->u);
01068                 rt_nurb_kvnorm( &srf->v);
01069 
01070                 ntohd( (unsigned char *)srf->ctl_points, cp,
01071                         coords * srf->s_size[0] * srf->s_size[1] );
01072 
01073                 cp += coords * srf->s_size[0] * srf->s_size[1] * SIZEOF_NETWORK_DOUBLE;
01074 
01075                 for( i=0 ; i<srf->s_size[0] * srf->s_size[1] ; i++ )
01076                 {
01077                         if( coords == 3 )
01078                         {
01079                                 VMOVE( tmp_vec, &srf->ctl_points[i*coords] );
01080                                 MAT4X3PNT( &srf->ctl_points[i*coords], mat, tmp_vec );
01081                         }
01082                         else if( coords == 4 )
01083                         {
01084                                 HMOVE( tmp_vec, &srf->ctl_points[i*coords] );
01085                                 MAT4X4PNT( &srf->ctl_points[i*coords], mat, tmp_vec );
01086                         }
01087                         else
01088                         {
01089                                 bu_log("rt_nurb_internal: %d invalid elements per vect\n", coords);
01090                                 return (-1);
01091                         }
01092                 }
01093 
01094                 /* bound the surface for tolerancing and other bounding box tests */
01095                 rt_nurb_s_bound( sip->srfs[s], sip->srfs[s]->min_pt,
01096                         sip->srfs[s]->max_pt);
01097         }
01098         return (0);
01099 }
01100 
01101 
01102 int
01103 rt_nurb_grans(struct face_g_snurb *srf)
01104 {
01105         int total_knots, total_points;
01106         int     k_gran;
01107         int     p_gran;
01108 
01109         total_knots = srf->u.k_size + srf->v.k_size;
01110         k_gran = ((total_knots * sizeof(dbfloat_t)) + sizeof(union record)-1)
01111                 / sizeof(union record);
01112 
01113         total_points = RT_NURB_EXTRACT_COORDS(srf->pt_type) *
01114                 (srf->s_size[0] * srf->s_size[1]);
01115         p_gran = ((total_points * sizeof(dbfloat_t)) + sizeof(union record)-1)
01116                 / sizeof(union record);
01117 
01118         return 1 + k_gran + p_gran;
01119 }
01120 
01121 /**
01122  *                      R T _ N U R B _ I F R E E
01123  */
01124 void
01125 rt_nurb_ifree(struct rt_db_internal *ip)
01126 {
01127         register struct rt_nurb_internal * sip;
01128         register int                     i;
01129 
01130         RT_CK_DB_INTERNAL(ip);
01131         sip = ( struct rt_nurb_internal *) ip->idb_ptr;
01132         RT_NURB_CK_MAGIC(sip);
01133 
01134         /* Free up storage for the nurb surfaces */
01135         for( i = 0; i < sip->nsrf; i++)
01136         {
01137                 rt_nurb_free_snurb( sip->srfs[i], (struct resource *)NULL );
01138         }
01139         bu_free( (char *)sip->srfs, "nurb surfs[]" );
01140         sip->magic = 0;
01141         sip->nsrf = 0;
01142         bu_free( (char *)sip, "sip ifree");
01143         ip->idb_ptr = GENPTR_NULL;
01144 }
01145 
01146 /**
01147  *                      R T _ N U R B _ D E S C R I B E
01148  */
01149 int
01150 rt_nurb_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
01151 {
01152         register int            j;
01153         register struct rt_nurb_internal * sip =
01154                 (struct rt_nurb_internal *) ip->idb_ptr;
01155         int                     i;
01156         int                     surf;
01157 
01158         RT_NURB_CK_MAGIC(sip);
01159         bu_vls_strcat( str, "Non Uniform Rational B-Spline solid (NURB)\n");
01160 
01161         bu_vls_printf( str, "\t%d surfaces\n", sip->nsrf);
01162         if( verbose < 2 )  return 0;
01163 
01164         for( surf = 0; surf < sip->nsrf; surf++)
01165         {
01166                 register struct face_g_snurb    * np;
01167                 register fastf_t        * mp;
01168                 int                     ncoord;
01169 
01170                 np = sip->srfs[surf];
01171                 NMG_CK_SNURB(np);
01172                 mp = np->ctl_points;
01173                 ncoord = RT_NURB_EXTRACT_COORDS(np->pt_type);
01174 
01175                 bu_vls_printf( str,
01176                         "\tSurface %d: order %d x %d, mesh %d x %d\n",
01177                         surf, np->order[0], np->order[1],
01178                         np->s_size[0], np->s_size[1]);
01179 
01180                 bu_vls_printf( str, "\t\tVert (%g, %g, %g)\n",
01181                         INTCLAMP(mp[X] * mm2local),
01182                         INTCLAMP(mp[Y] * mm2local),
01183                         INTCLAMP(mp[Z] * mm2local) );
01184 
01185                 if( verbose < 3 ) continue;
01186 
01187                 /* Print out the knot vectors */
01188                 bu_vls_printf( str, "\tU: ");
01189                 for( i=0; i < np->u.k_size; i++ )
01190                         bu_vls_printf( str, "%g, ", INTCLAMP(np->u.knots[i]) );
01191                 bu_vls_printf( str, "\n\tV: ");
01192                 for( i=0; i < np->v.k_size; i++ )
01193                         bu_vls_printf( str, "%g, ", INTCLAMP(np->v.knots[i]) );
01194                 bu_vls_printf( str, "\n");
01195 
01196                 /* print out all the points */
01197                 for(i=0; i < np->s_size[0]; i++)
01198                 {
01199                         bu_vls_printf( str, "\tRow %d:\n", i);
01200                         for( j = 0; j < np->s_size[1]; j++)
01201                         {
01202                                 if( ncoord == 3 ) {
01203                                         bu_vls_printf( str, "\t\t(%g, %g, %g)\n",
01204                                                 INTCLAMP(mp[X] * mm2local),
01205                                                 INTCLAMP(mp[Y] * mm2local),
01206                                                 INTCLAMP(mp[Z] * mm2local) );
01207                                 } else {
01208                                         bu_vls_printf( str, "\t\t(%g, %g, %g, %g)\n",
01209                                                 INTCLAMP(mp[X] * mm2local),
01210                                                 INTCLAMP(mp[Y] * mm2local),
01211                                                 INTCLAMP(mp[Z] * mm2local),
01212                                                 INTCLAMP(mp[W]) );
01213                                 }
01214                                 mp += ncoord;
01215                         }
01216                 }
01217         }
01218         return 0;
01219 }
01220 
01221 
01222 int
01223 rt_nurb_tclget(Tcl_Interp *interp, const struct rt_db_internal *intern, const char *attr)
01224 {
01225         struct rt_nurb_internal *nurb=(struct rt_nurb_internal *)intern->idb_ptr;
01226         Tcl_DString             ds;
01227         struct bu_vls           vls;
01228         struct face_g_snurb     *srf;
01229         int                     i, j, k;
01230         int                     coords;
01231         int                     status;
01232 
01233         RT_NURB_CK_MAGIC( nurb );
01234 
01235         Tcl_DStringInit( &ds );
01236         bu_vls_init( &vls );
01237 
01238         if( attr == (char *)NULL ) {
01239                 bu_vls_strcpy( &vls, "bspline" );
01240                 bu_vls_printf( &vls, " N %d S {", nurb->nsrf );
01241                 for( i=0 ; i<nurb->nsrf ; i++ ) {
01242                         srf = nurb->srfs[i];
01243                         bu_vls_printf( &vls, " { O {%d %d} s {%d %d} T %d u {",
01244                                        srf->order[0], srf->order[1],
01245                                        srf->s_size[0], srf->s_size[1],
01246                                        srf->pt_type/* !!! -- export this?, srf->u.k_size */ );
01247                         for( j=0 ; j<srf->u.k_size ; j++ ) {
01248                                 bu_vls_printf( &vls, " %.25G", srf->u.knots[j] );
01249                         }
01250                         bu_vls_printf( &vls, "} v {"/* !!! -- export this?, srf->v.k_size */ );
01251                         for( j=0 ; j<srf->v.k_size ; j++ ) {
01252                                 bu_vls_printf( &vls, " %.25G", srf->v.knots[j] );
01253                         }
01254                         bu_vls_strcat( &vls, "} P {" );
01255 
01256                         coords = RT_NURB_EXTRACT_COORDS( srf->pt_type );
01257                         for( j=0 ; j<srf->s_size[0]*srf->s_size[1] ; j++ ) {
01258                                 for( k=0 ; k<coords ; k++ ) {
01259                                         bu_vls_printf( &vls, " %.25G",
01260                                                        srf->ctl_points[j*coords + k] );
01261                                 }
01262                         }
01263                         bu_vls_strcat( &vls, " } }" );
01264                 }
01265                 bu_vls_printf( &vls, " }" );
01266                 status = TCL_OK;
01267         } else {
01268                 bu_vls_printf( &vls, "Nurb has no attribute '%s'", attr );
01269                 status = TCL_ERROR;
01270         }
01271 
01272         Tcl_DStringAppend( &ds, bu_vls_addr( &vls ), -1 );
01273         Tcl_DStringResult( interp, &ds );
01274         Tcl_DStringFree( &ds );
01275         bu_vls_free( &vls );
01276 
01277         return( status );
01278 }
01279 
01280 int
01281 rt_nurb_tcladjust(Tcl_Interp *interp, struct rt_db_internal *intern, int argc, char **argv)
01282 {
01283         struct rt_nurb_internal *nurb;
01284         int srf_no;
01285         Tcl_Obj *obj, *list, **srf_array, **srf_param_array;
01286         struct face_g_snurb *srf;
01287         int i;
01288         char *key;
01289         int len;
01290 
01291         RT_CK_DB_INTERNAL( intern );
01292         nurb = (struct rt_nurb_internal *)intern->idb_ptr;
01293         RT_NURB_CK_MAGIC( nurb );
01294 
01295         while( argc >= 2 ) {
01296                 obj = Tcl_NewStringObj( argv[1], -1 );
01297                 list = Tcl_NewListObj( 0, NULL );
01298                 if( Tcl_ListObjAppendList( interp, list, obj ) != TCL_OK ) {
01299                         return( TCL_ERROR );
01300                 }
01301 
01302                 if( !strcmp( argv[0], "N" ) ) {
01303                         if( nurb->srfs ) {
01304                                 for( i=0 ; i<nurb->nsrf ; i++ )
01305                                         rt_nurb_free_snurb( nurb->srfs[i], NULL );
01306                                 bu_free( (char *)nurb->srfs, "nurb surfaces" );
01307                         }
01308                         nurb->nsrf = atoi( argv[1] );
01309                         nurb->srfs = (struct face_g_snurb **) bu_calloc(
01310                                 nurb->nsrf, sizeof( struct face_g_snurb *), "nurb srfs[]");
01311                 } else if( !strcmp( argv[0], "S" ) ) {
01312                         (void)Tcl_ListObjGetElements( interp, list, &len, &srf_array );
01313                         for( srf_no=0 ; srf_no < nurb->nsrf ; srf_no++ ) {
01314                                 int n_params=0;
01315                                 int *order=NULL, *s_size=NULL, u_size=0, v_size=0, pt_type=0;
01316                                 fastf_t *u_pts=NULL, *v_pts=NULL;
01317 
01318                                 (void)Tcl_ListObjGetElements( interp, srf_array[srf_no], &n_params,
01319                                                               &srf_param_array );
01320 
01321                                 for( i=0 ; i<n_params ; i+= 2 ) {
01322                                         int tmp_len;
01323 
01324                                         key = Tcl_GetStringFromObj( srf_param_array[i], NULL );
01325                                         if( !strcmp( key, "O" ) ) {
01326                                                 tmp_len = 0;
01327                                                 if( tcl_obj_to_int_array( interp, srf_param_array[i+1],
01328                                                               &order, &tmp_len ) != 2 ) {
01329                                                         Tcl_SetResult( interp,
01330                                                               "ERROR: unable to parse surface\n",
01331                                                                TCL_STATIC );
01332                                                         return( TCL_ERROR );
01333                                                 }
01334                                         } else if( !strcmp( key, "s" ) ) {
01335                                                 tmp_len = 0;
01336                                                 if( tcl_obj_to_int_array( interp, srf_param_array[i+1],
01337                                                               &s_size, &tmp_len ) != 2 ) {
01338                                                         Tcl_SetResult( interp,
01339                                                               "ERROR: unable to parse surface\n",
01340                                                                TCL_STATIC );
01341                                                         return( TCL_ERROR );
01342                                                 }
01343                                         } else if( !strcmp( key, "T" ) ) {
01344                                                 pt_type = atoi( Tcl_GetStringFromObj(
01345                                                                      srf_param_array[i+1], NULL ) );
01346                                         } else if( !strcmp( key, "u" ) ) {
01347                                                 tcl_obj_to_fastf_array( interp, srf_param_array[i+1], &u_pts,
01348                                                                         &u_size );
01349                                         } else if( !strcmp( key, "v" ) ) {
01350                                                 tcl_obj_to_fastf_array( interp, srf_param_array[i+1], &v_pts,
01351                                                                         &v_size );
01352                                         } else if( !strcmp( key, "P" ) ) {
01353                                                 int tmp2;
01354 
01355                                                 if( !order || !s_size || !u_pts || !v_pts ||
01356                                                     u_size == 0 || v_size == 0 || pt_type == 0 ) {
01357                                                         Tcl_SetResult( interp,
01358                                                             "ERROR: Need all other details set before ctl points\n",
01359                                                             TCL_STATIC );
01360                                                         return( TCL_ERROR );
01361                                                 }
01362                                                 nurb->srfs[srf_no] = (struct face_g_snurb *) rt_nurb_new_snurb(
01363                                                       order[0],order[1],
01364                                                       u_size,v_size,
01365                                                       s_size[0],s_size[1],
01366                                                       pt_type, (struct resource *)NULL);
01367                                                 srf = nurb->srfs[srf_no];
01368                                                 bu_free( (char *)order, "order" );
01369                                                 bu_free( (char *)s_size, "s_size" );
01370                                                 (void)memcpy( srf->u.knots, u_pts,
01371                                                               srf->u.k_size * sizeof( fastf_t ) );
01372                                                 (void)memcpy( srf->v.knots, v_pts,
01373                                                               srf->v.k_size * sizeof( fastf_t ) );
01374                                                 bu_free( (char *)u_pts, "u_pts" );
01375                                                 bu_free( (char *)v_pts, "v_pts" );
01376                                                 tmp_len = srf->s_size[0] * srf->s_size[1] *
01377                                                         RT_NURB_EXTRACT_COORDS(srf->pt_type );
01378                                                 tmp2 = tmp_len;
01379                                                 if( tcl_obj_to_fastf_array( interp, srf_param_array[i+1],
01380                                                            &srf->ctl_points, &tmp_len ) != tmp2 ) {
01381                                                         Tcl_SetResult( interp,
01382                                                               "ERROR: unable to parse surface\n",
01383                                                                TCL_STATIC );
01384                                                         return( TCL_ERROR );
01385                                                 }
01386                                         }
01387                                 }
01388                         }
01389                 }
01390 
01391                 Tcl_DecrRefCount( list );
01392 
01393                 argc -= 2;
01394                 argv += 2;
01395         }
01396 
01397         return( TCL_OK );
01398 }
01399 
01400 /*
01401  * Local Variables:
01402  * mode: C
01403  * tab-width: 8
01404  * c-basic-offset: 4
01405  * indent-tabs-mode: t
01406  * End:
01407  * ex: shiftwidth=4 tabstop=8
01408  */

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