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 #include "common.h"
00040
00041
00042
00043 #include <stdio.h>
00044 #include "machine.h"
00045 #include "vmath.h"
00046 #include "nmg.h"
00047 #include "raytrace.h"
00048 #include "nurb.h"
00049 #include "../librt/debug.h"
00050
00051
00052 void rt_nurb_pbound(struct face_g_snurb *srf, fastf_t *vmin, fastf_t *vmax);
00053
00054 struct face_g_snurb *
00055 rt_nurb_project_srf(const struct face_g_snurb *srf, fastf_t *plane1, fastf_t *plane2, struct resource *res)
00056 {
00057
00058 register struct face_g_snurb *psrf;
00059 register fastf_t *mp1, *mp2;
00060 int n_pt_type;
00061 int rational;
00062 int i;
00063
00064 if (rt_g.NMG_debug & DEBUG_RT_ISECT)
00065 bu_log( "rt_nurb_project_srf: projecting surface, planes = (%g %g %g %g) (%g %g %g %g)\n",
00066 V4ARGS( plane1 ), V4ARGS( plane2 ) );
00067
00068 rational = RT_NURB_IS_PT_RATIONAL( srf->pt_type);
00069
00070 n_pt_type = RT_NURB_MAKE_PT_TYPE( 2, RT_NURB_PT_PROJ, 0);
00071
00072 psrf = (struct face_g_snurb *) rt_nurb_new_snurb( srf->order[0], srf->order[1],
00073 srf->u.k_size, srf->v.k_size,
00074 srf->s_size[0], srf->s_size[1], n_pt_type, res);
00075
00076 psrf->dir = RT_NURB_SPLIT_COL;
00077
00078 for ( i = 0; i < srf->u.k_size; i++) {
00079 psrf->u.knots[i] = srf->u.knots[i];
00080 }
00081
00082 for ( i = 0; i < srf->v.k_size; i++) {
00083 psrf->v.knots[i] = srf->v.knots[i];
00084 }
00085
00086 mp1 = srf->ctl_points;
00087 mp2 = psrf->ctl_points;
00088
00089 for ( i = 0; i < srf->s_size[0] * srf->s_size[1]; i++) {
00090
00091 if ( rational ) {
00092 mp2[0] = (mp1[0] / mp1[3] * plane1[0] +
00093 mp1[1] / mp1[3] * plane1[1] +
00094 mp1[2] / mp1[3] * plane1[2] - plane1[3]) *
00095 mp1[3];
00096 mp2[1] = (mp1[0] / mp1[3] * plane2[0] +
00097 mp1[1] / mp1[3] * plane2[1] +
00098 mp1[2] / mp1[3] * plane2[2] - plane2[3]) *
00099 mp1[3];
00100 } else
00101 {
00102 mp2[0] = mp1[0] * plane1[0] + mp1[1] * plane1[1] +
00103 mp1[2] * plane1[2] - plane1[3];
00104 mp2[1] = mp1[0] * plane2[0] + mp1[1] * plane2[1] +
00105 mp1[2] * plane2[2] - plane2[3];
00106 }
00107
00108 if (rt_g.NMG_debug & DEBUG_RT_ISECT)
00109 {
00110 if( rational )
00111 bu_log( "\tmesh pt (%g %g %g %g), becomes (%g %g)\n", V4ARGS( mp1 ), mp2[0], mp2[1] );
00112 else
00113 bu_log( "\tmesh pt (%g %g %g), becomes (%g %g)\n", V3ARGS( mp1 ), mp2[0], mp2[1] );
00114 }
00115
00116 mp1 += RT_NURB_EXTRACT_COORDS(srf->pt_type);
00117 mp2 += RT_NURB_EXTRACT_COORDS(psrf->pt_type);
00118 }
00119
00120 return (struct face_g_snurb *) psrf;
00121 }
00122
00123
00124
00125
00126
00127
00128 #define FINDZERO(x0,x1,y0,y1) (x0 - y0 * ( x1 - x0) / (y1-y0))
00129
00130 struct internal_line {
00131 fastf_t a, b;
00132 };
00133
00134 struct internal_convex_hull {
00135 fastf_t param;
00136 fastf_t min, max;
00137 };
00138
00139
00140 #define SIGN(a) ((a < 0.0)? -1 : 1)
00141
00142 void
00143 rt_nurb_clip_srf(const struct face_g_snurb *srf, int dir, fastf_t *min, fastf_t *max)
00144 {
00145 struct internal_convex_hull ch[20];
00146 register fastf_t * mp1;
00147 fastf_t * p1, *p2, *p3, *p4;
00148 fastf_t v1[2], v2[2], v3[2];
00149 struct internal_line l1;
00150 fastf_t norm;
00151 fastf_t value;
00152 int i;
00153 register int j;
00154 int k;
00155 int coords;
00156 int col_size, row_size;
00157
00158 col_size = srf->s_size[1];
00159 row_size = srf->s_size[0];
00160
00161 coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
00162
00163 p1 = srf->ctl_points;
00164 p2 = srf->ctl_points + coords * (col_size - 1);
00165 p3 = srf->ctl_points + (coords * col_size *
00166 (row_size - 1));
00167 p4 = srf->ctl_points + (coords * col_size *
00168 (row_size - 1)) +
00169 ((col_size - 1) * coords);
00170
00171 if ( dir == RT_NURB_SPLIT_ROW) {
00172 v1[0] = p1[0] - p3[0];
00173 v1[1] = p1[1] - p3[1];
00174
00175 v2[0] = p2[0] - p4[0];
00176 v2[1] = p2[1] - p4[1];
00177 } else
00178 {
00179 v1[0] = p1[0] - p2[0];
00180 v1[1] = p1[1] - p2[1];
00181
00182 v2[0] = p3[0] - p4[0];
00183 v2[1] = p3[1] - p4[1];
00184 }
00185
00186 v3[0] = v1[0] + v2[0];
00187 v3[1] = v1[1] + v1[1];
00188
00189 norm = sqrt( v3[1] * v3[1] + v3[0] * v3[0]);
00190 l1.a = v3[1] / norm;
00191 l1.b = -v3[0] / norm;
00192
00193 *min = 1.0e8;
00194 *max = -1.0e8;
00195
00196 if( dir == RT_NURB_SPLIT_ROW)
00197 {
00198 for( i = 0; i < col_size; i++)
00199 {
00200 ch[i].param = (fastf_t) i / (col_size - 1.0);
00201 ch[i].min = 1.0e8;
00202 ch[i].max = -1.0e8;
00203 }
00204
00205 mp1 = srf->ctl_points;
00206
00207 for( i = 0; i < row_size; i++)
00208 {
00209 for( j = 0; j < col_size; j++)
00210 {
00211 value = - (mp1[0] * l1.a + mp1[1] * l1.b);
00212 if( value <= ch[j].min)
00213 ch[j].min = value;
00214 if( value >= ch[j].max)
00215 ch[j].max = value;
00216 mp1 += coords;
00217 }
00218 }
00219
00220 for( k = 0; k < col_size - 1; k++)
00221 for( j = k+1; j < col_size; j++)
00222 {
00223 fastf_t d;
00224 fastf_t param1, param2;
00225
00226 param1 = ch[k].param;
00227 param2 = ch[j].param;
00228
00229 d = FINDZERO( param1, param2, ch[k].max, ch[j].max);
00230 if( d <= *min ) *min = d * .99;
00231 if( d >= *max ) *max = d * .99 + .01;
00232
00233 d = FINDZERO( param1, param2, ch[k].min, ch[j].min);
00234 if( d <= *min ) *min = d * .99;
00235 if( d >= *max ) *max = d * .99 + .01;
00236 }
00237
00238 if (*min <= 0.0)
00239 *min = 0.0;
00240 if (*max >= 1.0)
00241 *max = 1.0;
00242 if ( SIGN(ch[0].min) != SIGN(ch[0].max))
00243 *min = 0.0;
00244 i = SIGN(ch[col_size -1].min);
00245 j = SIGN(ch[col_size -1].max);
00246 if ( i != j)
00247 *max = 1.0;
00248 } else
00249 {
00250 for( i = 0; i < row_size; i++)
00251 {
00252 ch[i].param = (fastf_t) i / (row_size - 1.0);
00253 ch[i].min = 1.0e8;
00254 ch[i].max = -1.0e8;
00255 }
00256
00257
00258 for( i = 0; i < col_size; i++)
00259 {
00260 int stride;
00261
00262 stride = coords * col_size;
00263
00264 mp1 = srf->ctl_points + i * coords;
00265 for( j = 0; j < row_size; j++)
00266 {
00267 value = - (mp1[0] * l1.a + mp1[1] * l1.b);
00268 if( value <= ch[j].min)
00269 ch[j].min = value;
00270 if( value >= ch[j].max)
00271 ch[j].max = value;
00272 mp1 += stride;
00273 }
00274 }
00275
00276 for( k = 0; k < row_size - 1; k++)
00277 for( j = k+1; j < row_size; j++)
00278 {
00279 fastf_t d;
00280 fastf_t param1, param2;
00281
00282 param1 = ch[k].param;
00283 param2 = ch[j].param;
00284
00285 d = FINDZERO( param1, param2, ch[k].max, ch[j].max);
00286 if( d <= *min ) *min = d * .99;
00287 if( d >= *max ) *max = d * .99 + .01;
00288
00289 d = FINDZERO( param1, param2, ch[k].min, ch[j].min);
00290 if( d <= *min ) *min = d * .99;
00291 if( d >= *max ) *max = d * .99 + .01;
00292 }
00293 if (*min <= 0.0)
00294 *min = 0.0;
00295 if (*max >= 1.0)
00296 *max = 1.0;
00297 if ( SIGN(ch[0].min) != SIGN(ch[0].max))
00298 *min = 0.0;
00299 i = SIGN(ch[row_size-1 ].min);
00300 j = SIGN(ch[row_size -1].max);
00301 if ( i != j )
00302 *max = 1.0; }
00303 }
00304
00305
00306
00307
00308 struct face_g_snurb *
00309 rt_nurb_region_from_srf(const struct face_g_snurb *srf, int dir, fastf_t param1, fastf_t param2, struct resource *res)
00310 {
00311 register int i;
00312 struct face_g_snurb *region;
00313 struct knot_vector new_knots;
00314 fastf_t knot_vec[40];
00315
00316
00317
00318 new_knots.knots = & knot_vec[0];
00319
00320 if ( dir == RT_NURB_SPLIT_ROW) {
00321 new_knots.k_size = srf->order[0] * 2;
00322
00323 for ( i = 0; i < srf->order[0]; i++) {
00324 knot_vec[i] = param1;
00325 knot_vec[i+srf->order[0]] = param2;
00326 }
00327 } else
00328 {
00329 new_knots.k_size = srf->order[1] * 2;
00330
00331 for ( i = 0; i < srf->order[1]; i++) {
00332 knot_vec[i] = param1;
00333 knot_vec[i+srf->order[1]] = param2;
00334 }
00335
00336 }
00337 if( new_knots.k_size >= 40 ) rt_bomb("rt_nurb_region_from_srf() local kv overflow\n");
00338
00339 region = rt_nurb_s_refine( srf, dir, &new_knots, res);
00340
00341 return region;
00342 }
00343
00344
00345
00346
00347 struct rt_nurb_uv_hit *
00348 rt_nurb_intersect(const struct face_g_snurb *srf, fastf_t *plane1, fastf_t *plane2, double uv_tol, struct resource *res)
00349 {
00350 struct rt_nurb_uv_hit * h;
00351 struct face_g_snurb * psrf,
00352 * osrf;
00353 int dir,
00354 sub;
00355
00356 point_t vmin,
00357 vmax;
00358 fastf_t u[2],
00359 v[2];
00360 struct bu_list plist;
00361
00362 NMG_CK_SNURB(srf);
00363
00364 h = (struct rt_nurb_uv_hit *) 0;
00365 BU_LIST_INIT( &plist );
00366
00367
00368
00369 psrf = rt_nurb_project_srf( srf, plane2, plane1, res );
00370 psrf->dir = 1;
00371 BU_LIST_APPEND( &plist, &psrf->l );
00372
00373 if( RT_G_DEBUG & DEBUG_SPLINE )
00374 rt_nurb_s_print("srf", psrf);
00375
00376
00377
00378
00379 top:
00380 while( BU_LIST_WHILE( psrf, face_g_snurb, &plist ) ) {
00381 int flat;
00382
00383 BU_LIST_DEQUEUE( &psrf->l );
00384 NMG_CK_SNURB(psrf);
00385 sub = 0;
00386 flat = 0;
00387 dir = psrf->dir;
00388
00389 while(!flat)
00390 {
00391 fastf_t smin, smax;
00392
00393 sub++;
00394 dir = (dir == 0)?1:0;
00395
00396 if( RT_G_DEBUG & DEBUG_SPLINE )
00397 rt_nurb_s_print("psrf", psrf);
00398
00399 rt_nurb_pbound( psrf, vmin, vmax);
00400
00401
00402 if( !(vmin[0] <= 0.0 && vmin[1] <= 0.0 &&
00403 vmax[0] >= 0.0 && vmax[1] >= 0.0 ))
00404 {
00405 if( RT_G_DEBUG & DEBUG_SPLINE )
00406 bu_log( "this srf doesn't include the origin\n" );
00407 flat = 1;
00408 rt_nurb_free_snurb( psrf, res );
00409 continue;
00410 }
00411
00412 rt_nurb_clip_srf( psrf, dir, &smin, &smax);
00413
00414 if( (smax - smin) > .8) {
00415
00416
00417 if( RT_G_DEBUG & DEBUG_SPLINE )
00418 bu_log( "splitting this surface\n" );
00419 rt_nurb_s_split( &plist, psrf, dir, res );
00420 rt_nurb_free_snurb( psrf, res );
00421 goto top;
00422 }
00423 if( smin > 1.0 || smax < 0.0 )
00424 {
00425 if( RT_G_DEBUG & DEBUG_SPLINE )
00426 bu_log( "eliminating this surface (smin=%g, smax=%g)\n", smin, smax );
00427 flat = 1;
00428 rt_nurb_free_snurb( psrf, res );
00429 continue;
00430 }
00431 if ( dir == RT_NURB_SPLIT_ROW)
00432 {
00433 smin = (1.0 - smin) * psrf->u.knots[0] +
00434 smin * psrf->u.knots[
00435 psrf->u.k_size -1];
00436 smax = (1.0 - smax) * psrf->u.knots[0] +
00437 smax * psrf->u.knots[
00438 psrf->u.k_size -1];
00439 } else
00440 {
00441 smin = (1.0 - smin) * psrf->v.knots[0] +
00442 smin * psrf->v.knots[
00443 psrf->v.k_size -1];
00444 smax = (1.0 - smax) * psrf->v.knots[0] +
00445 smax * psrf->v.knots[
00446 psrf->v.k_size -1];
00447 }
00448
00449 osrf = psrf;
00450 psrf = (struct face_g_snurb *) rt_nurb_region_from_srf(
00451 osrf, dir, smin, smax, res);
00452
00453 psrf->dir = dir;
00454 rt_nurb_free_snurb(osrf, res);
00455
00456 if( RT_G_DEBUG & DEBUG_SPLINE )
00457 {
00458 bu_log( "After call to rt_nurb_region_from_srf() (smin=%g, smax=%g)\n", smin, smax );
00459 rt_nurb_s_print("psrf", psrf);
00460 }
00461
00462 u[0] = psrf->u.knots[0];
00463 u[1] = psrf->u.knots[psrf->u.k_size -1];
00464
00465 v[0] = psrf->v.knots[0];
00466 v[1] = psrf->v.knots[psrf->v.k_size -1];
00467
00468 if( (u[1] - u[0]) < uv_tol && (v[1] - v[0]) < uv_tol)
00469 {
00470 struct rt_nurb_uv_hit * hit;
00471
00472 if( RT_G_DEBUG & DEBUG_SPLINE )
00473 {
00474 fastf_t p1[4], p2[4];
00475 int coords;
00476 vect_t diff;
00477
00478 coords = RT_NURB_EXTRACT_COORDS( srf->pt_type );
00479 rt_nurb_s_eval( srf, u[0], v[0], p1 );
00480 rt_nurb_s_eval( srf, u[1], v[1], p2 );
00481
00482 if( RT_NURB_IS_PT_RATIONAL( srf->pt_type ) )
00483 {
00484 fastf_t inv_w;
00485
00486 inv_w = 1.0 / p1[coords-1];
00487 VSCALE( p1, p1, inv_w )
00488
00489 inv_w = 1.0 / p2[coords-1];
00490 VSCALE( p2, p2, inv_w )
00491 }
00492
00493 VSUB2( diff, p1, p2 )
00494 bu_log( "Precision of hit point = %g (%f %f %f) <-> (%f %f %f)\n",
00495 MAGNITUDE( diff ), V3ARGS( p1 ), V3ARGS( p2 ) );
00496 }
00497
00498 hit = (struct rt_nurb_uv_hit *) bu_malloc(
00499 sizeof( struct rt_nurb_uv_hit), "hit" );
00500
00501 hit->next = (struct rt_nurb_uv_hit *)0;
00502 hit->sub = sub;
00503 hit->u = (u[0] + u[1])/2.0;
00504 hit->v = (v[0] + v[1])/2.0;
00505
00506 if( h == (struct rt_nurb_uv_hit *)0)
00507 h = hit;
00508 else
00509 {
00510 hit->next = h;
00511 h = hit;
00512 }
00513 flat = 1;
00514 rt_nurb_free_snurb( psrf, res );
00515 }
00516 if( (u[1] - u[0]) > (v[1] - v[0]) )
00517 dir = 1;
00518 else dir = 0;
00519 }
00520 }
00521
00522 return (struct rt_nurb_uv_hit *)h;
00523 }
00524
00525 void
00526 rt_nurb_pbound(struct face_g_snurb *srf, fastf_t *vmin, fastf_t *vmax)
00527 {
00528 register fastf_t * ptr;
00529 register int coords;
00530 int i;
00531
00532 vmin[0] = vmin[1] = vmin[2] = INFINITY;
00533 vmax[0] = vmax[1] = vmax[2] = -INFINITY;
00534
00535 ptr = srf->ctl_points;
00536
00537 coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
00538
00539 for( i = (srf->s_size[RT_NURB_SPLIT_ROW] *
00540 srf->s_size[RT_NURB_SPLIT_COL] ); i > 0; i--)
00541 {
00542 V_MIN( (vmin[0]), (ptr[0]));
00543 V_MAX( (vmax[0]), (ptr[0]));
00544
00545 V_MIN( (vmin[1]), (ptr[1]));
00546 V_MAX( (vmax[1]), (ptr[1]));
00547
00548 ptr += coords;
00549 }
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560