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 #ifndef lint
00037 static const char rcs_ident[] = "$Header: /cvsroot/brlcad/brlcad/src/librt/nurb_trim.c,v 14.11 2006/09/16 02:04:25 lbutler Exp $";
00038 #endif
00039
00040 #include "common.h"
00041
00042
00043
00044 #include <stdio.h>
00045 #include <math.h>
00046
00047 #include "machine.h"
00048 #include "vmath.h"
00049 #include "raytrace.h"
00050 #include "nurb.h"
00051
00052 extern void rt_clip_cnurb(struct bu_list *plist, struct edge_g_cnurb *crv, fastf_t u, fastf_t v);
00053
00054 struct _interior_line {
00055 int axis;
00056 fastf_t o_dist;
00057 };
00058
00059 #define QUAD1 0
00060 #define QUAD2 1
00061 #define QUAD3 2
00062 #define QUAD4 3
00063
00064
00065 #define TRIM_OUT 0
00066 #define TRIM_IN 1
00067 #define TRIM_ON 2
00068
00069
00070
00071
00072
00073 #define CASE_A 0
00074 #define CASE_B 2
00075 #define CASE_C 3
00076
00077 int quad_table[16] = {
00078 0,0,0,0,0,3,0,3,0,2,3,3,0,3,3,3
00079 };
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 int
00090 rt_trim_case(struct edge_g_cnurb *trim, fastf_t u, fastf_t v)
00091 {
00092 int quadrant;
00093 int qstats;
00094 fastf_t * pts;
00095 int coords, rat;
00096 int i;
00097
00098 qstats = 0;
00099
00100 coords = RT_NURB_EXTRACT_COORDS(trim->pt_type);
00101 pts = trim->ctl_points;
00102 rat = RT_NURB_IS_PT_RATIONAL( trim->pt_type );
00103
00104
00105
00106
00107
00108 if( rat )
00109 for( i = 0; i < trim->c_size; i++)
00110 {
00111 if(pts[0]/pts[2] > u )
00112 quadrant = (pts[1]/pts[2] >= v)? QUAD1:QUAD4;
00113 else
00114 quadrant = (pts[1]/pts[2] >= v)? QUAD2:QUAD3;
00115
00116 qstats |= (1 << quadrant);
00117 pts += coords;
00118 }
00119 else
00120 for( i = 0; i < trim->c_size; i++)
00121 {
00122 if(pts[0] > u )
00123 quadrant = (pts[1] >= v)? QUAD1:QUAD4;
00124 else
00125 quadrant = (pts[1] >= v)? QUAD2:QUAD3;
00126
00127 qstats |= (1 << quadrant);
00128 pts += coords;
00129 }
00130
00131 return quad_table[qstats];
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141 int
00142 rt_process_caseb(struct edge_g_cnurb *trim, fastf_t u, fastf_t v)
00143 {
00144 int q1, q2;
00145 fastf_t * pts;
00146 int rat;
00147
00148 rat = RT_NURB_IS_PT_RATIONAL( trim->pt_type );
00149
00150 pts = trim->ctl_points;
00151
00152 if( rat)
00153 {
00154 if( pts[0]/pts[2] > u) q1 = (pts[1]/pts[2] >= v)?QUAD1:QUAD4;
00155 else q1 = (pts[1]/pts[2] >= v)?QUAD2:QUAD3;
00156
00157
00158 pts = trim->ctl_points + RT_NURB_EXTRACT_COORDS(trim->pt_type) *
00159 (trim->c_size -1);
00160 if( pts[0]/pts[2] > u) q2 = (pts[1]/pts[2] >= v)?QUAD1:QUAD4;
00161 else q2 = (pts[1]/pts[2] >= v)?QUAD2:QUAD3;
00162
00163 } else
00164 {
00165 if( pts[0] > u) q1 = (pts[1] >= v)?QUAD1:QUAD4;
00166 else q1 = (pts[1] >= v)?QUAD2:QUAD3;
00167
00168
00169 pts = trim->ctl_points +
00170 RT_NURB_EXTRACT_COORDS(trim->pt_type) *
00171 (trim->c_size -1);
00172 if( pts[0] > u) q2 = (pts[1] >= v)?QUAD1:QUAD4;
00173 else q2 = (pts[1] >= v)?QUAD2:QUAD3;
00174 }
00175
00176 if( q1 != q2 )
00177 return TRIM_IN;
00178 else
00179 return TRIM_OUT;
00180
00181 }
00182
00183
00184
00185 int
00186 rt_nurb_uv_dist(struct edge_g_cnurb *trim, fastf_t u, fastf_t v)
00187 {
00188
00189 fastf_t dist;
00190 fastf_t * ptr;
00191 int coords;
00192 int rat;
00193 fastf_t u2, v2;
00194
00195 ptr = trim->ctl_points;
00196 coords = RT_NURB_EXTRACT_COORDS(trim->pt_type);
00197 rat = RT_NURB_IS_PT_RATIONAL(trim->pt_type);
00198
00199 u2 = 0.0;
00200 v2 = 0.0;
00201
00202 if ( rat )
00203 {
00204 u2 = ptr[0]/ptr[2] - u; u2 *= u2;
00205 v2 = ptr[1]/ptr[2] - v; v2 *= v2;
00206 }
00207 else
00208 {
00209 u2 = ptr[0] - u; u2 *= u2;
00210 v2 = ptr[1] - v; v2 *= v2;
00211 }
00212
00213 dist = sqrt( u2 + v2);
00214 if ( NEAR_ZERO( dist, 1.0e-4) )
00215 return TRIM_ON;
00216
00217 ptr = trim->ctl_points + coords * (trim->c_size -1);
00218
00219 u2 = 0.0;
00220 v2 = 0.0;
00221
00222 if ( rat )
00223 {
00224 u2 = ptr[0]/ptr[2] - u; u2 *= u2;
00225 v2 = ptr[1]/ptr[2] - v; v2 *= v2;
00226 }
00227 else
00228 {
00229 u2 = ptr[0] - u; u2 *= u2;
00230 v2 = ptr[1] - v; v2 *= v2;
00231 }
00232
00233 dist = sqrt( u2 + v2);
00234 if ( NEAR_ZERO( dist, 1.0e-4) )
00235 return TRIM_ON;
00236
00237 return TRIM_OUT;
00238
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 int
00257 rt_process_casec(struct edge_g_cnurb *trim, fastf_t u, fastf_t v)
00258 {
00259
00260 struct edge_g_cnurb * clip;
00261 int jordan_hit;
00262 struct bu_list plist;
00263 int trim_flag = 0;
00264 int caset;
00265
00266
00267
00268 if( rt_nurb_uv_dist(trim, u, v) == TRIM_ON) return TRIM_IN;
00269
00270 jordan_hit = 0;
00271
00272 BU_LIST_INIT(&plist);
00273
00274 if( nurb_crv_is_bezier( trim ) )
00275 rt_clip_cnurb(&plist, trim, u, v);
00276 else
00277 nurb_c_to_bezier( &plist, trim );
00278
00279 while( BU_LIST_WHILE( clip, edge_g_cnurb, &plist ) )
00280 {
00281 BU_LIST_DEQUEUE( &clip->l );
00282
00283 caset = rt_trim_case(clip, u,v);
00284
00285 trim_flag = 0;
00286
00287 if( caset == CASE_B)
00288 trim_flag = rt_process_caseb(clip, u, v);
00289 if( caset == CASE_C)
00290 trim_flag = rt_process_casec(clip, u, v);
00291
00292 rt_nurb_free_cnurb( clip );
00293
00294 if( trim_flag == TRIM_IN) jordan_hit++;
00295 if( trim_flag == TRIM_ON) break;
00296 }
00297
00298 while( BU_LIST_WHILE( clip, edge_g_cnurb, &plist) )
00299 {
00300 BU_LIST_DEQUEUE( &clip->l );
00301 rt_nurb_free_cnurb( clip );
00302 }
00303
00304 if( trim_flag == TRIM_ON)
00305 return TRIM_ON;
00306
00307 else if( jordan_hit & 01 )
00308 return TRIM_IN;
00309 else
00310 return TRIM_OUT;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 int
00324 rt_uv_in_trim(struct edge_g_cnurb *trim, fastf_t u, fastf_t v)
00325 {
00326
00327 int quad_case;
00328
00329 quad_case = rt_trim_case( trim, u, v);
00330
00331
00332 if( quad_case == CASE_A )
00333 return TRIM_OUT;
00334 if( quad_case == CASE_B )
00335 return rt_process_caseb(trim, u, v);
00336 if( quad_case == CASE_C )
00337 return rt_process_casec(trim, u, v);
00338
00339 bu_log( "rt_uv_in_trim: rt_trim_case() returned illegal value %d\n", quad_case );
00340 return( -1 );
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 fastf_t
00354 rt_trim_line_pt_dist(struct _interior_line *l, fastf_t *pt, int pt_type)
00355 {
00356 fastf_t h;
00357 int h_flag;
00358
00359 h_flag = RT_NURB_IS_PT_RATIONAL(pt_type);
00360
00361 if( l->axis == 0)
00362 {
00363 if( h_flag) h = (pt[1] / pt[2] - l->o_dist) * pt[2];
00364 else h = pt[1] - l->o_dist;
00365
00366 } else
00367 {
00368 if( h_flag) h = (pt[0] / pt[2] - l->o_dist) * pt[2];
00369 else h = pt[0] - l->o_dist;
00370
00371 }
00372
00373 return h;
00374 }
00375
00376
00377 int
00378 _SIGN(fastf_t f)
00379 {
00380 if (f < 0.0)
00381 return -1;
00382 else
00383 return 1;
00384
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 void
00401 rt_clip_cnurb(struct bu_list *plist, struct edge_g_cnurb *crv, fastf_t u, fastf_t v)
00402 {
00403 fastf_t ds1, dt1;
00404 struct _interior_line s_line, t_line;
00405 int axis, i;
00406 fastf_t umin, umax;
00407 int coords;
00408 struct edge_g_cnurb * c1, *c2, *tmp;
00409 fastf_t m1, m2;
00410 int zero_changed;
00411 fastf_t *ptr;
00412 fastf_t dist[10];
00413
00414 coords = RT_NURB_EXTRACT_COORDS( crv->pt_type);
00415
00416 s_line.axis = 0; s_line.o_dist = v;
00417 t_line.axis = 1; t_line.o_dist = u;
00418
00419 ds1 = 0.0;
00420 dt1 = 0.0;
00421
00422 ptr = crv->ctl_points;
00423
00424
00425
00426
00427 for( i = 0; i < crv->c_size; i++, ptr += coords)
00428 {
00429 ds1 +=
00430 fabs( rt_trim_line_pt_dist( &s_line, ptr, crv->pt_type) );
00431 dt1 +=
00432 fabs( rt_trim_line_pt_dist( &t_line, ptr, crv->pt_type) );
00433 }
00434
00435 if( ds1 >= dt1 ) axis = 0; else axis = 1;
00436
00437 ptr = crv->ctl_points;
00438
00439 for( i = 0; i < crv->c_size; i++)
00440 {
00441 if( axis == 1)
00442 dist[i] = rt_trim_line_pt_dist(&t_line, ptr, crv->pt_type);
00443 else
00444 dist[i] = rt_trim_line_pt_dist(&s_line, ptr, crv->pt_type);
00445
00446 ptr += coords;
00447 }
00448
00449
00450
00451
00452
00453
00454 umin = 10e40;
00455 umax = -10e40;
00456 zero_changed = 0;
00457
00458 for( i = 0; i < crv->c_size; i++)
00459 {
00460 fastf_t d1, d2;
00461 fastf_t x0, x1, zero;
00462
00463 if ( i == (crv->c_size -1 ) )
00464 {
00465 d1 = dist[i];
00466 d2 = dist[0];
00467 x0 = (fastf_t) i / (fastf_t) (crv->c_size - 1);
00468 x1 = 0.0;
00469 } else
00470 {
00471 d1 = dist[i];
00472 d2 = dist[i+1];
00473 x0 = (fastf_t) i / (fastf_t) (crv->c_size - 1 );
00474 x1 = (i+1.0) / (crv->c_size - 1);
00475 }
00476
00477 if( _SIGN(d1) != _SIGN(d2) )
00478 {
00479 zero = x0 - d1 * (x1 - x0)/ (d2-d1);
00480 if( zero <= umin)
00481 umin = zero * .99;
00482 if( zero >= umax)
00483 umax = zero * .99 + .01;
00484 zero_changed = 1;
00485 }
00486 }
00487
00488 if( !zero_changed)
00489 return;
00490
00491
00492
00493 if( umax - umin < .2)
00494 {
00495 umin = .3; umax = .6;
00496 }
00497
00498
00499
00500 m1 = (crv->k.knots[0] * (1 - umin)) +
00501 crv->k.knots[crv->k.k_size -1] * umin;
00502
00503 m2 = (crv->k.knots[0] * (1-umax)) +
00504 crv->k.knots[crv->k.k_size -1] * umax;
00505
00506
00507 c1 = (struct edge_g_cnurb *) rt_nurb_c_xsplit(crv, m1);
00508 c2 = rt_nurb_c_xsplit((struct edge_g_cnurb *) c1->l.forw, m2);
00509
00510 tmp = (struct edge_g_cnurb *) c1->l.forw;
00511 BU_LIST_DEQUEUE( &tmp->l);
00512 rt_nurb_free_cnurb( tmp );
00513
00514 BU_LIST_INIT( plist );
00515 BU_LIST_INSERT( &c2->l, plist);
00516 BU_LIST_APPEND( plist, &c1->l);
00517 }
00518
00519
00520
00521 int
00522 nmg_uv_in_lu(const fastf_t u, const fastf_t v, const struct loopuse *lu)
00523 {
00524 struct edgeuse *eu;
00525 int crossings=0;
00526
00527 NMG_CK_LOOPUSE( lu );
00528
00529 if( BU_LIST_FIRST_MAGIC( &lu->down_hd ) != NMG_EDGEUSE_MAGIC )
00530 return( 0 );
00531
00532 for( BU_LIST_FOR( eu, edgeuse, &lu->down_hd ) )
00533 {
00534 struct edge_g_cnurb *eg;
00535
00536 if( !eu->g.magic_p )
00537 {
00538 bu_log( "nmg_uv_in_lu: eu (x%x) has no geometry!!!\n", eu );
00539 bu_bomb( "nmg_uv_in_lu: eu has no geometry!!!\n" );
00540 }
00541
00542 if( *eu->g.magic_p != NMG_EDGE_G_CNURB_MAGIC )
00543 {
00544 bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing eu (x%x) that is not CNURB!!!!\n",
00545 lu, eu );
00546 bu_bomb( "nmg_uv_in_lu: Called with lu containing eu that is not CNURB!!!\n" );
00547 }
00548
00549 eg = eu->g.cnurb_p;
00550
00551 if( eg->order <= 0 )
00552 {
00553 struct vertexuse *vu1, *vu2;
00554 struct vertexuse_a_cnurb *vua1, *vua2;
00555 point_t uv1, uv2;
00556 fastf_t slope, intersept;
00557 fastf_t u_on_curve;
00558
00559 vu1 = eu->vu_p;
00560 vu2 = eu->eumate_p->vu_p;
00561
00562 if( !vu1->a.magic_p || !vu2->a.magic_p )
00563 {
00564 bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing vu with no attribute!!!!\n",
00565 lu );
00566 bu_bomb( "nmg_uv_in_lu: Called with lu containing vu with no attribute!!!\n" );
00567 }
00568
00569 if( *vu1->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC ||
00570 *vu2->a.magic_p != NMG_VERTEXUSE_A_CNURB_MAGIC )
00571 {
00572 bu_log( "nmg_uv_in_lu: Called with lu (x%x) containing vu that is not CNURB!!!!\n",
00573 lu );
00574 bu_bomb( "nmg_uv_in_lu: Called with lu containing vu that is not CNURB!!!\n" );
00575 }
00576
00577 vua1 = vu1->a.cnurb_p;
00578 vua2 = vu2->a.cnurb_p;
00579
00580 VMOVE( uv1, vua1->param );
00581 VMOVE( uv2, vua2->param );
00582
00583 if( RT_NURB_IS_PT_RATIONAL( eg->pt_type ) )
00584 {
00585 uv1[0] /= uv1[2];
00586 uv1[1] /= uv1[2];
00587 uv2[0] /= uv2[2];
00588 uv2[1] /= uv2[2];
00589 }
00590
00591 if( uv1[1] < v && uv2[1] < v )
00592 continue;
00593 if( uv1[1] > v && uv2[1] > v )
00594 continue;
00595 if( uv1[0] <= u && uv2[0] <= u )
00596 continue;
00597 if( uv1[0] == uv2[0] )
00598 {
00599 if( (uv1[1] <= v && uv2[1] >= v) ||
00600 (uv2[1] <= v && uv1[1] >= v) )
00601 crossings++;
00602
00603 continue;
00604 }
00605
00606
00607 slope = (uv1[1] - uv2[1])/(uv1[0] - uv2[0]);
00608 intersept = uv1[1] - slope * uv1[0];
00609 u_on_curve = (v - intersept)/slope;
00610 if( u_on_curve > u )
00611 crossings++;
00612 }
00613 else
00614 crossings += rt_uv_in_trim( eg, u, v );
00615 }
00616
00617 if( crossings & 01 )
00618 return( 1 );
00619 else
00620 return( 0 );
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631