00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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"
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
00066
00067 struct nurb_specific {
00068 struct nurb_specific * next;
00069 struct face_g_snurb * srf;
00070 struct bu_list bez_hd;
00071 };
00072
00073 struct nurb_hit {
00074 struct nurb_hit * next;
00075 struct nurb_hit * prev;
00076 fastf_t hit_dist;
00077 point_t hit_point;
00078 vect_t hit_normal;
00079 fastf_t hit_uv[2];
00080 char * hit_private;
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
00095
00096
00097
00098
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
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
00129 (void)rt_nurb_bezier( &n->bez_hd, sip->srfs[i], (struct resource *)NULL );
00130
00131
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
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
00179 rt_nurb_s_print("NURB", nurb->srf);
00180 }
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
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
00219
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
00231
00232
00233 bn_mk_plane_3pts( plane1, p1, p3, p2, tol );
00234 bn_mk_plane_3pts( plane2, p1, p2, p4, tol );
00235
00236
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
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
00279 }
00280
00281
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);
00331 }
00332
00333 #define SEG_MISS(SEG) (SEG).seg_stp=(struct soltab *) 0;
00334
00335
00336
00337
00338
00339
00340 void
00341 rt_nurb_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
00342
00343
00344
00345
00346
00347 {
00348 rt_vstub( stp, rp, segp, n, ap );
00349 }
00350
00351
00352
00353
00354
00355
00356 void
00357 rt_nurb_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00358 {
00359
00360
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
00381
00382
00383
00384 void
00385 rt_nurb_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00386 {
00387
00388
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
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
00409
00410
00411
00412
00413
00414
00415 void
00416 rt_nurb_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00417 {
00418
00419
00420 uvp->uv_u = hitp->hit_vpriv[0];
00421 uvp->uv_v = hitp->hit_vpriv[1];
00422 return;
00423 }
00424
00425
00426
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
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 );
00450 bu_free( (char *)nurb, "nurb_specific" );
00451 }
00452 }
00453
00454
00455
00456
00457 int
00458 rt_nurb_class(void)
00459 {
00460 return(0);
00461 }
00462
00463
00464
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
00499
00500 if( ttol->rel <= 0.0 || ttol->rel >= 1.0 ) {
00501 rel = 0.0;
00502 } else {
00503
00504 rel = ttol->rel * 2 * bound;
00505 }
00506 if( ttol->abs <= 0.0 ) {
00507 if( rel <= 0.0 ) {
00508
00509 rel = 2 * 0.10 * bound;
00510 } else {
00511
00512 }
00513 } else {
00514
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
00521 tess = 0.25;
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
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
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
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
00748 if( hit->hit_dist < .001)
00749 {
00750
00751 bu_free( (char *) hit, "internal_add_hit: hit");
00752 return;
00753 }
00754 #endif
00755
00756
00757 if( head->next == (struct nurb_hit *) 0)
00758 {
00759 head->next = hit;
00760 hit->prev = head;
00761 return;
00762 }
00763
00764
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
00770 f = hit->hit_dist - h_ptr->hit_dist;
00771 if( NEAR_ZERO( f, tol->dist ) ) goto duplicate;
00772
00773
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
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
00842
00843
00844
00845
00846 total_grans = 1;
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
00917 + 2 * SIZEOF_NETWORK_LONG
00918 + srf->u.k_size * SIZEOF_NETWORK_DOUBLE
00919 + srf->v.k_size * SIZEOF_NETWORK_DOUBLE
00920 + 2 * SIZEOF_NETWORK_LONG
00921 + RT_NURB_EXTRACT_COORDS(srf->pt_type) *
00922 (srf->s_size[0] * srf->s_size[1]) * SIZEOF_NETWORK_DOUBLE;
00923
00924 return total_bytes;
00925 }
00926
00927
00928
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
00944
00945
00946
00947
00948 BU_INIT_EXTERNAL(ep);
00949 ep->ext_nbytes = SIZEOF_NETWORK_LONG;
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
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
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
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
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
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
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
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 );
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 {" );
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
01402
01403
01404
01405
01406
01407
01408