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
00039 #ifndef lint
00040 static const char RCSarbn[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_arbn.c,v 14.13 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00041 #endif
00042
00043 #include "common.h"
00044
00045 #include <stdlib.h>
00046 #include <stdio.h>
00047 #ifdef HAVE_STRING_H
00048 # include <string.h>
00049 #endif
00050 #include <math.h>
00051 #include <ctype.h>
00052
00053 #include "machine.h"
00054 #include "tcl.h"
00055 #include "vmath.h"
00056 #include "nmg.h"
00057 #include "db.h"
00058 #include "raytrace.h"
00059 #include "rtgeom.h"
00060 #include "./debug.h"
00061
00062
00063 BU_EXTERN(void rt_arbn_print, (const struct soltab *stp) );
00064 BU_EXTERN(void rt_arbn_ifree, (struct rt_db_internal *ip) );
00065
00066
00067
00068
00069
00070
00071
00072
00073 int
00074 rt_arbn_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00075 {
00076 struct rt_arbn_internal *aip;
00077 vect_t work;
00078 fastf_t f;
00079 register int i;
00080 int j;
00081 int k;
00082 int *used = (int *)0;
00083 const struct bn_tol *tol = &rtip->rti_tol;
00084
00085 RT_CK_DB_INTERNAL( ip );
00086 aip = (struct rt_arbn_internal *)ip->idb_ptr;
00087 RT_ARBN_CK_MAGIC(aip);
00088
00089 used = (int *)bu_malloc(aip->neqn*sizeof(int), "arbn used[]");
00090
00091
00092
00093
00094
00095
00096
00097
00098 for( i=0; i<aip->neqn; i++ ) {
00099 used[i] = 0;
00100 }
00101 for( i=0; i<aip->neqn-2; i++ ) {
00102 for( j=i+1; j<aip->neqn-1; j++ ) {
00103 double dot;
00104
00105
00106 dot = VDOT( aip->eqn[i], aip->eqn[j] );
00107 if( BN_VECT_ARE_PARALLEL(dot, tol) ) continue;
00108
00109
00110 for( k=j+1; k<aip->neqn; k++ ) {
00111 register int m;
00112 point_t pt;
00113 int next_k;
00114
00115 next_k = 0;
00116
00117 if( bn_mkpoint_3planes( pt, aip->eqn[i], aip->eqn[j], aip->eqn[k] ) < 0 ) continue;
00118
00119
00120 for( m=0; m<aip->neqn; m++ ) {
00121 if( i==m || j==m || k==m ) continue;
00122 if( VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist )
00123 {
00124 next_k = 1;
00125 break;
00126 }
00127 }
00128 if( next_k != 0) continue;
00129
00130 VMINMAX( stp->st_min, stp->st_max, pt );
00131
00132
00133 used[i]++;
00134 used[j]++;
00135 used[k]++;
00136 }
00137 }
00138 }
00139
00140
00141 for( i=0; i<aip->neqn; i++ ) {
00142 if( used[i] != 0 ) continue;
00143 bu_log("arbn(%s) face %d unused, solid is not convex\n",
00144 stp->st_name, i);
00145 bu_free( (char *)used, "arbn used[]");
00146 return(-1);
00147 }
00148 bu_free( (char *)used, "arbn used[]");
00149
00150 stp->st_specific = (genptr_t)aip;
00151 ip->idb_ptr = GENPTR_NULL;
00152
00153 VADD2SCALE( stp->st_center, stp->st_min, stp->st_max, 0.5 );
00154 VSUB2SCALE( work, stp->st_max, stp->st_min, 0.5 );
00155
00156 f = work[X];
00157 if( work[Y] > f ) f = work[Y];
00158 if( work[Z] > f ) f = work[Z];
00159 stp->st_aradius = f;
00160 stp->st_bradius = MAGNITUDE(work);
00161 return(0);
00162 }
00163
00164
00165
00166
00167 void
00168 rt_arbn_print(register const struct soltab *stp)
00169 {
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 int
00184 rt_arbn_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00185 {
00186 register struct rt_arbn_internal *aip =
00187 (struct rt_arbn_internal *)stp->st_specific;
00188 register int i;
00189 LOCAL int iplane, oplane;
00190 LOCAL fastf_t in, out;
00191
00192 in = -INFINITY;
00193 out = INFINITY;
00194 iplane = oplane = -1;
00195
00196 for( i = aip->neqn-1; i >= 0; i-- ) {
00197 FAST fastf_t slant_factor;
00198 FAST fastf_t norm_dist;
00199 FAST fastf_t s;
00200
00201 norm_dist = VDOT( aip->eqn[i], rp->r_pt ) - aip->eqn[i][3];
00202 if( (slant_factor = -VDOT( aip->eqn[i], rp->r_dir )) < -1.0e-10 ) {
00203
00204 if( out > (s = norm_dist/slant_factor) ) {
00205 out = s;
00206 oplane = i;
00207 }
00208 } else if ( slant_factor > 1.0e-10 ) {
00209
00210 if( in < (s = norm_dist/slant_factor) ) {
00211 in = s;
00212 iplane = i;
00213 }
00214 } else {
00215
00216
00217
00218
00219
00220 if( norm_dist > SQRT_SMALL_FASTF )
00221 return( 0 );
00222 }
00223 if( in > out )
00224 return( 0 );
00225 }
00226
00227
00228 if( iplane == -1 || oplane == -1 ) {
00229 bu_log("rt_arbn_shoot(%s): 1 hit => MISS\n",
00230 stp->st_name);
00231 return( 0 );
00232 }
00233 if( in >= out || out >= INFINITY )
00234 return( 0 );
00235
00236 {
00237 register struct seg *segp;
00238
00239 RT_GET_SEG( segp, ap->a_resource );
00240 segp->seg_stp = stp;
00241 segp->seg_in.hit_dist = in;
00242 segp->seg_in.hit_surfno = iplane;
00243
00244 segp->seg_out.hit_dist = out;
00245 segp->seg_out.hit_surfno = oplane;
00246 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00247 }
00248 return(2);
00249 }
00250
00251
00252
00253
00254 void
00255 rt_arbn_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
00256
00257
00258
00259
00260
00261 {
00262 rt_vstub( stp, rp, segp, n, ap );
00263 }
00264
00265
00266
00267
00268
00269
00270 void
00271 rt_arbn_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00272 {
00273 register struct rt_arbn_internal *aip =
00274 (struct rt_arbn_internal *)stp->st_specific;
00275 int h;
00276
00277 VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
00278 h = hitp->hit_surfno;
00279 if( h < 0 || h > aip->neqn ) {
00280 bu_log("rt_arbn_norm(%s): hit_surfno=%d?\n", h );
00281 VSETALL( hitp->hit_normal, 0 );
00282 return;
00283 }
00284 VMOVE( hitp->hit_normal, aip->eqn[h] );
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294 void
00295 rt_arbn_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00296 {
00297
00298 bn_vec_ortho( cvp->crv_pdir, hitp->hit_normal );
00299 cvp->crv_c1 = cvp->crv_c2 = 0;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 void
00311 rt_arbn_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00312 {
00313 uvp->uv_u = uvp->uv_v = 0;
00314 uvp->uv_du = uvp->uv_dv = 0;
00315 }
00316
00317
00318
00319
00320 void
00321 rt_arbn_free(register struct soltab *stp)
00322 {
00323 register struct rt_arbn_internal *aip =
00324 (struct rt_arbn_internal *)stp->st_specific;
00325
00326 bu_free( (char *)aip->eqn, "rt_arbn_internal eqn[]");
00327 bu_free( (char *)aip, "rt_arbn_internal" );
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 int
00342 rt_arbn_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00343 {
00344 register struct rt_arbn_internal *aip;
00345 register int i;
00346 register int j;
00347 register int k;
00348
00349 RT_CK_DB_INTERNAL(ip);
00350 aip = (struct rt_arbn_internal *)ip->idb_ptr;
00351 RT_ARBN_CK_MAGIC(aip);
00352
00353 for( i=0; i<aip->neqn-1; i++ ) {
00354 for( j=i+1; j<aip->neqn; j++ ) {
00355 double dot;
00356 int point_count;
00357 point_t a,b;
00358 vect_t dist;
00359
00360
00361 dot = VDOT( aip->eqn[i], aip->eqn[j] );
00362 if( BN_VECT_ARE_PARALLEL(dot, tol) ) continue;
00363
00364
00365 point_count = 0;
00366 for( k=0; k<aip->neqn; k++ ) {
00367 register int m;
00368 point_t pt;
00369 int next_k;
00370
00371 next_k = 0;
00372
00373 if( k==i || k==j ) continue;
00374 if( bn_mkpoint_3planes( pt, aip->eqn[i], aip->eqn[j], aip->eqn[k] ) < 0 ) continue;
00375
00376
00377 for( m=0; m<aip->neqn; m++ ) {
00378 if( i==m || j==m || k==m ) continue;
00379 if( VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist )
00380 {
00381 next_k = 1;
00382 break;
00383 }
00384 }
00385
00386 if( next_k != 0) continue;
00387
00388 if( point_count <= 0 ) {
00389 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_MOVE );
00390 VMOVE( a, pt );
00391 } else if( point_count == 1 ) {
00392 VSUB2( dist, pt, a );
00393 if( MAGSQ(dist) < tol->dist_sq ) continue;
00394 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
00395 VMOVE( b, pt );
00396 } else {
00397 VSUB2( dist, pt, a );
00398 if( MAGSQ(dist) < tol->dist_sq ) continue;
00399 VSUB2( dist, pt, b );
00400 if( MAGSQ(dist) < tol->dist_sq ) continue;
00401 bu_log("rt_arbn_plot() error, point_count=%d (>2) on edge %d/%d, non-convex\n",
00402 point_count+1,
00403 i, j );
00404 VPRINT(" a", a);
00405 VPRINT(" b", b);
00406 VPRINT("pt", pt);
00407 RT_ADD_VLIST( vhead, pt, BN_VLIST_LINE_DRAW );
00408 }
00409 point_count++;
00410 }
00411
00412
00413
00414 }
00415 }
00416 return(0);
00417 }
00418
00419
00420
00421
00422 int
00423 rt_arbn_class(void)
00424 {
00425 return(0);
00426 }
00427
00428
00429
00430 struct arbn_pts
00431 {
00432 point_t pt;
00433 int plane_no[3];
00434 struct vertex **vp;
00435 };
00436 struct arbn_edges
00437 {
00438 int v1_no,v2_no;
00439 };
00440
00441 #define LOC(i,j) i*(aip->neqn)+j
00442
00443 static void
00444 Sort_edges(struct arbn_edges *edges, int *edge_count, const struct rt_arbn_internal *aip)
00445 {
00446 int face;
00447
00448 for( face=0 ; face<aip->neqn ; face++ )
00449 {
00450 int done=0;
00451 int edge1,edge2;
00452
00453 if( edge_count[face] < 3 )
00454 continue;
00455
00456 edge1 = 0;
00457 edge2 = 0;
00458 while( !done )
00459 {
00460 int edge3;
00461 int tmp_v1,tmp_v2;
00462
00463
00464 while( ++edge2 < edge_count[face] &&
00465 edges[LOC(face,edge1)].v2_no == edges[LOC(face,edge2)].v1_no )
00466 edge1++;
00467 if( edge2 == edge_count[face] )
00468 {
00469
00470 done = 1;
00471 continue;
00472 }
00473
00474
00475 edge3 = edge2 - 1;
00476 while( ++edge3 < edge_count[face] &&
00477 edges[LOC(face,edge1)].v2_no != edges[LOC(face,edge3)].v1_no &&
00478 edges[LOC(face,edge1)].v2_no != edges[LOC(face,edge3)].v2_no );
00479
00480 if( edge3 == edge_count[face] )
00481 rt_bomb( "rt_arbn_tess: Sort_edges: Cannot find next edge in loop\n" );
00482
00483 if( edge2 != edge3 )
00484 {
00485
00486 tmp_v1 = edges[LOC(face,edge2)].v1_no;
00487 tmp_v2 = edges[LOC(face,edge2)].v2_no;
00488 edges[LOC(face,edge2)].v1_no = edges[LOC(face,edge3)].v1_no;
00489 edges[LOC(face,edge2)].v2_no = edges[LOC(face,edge3)].v2_no;
00490 edges[LOC(face,edge3)].v1_no = tmp_v1;
00491 edges[LOC(face,edge3)].v2_no = tmp_v2;
00492 }
00493 if( edges[LOC(face,edge1)].v2_no == edges[LOC(face,edge2)].v2_no )
00494 {
00495
00496 tmp_v1 = edges[LOC(face,edge2)].v1_no;
00497 edges[LOC(face,edge2)].v1_no = edges[LOC(face,edge2)].v2_no;
00498 edges[LOC(face,edge2)].v2_no = tmp_v1;
00499 }
00500
00501 edge1 = edge2;
00502 }
00503 }
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 int
00518 rt_arbn_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00519 {
00520 LOCAL struct rt_arbn_internal *aip;
00521 struct shell *s;
00522 struct faceuse **fu;
00523 int nverts;
00524 int point_count=0;
00525 int face_count=0;
00526 int i,j,k,l,n;
00527 struct arbn_pts *pts;
00528 struct arbn_edges *edges;
00529 int *edge_count;
00530 int max_edge_count;
00531 struct vertex **verts;
00532 struct vertex ***loop_verts;
00533
00534 RT_CK_DB_INTERNAL(ip);
00535 aip = (struct rt_arbn_internal *)ip->idb_ptr;
00536 RT_ARBN_CK_MAGIC(aip);
00537
00538
00539 nverts = aip->neqn * (aip->neqn-1) * (aip->neqn-2) / 6;
00540 pts = (struct arbn_pts *)bu_calloc( nverts , sizeof( struct arbn_pts ) , "rt_arbn_tess: pts" );
00541
00542
00543 edges = (struct arbn_edges *)bu_calloc( aip->neqn*aip->neqn , sizeof( struct arbn_edges ) ,
00544 "rt_arbn_tess: edges" );
00545 edge_count = (int *)bu_calloc( aip->neqn , sizeof( int ) , "rt_arbn_tess: edge_count" );
00546
00547
00548 fu = (struct faceuse **)bu_calloc( aip->neqn , sizeof( struct faceuse *) , "rt_arbn_tess: fu" );
00549
00550
00551 for( i=0 ; i<aip->neqn ; i++ )
00552 {
00553 for( j=i+1 ; j<aip->neqn ; j++ )
00554 {
00555 for( k=j+1 ; k<aip->neqn ; k++ )
00556 {
00557 int keep_point=1;
00558
00559 if( bn_mkpoint_3planes( pts[point_count].pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]))
00560 continue;
00561
00562 for( l=0 ; l<aip->neqn ; l++ )
00563 {
00564 if( l == i || l == j || l == k )
00565 continue;
00566 if( DIST_PT_PLANE( pts[point_count].pt , aip->eqn[l] ) > tol->dist )
00567 {
00568 keep_point = 0;
00569 break;
00570 }
00571 }
00572 if( keep_point )
00573 {
00574 pts[point_count].plane_no[0] = i;
00575 pts[point_count].plane_no[1] = j;
00576 pts[point_count].plane_no[2] = k;
00577 point_count++;
00578 }
00579 }
00580 }
00581 }
00582
00583
00584 verts = (struct vertex **)bu_calloc( point_count , sizeof( struct vertex *) ,
00585 "rt_arbn_tess: verts" );
00586
00587
00588 for( i=0 ; i<point_count ; i++ )
00589 pts[i].vp = &verts[i];
00590
00591
00592 for( i=0 ; i<point_count ; i++ )
00593 {
00594 for( j=i+1 ; j<point_count ; j++ )
00595 {
00596 vect_t dist;
00597
00598 VSUB2( dist , pts[i].pt , pts[j].pt )
00599 if( MAGSQ( dist ) < tol->dist_sq )
00600 {
00601
00602 pts[j].vp = pts[i].vp;
00603 }
00604 }
00605 }
00606
00607
00608 for( i=0 ; i<aip->neqn ; i++ )
00609 {
00610
00611 for( j=0 ; j<point_count ; j++ )
00612 {
00613 if( pts[j].plane_no[0] != i && pts[j].plane_no[1] != i && pts[j].plane_no[2] != i )
00614 continue;
00615
00616
00617 for( k=j+1 ; k<point_count ; k++ )
00618 {
00619 int match=(-1);
00620 int pt1,pt2;
00621 int duplicate=0;
00622
00623
00624 if( pts[k].plane_no[0] != i && pts[k].plane_no[1] != i && pts[k].plane_no[2] != i )
00625 continue;
00626
00627 for( l=0 ; l<3 ; l++ )
00628 {
00629 for( n=0 ; n<3 ; n++ )
00630 {
00631 if( pts[j].plane_no[l] == pts[k].plane_no[n] &&
00632 pts[j].plane_no[l] != i )
00633 {
00634 match = pts[j].plane_no[l];
00635 break;
00636 }
00637 }
00638 if( match != (-1) )
00639 break;
00640 }
00641
00642 if( match == (-1) )
00643 continue;
00644
00645
00646 pt1 = j;
00647 pt2 = k;
00648 for( l=0 ; l<pt1 ; l++ )
00649 {
00650 if( pts[pt1].vp == pts[l].vp )
00651 {
00652 pt1 = l;
00653 break;
00654 }
00655 }
00656 for( l=0 ; l<pt2 ; l++ )
00657 {
00658 if( pts[pt2].vp == pts[l].vp )
00659 {
00660 pt2 = l;
00661 break;
00662 }
00663 }
00664
00665
00666 if( pt1 == pt2 )
00667 continue;
00668
00669
00670 for( l=0 ; l<edge_count[i] ; l++ )
00671 {
00672 if( (edges[LOC(i,l)].v1_no == pt1 &&
00673 edges[LOC(i,l)].v2_no == pt2) ||
00674 (edges[LOC(i,l)].v2_no == pt1 &&
00675 edges[LOC(i,l)].v1_no == pt2) )
00676 {
00677 duplicate = 1;
00678 break;
00679 }
00680 }
00681 if( duplicate )
00682 continue;
00683
00684
00685 if( edge_count[i] == aip->neqn )
00686 {
00687 bu_log( "Too many edges found for one face\n" );
00688 goto fail;
00689 }
00690 edges[LOC( i , edge_count[i] )].v1_no = pt1;
00691 edges[LOC( i , edge_count[i] )].v2_no = pt2;
00692 edge_count[i]++;
00693 }
00694 }
00695 }
00696
00697
00698 Sort_edges( edges , edge_count , aip );
00699
00700
00701 max_edge_count = 0;
00702 for( i=0 ; i<aip->neqn ; i++ )
00703 if( edge_count[i] > max_edge_count )
00704 max_edge_count = edge_count[i];
00705
00706
00707 loop_verts = (struct vertex ***) bu_calloc( max_edge_count , sizeof( struct vertex **) ,
00708 "rt_arbn_tess: loop_verts" );
00709
00710 *r = nmg_mrsv( m );
00711 s = BU_LIST_FIRST(shell, &(*r)->s_hd);
00712
00713
00714 for( i=0 ; i<aip->neqn ; i++ )
00715 {
00716 int loop_length=0;
00717
00718 for( j=0 ; j<edge_count[i] ; j++ )
00719 {
00720
00721 if( pts[edges[LOC(i,j)].v1_no].vp == pts[edges[LOC(i,j)].v2_no].vp )
00722 continue;
00723
00724
00725 loop_verts[loop_length] = pts[edges[LOC(i,j)].v2_no].vp;
00726 loop_length++;
00727 }
00728
00729
00730 if( loop_length > 2 )
00731 fu[face_count++] = nmg_cmface( s , loop_verts , loop_length );
00732 }
00733
00734
00735 for( i=0 ; i<point_count ; i++ )
00736 {
00737 if( !(*pts[i].vp) )
00738 continue;
00739
00740 if( (*pts[i].vp)->vg_p )
00741 continue;
00742
00743 nmg_vertex_gv( *pts[i].vp , pts[i].pt );
00744 }
00745
00746 bu_free( (char *)pts , "rt_arbn_tess: pts" );
00747 bu_free( (char *)edges , "rt_arbn_tess: edges" );
00748 bu_free( (char *)edge_count , "rt_arbn_tess: edge_count" );
00749 bu_free( (char *)verts , "rt_arbn_tess: verts" );
00750 bu_free( (char *)loop_verts , "rt_arbn_tess: loop_verts" );
00751
00752
00753 for( i=0 ; i<face_count ; i++ )
00754 {
00755 if( nmg_fu_planeeqn( fu[i] , tol ) )
00756 {
00757 bu_log( "Failed to calculate face plane equation\n" );
00758 bu_free( (char *)fu , "rt_arbn_tess: fu" );
00759 nmg_kr( *r );
00760 *r = (struct nmgregion *)NULL;
00761 return( -1 );
00762 }
00763 }
00764
00765 bu_free( (char *)fu , "rt_arbn_tess: fu" );
00766
00767 nmg_fix_normals( s , tol );
00768
00769 (void)nmg_mark_edges_real( &s->l.magic );
00770
00771
00772 nmg_region_a( *r, tol );
00773
00774 return( 0 );
00775
00776 fail:
00777 bu_free( (char *)pts , "rt_arbn_tess: pts" );
00778 bu_free( (char *)edges , "rt_arbn_tess: edges" );
00779 bu_free( (char *)edge_count , "rt_arbn_tess: edge_count" );
00780 bu_free( (char *)verts , "rt_arbn_tess: verts" );
00781 return( -1 );
00782 }
00783
00784
00785
00786
00787
00788
00789
00790 int
00791 rt_arbn_import(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
00792 {
00793 union record *rp;
00794 struct rt_arbn_internal *aip;
00795 register int i;
00796
00797 BU_CK_EXTERNAL( ep );
00798 rp = (union record *)ep->ext_buf;
00799 if( rp->u_id != DBID_ARBN ) {
00800 bu_log("rt_arbn_import: defective record, id=x%x\n", rp->u_id );
00801 return(-1);
00802 }
00803
00804 RT_CK_DB_INTERNAL( ip );
00805 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00806 ip->idb_type = ID_ARBN;
00807 ip->idb_meth = &rt_functab[ID_ARBN];
00808 ip->idb_ptr = bu_malloc( sizeof(struct rt_arbn_internal), "rt_arbn_internal");
00809 aip = (struct rt_arbn_internal *)ip->idb_ptr;
00810 aip->magic = RT_ARBN_INTERNAL_MAGIC;
00811 aip->neqn = bu_glong( rp->n.n_neqn );
00812 if( aip->neqn <= 0 ) return(-1);
00813 aip->eqn = (plane_t *)bu_malloc( aip->neqn*sizeof(plane_t), "arbn plane eqn[]");
00814
00815 ntohd( (unsigned char *)aip->eqn, (unsigned char *)(&rp[1]), aip->neqn*4 );
00816
00817
00818 # include "noalias.h"
00819 for( i=0; i < aip->neqn; i++ ) {
00820 point_t orig_pt;
00821 point_t pt;
00822 vect_t norm;
00823
00824
00825 VSCALE( orig_pt, aip->eqn[i], aip->eqn[i][3] );
00826
00827
00828 MAT4X3VEC( norm, mat, aip->eqn[i] );
00829 MAT4X3PNT( pt, mat, orig_pt );
00830
00831
00832 VUNITIZE( norm );
00833 VMOVE( aip->eqn[i], norm );
00834 aip->eqn[i][3] = VDOT( pt, norm );
00835 }
00836
00837 return(0);
00838 }
00839
00840
00841
00842
00843 int
00844 rt_arbn_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00845 {
00846 struct rt_arbn_internal *aip;
00847 union record *rec;
00848 int ngrans;
00849 double *sbuf;
00850 register double *sp;
00851 register int i;
00852
00853 RT_CK_DB_INTERNAL(ip);
00854 if( ip->idb_type != ID_ARBN ) return(-1);
00855 aip = (struct rt_arbn_internal *)ip->idb_ptr;
00856 RT_ARBN_CK_MAGIC(aip);
00857
00858 if( aip->neqn <= 0 ) return(-1);
00859
00860
00861
00862
00863
00864 ngrans = (aip->neqn * 8 * 4 + sizeof(union record)-1 ) /
00865 sizeof(union record);
00866
00867 BU_CK_EXTERNAL(ep);
00868 ep->ext_nbytes = (ngrans + 1) * sizeof(union record);
00869 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "arbn external");
00870 rec = (union record *)ep->ext_buf;
00871
00872 rec[0].n.n_id = DBID_ARBN;
00873 (void)bu_plong( rec[0].n.n_neqn, aip->neqn );
00874 (void)bu_plong( rec[0].n.n_grans, ngrans );
00875
00876
00877 sp = sbuf = (double *)bu_malloc(
00878 aip->neqn * sizeof(double) * 4, "arbn temp");
00879 for( i=0; i<aip->neqn; i++ ) {
00880
00881 *sp++ = aip->eqn[i][X];
00882 *sp++ = aip->eqn[i][Y];
00883 *sp++ = aip->eqn[i][Z];
00884 *sp++ = aip->eqn[i][3] * local2mm;
00885 }
00886
00887 htond( (unsigned char *)&rec[1], (unsigned char *)sbuf, aip->neqn * 4 );
00888
00889 bu_free( (char *)sbuf, "arbn temp" );
00890 return(0);
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900 int
00901 rt_arbn_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
00902 {
00903 struct rt_arbn_internal *aip;
00904 register int i;
00905 unsigned long neqn;
00906 int double_count;
00907 int byte_count;
00908
00909 BU_CK_EXTERNAL( ep );
00910
00911 neqn = bu_glong((unsigned char *)ep->ext_buf);
00912 double_count = neqn * ELEMENTS_PER_PLANE;
00913 byte_count = double_count * SIZEOF_NETWORK_DOUBLE;
00914
00915 BU_ASSERT_LONG(ep->ext_nbytes, ==, 4+ byte_count);
00916
00917 RT_CK_DB_INTERNAL( ip );
00918 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00919 ip->idb_type = ID_ARBN;
00920 ip->idb_meth = &rt_functab[ID_ARBN];
00921 ip->idb_ptr = bu_malloc( sizeof(struct rt_arbn_internal), "rt_arbn_internal");
00922
00923 aip = (struct rt_arbn_internal *)ip->idb_ptr;
00924 aip->magic = RT_ARBN_INTERNAL_MAGIC;
00925 aip->neqn = neqn;
00926 if (aip->neqn <= 0) return(-1);
00927 aip->eqn = (plane_t *)bu_malloc(byte_count, "arbn plane eqn[]");
00928
00929 ntohd((unsigned char *)aip->eqn, (unsigned char *)ep->ext_buf + 4, double_count);
00930
00931
00932 # include "noalias.h"
00933 if( mat && !bn_mat_is_identity( mat ) ) {
00934 for (i=0; i < aip->neqn; i++) {
00935 point_t orig_pt;
00936 point_t pt;
00937 vect_t norm;
00938
00939
00940 VSCALE( orig_pt, aip->eqn[i], aip->eqn[i][3] );
00941
00942
00943 MAT4X3VEC( norm, mat, aip->eqn[i] );
00944 MAT4X3PNT( pt, mat, orig_pt );
00945
00946
00947 VUNITIZE( norm );
00948 VMOVE( aip->eqn[i], norm );
00949 aip->eqn[i][3] = VDOT( pt, norm );
00950 }
00951 }
00952
00953 return(0);
00954 }
00955
00956
00957
00958
00959 int
00960 rt_arbn_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00961 {
00962 struct rt_arbn_internal *aip;
00963 register int i;
00964 fastf_t *vec;
00965 register fastf_t *sp;
00966 int double_count;
00967 int byte_count;
00968
00969 RT_CK_DB_INTERNAL(ip);
00970 if( ip->idb_type != ID_ARBN ) return(-1);
00971 aip = (struct rt_arbn_internal *)ip->idb_ptr;
00972 RT_ARBN_CK_MAGIC(aip);
00973
00974 if( aip->neqn <= 0 ) return(-1);
00975
00976 double_count = aip->neqn * ELEMENTS_PER_PLANE;
00977 byte_count = double_count * SIZEOF_NETWORK_DOUBLE;
00978
00979 BU_CK_EXTERNAL(ep);
00980 ep->ext_nbytes = 4 + byte_count;
00981 ep->ext_buf = (genptr_t)bu_malloc(ep->ext_nbytes, "arbn external");
00982
00983 (void)bu_plong((unsigned char *)ep->ext_buf, aip->neqn);
00984
00985
00986 sp = vec = (double *)bu_malloc(byte_count, "arbn temp");
00987 for (i=0; i<aip->neqn; i++) {
00988
00989 *sp++ = aip->eqn[i][X];
00990 *sp++ = aip->eqn[i][Y];
00991 *sp++ = aip->eqn[i][Z];
00992 *sp++ = aip->eqn[i][3] * local2mm;
00993 }
00994
00995
00996 htond((unsigned char *)ep->ext_buf + 4, (unsigned char *)vec, double_count);
00997
00998 bu_free((char *)vec, "arbn temp");
00999 return(0);
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010 int
01011 rt_arbn_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
01012 {
01013 register struct rt_arbn_internal *aip =
01014 (struct rt_arbn_internal *)ip->idb_ptr;
01015 char buf[256];
01016 int i;
01017
01018 RT_ARBN_CK_MAGIC(aip);
01019 sprintf(buf, "arbn bounded by %d planes\n", aip->neqn);
01020 bu_vls_strcat( str, buf );
01021
01022 if( !verbose ) return(0);
01023
01024 for( i=0; i < aip->neqn; i++ ) {
01025 sprintf(buf, "\t%d: (%g, %g, %g) %g\n",
01026 i,
01027 INTCLAMP(aip->eqn[i][X]),
01028 INTCLAMP(aip->eqn[i][Y]),
01029 INTCLAMP(aip->eqn[i][Z]),
01030 INTCLAMP(aip->eqn[i][3] * mm2local) );
01031 bu_vls_strcat( str, buf );
01032 }
01033 return(0);
01034 }
01035
01036
01037
01038
01039
01040
01041
01042 void
01043 rt_arbn_ifree(struct rt_db_internal *ip)
01044 {
01045 struct rt_arbn_internal *aip;
01046
01047 RT_CK_DB_INTERNAL(ip);
01048 aip = (struct rt_arbn_internal *)ip->idb_ptr;
01049 RT_ARBN_CK_MAGIC(aip);
01050
01051 if( aip->neqn > 0 )
01052 bu_free( (char *)aip->eqn, "rt_arbn_internal eqn[]");
01053 bu_free( (char *)aip, "rt_arbn_internal" );
01054
01055 ip->idb_ptr = (genptr_t)0;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070 int
01071 rt_arbn_tclget(Tcl_Interp *interp, const struct rt_db_internal *intern, const char *attr)
01072 {
01073 register struct rt_arbn_internal *arbn=(struct rt_arbn_internal *)intern->idb_ptr;
01074 Tcl_DString ds;
01075 struct bu_vls vls;
01076 int i;
01077
01078 RT_ARBN_CK_MAGIC( arbn );
01079
01080 Tcl_DStringInit( &ds );
01081 bu_vls_init( &vls );
01082
01083 if( attr == (char *)NULL ) {
01084 bu_vls_strcpy( &vls, "arbn" );
01085 bu_vls_printf( &vls, " N %d", arbn->neqn );
01086 for( i=0 ; i<arbn->neqn ; i++ ) {
01087 bu_vls_printf( &vls, " P%d {%.25g %.25g %.25g %.25g}", i,
01088 V4ARGS( arbn->eqn[i] ) );
01089 }
01090 }
01091 else if( !strcmp( attr, "N" ) )
01092 bu_vls_printf( &vls, "%d", arbn->neqn );
01093 else if( !strcmp( attr, "P" ) ) {
01094 for( i=0 ; i<arbn->neqn ; i++ ) {
01095 bu_vls_printf( &vls, " P%d {%.25g %.25g %.25g %.25g}", i,
01096 V4ARGS( arbn->eqn[i] ) );
01097 }
01098 }
01099 else if( attr[0] == 'P' ) {
01100 if( isdigit( attr[1] ) == 0 ) {
01101 Tcl_SetResult( interp, "ERROR: Illegal plane number\n",
01102 TCL_STATIC );
01103 bu_vls_free( &vls );
01104 return( TCL_ERROR );
01105 }
01106
01107 i = atoi( &attr[1] );
01108 if( i >= arbn->neqn || i < 0 ) {
01109 Tcl_SetResult( interp, "ERROR: Illegal plane number\n",
01110 TCL_STATIC );
01111 bu_vls_free( &vls );
01112 return( TCL_ERROR );
01113 }
01114
01115 bu_vls_printf( &vls, "%.25g %.25g %.25g %.25g", V4ARGS( arbn->eqn[i] ) );
01116 }
01117 else {
01118 Tcl_SetResult( interp,"ERROR: Unknown attribute, choices are N, P, or P#\n",
01119 TCL_STATIC );
01120 bu_vls_free( &vls );
01121 return( TCL_ERROR );
01122 }
01123
01124 Tcl_DStringAppend( &ds, bu_vls_addr( &vls ), -1 );
01125 Tcl_DStringResult( interp, &ds );
01126 Tcl_DStringFree( &ds );
01127 bu_vls_free( &vls );
01128 return( TCL_OK );
01129 }
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143 int
01144 rt_arbn_tcladjust(Tcl_Interp *interp, struct rt_db_internal *intern, int argc, char **argv)
01145 {
01146 struct rt_arbn_internal *arbn;
01147 unsigned char *c;
01148 int len;
01149 int i, j;
01150 fastf_t *new_planes;
01151 fastf_t *array;
01152
01153 RT_CK_DB_INTERNAL( intern );
01154
01155 arbn = (struct rt_arbn_internal *)intern->idb_ptr;
01156 RT_ARBN_CK_MAGIC( arbn );
01157
01158 while( argc >= 2 ) {
01159 if( !strcmp( argv[0], "N" ) ) {
01160 i = atoi( argv[1] );
01161 if( i == arbn->neqn )
01162 goto cont;
01163 if( i > 0 ) {
01164 arbn->eqn = (plane_t *)bu_realloc( arbn->eqn,
01165 i * sizeof( plane_t ),
01166 "arbn->eqn");
01167 for( j=arbn->neqn ; j<i ; j++ ) {
01168 VSETALLN( arbn->eqn[j], 0.0, 4 );
01169 }
01170 arbn->neqn = i;
01171 } else {
01172 Tcl_SetResult( interp,
01173 "ERROR: number of planes must be greater than 0\n",
01174 TCL_STATIC );
01175 }
01176 }
01177 else if( !strcmp( argv[0], "P" ) ) {
01178
01179 c = (unsigned char *)argv[1];
01180 while( *c != '\0' ) {
01181 if( *c == '{' || *c == '}' )
01182 *c = ' ';
01183 c++;
01184 }
01185 len = 0;
01186 (void)tcl_list_to_fastf_array( interp, argv[1], &new_planes, &len );
01187
01188 if( len%4 ) {
01189 Tcl_SetResult( interp,
01190 "ERROR: Incorrect number of plane coefficients\n",
01191 TCL_STATIC );
01192 if( len )
01193 bu_free( (char *)new_planes, "new_planes" );
01194 return( TCL_ERROR );
01195 }
01196 if( arbn->eqn )
01197 bu_free( (char *)arbn->eqn, "arbn->eqn" );
01198 arbn->eqn = (plane_t *)new_planes;
01199 arbn->neqn = len / 4;
01200 for( i=0 ; i<arbn->neqn ; i++ )
01201 VUNITIZE( arbn->eqn[i] );
01202 }
01203 else if( argv[0][0] == 'P' ) {
01204 if( argv[0][1] == '+' ) {
01205 i = arbn->neqn;
01206 arbn->neqn++;
01207 arbn->eqn = (plane_t *)bu_realloc( arbn->eqn,
01208 (arbn->neqn) * sizeof( plane_t ),
01209 "arbn->eqn" );
01210 }
01211 else if( isdigit( argv[0][1] ) ) {
01212 i = atoi( &argv[0][1] );
01213 } else {
01214 Tcl_SetResult( interp,
01215 "ERROR: illegal argument, choices are P, P#, P+, or N\n",
01216 TCL_STATIC );
01217 return( TCL_ERROR );
01218 }
01219 if( i < 0 || i >= arbn->neqn ) {
01220 Tcl_SetResult( interp,
01221 "ERROR: plane number out of range\n",
01222 TCL_STATIC );
01223 return( TCL_ERROR );
01224 }
01225 len = 4;
01226 array = (fastf_t *)&arbn->eqn[i];
01227 if( tcl_list_to_fastf_array( interp, argv[1],
01228 &array, &len ) != 4 ) {
01229 Tcl_SetResult( interp,
01230 "ERROR: incorrect number of coefficients for a plane\n",
01231 TCL_STATIC );
01232 return( TCL_ERROR );
01233 }
01234 VUNITIZE( arbn->eqn[i] );
01235 }
01236 else {
01237 Tcl_SetResult( interp,
01238 "ERROR: illegal argument, choices are P, P#, P+, or N\n",
01239 TCL_STATIC );
01240 return( TCL_ERROR );
01241 }
01242 cont:
01243 argc -= 2;
01244 argv += 2;
01245 }
01246 return( TCL_OK );
01247 }
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258