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
00040
00041
00042
00043
00044
00045
00046
00047
00048 #ifndef lint
00049 static const char RCScut[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/cut.c,v 14.11 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00050 #endif
00051
00052 #include "common.h"
00053
00054 #include <stdlib.h>
00055 #include <stdio.h>
00056 #include <math.h>
00057 #ifdef HAVE_STRING_H
00058 # include <string.h>
00059 #else
00060 # include <strings.h>
00061 #endif
00062
00063 #include "machine.h"
00064 #include "vmath.h"
00065 #include "raytrace.h"
00066 #include "nmg.h"
00067 #include "plot3.h"
00068 #include "./debug.h"
00069
00070
00071 HIDDEN int rt_ck_overlap BU_ARGS((const vect_t min,
00072 const vect_t max,
00073 const struct soltab *stp,
00074 const struct rt_i *rtip));
00075 HIDDEN int rt_ct_box BU_ARGS((struct rt_i *rtip,
00076 union cutter *cutp,
00077 int axis, double where, int force));
00078 HIDDEN void rt_ct_optim BU_ARGS((struct rt_i *rtip,
00079 union cutter *cutp, int depth));
00080 HIDDEN void rt_ct_free BU_ARGS((struct rt_i *rtip,
00081 union cutter *cutp));
00082 HIDDEN void rt_ct_release_storage BU_ARGS((union cutter *cutp));
00083
00084 HIDDEN void rt_ct_measure BU_ARGS((struct rt_i *rtip,
00085 union cutter *cutp, int depth));
00086 HIDDEN union cutter *rt_ct_get BU_ARGS((struct rt_i *rtip));
00087 void rt_plot_cut BU_ARGS((FILE *fp, struct rt_i *rtip,
00088 union cutter *cutp, int lvl));
00089
00090 BU_EXTERN(void rt_pr_cut_info, (const struct rt_i *rtip,
00091 const char *str));
00092 HIDDEN int rt_ct_old_assess(register union cutter *,
00093 register int,
00094 double *,
00095 double *);
00096
00097 #define AXIS(depth) ((depth)%3)
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 union cutter *
00111 rt_cut_one_axis(struct bu_ptbl *boxes, struct rt_i *rtip, int axis, int min, int max, struct nugridnode *nuginfop)
00112 {
00113 register struct soltab *stp;
00114 union cutter *box;
00115 int cur;
00116 int slice;
00117
00118 BU_CK_PTBL(boxes);
00119 RT_CK_RTI(rtip);
00120
00121 if( min == max ) {
00122
00123 slice = min;
00124 box = (union cutter *)bu_calloc( 1, sizeof(union cutter),
00125 "union cutter");
00126 box->bn.bn_type = CUT_BOXNODE;
00127 box->bn.bn_len = 0;
00128 box->bn.bn_maxlen = rtip->nsolids;
00129 box->bn.bn_list = (struct soltab **)bu_malloc(
00130 box->bn.bn_maxlen * sizeof(struct soltab *),
00131 "xbox boxnode []" );
00132 VMOVE( box->bn.bn_min, rtip->mdl_min );
00133 VMOVE( box->bn.bn_max, rtip->mdl_max );
00134 box->bn.bn_min[axis] = nuginfop->nu_axis[axis][slice].nu_spos;
00135 box->bn.bn_max[axis] = nuginfop->nu_axis[axis][slice].nu_epos;
00136 box->bn.bn_len = 0;
00137
00138
00139 RT_VISIT_ALL_SOLTABS_START( stp, rtip ) {
00140 RT_CHECK_SOLTAB(stp);
00141 if( !rt_ck_overlap( box->bn.bn_min, box->bn.bn_max,
00142 stp, rtip ) )
00143 continue;
00144 box->bn.bn_list[box->bn.bn_len++] = stp;
00145 } RT_VISIT_ALL_SOLTABS_END
00146
00147 bu_ptbl_ins( boxes, (long *)box );
00148 return box;
00149 }
00150
00151 cur = (min + max + 1) / 2;
00152
00153 box = (union cutter *)bu_calloc( 1, sizeof(union cutter),
00154 "union cutter");
00155 box->cn.cn_type = CUT_CUTNODE;
00156 box->cn.cn_axis = axis;
00157 box->cn.cn_point = nuginfop->nu_axis[axis][cur].nu_spos;
00158 box->cn.cn_l = rt_cut_one_axis( boxes, rtip, axis, min, cur-1, nuginfop );
00159 box->cn.cn_r = rt_cut_one_axis( boxes, rtip, axis, cur, max, nuginfop );
00160 return box;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170 void
00171 rt_cut_optimize_parallel(int cpu, genptr_t arg)
00172 {
00173 struct rt_i *rtip = (struct rt_i *)arg;
00174 union cutter *cp;
00175 int i;
00176
00177 RT_CK_RTI(rtip);
00178 for(;;) {
00179
00180 bu_semaphore_acquire( RT_SEM_WORKER );
00181 i = rtip->rti_cuts_waiting.end--;
00182 bu_semaphore_release( RT_SEM_WORKER );
00183 i -= 1;
00184
00185 if( i < 0 ) break;
00186
00187 cp = (union cutter *)BU_PTBL_GET( &rtip->rti_cuts_waiting, i );
00188
00189 rt_ct_optim( rtip, cp, Z );
00190 }
00191 }
00192
00193 #define CMP(_p1,_p2,_memb,_ind) \
00194 (*(const struct soltab **)(_p1))->_memb[_ind] < \
00195 (*(const struct soltab **)(_p2))->_memb[_ind] ? -1 : \
00196 (*(const struct soltab **)(_p1))->_memb[_ind] > \
00197 (*(const struct soltab **)(_p2))->_memb[_ind] ? 1 : 0
00198
00199
00200 HIDDEN int rt_projXmin_comp BU_ARGS((const void * p1, const void * p2));
00201 HIDDEN int rt_projXmax_comp BU_ARGS((const void * p1, const void * p2));
00202 HIDDEN int rt_projYmin_comp BU_ARGS((const void * p1, const void * p2));
00203 HIDDEN int rt_projYmax_comp BU_ARGS((const void * p1, const void * p2));
00204 HIDDEN int rt_projZmin_comp BU_ARGS((const void * p1, const void * p2));
00205 HIDDEN int rt_projZmax_comp BU_ARGS((const void * p1, const void * p2));
00206
00207 HIDDEN int
00208 rt_projXmin_comp(const void *p1, const void *p2)
00209 {
00210 return CMP(p1,p2,st_min,X);
00211 }
00212
00213 HIDDEN int
00214 rt_projXmax_comp(const void *p1, const void *p2)
00215 {
00216 return CMP(p1,p2,st_max,X);
00217 }
00218
00219 HIDDEN int
00220 rt_projYmin_comp(const void *p1, const void *p2)
00221 {
00222 return CMP(p1,p2,st_min,Y);
00223 }
00224
00225 HIDDEN int
00226 rt_projYmax_comp(const void *p1, const void *p2)
00227 {
00228 return CMP(p1,p2,st_max,Y);
00229 }
00230
00231 HIDDEN int
00232 rt_projZmin_comp(const void *p1, const void *p2)
00233 {
00234 return CMP(p1,p2,st_min,Z);
00235 }
00236
00237 HIDDEN int
00238 rt_projZmax_comp(const void *p1, const void *p2)
00239 {
00240 return CMP(p1,p2,st_max,Z);
00241 }
00242
00243 HIDDEN struct cmp_pair {
00244 int (*cmp_min) BU_ARGS((const void *, const void *));
00245 int (*cmp_max) BU_ARGS((const void *, const void *));
00246 } pairs[] = {
00247 { rt_projXmin_comp, rt_projXmax_comp },
00248 { rt_projYmin_comp, rt_projYmax_comp },
00249 { rt_projZmin_comp, rt_projZmax_comp }
00250 };
00251
00252
00253
00254
00255
00256
00257
00258
00259 void
00260 rt_nugrid_cut(register struct nugridnode *nugnp, register struct boxnode *fromp, struct rt_i *rtip, int just_collect_info, int depth)
00261 {
00262 #define USE_HIST 0
00263 #if USE_HIST
00264 struct bu_hist start_hist[3];
00265 struct bu_hist end_hist[3];
00266 #endif
00267 register struct soltab **stpp;
00268
00269 int nu_ncells;
00270 int nu_sol_per_cell;
00271 int nu_max_ncells;
00272 int pseudo_depth;
00273 register int i;
00274 int xp, yp, zp;
00275 vect_t xmin, xmax, ymin, ymax, zmin, zmax;
00276 struct boxnode nu_xbox, nu_ybox, nu_zbox;
00277
00278 if( nugnp->nu_type != CUT_NUGRIDNODE )
00279 rt_bomb( "rt_nugrid_cut: passed non-nugridnode" );
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 if( rtip->rti_nu_gfactor < 0.01 ||
00333 rtip->rti_nu_gfactor > 10*RT_NU_GFACTOR_DEFAULT ) {
00334 rtip->rti_nu_gfactor = RT_NU_GFACTOR_DEFAULT;
00335 bu_log(
00336 "rt_nugrid_cut: warning: rtip->rti_nu_gfactor not set, setting to %g\n",
00337 RT_NU_GFACTOR_DEFAULT );
00338 }
00339
00340 nu_ncells = (int)ceil( 2.0 + rtip->rti_nu_gfactor *
00341 pow( (double)fromp->bn_len, 1.0/3.0 ) );
00342 if( rtip->rti_nugrid_dimlimit > 0 &&
00343 nu_ncells > rtip->rti_nugrid_dimlimit )
00344 nu_ncells = rtip->rti_nugrid_dimlimit;
00345 nu_sol_per_cell = (fromp->bn_len + nu_ncells - 1) / nu_ncells;
00346 nu_max_ncells = 2*nu_ncells + 8;
00347 #if 0
00348 pseudo_depth = depth+(int)log((double)(nu_ncells*nu_ncells*nu_ncells));
00349 #else
00350 pseudo_depth = depth;
00351 #endif
00352
00353 if( RT_G_DEBUG&DEBUG_CUT )
00354 bu_log(
00355 "\nnu_ncells=%d, nu_sol_per_cell=%d, nu_max_ncells=%d\n",
00356 nu_ncells, nu_sol_per_cell, nu_max_ncells );
00357
00358 #if USE_HIST
00359 for( i=0; i<3; i++ ) {
00360 bu_hist_init( &start_hist[i],
00361 fromp->bn_min[i],
00362 fromp->bn_max[i],
00363 nu_ncells*100 );
00364 bu_hist_init( &end_hist[i],
00365 fromp->bn_min[i],
00366 fromp->bn_max[i],
00367 nu_ncells*100 );
00368 }
00369
00370
00371 for( i = 0, stpp = fromp->bn_list;
00372 i < fromp->bn_len;
00373 i++, stpp++ ) {
00374 register struct soltab *stp = *stpp;
00375 RT_CK_SOLTAB( stp );
00376 if( stp->st_aradius <= 0 ) continue;
00377 if( stp->st_aradius >= INFINITY ) continue;
00378 for( j=0; j<3; j++ ) {
00379 BU_HIST_TALLY( &start_hist[j],stp->st_min[j] );
00380 BU_HIST_TALLY( &end_hist[j], stp->st_max[j] );
00381 }
00382 }
00383 #endif
00384
00385
00386
00387 for( i=0; i<3; i++ )
00388 nugnp->nu_axis[i] = (struct nu_axis *)bu_malloc(
00389 nu_max_ncells*sizeof(struct nu_axis), "NUgrid axis" );
00390
00391 #if USE_HIST
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 for( i=0; i<3; i++ ) {
00406 fastf_t pos;
00407 int nstart = 0;
00408 int nend = 0;
00409 struct bu_hist *shp = &start_hist[i];
00410 struct bu_hist *ehp = &end_hist[i];
00411 int hindex = 0;
00412 int axi = 0;
00413
00414 if( shp->hg_min != ehp->hg_min )
00415 rt_bomb("cut_it: hg_min error\n");
00416 pos = shp->hg_min;
00417 nugnp->nu_axis[i][axi].nu_spos = pos;
00418 for( hindex = 0; hindex < shp->hg_nbins; hindex++ ) {
00419 if( pos > shp->hg_max ) break;
00420
00421
00422 nstart += shp->hg_bins[hindex];
00423 nend += ehp->hg_bins[hindex];
00424 pos += shp->hg_clumpsize;
00425 #if 1
00426 if( nstart < nu_sol_per_cell &&
00427 nend < nu_sol_per_cell ) continue;
00428 #else
00429 if( nstart + nend < 2 * nu_sol_per_cell )
00430 continue;
00431 #endif
00432
00433 nugnp->nu_axis[i][axi].nu_epos = pos;
00434 nugnp->nu_axis[i][axi].nu_width =
00435 pos - nugnp->nu_axis[i][axi].nu_spos;
00436 if( axi >= nu_max_ncells-1 ) {
00437 bu_log("NUgrid ran off end, axis=%d, axi=%d\n",
00438 i, axi);
00439 pos = shp->hg_max+1;
00440 break;
00441 }
00442 nugnp->nu_axis[i][++axi].nu_spos = pos;
00443 nstart = 0;
00444 nend = 0;
00445 }
00446
00447 nugnp->nu_axis[i][axi].nu_epos = pos;
00448 nugnp->nu_axis[i][axi].nu_width =
00449 pos - nugnp->nu_axis[i][axi].nu_spos;
00450 nugnp->nu_cells_per_axis[i] = axi+1;
00451 }
00452
00453
00454 for( i=0; i<3; i++ ) {
00455 bu_hist_free( &start_hist[i] );
00456 bu_hist_free( &end_hist[i] );
00457 }
00458 #else
00459 {
00460 struct soltab **list_min, **list_max;
00461 register struct soltab **l1, **l2;
00462 register int nstart, nend, axi, len = fromp->bn_len;
00463 register fastf_t pos;
00464
00465 list_min = (struct soltab **)bu_malloc( len *
00466 sizeof(struct soltab *),
00467 "min solid list" );
00468 list_max = (struct soltab **)bu_malloc( len *
00469 sizeof(struct soltab *),
00470 "max solid list" );
00471 bcopy( fromp->bn_list, list_min, len*sizeof(struct soltab *) );
00472 bcopy( fromp->bn_list, list_max, len*sizeof(struct soltab *) );
00473 for( i=0; i<3; i++ ) {
00474 qsort( (genptr_t)list_min, len,
00475 sizeof(struct soltab *), pairs[i].cmp_min );
00476 qsort( (genptr_t)list_max, len,
00477 sizeof(struct soltab *), pairs[i].cmp_max );
00478 nstart = nend = axi = 0;
00479 l1 = list_min;
00480 l2 = list_max;
00481
00482 pos = fromp->bn_min[i];
00483 nugnp->nu_axis[i][axi].nu_spos = pos;
00484
00485 while( l1-list_min < len ||
00486 l2-list_max < len ) {
00487 if( l2-list_max >= len ||
00488 (l1-list_min < len &&
00489 (*l1)->st_min[i] < (*l2)->st_max[i]) ) {
00490 pos = (*l1++)->st_min[i];
00491 ++nstart;
00492 } else {
00493 pos = (*l2++)->st_max[i];
00494 ++nend;
00495 }
00496
00497 #if 1
00498 if( nstart < nu_sol_per_cell &&
00499 nend < nu_sol_per_cell )
00500 #else
00501 if( nstart + nend < nu_sol_per_cell )
00502 #endif
00503 continue;
00504
00505
00506 if( pos <= nugnp->nu_axis[i][axi].nu_spos
00507 #if 1
00508 + 1.0
00509 #endif
00510 + rtip->rti_tol.dist )
00511 continue;
00512
00513
00514
00515 if( pos >= fromp->bn_max[i]
00516 #if 1
00517 - 1.0
00518 #endif
00519 - rtip->rti_tol.dist )
00520 continue;
00521
00522
00523 nugnp->nu_axis[i][axi].nu_epos = pos;
00524 nugnp->nu_axis[i][axi].nu_width =
00525 pos - nugnp->nu_axis[i][axi].nu_spos;
00526 if( axi >= nu_max_ncells-1 ) {
00527 bu_log(
00528 "NUgrid ran off end, axis=%d, axi=%d\n",
00529 i, axi);
00530 rt_bomb( "rt_nugrid_cut: NUgrid ran off end" );
00531 }
00532 nugnp->nu_axis[i][++axi].nu_spos = pos;
00533 nstart = 0;
00534 nend = 0;
00535 }
00536
00537 if( pos < fromp->bn_max[i] ) pos = fromp->bn_max[i];
00538 nugnp->nu_axis[i][axi].nu_epos = pos;
00539 nugnp->nu_axis[i][axi].nu_width =
00540 pos - nugnp->nu_axis[i][axi].nu_spos;
00541 nugnp->nu_cells_per_axis[i] = axi+1;
00542 }
00543 bu_free( (genptr_t)list_min, "solid list min sort" );
00544 bu_free( (genptr_t)list_max, "solid list max sort" );
00545 }
00546
00547 #endif
00548
00549 nugnp->nu_stepsize[X] = 1;
00550 nugnp->nu_stepsize[Y] = nugnp->nu_cells_per_axis[X] *
00551 nugnp->nu_stepsize[X];
00552 nugnp->nu_stepsize[Z] = nugnp->nu_cells_per_axis[Y] *
00553 nugnp->nu_stepsize[Y];
00554
00555
00556 if( RT_G_DEBUG&DEBUG_CUT ) for( i=0; i<3; i++ ) {
00557 register int j;
00558 bu_log( "NUgrid %c axis: %d cells\n", "XYZ*"[i],
00559 nugnp->nu_cells_per_axis[i] );
00560 for( j=0; j<nugnp->nu_cells_per_axis[i]; j++ ) {
00561 bu_log( " %g .. %g, w=%g\n",
00562 nugnp->nu_axis[i][j].nu_spos,
00563 nugnp->nu_axis[i][j].nu_epos,
00564 nugnp->nu_axis[i][j].nu_width );
00565 }
00566 }
00567
00568
00569
00570
00571 if( just_collect_info ) return;
00572
00573
00574 nugnp->nu_grid = (union cutter *)bu_malloc(
00575 nugnp->nu_cells_per_axis[X] *
00576 nugnp->nu_cells_per_axis[Y] *
00577 nugnp->nu_cells_per_axis[Z] * sizeof(union cutter),
00578 "3-D NUgrid union cutter []" );
00579 nu_xbox.bn_len = 0;
00580 nu_xbox.bn_maxlen = fromp->bn_len;
00581 nu_xbox.bn_list = (struct soltab **)bu_malloc(
00582 nu_xbox.bn_maxlen * sizeof(struct soltab *),
00583 "xbox boxnode []" );
00584 nu_ybox.bn_len = 0;
00585 nu_ybox.bn_maxlen = fromp->bn_len;
00586 nu_ybox.bn_list = (struct soltab **)bu_malloc(
00587 nu_ybox.bn_maxlen * sizeof(struct soltab *),
00588 "ybox boxnode []" );
00589 nu_zbox.bn_len = 0;
00590 nu_zbox.bn_maxlen = fromp->bn_len;
00591 nu_zbox.bn_list = (struct soltab **)bu_malloc(
00592 nu_zbox.bn_maxlen * sizeof(struct soltab *),
00593 "zbox boxnode []" );
00594
00595 for( xp = 0; xp < nugnp->nu_cells_per_axis[X]; xp++ ) {
00596 VMOVE( xmin, fromp->bn_min );
00597 VMOVE( xmax, fromp->bn_max );
00598 xmin[X] = nugnp->nu_axis[X][xp].nu_spos;
00599 xmax[X] = nugnp->nu_axis[X][xp].nu_epos;
00600 VMOVE( nu_xbox.bn_min, xmin );
00601 VMOVE( nu_xbox.bn_max, xmax );
00602 nu_xbox.bn_len = 0;
00603
00604
00605 for( i = 0, stpp = fromp->bn_list;
00606 i < fromp->bn_len;
00607 i++, stpp++ ) {
00608 if( !rt_ck_overlap( xmin, xmax, *stpp, rtip ) )
00609 continue;
00610 nu_xbox.bn_list[nu_xbox.bn_len++] = *stpp;
00611 }
00612
00613
00614 for( yp = 0; yp < nugnp->nu_cells_per_axis[Y]; yp++ ) {
00615 VMOVE( ymin, xmin );
00616 VMOVE( ymax, xmax );
00617 ymin[Y] = nugnp->nu_axis[Y][yp].nu_spos;
00618 ymax[Y] = nugnp->nu_axis[Y][yp].nu_epos;
00619 VMOVE( nu_ybox.bn_min, ymin );
00620 VMOVE( nu_ybox.bn_max, ymax );
00621 nu_ybox.bn_len = 0;
00622
00623 for( i=0; i<nu_xbox.bn_len; i++ ) {
00624 if( !rt_ck_overlap( ymin, ymax,
00625 nu_xbox.bn_list[i],
00626 rtip ) )
00627 continue;
00628 nu_ybox.bn_list[nu_ybox.bn_len++] =
00629 nu_xbox.bn_list[i];
00630 }
00631
00632
00633 for( zp = 0; zp < nugnp->nu_cells_per_axis[Z]; zp++ ) {
00634 register union cutter *cutp =
00635 &nugnp->nu_grid[
00636 zp*nugnp->nu_stepsize[Z] +
00637 yp*nugnp->nu_stepsize[Y] +
00638 xp*nugnp->nu_stepsize[X]];
00639
00640 VMOVE( zmin, ymin );
00641 VMOVE( zmax, ymax );
00642 zmin[Z] = nugnp->nu_axis[Z][zp].nu_spos;
00643 zmax[Z] = nugnp->nu_axis[Z][zp].nu_epos;
00644 cutp->cut_type = CUT_BOXNODE;
00645 VMOVE( cutp->bn.bn_min, zmin );
00646 VMOVE( cutp->bn.bn_max, zmax );
00647
00648
00649 nu_zbox.bn_len = 0;
00650
00651 for( i=0; i<nu_ybox.bn_len; i++ ) {
00652 if( !rt_ck_overlap( zmin, zmax,
00653 nu_ybox.bn_list[i],
00654 rtip ) )
00655 continue;
00656 nu_zbox.bn_list[nu_zbox.bn_len++] =
00657 nu_ybox.bn_list[i];
00658 }
00659
00660 if( nu_zbox.bn_len <= 0 ) {
00661
00662 cutp->bn.bn_list = (struct soltab **)0;
00663 cutp->bn.bn_len = 0;
00664 cutp->bn.bn_maxlen = 0;
00665 continue;
00666 }
00667
00668
00669
00670 cutp->bn.bn_list =
00671 (struct soltab **)bu_malloc(
00672 nu_zbox.bn_len *
00673 sizeof(struct soltab *),
00674 "NUgrid cell bn_list[]" );
00675 cutp->bn.bn_len = cutp->bn.bn_maxlen =
00676 nu_zbox.bn_len;
00677 bcopy( (char *)nu_zbox.bn_list,
00678 (char *)cutp->bn.bn_list,
00679 nu_zbox.bn_len *
00680 sizeof(struct soltab *) );
00681
00682 if( rtip->rti_nugrid_dimlimit > 0 ) {
00683 #if 1
00684 rt_ct_optim( rtip, cutp, pseudo_depth);
00685 #else
00686
00687
00688 if( cutp->bn.bn_len > 5 &&
00689 cutp->bn.bn_len < fromp->bn_len>>1 ) {
00690
00691
00692
00693 union cutter temp;
00694
00695 temp = *cutp;
00696 cutp->cut_type = CUT_NUGRIDNODE;
00697
00698 rt_nugrid_cut( &cutp->nugn,
00699 &temp.bn, rtip, 0,
00700 depth+1 );
00701 }
00702 #endif
00703 }
00704 }
00705 }
00706 }
00707
00708 bu_free( (genptr_t)nu_zbox.bn_list, "nu_zbox bn_list[]" );
00709 bu_free( (genptr_t)nu_ybox.bn_list, "nu_ybox bn_list[]" );
00710 bu_free( (genptr_t)nu_xbox.bn_list, "nu_xbox bn_list[]" );
00711 }
00712
00713 int
00714 rt_split_mostly_empty_cells( struct rt_i *rtip, union cutter *cutp )
00715 {
00716 point_t max, min;
00717 struct soltab *stp;
00718 struct rt_piecelist pl;
00719 fastf_t range[3], empty[3], tmp;
00720 int upper_or_lower[3];
00721 fastf_t max_empty;
00722 int max_empty_dir;
00723 int i;
00724 int num_splits=0;
00725
00726 switch( cutp->cut_type ) {
00727 case CUT_CUTNODE:
00728 num_splits += rt_split_mostly_empty_cells( rtip, cutp->cn.cn_l );
00729 num_splits += rt_split_mostly_empty_cells( rtip, cutp->cn.cn_r );
00730 break;
00731 case CUT_BOXNODE:
00732
00733 if( cutp->bn.bn_len == 0 && cutp->bn.bn_piecelen == 0 ) {
00734 break;
00735 }
00736 VSETALL( min, MAX_FASTF );
00737 VREVERSE( max, min );
00738
00739 for( i=0 ; i<cutp->bn.bn_len ; i++ ) {
00740 stp = cutp->bn.bn_list[i];
00741 VMIN( min, stp->st_min );
00742 VMAX( max, stp->st_max );
00743 }
00744
00745 for( i=0 ; i<cutp->bn.bn_piecelen ; i++ ) {
00746 int j;
00747
00748 pl = cutp->bn.bn_piecelist[i];
00749 for( j=0 ; j<pl.npieces ; j++ ) {
00750 int piecenum;
00751
00752 piecenum = pl.pieces[j];
00753 VMIN( min, pl.stp->st_piece_rpps[piecenum].min );
00754 VMAX( max, pl.stp->st_piece_rpps[piecenum].max );
00755 }
00756 }
00757
00758
00759 for( i=X ; i<=Z ; i++ ) {
00760 if( min[i] < cutp->bn.bn_min[i] ) {
00761 min[i] = cutp->bn.bn_min[i];
00762 }
00763 if( max[i] > cutp->bn.bn_max[i] ) {
00764 max[i] = cutp->bn.bn_max[i];
00765 }
00766 }
00767
00768
00769 VSUB2( range, cutp->bn.bn_max, cutp->bn.bn_min );
00770 for( i=X ; i<=Z ; i++ ) {
00771 empty[i] = cutp->bn.bn_max[i] - max[i];
00772 upper_or_lower[i] = 1;
00773 tmp = min[i] - cutp->bn.bn_min[i];
00774 if( tmp > empty[i] ) {
00775 empty[i] = tmp;
00776 upper_or_lower[i] = 0;
00777 }
00778 }
00779 max_empty = empty[X];
00780 max_empty_dir = X;
00781 if( empty[Y] > max_empty ) {
00782 max_empty = empty[Y];
00783 max_empty_dir = Y;
00784 }
00785 if( empty[Z] > max_empty ) {
00786 max_empty = empty[Z];
00787 max_empty_dir = Z;
00788 }
00789 if( max_empty / range[max_empty_dir] > 0.5 ) {
00790
00791
00792 fastf_t where;
00793
00794
00795 if( upper_or_lower[max_empty_dir] ) {
00796 where = max[max_empty_dir] + rtip->rti_tol.dist;
00797 if( where >= cutp->bn.bn_max[max_empty_dir] ) {
00798 return( num_splits );
00799 }
00800 } else {
00801 where = min[max_empty_dir] - rtip->rti_tol.dist;
00802 if( where <= cutp->bn.bn_min[max_empty_dir] ) {
00803 return( num_splits );
00804 }
00805 }
00806 if( where - cutp->bn.bn_min[max_empty_dir] < 2.0 ||
00807 cutp->bn.bn_max[max_empty_dir] - where < 2.0 ) {
00808
00809 return( num_splits );
00810 }
00811 if( rt_ct_box( rtip, cutp, max_empty_dir, where, 1 ) ) {
00812 num_splits++;
00813 num_splits += rt_split_mostly_empty_cells( rtip, cutp->cn.cn_l );
00814 num_splits += rt_split_mostly_empty_cells( rtip, cutp->cn.cn_r );
00815 }
00816 }
00817 break;
00818 }
00819
00820 return( num_splits );
00821 }
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 void
00836 rt_cut_it(register struct rt_i *rtip, int ncpu)
00837 {
00838 register struct soltab *stp;
00839 union cutter *finp;
00840 FILE *plotfp;
00841 int num_splits=0;
00842
00843
00844 BU_GETUNION( finp, cutter );
00845 finp->cut_type = CUT_BOXNODE;
00846 VMOVE( finp->bn.bn_min, rtip->mdl_min );
00847 VMOVE( finp->bn.bn_max, rtip->mdl_max );
00848 finp->bn.bn_len = 0;
00849 finp->bn.bn_maxlen = rtip->nsolids+1;
00850 finp->bn.bn_list = (struct soltab **)bu_malloc(
00851 finp->bn.bn_maxlen * sizeof(struct soltab *),
00852 "rt_cut_it: initial list alloc" );
00853
00854 rtip->rti_inf_box.cut_type = CUT_BOXNODE;
00855
00856 RT_VISIT_ALL_SOLTABS_START( stp, rtip ) {
00857
00858 if( stp->st_aradius <= 0 ) continue;
00859
00860
00861 rt_cut_extend( finp, stp, rtip );
00862
00863 if( stp->st_aradius >= INFINITY ) {
00864
00865 rt_cut_extend( &rtip->rti_inf_box, stp, rtip );
00866 }
00867 } RT_VISIT_ALL_SOLTABS_END
00868
00869
00870
00871
00872
00873 rtip->rti_cutlen = (int)log((double)rtip->nsolids);
00874 rtip->rti_cutdepth = 2 * rtip->rti_cutlen;
00875 if( rtip->rti_cutlen < 3 ) rtip->rti_cutlen = 3;
00876 if( rtip->rti_cutdepth < 12 ) rtip->rti_cutdepth = 12;
00877 if( rtip->rti_cutdepth > 24 ) rtip->rti_cutdepth = 24;
00878 if( RT_G_DEBUG&DEBUG_CUT )
00879 bu_log( "Before Space Partitioning: Max Tree Depth=%d, Cuttoff primitive count=%d\n",
00880 rtip->rti_cutdepth, rtip->rti_cutlen );
00881
00882 bu_ptbl_init( &rtip->rti_cuts_waiting, rtip->nsolids,
00883 "rti_cuts_waiting ptbl" );
00884
00885 if( rtip->rti_hasty_prep ) {
00886 rtip->rti_space_partition = RT_PART_NUBSPT;
00887 rtip->rti_cutdepth = 6;
00888 }
00889
00890 switch( rtip->rti_space_partition ) {
00891 case RT_PART_NUGRID:
00892 rtip->rti_CutHead.cut_type = CUT_NUGRIDNODE;
00893 rt_nugrid_cut( &rtip->rti_CutHead.nugn, &finp->bn, rtip, 0,0 );
00894 rt_fr_cut( rtip, finp );
00895 break;
00896 case RT_PART_NUBSPT: {
00897 #ifdef NEW_WAY
00898 struct nugridnode nuginfo;
00899
00900
00901
00902 nuginfo.nu_type = CUT_NUGRIDNODE;
00903 rt_nugrid_cut( &nuginfo, &fin_box, rtip, 1, 0 );
00904 #endif
00905 rtip->rti_CutHead = *finp;
00906 #ifdef NEW_WAY
00907 if( rtip->nsolids < 50000 ) {
00908 #endif
00909
00910
00911
00912
00913
00914
00915 rt_ct_optim( rtip, &rtip->rti_CutHead, 0 );
00916 #ifdef NEW_WAY
00917 } else {
00918
00919 XXX This hasnt been tested since massive
00920 NUgrid changes were made
00921
00922
00923 union cutter *head;
00924 int i;
00925
00926 head = rt_cut_one_axis( &rtip->rti_cuts_waiting, rtip,
00927 Y, 0, nuginfo.nu_cells_per_axis[Y]-1, &nuginfo );
00928 rtip->rti_CutHead = *head;
00929 bu_free( (char *)head, "union cutter" );
00930
00931 if(RT_G_DEBUG&DEBUG_CUTDETAIL) {
00932 for( i=0; i<3; i++ ) {
00933 bu_log("\nNUgrid %c axis: %d cells\n",
00934 "XYZ*"[i], nuginfo.nu_cells_per_axis[i] );
00935 }
00936 rt_pr_cut( &rtip->rti_CutHead, 0 );
00937 }
00938
00939 if( ncpu <= 1 ) {
00940 rt_cut_optimize_parallel(0, rtip);
00941 } else {
00942 bu_parallel( rt_cut_optimize_parallel, ncpu, rtip );
00943 }
00944 }
00945 #endif
00946
00947 num_splits = rt_split_mostly_empty_cells( rtip, &rtip->rti_CutHead );
00948
00949 if( RT_G_DEBUG&DEBUG_CUT ) {
00950 bu_log( "rt_split_mostly_empty_cells(): split %d cells\n", num_splits );
00951 }
00952
00953 break; }
00954 default:
00955 rt_bomb( "rt_cut_it: unknown space partitioning method\n" );
00956 }
00957
00958 bu_free( (genptr_t)finp, "finite solid box" );
00959
00960
00961
00962 bu_hist_init( &rtip->rti_hist_cellsize, 0.0, 400.0, 400 );
00963 bu_hist_init( &rtip->rti_hist_cell_pieces, 0.0, 400.0, 400 );
00964 bu_hist_init( &rtip->rti_hist_cutdepth, 0.0,
00965 (fastf_t)rtip->rti_cutdepth+1, rtip->rti_cutdepth+1 );
00966 bzero( rtip->rti_ncut_by_type, sizeof(rtip->rti_ncut_by_type) );
00967 rt_ct_measure( rtip, &rtip->rti_CutHead, 0 );
00968 if( RT_G_DEBUG&DEBUG_CUT ) {
00969 rt_pr_cut_info( rtip, "Cut" );
00970 }
00971
00972 if( RT_G_DEBUG&DEBUG_CUTDETAIL ) {
00973
00974 rt_pr_cut( &rtip->rti_CutHead, 0 );
00975 }
00976
00977 if( RT_G_DEBUG&DEBUG_PLOTBOX ) {
00978
00979 if( (plotfp=fopen("rtcut.plot", "w"))!=NULL ) {
00980 pdv_3space( plotfp, rtip->rti_pmin, rtip->rti_pmax );
00981
00982 rt_plot_cut( plotfp, rtip, &rtip->rti_CutHead, 0 );
00983 (void)fclose(plotfp);
00984 }
00985 }
00986 }
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 void
00998 rt_cut_extend(register union cutter *cutp, struct soltab *stp, const struct rt_i *rtip)
00999 {
01000 RT_CK_SOLTAB(stp);
01001 RT_CK_RTI(rtip);
01002
01003 BU_ASSERT( cutp->cut_type == CUT_BOXNODE );
01004
01005 if(RT_G_DEBUG&DEBUG_CUTDETAIL) {
01006 bu_log("rt_cut_extend(cutp=x%x) %s npieces=%d\n",
01007 cutp, stp->st_name, stp->st_npieces);
01008 }
01009
01010 if( stp->st_npieces > 0 ) {
01011 struct rt_piecelist *plp;
01012 register int i;
01013
01014 if( cutp->bn.bn_piecelist == NULL ) {
01015
01016 BU_ASSERT( rtip->nsolids > 0 );
01017 cutp->bn.bn_piecelist = (struct rt_piecelist *) bu_malloc(
01018 sizeof(struct rt_piecelist) * (rtip->nsolids + 2),
01019 "rt_ct_box bn_piecelist (root node)" );
01020 cutp->bn.bn_piecelen = 0;
01021 cutp->bn.bn_maxpiecelen = rtip->nsolids + 2;
01022 }
01023 plp = &cutp->bn.bn_piecelist[cutp->bn.bn_piecelen++];
01024 plp->magic = RT_PIECELIST_MAGIC;
01025 plp->stp = stp;
01026
01027
01028 plp->npieces = stp->st_npieces;
01029 plp->pieces = (long *)bu_malloc(
01030 sizeof(long) * plp->npieces,
01031 "pieces[]" );
01032 for( i = stp->st_npieces-1; i >= 0; i-- )
01033 plp->pieces[i] = i;
01034
01035 return;
01036 }
01037
01038
01039 if( cutp->bn.bn_len >= cutp->bn.bn_maxlen ) {
01040
01041 if( cutp->bn.bn_maxlen <= 0 ) {
01042
01043 if( rtip->rti_cutlen > rtip->nsolids )
01044 cutp->bn.bn_maxlen = rtip->rti_cutlen;
01045 else
01046 cutp->bn.bn_maxlen = rtip->nsolids + 2;
01047 cutp->bn.bn_list = (struct soltab **)bu_malloc(
01048 cutp->bn.bn_maxlen * sizeof(struct soltab *),
01049 "rt_cut_extend: initial list alloc" );
01050 } else {
01051 cutp->bn.bn_maxlen *= 8;
01052 cutp->bn.bn_list = (struct soltab **) bu_realloc(
01053 (genptr_t)cutp->bn.bn_list,
01054 sizeof(struct soltab *) * cutp->bn.bn_maxlen,
01055 "rt_cut_extend: list extend" );
01056 }
01057 }
01058 cutp->bn.bn_list[cutp->bn.bn_len++] = stp;
01059 }
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072 HIDDEN int
01073 rt_ct_plan(struct rt_i *rtip, union cutter *cutp, int depth)
01074 {
01075 int axis;
01076 int status[3];
01077 double where[3];
01078 double offcenter[3];
01079 int best;
01080 double bestoff;
01081
01082 RT_CK_RTI(rtip);
01083 for( axis = X; axis <= Z; axis++ ) {
01084 #if 0
01085
01086 status[axis] = rt_ct_assess(
01087 cutp, axis, &where[axis], &offcenter[axis] );
01088 #else
01089
01090 status[axis] = rt_ct_old_assess(
01091 cutp, axis, &where[axis], &offcenter[axis] );
01092 #endif
01093 }
01094
01095 for(;;) {
01096 best = -1;
01097 bestoff = INFINITY;
01098 for( axis = X; axis <= Z; axis++ ) {
01099 if( status[axis] <= 0 ) continue;
01100 if( offcenter[axis] >= bestoff ) continue;
01101
01102 best = axis;
01103 bestoff = offcenter[axis];
01104 }
01105
01106 if( best < 0 ) return(-1);
01107
01108 if( rt_ct_box( rtip, cutp, best, where[best], 0 ) > 0 )
01109 return(0);
01110
01111
01112
01113
01114
01115
01116 status[best] = 0;
01117 }
01118 }
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131 HIDDEN int
01132 rt_ct_assess(register union cutter *cutp, register int axis, double *where_p, double *offcenter_p)
01133 {
01134 register int i;
01135 register double val;
01136 register double where;
01137 register double offcenter;
01138 register double middle;
01139 register double left, right;
01140
01141 if( cutp->bn.bn_len <= 1 ) return(0);
01142
01143
01144
01145
01146
01147 if( (right=cutp->bn.bn_max[axis])-(left=cutp->bn.bn_min[axis]) <= 2.0 )
01148 return(0);
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 middle = (left + right) * 0.5;
01168 where = offcenter = INFINITY;
01169 for( i=0; i < cutp->bn.bn_len; i++ ) {
01170
01171 val = cutp->bn.bn_list[i]->st_min[axis];
01172 if( val > left && val < right ) {
01173 register double d;
01174 if( (d = val - middle) < 0 ) d = (-d);
01175 if( d < offcenter ) {
01176 offcenter = d;
01177 where = val;
01178 }
01179 }
01180
01181 val = cutp->bn.bn_list[i]->st_max[axis];
01182 if( val > left && val < right ) {
01183 register double d;
01184 if( (d = val - middle) < 0 ) d = (-d);
01185 if( d < offcenter ) {
01186 offcenter = d;
01187 where = val;
01188 }
01189 }
01190 }
01191 if( offcenter >= INFINITY )
01192 return(0);
01193 if( where <= left || where >= right )
01194 return(0);
01195
01196 if( where - left <= 1.0 || right - where <= 1.0 )
01197 return(0);
01198
01199 *where_p = where;
01200 *offcenter_p = offcenter;
01201 return(1);
01202 }
01203
01204 #define PIECE_BLOCK 512
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216 HIDDEN int
01217 rt_ct_populate_box(union cutter *outp, const union cutter *inp, struct rt_i *rtip)
01218 {
01219 register int i;
01220 int success = 0;
01221 const struct bn_tol *tol = &rtip->rti_tol;
01222
01223
01224 outp->bn.bn_len = 0;
01225 outp->bn.bn_maxlen = inp->bn.bn_len;
01226 if( outp->bn.bn_maxlen > 0 ) {
01227 outp->bn.bn_list = (struct soltab **) bu_malloc(
01228 sizeof(struct soltab *) * outp->bn.bn_maxlen,
01229 "bn_list" );
01230 for( i = inp->bn.bn_len-1; i >= 0; i-- ) {
01231 struct soltab *stp = inp->bn.bn_list[i];
01232 if( !rt_ck_overlap(outp->bn.bn_min, outp->bn.bn_max,
01233 stp, rtip))
01234 continue;
01235 outp->bn.bn_list[outp->bn.bn_len++] = stp;
01236 }
01237 if( outp->bn.bn_len < inp->bn.bn_len ) success = 1;
01238 } else {
01239 outp->bn.bn_list = (struct soltab **)NULL;
01240 }
01241
01242
01243 outp->bn.bn_piecelen = 0;
01244 if( inp->bn.bn_piecelen <= 0 ) {
01245 outp->bn.bn_piecelist = (struct rt_piecelist *)NULL;
01246 outp->bn.bn_maxpiecelen = 0;
01247 return success;
01248 }
01249
01250 outp->bn.bn_piecelist = (struct rt_piecelist *) bu_malloc(
01251 sizeof(struct rt_piecelist) * inp->bn.bn_piecelen,
01252 "rt_piecelist" );
01253 outp->bn.bn_maxpiecelen = inp->bn.bn_piecelen;
01254 #if 0
01255 for( i = inp->bn.bn_piecelen-1; i >= 0; i-- ) {
01256 struct rt_piecelist *plp = &inp->bn.bn_piecelist[i];
01257 struct soltab *stp = plp->stp;
01258 struct rt_piecelist *olp = &outp->bn.bn_piecelist[outp->bn.bn_piecelen];
01259 int j;
01260
01261 RT_CK_PIECELIST(plp);
01262 RT_CK_SOLTAB(stp);
01263 olp->pieces = (long *)bu_malloc(
01264 sizeof(long) * plp->npieces,
01265 "olp->pieces[]" );
01266 olp->npieces = 0;
01267
01268
01269 for( j = plp->npieces-1; j >= 0; j-- ) {
01270 long indx = plp->pieces[j];
01271 struct bound_rpp *rpp = &stp->st_piece_rpps[indx];
01272 if( !V3RPP_OVERLAP_TOL(
01273 outp->bn.bn_min, outp->bn.bn_max,
01274 rpp->min, rpp->max, tol) )
01275 continue;
01276 olp->pieces[olp->npieces++] = indx;
01277 }
01278 if( olp->npieces > 0 ) {
01279
01280 olp->magic = RT_PIECELIST_MAGIC;
01281 olp->stp = stp;
01282 outp->bn.bn_piecelen++;
01283 if( olp->npieces < plp->npieces ) success = 1;
01284 } else {
01285 bu_free( (char *)olp->pieces, "olp->pieces[]");
01286 olp->pieces = NULL;
01287 }
01288 }
01289
01290 #else
01291 for( i = inp->bn.bn_piecelen-1; i >= 0; i-- ) {
01292 struct rt_piecelist *plp = &inp->bn.bn_piecelist[i];
01293 struct soltab *stp = plp->stp;
01294 struct rt_piecelist *olp = &outp->bn.bn_piecelist[outp->bn.bn_piecelen];
01295 int j,k;
01296 long piece_list[PIECE_BLOCK];
01297 long piece_count=0;
01298 long *more_pieces=NULL;
01299 long more_piece_count=0;
01300 long more_piece_len=0;
01301
01302 RT_CK_PIECELIST(plp);
01303 RT_CK_SOLTAB(stp);
01304
01305
01306 for( j = plp->npieces-1; j >= 0; j-- ) {
01307 long indx = plp->pieces[j];
01308 struct bound_rpp *rpp = &stp->st_piece_rpps[indx];
01309 if( !V3RPP_OVERLAP_TOL(
01310 outp->bn.bn_min, outp->bn.bn_max,
01311 rpp->min, rpp->max, tol) )
01312 continue;
01313 if( piece_count < PIECE_BLOCK ) {
01314 piece_list[piece_count++] = indx;
01315 } else if( more_piece_count >= more_piece_len ) {
01316
01317 more_piece_len += PIECE_BLOCK;
01318 more_pieces = (long *)bu_realloc( more_pieces, more_piece_len * sizeof( long ),
01319 "more_pieces" );
01320 more_pieces[more_piece_count++] = indx;
01321 } else {
01322 more_pieces[more_piece_count++] = indx;
01323 }
01324 }
01325 olp->npieces = piece_count + more_piece_count;
01326 if( olp->npieces > 0 ) {
01327
01328 olp->magic = RT_PIECELIST_MAGIC;
01329 olp->stp = stp;
01330 outp->bn.bn_piecelen++;
01331 olp->pieces = (long *)bu_malloc( sizeof(long) * olp->npieces, "olp->pieces[]" );
01332 for( j=0 ; j<piece_count ; j++ ) {
01333 olp->pieces[j] = piece_list[j];
01334 }
01335 k = piece_count;
01336 for( j=0 ; j<more_piece_count ; j++ ) {
01337 olp->pieces[k++] = more_pieces[j];
01338 }
01339 if( more_pieces ) {
01340 bu_free( (char *)more_pieces, "more_pieces" );
01341 }
01342 if( olp->npieces < plp->npieces ) success = 1;
01343 } else {
01344 olp->pieces = NULL;
01345
01346 }
01347 }
01348 #endif
01349
01350 return success;
01351 }
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372 HIDDEN int
01373 rt_ct_box(struct rt_i *rtip, register union cutter *cutp, register int axis, double where, int force)
01374 {
01375 register union cutter *rhs, *lhs;
01376 int success = 0;
01377
01378 RT_CK_RTI(rtip);
01379 if(RT_G_DEBUG&DEBUG_CUTDETAIL) {
01380 bu_log("rt_ct_box(x%x, %c) %g .. %g .. %g\n",
01381 cutp, "XYZ345"[axis],
01382 cutp->bn.bn_min[axis],
01383 where,
01384 cutp->bn.bn_max[axis]);
01385 }
01386
01387
01388 lhs = rt_ct_get(rtip);
01389 lhs->bn.bn_type = CUT_BOXNODE;
01390 VMOVE( lhs->bn.bn_min, cutp->bn.bn_min );
01391 VMOVE( lhs->bn.bn_max, cutp->bn.bn_max );
01392 lhs->bn.bn_max[axis] = where;
01393
01394 success = rt_ct_populate_box( lhs, cutp, rtip );
01395
01396
01397 rhs = rt_ct_get(rtip);
01398 rhs->bn.bn_type = CUT_BOXNODE;
01399 VMOVE( rhs->bn.bn_min, cutp->bn.bn_min );
01400 VMOVE( rhs->bn.bn_max, cutp->bn.bn_max );
01401 rhs->bn.bn_min[axis] = where;
01402
01403 success += rt_ct_populate_box( rhs, cutp, rtip );
01404
01405
01406 if( success == 0 && !force ) {
01407
01408
01409
01410
01411 if(RT_G_DEBUG&DEBUG_CUTDETAIL) {
01412 static char axis_str[] = "XYZw";
01413 bu_log("rt_ct_box: no luck, len=%d, axis=%c\n",
01414 cutp->bn.bn_len, axis_str[axis] );
01415 }
01416 rt_ct_free( rtip, rhs );
01417 rt_ct_free( rtip, lhs );
01418 return(0);
01419 }
01420
01421
01422 rt_ct_release_storage( cutp );
01423
01424 cutp->cut_type = CUT_CUTNODE;
01425 cutp->cn.cn_axis = axis;
01426 cutp->cn.cn_point = where;
01427 cutp->cn.cn_l = lhs;
01428 cutp->cn.cn_r = rhs;
01429 return(1);
01430 }
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445 HIDDEN int
01446 rt_ck_overlap(register const fastf_t *min, register const fastf_t *max, register const struct soltab *stp, register const struct rt_i *rtip)
01447 {
01448 RT_CHECK_SOLTAB(stp);
01449 if( RT_G_DEBUG&DEBUG_BOXING ) {
01450 bu_log("rt_ck_overlap(%s)\n",stp->st_name);
01451 VPRINT(" box min", min);
01452 VPRINT(" sol min", stp->st_min);
01453 VPRINT(" box max", max);
01454 VPRINT(" sol max", stp->st_max);
01455 }
01456
01457 if( stp->st_aradius <= 0 ) return(0);
01458
01459
01460 if( stp->st_aradius < INFINITY ) {
01461 if( V3RPP_DISJOINT( stp->st_min, stp->st_max, min, max ) )
01462 goto fail;
01463 }
01464
01465
01466 if( rt_functab[stp->st_id].ft_classify( stp, min, max,
01467 &rtip->rti_tol ) == RT_CLASSIFY_OUTSIDE ) goto fail;
01468
01469 if( RT_G_DEBUG&DEBUG_BOXING ) bu_log("rt_ck_overlap: TRUE\n");
01470 return(1);
01471 fail:
01472 if( RT_G_DEBUG&DEBUG_BOXING ) bu_log("rt_ck_overlap: FALSE\n");
01473 return(0);
01474 }
01475
01476
01477
01478
01479
01480
01481 HIDDEN int
01482 rt_ct_piececount(const union cutter *cutp)
01483 {
01484 int i;
01485 int count;
01486
01487 BU_ASSERT( cutp->cut_type == CUT_BOXNODE );
01488
01489 count = cutp->bn.bn_len;
01490
01491 if( cutp->bn.bn_piecelen <= 0 ) return count;
01492
01493 for( i = cutp->bn.bn_piecelen-1; i >= 0; i-- ) {
01494 count += cutp->bn.bn_piecelist[i].npieces;
01495 }
01496 return count;
01497 }
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508 HIDDEN void
01509 rt_ct_optim(struct rt_i *rtip, register union cutter *cutp, int depth)
01510 {
01511 int oldlen;
01512
01513 if( cutp->cut_type == CUT_CUTNODE ) {
01514 rt_ct_optim( rtip, cutp->cn.cn_l, depth+1 );
01515 rt_ct_optim( rtip, cutp->cn.cn_r, depth+1 );
01516 return;
01517 }
01518 if( cutp->cut_type != CUT_BOXNODE ) {
01519 bu_log("rt_ct_optim: bad node x%x\n", cutp->cut_type);
01520 return;
01521 }
01522
01523 oldlen = rt_ct_piececount(cutp);
01524 if( RT_G_DEBUG&DEBUG_CUTDETAIL ) bu_log("rt_ct_optim( cutp=x%x, depth=%d ) piececount=%d\n", cutp, depth, oldlen);
01525
01526
01527
01528
01529 if( oldlen <= 1 )
01530 return;
01531 if( depth > rtip->rti_cutdepth ) return;
01532
01533
01534
01535 if( depth >= 6 && oldlen <= rtip->rti_cutlen )
01536 return;
01537 #if NEW_WAY
01538
01539
01540
01541
01542 if( rt_ct_plan( rtip, cutp, depth ) < 0 ) {
01543
01544 return;
01545 }
01546 #else
01547
01548 {
01549 int did_a_cut;
01550 int i;
01551 int axis;
01552 double where, offcenter;
01553
01554
01555
01556
01557
01558
01559
01560 axis = AXIS(depth);
01561 #if 1
01562 did_a_cut = 0;
01563 for( i=0 ; i<3 ; i++ ) {
01564 axis += i;
01565 if( axis > Z ) {
01566 axis = X;
01567 }
01568 if( cutp->bn.bn_max[axis]-cutp->bn.bn_min[axis] < 2.0 ) {
01569 continue;
01570 }
01571 if( rt_ct_old_assess( cutp, axis, &where, &offcenter ) <= 0 ) {
01572 continue;
01573 }
01574 if( rt_ct_box( rtip, cutp, axis, where, 0 ) == 0 ) {
01575 continue;
01576 } else {
01577 did_a_cut = 1;
01578 break;
01579 }
01580 }
01581
01582 if( !did_a_cut ) {
01583 return;
01584 }
01585 #else
01586 if( cutp->bn.bn_max[axis]-cutp->bn.bn_min[axis] < 2.0 )
01587 return;
01588 if( rt_ct_old_assess( cutp, axis, &where, &offcenter ) <= 0 )
01589 return;
01590 if( rt_ct_box( rtip, cutp, axis, where, 0 ) == 0 ) {
01591 if( rt_ct_old_assess( cutp, AXIS(depth+1), &where, &offcenter ) <= 0 )
01592 return;
01593 if( rt_ct_box( rtip, cutp, AXIS(depth+1), where, 0 ) == 0 )
01594 return;
01595 }
01596 #endif
01597 if( rt_ct_piececount(cutp->cn.cn_l) >= oldlen &&
01598 rt_ct_piececount(cutp->cn.cn_r) >= oldlen ) {
01599 if( RT_G_DEBUG&DEBUG_CUTDETAIL )
01600 bu_log("rt_ct_optim(cutp=x%x, depth=%d) oldlen=%d, lhs=%d, rhs=%d, hopeless\n",
01601 cutp, depth, oldlen,
01602 rt_ct_piececount(cutp->cn.cn_l),
01603 rt_ct_piececount(cutp->cn.cn_r) );
01604 return;
01605 }
01606 }
01607 #endif
01608
01609 rt_ct_optim( rtip, cutp->cn.cn_l, depth+1 );
01610 rt_ct_optim( rtip, cutp->cn.cn_r, depth+1 );
01611 }
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622 HIDDEN int
01623 rt_ct_old_assess(register union cutter *cutp, register int axis, double *where_p, double *offcenter_p)
01624 {
01625 double val;
01626 double offcenter;
01627 double where;
01628 double middle;
01629 double d;
01630 fastf_t max, min;
01631 register int i;
01632 register double left, right;
01633
01634 if(RT_G_DEBUG&DEBUG_CUTDETAIL)bu_log("rt_ct_old_assess(x%x, %c)\n",cutp,"XYZ345"[axis]);
01635
01636
01637 if( (right=cutp->bn.bn_max[axis])-(left=cutp->bn.bn_min[axis]) < 2.0 )
01638 return(0);
01639
01640
01641
01642
01643
01644
01645
01646
01647 min = MAX_FASTF;
01648 max = -min;
01649 where = left;
01650 middle = (left + right) * 0.5;
01651 offcenter = middle - where;
01652 for( i=0; i < cutp->bn.bn_len; i++ ) {
01653 val = cutp->bn.bn_list[i]->st_min[axis];
01654 if( val < min ) min = val;
01655 if( val > max ) max = val;
01656 d = val - middle;
01657 if( d < 0 ) d = (-d);
01658 if( d < offcenter ) {
01659 offcenter = d;
01660 where = val-0.1;
01661 }
01662 val = cutp->bn.bn_list[i]->st_max[axis];
01663 if( val < min ) min = val;
01664 if( val > max ) max = val;
01665 d = val - middle;
01666 if( d < 0 ) d = (-d);
01667 if( d < offcenter ) {
01668 offcenter = d;
01669 where = val+0.1;
01670 }
01671 }
01672
01673
01674 for( i = cutp->bn.bn_piecelen-1; i >= 0; i-- ) {
01675 struct rt_piecelist *plp = &cutp->bn.bn_piecelist[i];
01676 struct soltab *stp = plp->stp;
01677 int j;
01678
01679 RT_CK_PIECELIST(plp);
01680 for( j = plp->npieces-1; j >= 0; j-- ) {
01681 int indx = plp->pieces[j];
01682 struct bound_rpp *rpp = &stp->st_piece_rpps[indx];
01683
01684 val = rpp->min[axis];
01685 if( val < min ) min = val;
01686 if( val > max ) max = val;
01687 d = val - middle;
01688 if( d < 0 ) d = (-d);
01689 if( d < offcenter ) {
01690 offcenter = d;
01691 where = val-0.1;
01692 }
01693 val = rpp->max[axis];
01694 if( val < min ) min = val;
01695 if( val > max ) max = val;
01696 d = val - middle;
01697 if( d < 0 ) d = (-d);
01698 if( d < offcenter ) {
01699 offcenter = d;
01700 where = val+0.1;
01701 }
01702 }
01703 }
01704
01705 if(RT_G_DEBUG&DEBUG_CUTDETAIL)bu_log("rt_ct_old_assess() left=%g, where=%g, right=%g, offcenter=%g\n",
01706
01707 left, where, right, offcenter);
01708
01709 if( where < min || where > max ) {
01710
01711
01712
01713 where = (max + min) / 2.0;
01714 offcenter = where - middle;
01715 if( offcenter < 0 ) {
01716 offcenter = -offcenter;
01717 }
01718 }
01719
01720 if( where <= left || where >= right )
01721 return(0);
01722
01723 if( where - left <= 1.0 || right - where <= 1.0 )
01724 return(0);
01725
01726
01727 *where_p = where;
01728 *offcenter_p = offcenter;
01729 return(1);
01730 }
01731
01732
01733
01734
01735
01736
01737 HIDDEN union cutter *
01738 rt_ct_get(struct rt_i *rtip)
01739 {
01740 register union cutter *cutp;
01741
01742 RT_CK_RTI(rtip);
01743 bu_semaphore_acquire(RT_SEM_MODEL);
01744 if( !rtip->rti_busy_cutter_nodes.l.magic )
01745 bu_ptbl_init( &rtip->rti_busy_cutter_nodes, 128, "rti_busy_cutter_nodes" );
01746
01747 if( rtip->rti_CutFree == CUTTER_NULL ) {
01748 register int bytes;
01749
01750 bytes = bu_malloc_len_roundup(64*sizeof(union cutter));
01751 cutp = (union cutter *)bu_malloc(bytes," rt_ct_get");
01752
01753 bu_ptbl_ins( &rtip->rti_busy_cutter_nodes, (long *)cutp );
01754
01755 while( bytes >= sizeof(union cutter) ) {
01756 cutp->cut_forw = rtip->rti_CutFree;
01757 rtip->rti_CutFree = cutp++;
01758 bytes -= sizeof(union cutter);
01759 }
01760 }
01761 cutp = rtip->rti_CutFree;
01762 rtip->rti_CutFree = cutp->cut_forw;
01763 bu_semaphore_release(RT_SEM_MODEL);
01764
01765 cutp->cut_forw = CUTTER_NULL;
01766 return(cutp);
01767 }
01768
01769
01770
01771
01772
01773
01774 HIDDEN void
01775 rt_ct_release_storage(register union cutter *cutp)
01776 {
01777 int i;
01778
01779 switch( cutp->cut_type ) {
01780
01781 case CUT_CUTNODE:
01782 break;
01783
01784 case CUT_BOXNODE:
01785 if( cutp->bn.bn_list ) {
01786 bu_free( (char *)cutp->bn.bn_list, "bn_list[]");
01787 cutp->bn.bn_list = (struct soltab **)NULL;
01788 }
01789 cutp->bn.bn_len = 0;
01790 cutp->bn.bn_maxlen = 0;
01791
01792 if( cutp->bn.bn_piecelist ) {
01793 for( i=0 ; i<cutp->bn.bn_piecelen ; i++ ) {
01794 struct rt_piecelist *olp = &cutp->bn.bn_piecelist[i];
01795 if( olp->pieces ) {
01796 bu_free( (char *)olp->pieces, "olp->pieces" );
01797 }
01798 }
01799 bu_free( (char *)cutp->bn.bn_piecelist, "bn_piecelist[]" );
01800 cutp->bn.bn_piecelist = (struct rt_piecelist *)NULL;
01801 }
01802 cutp->bn.bn_piecelen = 0;
01803 cutp->bn.bn_maxpiecelen = 0;
01804 break;
01805
01806 case CUT_NUGRIDNODE:
01807 bu_free( (genptr_t)cutp->nugn.nu_grid, "NUGrid children" );
01808 cutp->nugn.nu_grid = NULL;
01809
01810 for( i=0; i<3; i++ ) {
01811 bu_free( (genptr_t)cutp->nugn.nu_axis[i],
01812 "NUGrid axis" );
01813 cutp->nugn.nu_axis[i] = NULL;
01814 }
01815 break;
01816
01817 default:
01818 bu_log("rt_ct_release_storage: Unknown type=x%x\n", cutp->cut_type );
01819 break;
01820 }
01821 }
01822
01823
01824
01825
01826
01827
01828 HIDDEN void
01829 rt_ct_free(struct rt_i *rtip, register union cutter *cutp)
01830 {
01831 RT_CK_RTI(rtip);
01832
01833 rt_ct_release_storage( cutp );
01834
01835
01836 bu_semaphore_acquire(RT_SEM_MODEL);
01837 cutp->cut_forw = rtip->rti_CutFree;
01838 rtip->rti_CutFree = cutp;
01839 bu_semaphore_release(RT_SEM_MODEL);
01840 }
01841
01842
01843
01844
01845
01846
01847 void
01848 rt_pr_cut(register const union cutter *cutp, int lvl)
01849
01850
01851 {
01852 register int i,j;
01853
01854 bu_log("%.8x ", cutp);
01855 for( i=lvl; i>0; i-- )
01856 bu_log(" ");
01857
01858 if( cutp == CUTTER_NULL ) {
01859 bu_log("Null???\n");
01860 return;
01861 }
01862
01863 switch( cutp->cut_type ) {
01864
01865 case CUT_CUTNODE:
01866 bu_log("CUT L %c < %f\n",
01867 "XYZ?"[cutp->cn.cn_axis],
01868 cutp->cn.cn_point );
01869 rt_pr_cut( cutp->cn.cn_l, lvl+1 );
01870
01871 bu_log("%.8x ", cutp);
01872 for( i=lvl; i>0; i-- )
01873 bu_log(" ");
01874 bu_log("CUT R %c >= %f\n",
01875 "XYZ?"[cutp->cn.cn_axis],
01876 cutp->cn.cn_point );
01877 rt_pr_cut( cutp->cn.cn_r, lvl+1 );
01878 return;
01879
01880 case CUT_BOXNODE:
01881 bu_log("BOX Contains %d prims (%d alloc), %d prims with pieces:\n",
01882 cutp->bn.bn_len, cutp->bn.bn_maxlen,
01883 cutp->bn.bn_piecelen );
01884 bu_log(" ");
01885 for( i=lvl; i>0; i-- )
01886 bu_log(" ");
01887 VPRINT(" min", cutp->bn.bn_min);
01888 bu_log(" ");
01889 for( i=lvl; i>0; i-- )
01890 bu_log(" ");
01891 VPRINT(" max", cutp->bn.bn_max);
01892
01893
01894 for( i=0; i < cutp->bn.bn_len; i++ ) {
01895 bu_log(" ");
01896 for( j=lvl; j>0; j-- )
01897 bu_log(" ");
01898 bu_log(" %s\n",
01899 cutp->bn.bn_list[i]->st_name);
01900 }
01901
01902
01903 for( i=0; i < cutp->bn.bn_piecelen; i++ ) {
01904 struct rt_piecelist *plp = &(cutp->bn.bn_piecelist[i]);
01905 struct soltab *stp;
01906 int j;
01907
01908 RT_CK_PIECELIST(plp);
01909 stp = plp->stp;
01910 RT_CK_SOLTAB(stp);
01911
01912 bu_log(" ");
01913 for( j=lvl; j>0; j-- )
01914 bu_log(" ");
01915 bu_log(" %s, %d pieces: ",
01916 stp->st_name, plp->npieces);
01917
01918
01919 for( j=0; j < plp->npieces; j++ ) {
01920 long indx = plp->pieces[j];
01921 bu_log("%ld, ", indx);
01922 }
01923 bu_log("\n");
01924 }
01925 return;
01926
01927 case CUT_NUGRIDNODE:
01928
01929 default:
01930 bu_log("Unknown type=x%x\n", cutp->cut_type );
01931 break;
01932 }
01933 return;
01934 }
01935
01936
01937
01938
01939
01940
01941
01942
01943 void
01944 rt_fr_cut(struct rt_i *rtip, register union cutter *cutp)
01945 {
01946 RT_CK_RTI(rtip);
01947 if( cutp == CUTTER_NULL ) {
01948 bu_log("rt_fr_cut NULL\n");
01949 return;
01950 }
01951
01952 switch( cutp->cut_type ) {
01953
01954 case CUT_CUTNODE:
01955 rt_fr_cut( rtip, cutp->cn.cn_l );
01956 rt_ct_free( rtip, cutp->cn.cn_l );
01957 cutp->cn.cn_l = CUTTER_NULL;
01958
01959 rt_fr_cut( rtip, cutp->cn.cn_r );
01960 rt_ct_free( rtip, cutp->cn.cn_r );
01961 cutp->cn.cn_r = CUTTER_NULL;
01962 return;
01963
01964 case CUT_BOXNODE:
01965 rt_ct_release_storage(cutp);
01966 return;
01967
01968 case CUT_NUGRIDNODE: {
01969 register int i;
01970 int len = cutp->nugn.nu_cells_per_axis[X] *
01971 cutp->nugn.nu_cells_per_axis[Y] *
01972 cutp->nugn.nu_cells_per_axis[Z];
01973 register union cutter *bp = cutp->nugn.nu_grid;
01974
01975 for( i = len-1; i >= 0; i-- ) {
01976 rt_fr_cut( rtip, bp );
01977 bp->cut_type = 7;
01978 bp++;
01979 }
01980
01981 rt_ct_release_storage(cutp);
01982 return; }
01983
01984 default:
01985 bu_log("rt_fr_cut: Unknown type=x%x\n", cutp->cut_type );
01986 break;
01987 }
01988 return;
01989 }
01990
01991
01992
01993
01994 HIDDEN void
01995 rt_plot_cut(FILE *fp, struct rt_i *rtip, register union cutter *cutp, int lvl)
01996 {
01997 RT_CK_RTI(rtip);
01998 switch( cutp->cut_type ) {
01999 case CUT_NUGRIDNODE: {
02000 union cutter *bp;
02001 int i, x, y, z;
02002 int xmax = cutp->nugn.nu_cells_per_axis[X],
02003 ymax = cutp->nugn.nu_cells_per_axis[Y],
02004 zmax = cutp->nugn.nu_cells_per_axis[Z];
02005 if( !cutp->nugn.nu_grid ) return;
02006
02007
02008
02009 for( i=0, bp=cutp->nugn.nu_grid; i < xmax*ymax*zmax; i++, bp++ ) {
02010 if( bp->cut_type != CUT_BOXNODE )
02011 rt_plot_cut( fp, rtip, bp, lvl );
02012 }
02013 pl_color( fp, 180, 180, 220 );
02014 --xmax; --ymax; --zmax;
02015
02016
02017 pd_3line( fp,
02018 cutp->nugn.nu_axis[X][0].nu_spos,
02019 cutp->nugn.nu_axis[Y][0].nu_spos,
02020 cutp->nugn.nu_axis[Z][0].nu_spos,
02021 cutp->nugn.nu_axis[X][0].nu_spos,
02022 cutp->nugn.nu_axis[Y][0].nu_spos,
02023 cutp->nugn.nu_axis[Z][zmax].nu_epos);
02024 for( y=0; y<=ymax; y++ ) {
02025 pd_3line( fp,
02026 cutp->nugn.nu_axis[X][0].nu_spos,
02027 cutp->nugn.nu_axis[Y][y].nu_epos,
02028 cutp->nugn.nu_axis[Z][0].nu_spos,
02029 cutp->nugn.nu_axis[X][0].nu_spos,
02030 cutp->nugn.nu_axis[Y][y].nu_epos,
02031 cutp->nugn.nu_axis[Z][zmax].nu_epos);
02032 }
02033 for( x=0; x<=xmax; x++ ) {
02034 pd_3line( fp,
02035 cutp->nugn.nu_axis[X][x].nu_epos,
02036 cutp->nugn.nu_axis[Y][0].nu_spos,
02037 cutp->nugn.nu_axis[Z][0].nu_spos,
02038 cutp->nugn.nu_axis[X][x].nu_epos,
02039 cutp->nugn.nu_axis[Y][0].nu_spos,
02040 cutp->nugn.nu_axis[Z][zmax].nu_epos);
02041 for( y=0; y<=ymax; y++ ) {
02042 pd_3line( fp,
02043 cutp->nugn.nu_axis[X][x].nu_epos,
02044 cutp->nugn.nu_axis[Y][y].nu_epos,
02045 cutp->nugn.nu_axis[Z][0].nu_spos,
02046 cutp->nugn.nu_axis[X][x].nu_epos,
02047 cutp->nugn.nu_axis[Y][y].nu_epos,
02048 cutp->nugn.nu_axis[Z][zmax].nu_epos);
02049 }
02050 }
02051
02052
02053 pd_3line( fp,
02054 cutp->nugn.nu_axis[X][0].nu_spos,
02055 cutp->nugn.nu_axis[Y][0].nu_spos,
02056 cutp->nugn.nu_axis[Z][0].nu_spos,
02057 cutp->nugn.nu_axis[X][xmax].nu_epos,
02058 cutp->nugn.nu_axis[Y][0].nu_spos,
02059 cutp->nugn.nu_axis[Z][0].nu_spos);
02060 for( z=0; z<=zmax; z++ ) {
02061 pd_3line( fp,
02062 cutp->nugn.nu_axis[X][0].nu_spos,
02063 cutp->nugn.nu_axis[Y][0].nu_spos,
02064 cutp->nugn.nu_axis[Z][z].nu_epos,
02065 cutp->nugn.nu_axis[X][zmax].nu_epos,
02066 cutp->nugn.nu_axis[Y][0].nu_spos,
02067 cutp->nugn.nu_axis[Z][z].nu_epos);
02068 }
02069 for( y=0; y<=ymax; y++ ) {
02070 pd_3line( fp,
02071 cutp->nugn.nu_axis[X][0].nu_spos,
02072 cutp->nugn.nu_axis[Y][y].nu_epos,
02073 cutp->nugn.nu_axis[Z][0].nu_spos,
02074 cutp->nugn.nu_axis[X][xmax].nu_epos,
02075 cutp->nugn.nu_axis[Y][y].nu_epos,
02076 cutp->nugn.nu_axis[Z][0].nu_spos);
02077 for( z=0; z<=zmax; z++ ) {
02078 pd_3line( fp,
02079 cutp->nugn.nu_axis[X][0].nu_spos,
02080 cutp->nugn.nu_axis[Y][y].nu_epos,
02081 cutp->nugn.nu_axis[Z][z].nu_epos,
02082 cutp->nugn.nu_axis[X][zmax].nu_epos,
02083 cutp->nugn.nu_axis[Y][y].nu_epos,
02084 cutp->nugn.nu_axis[Z][z].nu_epos);
02085 }
02086 }
02087
02088
02089 pd_3line( fp,
02090 cutp->nugn.nu_axis[X][0].nu_spos,
02091 cutp->nugn.nu_axis[Y][0].nu_spos,
02092 cutp->nugn.nu_axis[Z][0].nu_spos,
02093 cutp->nugn.nu_axis[X][0].nu_spos,
02094 cutp->nugn.nu_axis[Y][ymax].nu_epos,
02095 cutp->nugn.nu_axis[Z][0].nu_spos);
02096 for( z=0; z<=zmax; z++ ) {
02097 pd_3line( fp,
02098 cutp->nugn.nu_axis[X][0].nu_spos,
02099 cutp->nugn.nu_axis[Y][0].nu_spos,
02100 cutp->nugn.nu_axis[Z][z].nu_epos,
02101 cutp->nugn.nu_axis[X][0].nu_spos,
02102 cutp->nugn.nu_axis[Y][ymax].nu_epos,
02103 cutp->nugn.nu_axis[Z][z].nu_epos);
02104 }
02105 for( x=0; x<=xmax; x++ ) {
02106 pd_3line( fp,
02107 cutp->nugn.nu_axis[X][x].nu_epos,
02108 cutp->nugn.nu_axis[Y][0].nu_spos,
02109 cutp->nugn.nu_axis[Z][0].nu_spos,
02110 cutp->nugn.nu_axis[X][x].nu_epos,
02111 cutp->nugn.nu_axis[Y][ymax].nu_epos,
02112 cutp->nugn.nu_axis[Z][0].nu_spos);
02113 for( z=0; z<=zmax; z++ ) {
02114 pd_3line( fp,
02115 cutp->nugn.nu_axis[X][x].nu_epos,
02116 cutp->nugn.nu_axis[Y][0].nu_spos,
02117 cutp->nugn.nu_axis[Z][z].nu_epos,
02118 cutp->nugn.nu_axis[X][x].nu_epos,
02119 cutp->nugn.nu_axis[Y][ymax].nu_epos,
02120 cutp->nugn.nu_axis[Z][z].nu_epos);
02121 }
02122 }
02123
02124 return; }
02125 case CUT_CUTNODE:
02126 rt_plot_cut( fp, rtip, cutp->cn.cn_l, lvl+1 );
02127 rt_plot_cut( fp, rtip, cutp->cn.cn_r, lvl+1 );
02128 return;
02129 case CUT_BOXNODE:
02130
02131 pl_color( fp,
02132 (AXIS(lvl)==0)?255:0,
02133 (AXIS(lvl)==1)?255:0,
02134 (AXIS(lvl)==2)?255:0 );
02135 pdv_3box( fp, cutp->bn.bn_min, cutp->bn.bn_max );
02136 return;
02137 }
02138 return;
02139 }
02140
02141
02142
02143
02144
02145
02146
02147 HIDDEN void
02148 rt_ct_measure(register struct rt_i *rtip, register union cutter *cutp, int depth)
02149 {
02150 register int len;
02151
02152 RT_CK_RTI(rtip);
02153 switch( cutp->cut_type ) {
02154 case CUT_NUGRIDNODE: {
02155 register int i;
02156 register union cutter *bp;
02157 len = cutp->nugn.nu_cells_per_axis[X] *
02158 cutp->nugn.nu_cells_per_axis[Y] *
02159 cutp->nugn.nu_cells_per_axis[Z];
02160 rtip->rti_ncut_by_type[CUT_NUGRIDNODE]++;
02161 for( i=0, bp=cutp->nugn.nu_grid; i<len; i++, bp++ )
02162 rt_ct_measure( rtip, bp, depth+1 );
02163 return; }
02164 case CUT_CUTNODE:
02165 rtip->rti_ncut_by_type[CUT_CUTNODE]++;
02166 rt_ct_measure( rtip, cutp->cn.cn_l, len = (depth+1) );
02167 rt_ct_measure( rtip, cutp->cn.cn_r, len );
02168 return;
02169 case CUT_BOXNODE:
02170 rtip->rti_ncut_by_type[CUT_BOXNODE]++;
02171 rtip->rti_cut_totobj += (len = cutp->bn.bn_len);
02172 if( rtip->rti_cut_maxlen < len )
02173 rtip->rti_cut_maxlen = len;
02174 if( rtip->rti_cut_maxdepth < depth )
02175 rtip->rti_cut_maxdepth = depth;
02176 BU_HIST_TALLY( &rtip->rti_hist_cellsize, len );
02177 len = rt_ct_piececount( cutp ) - len;
02178 BU_HIST_TALLY( &rtip->rti_hist_cell_pieces, len );
02179 BU_HIST_TALLY( &rtip->rti_hist_cutdepth, depth );
02180 if( len == 0 ) {
02181 rtip->nempty_cells++;
02182 }
02183 return;
02184 default:
02185 bu_log("rt_ct_measure: bad node x%x\n", cutp->cut_type);
02186 return;
02187 }
02188 }
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199 void
02200 rt_cut_clean(struct rt_i *rtip)
02201 {
02202 genptr_t *p;
02203
02204 RT_CK_RTI(rtip);
02205
02206 if( rtip->rti_cuts_waiting.l.magic )
02207 bu_ptbl_free( &rtip->rti_cuts_waiting );
02208
02209
02210 rtip->rti_CutFree = CUTTER_NULL;
02211
02212 if( BU_LIST_UNINITIALIZED(&rtip->rti_busy_cutter_nodes.l) )
02213 return;
02214
02215
02216 for( BU_PTBL_FOR( p, (genptr_t *), &rtip->rti_busy_cutter_nodes ) ) {
02217 bu_free( *p, "rt_ct_get" );
02218 }
02219 bu_ptbl_free( &rtip->rti_busy_cutter_nodes );
02220 }
02221
02222
02223
02224
02225 void
02226 rt_pr_cut_info(const struct rt_i *rtip, const char *str)
02227 {
02228 const struct nugridnode *nugnp;
02229 int i;
02230
02231 RT_CK_RTI(rtip);
02232
02233 bu_log("%s %s: %d nu, %d cut, %d box (%d empty)\n",
02234 str,
02235 rtip->rti_space_partition == RT_PART_NUGRID ?
02236 "NUGrid" : "NUBSP",
02237 rtip->rti_ncut_by_type[CUT_NUGRIDNODE],
02238 rtip->rti_ncut_by_type[CUT_CUTNODE],
02239 rtip->rti_ncut_by_type[CUT_BOXNODE],
02240 rtip->nempty_cells );
02241 bu_log( "Cut: maxdepth=%d, nbins=%d, maxlen=%d, avg=%g\n",
02242 rtip->rti_cut_maxdepth,
02243 rtip->rti_ncut_by_type[CUT_BOXNODE],
02244 rtip->rti_cut_maxlen,
02245 ((double)rtip->rti_cut_totobj) /
02246 rtip->rti_ncut_by_type[CUT_BOXNODE] );
02247 bu_hist_pr( &rtip->rti_hist_cellsize,
02248 "cut_tree: Number of prims per leaf cell");
02249 bu_hist_pr( &rtip->rti_hist_cell_pieces,
02250 "cut_tree: Number of prim pieces per leaf cell");
02251 bu_hist_pr( &rtip->rti_hist_cutdepth,
02252 "cut_tree: Depth (height)");
02253
02254 switch( rtip->rti_space_partition ) {
02255 case RT_PART_NUGRID:
02256 nugnp = &rtip->rti_CutHead.nugn;
02257 if( nugnp->nu_type != CUT_NUGRIDNODE )
02258 bu_bomb( "rt_pr_cut_info: passed non-nugridnode" );
02259
02260 for( i=0; i<3; i++ ) {
02261 register int j;
02262 bu_log( "NUgrid %c axis: %d cells\n", "XYZ*"[i],
02263 nugnp->nu_cells_per_axis[i] );
02264 for( j=0; j<nugnp->nu_cells_per_axis[i]; j++ ) {
02265 bu_log( " %g .. %g, w=%g\n",
02266 nugnp->nu_axis[i][j].nu_spos,
02267 nugnp->nu_axis[i][j].nu_epos,
02268 nugnp->nu_axis[i][j].nu_width );
02269 }
02270 }
02271 break;
02272 case RT_PART_NUBSPT:
02273
02274 break;
02275 default:
02276 bu_bomb("rt_pr_cut_info() bad rti_space_partition\n");
02277 }
02278 }
02279
02280 void
02281 remove_from_bsp( struct soltab *stp, union cutter *cutp, struct bn_tol *tol )
02282 {
02283 int index;
02284 int i;
02285
02286 switch( cutp->cut_type ) {
02287 case CUT_BOXNODE:
02288 if( stp->st_npieces ) {
02289 int remove_count, new_count;
02290 struct rt_piecelist *new_piece_list;
02291
02292 index = 0;
02293 remove_count = 0;
02294 for( index=0 ; index<cutp->bn.bn_piecelen ; index++ ) {
02295 if( cutp->bn.bn_piecelist[index].stp == stp ) {
02296 remove_count++;
02297 }
02298 }
02299
02300 if( remove_count ) {
02301 new_count = cutp->bn.bn_piecelen - remove_count;
02302 if( new_count > 0 ) {
02303 new_piece_list = (struct rt_piecelist *)bu_calloc(
02304 new_count,
02305 sizeof( struct rt_piecelist ),
02306 "bn_piecelist" );
02307
02308 i = 0;
02309 for( index=0 ; index<cutp->bn.bn_piecelen ; index++ ) {
02310 if( cutp->bn.bn_piecelist[index].stp != stp ) {
02311 new_piece_list[i] = cutp->bn.bn_piecelist[index];
02312 i++;
02313 }
02314 }
02315 } else {
02316 new_count = 0;
02317 new_piece_list = NULL;
02318 }
02319
02320 for( index=0 ; index<cutp->bn.bn_piecelen ; index++ ) {
02321 if( cutp->bn.bn_piecelist[index].stp == stp ) {
02322 bu_free( cutp->bn.bn_piecelist[index].pieces, "pieces" );
02323 }
02324 }
02325 bu_free( cutp->bn.bn_piecelist, "piecelist" );
02326 cutp->bn.bn_piecelist = new_piece_list;
02327 cutp->bn.bn_piecelen = new_count;
02328 cutp->bn.bn_maxpiecelen = new_count;
02329 }
02330 } else {
02331 for( index=0 ; index < cutp->bn.bn_len ; index++ ) {
02332 if( cutp->bn.bn_list[index] == stp ) {
02333
02334 cutp->bn.bn_len--;
02335 for( i=index ; i < cutp->bn.bn_len ; i++ ) {
02336 cutp->bn.bn_list[i] = cutp->bn.bn_list[i+1];
02337 }
02338 return;
02339 }
02340 }
02341 }
02342 break;
02343 case CUT_CUTNODE:
02344 if( stp->st_min[cutp->cn.cn_axis] > cutp->cn.cn_point + tol->dist ) {
02345 remove_from_bsp( stp, cutp->cn.cn_r, tol );
02346 } else if( stp->st_max[cutp->cn.cn_axis] < cutp->cn.cn_point - tol->dist ) {
02347 remove_from_bsp( stp, cutp->cn.cn_l, tol );
02348 } else {
02349 remove_from_bsp( stp, cutp->cn.cn_r, tol );
02350 remove_from_bsp( stp, cutp->cn.cn_l, tol );
02351 }
02352 break;
02353 default:
02354 bu_log( "remove_from_bsp(): unrecognized cut type (%d) in BSP!!!\n" );
02355 bu_bomb( "remove_from_bsp(): unrecognized cut type in BSP!!!\n" );
02356 }
02357 }
02358
02359 #define PIECE_BLOCK 512
02360
02361 void
02362 insert_in_bsp( struct soltab *stp, union cutter *cutp )
02363 {
02364 int i,j;
02365
02366 switch( cutp->cut_type ) {
02367 case CUT_BOXNODE:
02368 if( stp->st_npieces == 0 ) {
02369
02370 if( cutp->bn.bn_len >= cutp->bn.bn_maxlen ) {
02371
02372 if( cutp->bn.bn_maxlen <= 0 ) {
02373
02374 cutp->bn.bn_maxlen = 5;
02375 cutp->bn.bn_list = (struct soltab **)bu_malloc(
02376 cutp->bn.bn_maxlen * sizeof(struct soltab *),
02377 "insert_in_bsp: initial list alloc" );
02378 } else {
02379 cutp->bn.bn_maxlen += 5;
02380 cutp->bn.bn_list = (struct soltab **) bu_realloc(
02381 (genptr_t)cutp->bn.bn_list,
02382 sizeof(struct soltab *) * cutp->bn.bn_maxlen,
02383 "insert_in_bsp: list extend" );
02384 }
02385 }
02386 cutp->bn.bn_list[cutp->bn.bn_len++] = stp;
02387
02388 } else {
02389
02390 long pieces[PIECE_BLOCK];
02391 long *more_pieces=NULL;
02392 long more_pieces_alloced=0;
02393 long more_pieces_count=0;
02394 long piece_count=0;
02395 struct rt_piecelist *plp;
02396
02397 for( i=0 ; i<stp->st_npieces ; i++ ) {
02398 struct bound_rpp *piece_rpp=&stp->st_piece_rpps[i];
02399 if( V3RPP_OVERLAP( piece_rpp->min, piece_rpp->max, cutp->bn.bn_min, cutp->bn.bn_max ) ) {
02400 if( piece_count < PIECE_BLOCK ) {
02401 pieces[piece_count++] = i;
02402 } else if( more_pieces_alloced == 0 ) {
02403 more_pieces_alloced = stp->st_npieces - PIECE_BLOCK;
02404 more_pieces = (long *)bu_malloc( sizeof( long ) * more_pieces_alloced,
02405 "more_pieces" );
02406 more_pieces[more_pieces_count++] = i;
02407 } else {
02408 more_pieces[more_pieces_count++] = i;
02409 }
02410 }
02411 }
02412
02413 if( cutp->bn.bn_piecelen >= cutp->bn.bn_maxpiecelen ) {
02414 cutp->bn.bn_piecelist = (struct rt_piecelist *)bu_realloc( cutp->bn.bn_piecelist,
02415 sizeof( struct rt_piecelist ) * (++cutp->bn.bn_maxpiecelen),
02416 "cutp->bn.bn_piecelist" );
02417 }
02418
02419 if( !piece_count ) {
02420 return;
02421 }
02422
02423 plp = &cutp->bn.bn_piecelist[cutp->bn.bn_piecelen++];
02424 plp->magic = RT_PIECELIST_MAGIC;
02425 plp->stp = stp;
02426 plp->npieces = piece_count + more_pieces_count;
02427 plp->pieces = (long *)bu_malloc( plp->npieces * sizeof( long ), "plp->pieces" );
02428 for( i=0 ; i<piece_count ; i++ ) {
02429 plp->pieces[i] = pieces[i];
02430 }
02431 j = piece_count;
02432 for( i=0 ; i<more_pieces_count ; i++ ) {
02433 plp->pieces[j++] = more_pieces[i];
02434 }
02435
02436 if( more_pieces ) {
02437 bu_free( (char *)more_pieces, "more_pieces" );
02438 }
02439 }
02440 break;
02441 case CUT_CUTNODE:
02442 if( stp->st_min[cutp->cn.cn_axis] >= cutp->cn.cn_point ) {
02443 insert_in_bsp( stp, cutp->cn.cn_r );
02444 } else if( stp->st_max[cutp->cn.cn_axis] < cutp->cn.cn_point ) {
02445 insert_in_bsp( stp, cutp->cn.cn_l );
02446 } else {
02447 insert_in_bsp( stp, cutp->cn.cn_r );
02448 insert_in_bsp( stp, cutp->cn.cn_l );
02449 }
02450 break;
02451 default:
02452 bu_log( "insert_in_bsp(): unrecognized cut type (%d) in BSP!!!\n" );
02453 bu_bomb( "insert_in_bsp(): unrecognized cut type in BSP!!!\n" );
02454 }
02455
02456 }
02457
02458 void
02459 fill_out_bsp( struct rt_i *rtip, union cutter *cutp, struct resource *resp, fastf_t bb[6] )
02460 {
02461 fastf_t bb2[6];
02462 int i, j;
02463
02464 switch( cutp->cut_type ) {
02465 case CUT_BOXNODE:
02466 j = 3;
02467 for( i=0 ; i<3 ; i++ ) {
02468 if( bb[i] >= INFINITY ) {
02469
02470 cutp->bn.bn_min[i] = rtip->mdl_min[i];
02471 }
02472 if( bb[j] <= -INFINITY ) {
02473
02474 cutp->bn.bn_max[i] = rtip->mdl_max[i];
02475 }
02476 j++;
02477 }
02478 break;
02479 case CUT_CUTNODE:
02480 VMOVE( bb2, bb );
02481 VMOVE( &bb2[3], &bb[3] );
02482 bb[cutp->cn.cn_axis] = cutp->cn.cn_point;
02483 fill_out_bsp( rtip, cutp->cn.cn_r, resp, bb );
02484 bb2[cutp->cn.cn_axis + 3] = cutp->cn.cn_point;
02485 fill_out_bsp( rtip, cutp->cn.cn_l, resp, bb2 );
02486 break;
02487 default:
02488 bu_log( "fill_out_bsp(): unrecognized cut type (%d) in BSP!!!\n" );
02489 bu_bomb( "fill_out_bsp(): unrecognized cut type in BSP!!!\n" );
02490 }
02491
02492 }
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502