00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00019 double ON_EvaluateBernsteinBasis(int degree, int i, double t)
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
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 {
00089 double
00090 s;
00091 if (degree < 0 || i < 0 || i > degree)
00092 return 0.0;
00093 switch(degree) {
00094 case 0:
00095 return 1.0;
00096 case 1:
00097 return ((i) ? t : 1.0-t);
00098 case 2:
00099 switch(i) {
00100 case 0:
00101 t = 1.0-t;
00102 return t*t;
00103 case 1:
00104 return 2.0*t*(1.0-t);
00105 default:
00106 return t*t;
00107 }
00108 case 3:
00109 switch(i) {
00110 case 0:
00111 t = 1.0 - t;
00112 return t*t*t;
00113 case 1:
00114 s = 1.0-t;
00115 return 3.0*s*s*t;
00116 case 2:
00117 return 3.0*(1.0-t)*t*t;
00118 default:
00119 return t*t*t;
00120 }
00121 case 4:
00122 switch(i) {
00123 case 0:
00124 t = 1.0-t;
00125 t = t*t;
00126 return t*t;
00127 case 1:
00128 s = 1.0-t;
00129 return 4.0*s*s*s*t;
00130 case 2:
00131 s = 1.0-t;
00132 return 6.0*s*s*t*t;
00133 case 3:
00134 return 4.0*(1.0-t)*t*t*t;
00135 default:
00136 t = t*t;
00137 return t*t;
00138 }
00139 default:
00140
00141
00142
00143 if (degree < 9)
00144 return (t*ON_EvaluateBernsteinBasis(degree-1,i-1,t)
00145 + (1-t)*ON_EvaluateBernsteinBasis(degree-1,i,t));
00146 else
00147 return ON_BinomialCoefficient(degree-i,i)*((degree==i)?1.0:pow(1.0-t,(double)(degree-i)))*((i)?pow(t,(double)i):1.0);
00148 }
00149 }
00150
00151
00152 void ON_EvaluatedeCasteljau(int dim, int order, int side, int cv_stride, double* cv, double t)
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 {
00238 double
00239 s, *P0, *P1;
00240 int
00241 j, d, off_minus_dim;
00242
00243 if (t == 0.0 || t == 1.0)
00244 return;
00245
00246 s = 1.0 - t;
00247
00248
00249 if (cv_stride > dim) {
00250 off_minus_dim = cv_stride - dim;
00251 if (side > 0) {
00252
00253 while (--order) {
00254 P0 = cv;
00255 P1 = P0 + cv_stride;
00256 j = order;
00257 while (j--) {
00258 d = dim;
00259 while (d--) {*P0 = (*P0 * s) + (*P1 * t); P0++; P1++;}
00260 P0 += off_minus_dim; P1 += off_minus_dim;}}
00261 }
00262 else {
00263
00264 cv += order*dim;
00265 while (--order) {
00266 P1 = cv;
00267 P0 = P1 - cv_stride;
00268 j = order;
00269 while (j--) {
00270 d = dim;
00271 while (d--) {P0--; P1--; *P1 = (*P0 * s) + (*P1 * t);}
00272 P0 -= off_minus_dim; P1 -= off_minus_dim;}}
00273 }
00274 }
00275 else {
00276 if (side > 0) {
00277
00278 while (--order) {
00279 P0 = cv;
00280 P1 = P0 + dim;
00281 j = order;
00282 while (j--) {
00283 d = dim;
00284 while (d--) {*P0 = (*P0 * s) + (*P1 * t); P0++; P1++;}}
00285 }
00286 }
00287 else {
00288
00289 cv += order*dim;
00290 while (--order) {
00291 P1 = cv;
00292 P0 = P1 - dim;
00293 j = order;
00294 while (j--) {
00295 d = dim;
00296 while (d--) {P0--; P1--; *P1 = (*P0 * s) + (*P1 * t);}}
00297 }
00298 }
00299 }
00300 }
00301
00302
00303
00304 bool ON_IncreaseBezierDegree(
00305 int dim,
00306 ON_BOOL32 is_rat,
00307 int order,
00308 int cv_stride,
00309 double* cv
00310 )
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 {
00350 double a0, a1, d, c0, c1;
00351 int j;
00352 double* newcv = cv;
00353 const int cvdim = (is_rat)?dim+1:dim;
00354 const int dcv = cv_stride - cvdim;
00355
00356
00357 j = cv_stride*order;
00358 newcv += j;
00359 memcpy( newcv, newcv-cv_stride, cvdim*sizeof(*newcv) );
00360 newcv -= (dcv+1);
00361 cv = newcv - cv_stride;
00362 a0 = order;
00363 a1 = 0.0;
00364 d = 1.0/a0;
00365 while (--order) {
00366 a0 -= 1.0;
00367 a1 += 1.0;
00368 c0 = d*a0;
00369 c1 = d*a1;
00370 j = cvdim;
00371 while(j--) {
00372 *newcv = c0 * *cv + c1 * *newcv;
00373 cv--;
00374 newcv--;
00375 }
00376 cv -= dcv;
00377 newcv -= dcv;
00378 }
00379 return true;
00380 }
00381
00382
00383 bool ON_RemoveBezierSingAt0(
00384 int dim,
00385 int order,
00386 int cv_stride,
00387 double* cv
00388 )
00389 {
00390 const int cvdim = dim+1;
00391 int j,k,ord0;
00392 ord0 = order;
00393 while(cv[dim] == 0.0) {
00394 order--;
00395 if (order < 2)
00396 return false;
00397 j = dim;
00398 while(j--) {
00399 if (cv[j] != 0.0)
00400 return false;
00401 }
00402 for (j=0; j<order; j++) {
00403 for (k=0; k<cvdim; k++)
00404 cv[j*cv_stride+k] = (order*cv[(j+1)*cv_stride+k])/(j+1);
00405 }
00406 }
00407 while (order < ord0)
00408 ON_IncreaseBezierDegree(dim,true,order++,cv_stride,cv);
00409 return true;
00410 }
00411
00412
00413 bool ON_RemoveBezierSingAt1(
00414 int dim,
00415 int order,
00416 int cv_stride,
00417 double* cv
00418 )
00419 {
00420 const int cvdim = dim+1;
00421 int i,k,ord0,CVlen;
00422 ord0 = order;
00423 CVlen=order*cvdim;
00424 while (order > 1 && cv[CVlen-1] == 0.0) {
00425 order--;
00426 if (order < 2)
00427 return false;
00428 i = dim;
00429 while(i--) {
00430 if (cv[CVlen-1-i] != 0.0)
00431 return false;
00432 }
00433 for (i=0; i<order; i++) {
00434 for (k=0; k<cvdim; k++)
00435 cv[i*cv_stride+k] = (order*cv[i*cv_stride+k])/(order-i);
00436 }
00437 CVlen -= cvdim;
00438 }
00439 while(order < ord0)
00440 ON_IncreaseBezierDegree(dim,true,order++,cv_stride,cv);
00441 return false;
00442 }
00443
00444
00445 bool ON_EvaluateBezier(
00446 int dim,
00447 ON_BOOL32 is_rat,
00448 int order,
00449 int cv_stride,
00450 const double* cv,
00451 double t0, double t1,
00452 int der_count,
00453 double t,
00454 int v_stride,
00455 double* v
00456 )
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 {
00510 unsigned char stack_buffer[4*64*sizeof(double)];
00511 double delta_t;
00512 register double alpha0;
00513 register double alpha1;
00514 register double *cv0, *cv1;
00515 register int i, j, k;
00516 double* CV, *tmp;
00517 void* free_me = 0;
00518 const int degree = order-1;
00519 const int cvdim = (is_rat)?dim+1:dim;
00520
00521 if ( cv_stride < cvdim )
00522 cv_stride = cvdim;
00523
00524 memset( v, 0, v_stride*(der_count+1)*sizeof(*v) );
00525
00526 #if defined( ON_DEBUG)
00527 if (t0==t1) {
00528 return false;
00529 }
00530 #endif
00531
00532 i = order*cvdim;
00533 j = 0;
00534 if (der_count > degree) {
00535 if (is_rat)
00536 j = (der_count-degree)*cvdim;
00537 else {
00538 der_count = degree;
00539 }
00540 }
00541
00542 size_t sizeofCV = (i+j)*sizeof(*CV);
00543
00544
00545
00546 CV = (double*)( (sizeofCV <= sizeof(stack_buffer)) ? stack_buffer : (free_me=onmalloc(sizeofCV)) );
00547 if (j) {
00548 memset( CV+i, 0, j*sizeof(*CV) );
00549 }
00550 cv0=CV;
00551 if ( t0 == t
00552 || (t <= 0.5*(t0+t1) && t != t1)
00553 )
00554 {
00555 for ( i = 0; i < order; i++ )
00556 {
00557 memcpy( cv0, cv, cvdim*sizeof(*cv0) );
00558 cv0 += cvdim;
00559 cv += cv_stride;
00560 }
00561 cv -= (cv_stride*order);
00562 delta_t = 1.0/(t1 - t);
00563 alpha1 = 1.0/(t1-t0);
00564 alpha0 = (t1-t)*alpha1;
00565 alpha1 *= t-t0;
00566 }
00567 else
00568 {
00569 cv += (cv_stride*order);
00570 k=order;
00571 while(k--)
00572 {
00573 cv -= cv_stride;
00574 memcpy( cv0, cv, cvdim*sizeof(*cv0) );
00575 cv0 += cvdim;
00576 }
00577 delta_t = 1.0/(t0 - t);
00578 alpha0 = 1.0/(t1-t0);
00579 alpha1 = (t1-t)*alpha0;
00580 alpha0 *= t-t0;
00581 }
00582
00583
00584 if (alpha1 != 0.0) {
00585 j = order; while (--j) {
00586 cv0 = CV;
00587 cv1 = cv0 + cvdim;
00588 i = j; while (i--) {
00589 k = cvdim;
00590 while (k--) {
00591 *cv0 = *cv0 * alpha0 + *cv1 * alpha1;
00592 cv0++;
00593 cv1++;
00594 }
00595 }
00596 }
00597 }
00598
00599
00600 if (is_rat && CV[dim] == 0.0)
00601 {
00602 if ( !ON_RemoveBezierSingAt0(dim,order,cvdim,CV) )
00603 {
00604 if ( free_me )
00605 onfree(free_me);
00606 return false;
00607 }
00608 }
00609
00610
00611 if (der_count) {
00612 tmp=CV;
00613 alpha0 = order;
00614 j = (der_count>=order)?order:der_count+1;
00615 CV += cvdim*j; while(--j) {
00616 alpha0 -= 1.0; cv1 = CV; cv0 = cv1-cvdim;
00617 i=j; while(i--) {
00618 alpha1 = alpha0 * delta_t;
00619 k=cvdim; while(k--) {
00620 cv0--;
00621 cv1--;
00622 *cv1 = alpha1*(*cv1 - *cv0);
00623 }
00624 }
00625 }
00626 CV=tmp;
00627 }
00628
00629 if ( 2 == order )
00630 {
00631
00632
00633
00634 j = cv_stride;
00635 for ( i = 0; i < cvdim; i++, j++ )
00636 {
00637 if ( cv[i] == cv[j] )
00638 {
00639 CV[i] = cv[i];
00640 }
00641 }
00642 }
00643
00644 if (is_rat) {
00645 ON_EvaluateQuotientRule( dim, der_count, cvdim, CV );
00646 }
00647
00648 for (i=0;i<=der_count;i++) {
00649 memcpy( v, CV, dim*sizeof(*v) );
00650 v += v_stride;
00651 CV += cvdim;
00652 }
00653
00654 if ( free_me )
00655 onfree(free_me);
00656
00657 return true;
00658 }
00659
00660
00661 bool ON_EvaluateNurbsBasis( int order, const double* knot,
00662 double t, double* N )
00663 {
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 register double a0, a1, x, y;
00737 const double *k0;
00738 double *t_k, *k_t, *N0;
00739 const int d = order-1;
00740 register int j, r;
00741
00742 t_k = (double*)alloca( d<<4 );
00743 k_t = t_k + d;
00744
00745 if (knot[d-1] == knot[d]) {
00746
00747 memset( N, 0, order*order*sizeof(*N) );
00748 return true;
00749 }
00750
00751 N += order*order-1;
00752 N[0] = 1.0;
00753 knot += d;
00754 k0 = knot - 1;
00755
00756 for (j = 0; j < d; j++ ) {
00757 N0 = N;
00758 N -= order+1;
00759 t_k[j] = t - *k0--;
00760 k_t[j] = *knot++ - t;
00761
00762 x = 0.0;
00763 for (r = 0; r <= j; r++) {
00764 a0 = t_k[j-r];
00765 a1 = k_t[r];
00766 y = N0[r]/(a0 + a1);
00767 N[r] = x + a1*y;
00768 x = a0*y;
00769 }
00770
00771 N[r] = x;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780 x = 1.0-ON_SQRT_EPSILON;
00781 if ( N[0] > x )
00782 {
00783 if ( N[0] != 1.0 && N[0] < 1.0 + ON_SQRT_EPSILON )
00784 {
00785 r = 1;
00786 for ( j = 1; j <= d && r; j++ )
00787 {
00788 if ( N[j] != 0.0 )
00789 r = 0;
00790 }
00791 if (r)
00792 N[0] = 1.0;
00793 }
00794 }
00795 else if ( N[d] > x )
00796 {
00797 if ( N[d] != 1.0 && N[d] < 1.0 + ON_SQRT_EPSILON )
00798 {
00799 r = 1;
00800 for ( j = 0; j < d && r; j++ )
00801 {
00802 if ( N[j] != 0.0 )
00803 r = 0;
00804 }
00805 if (r)
00806 N[d] = 1.0;
00807 }
00808 }
00809
00810 return true;
00811 }
00812
00813
00814 bool ON_EvaluateNurbsBasisDerivatives( int order, const double* knot,
00815 int der_count, double* N )
00816 {
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 double dN, c;
00844 const double *k0, *k1;
00845 double *a0, *a1, *ptr, **dk;
00846 int i, j, k, jmax;
00847
00848 const int d = order-1;
00849 const int Nstride = -der_count*order;
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861 dk = (double**)alloca( (der_count+1) << 3 );
00862 a0 = (double*)alloca( (order*(2 + ((d+1)>>1))) << 3 );
00863 a1 = a0 + order;
00864
00865
00866 dk[0] = a1 + order;
00867 for (k = 0; k < der_count; k++) {
00868 j = d-k;
00869 k0 = knot++;
00870 k1 = k0 + j;
00871 for (i = 0; i < j; i++)
00872 dk[k][i] = 1.0/(*k1++ - *k0++);
00873 dk[k+1] = dk[k] + j;
00874 }
00875 dk--;
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887 N += order;
00888
00889
00890
00891 for ( i=0; i<order; i++) {
00892 a0[0] = 1.0;
00893 for (k = 1; k <= der_count; k++) {
00894
00895 dN = 0.0;
00896 j = k-i;
00897 if (j <= 0) {
00898 dN = (a1[0] = a0[0]*dk[k][i-k])*N[i];
00899 j = 1;
00900 }
00901 jmax = d-i;
00902 if (jmax < k) {
00903 while (j <= jmax) {
00904 dN += (a1[j] = (a0[j] - a0[j-1])*dk[k][i+j-k])*N[i+j];
00905 j++;
00906 }
00907 }
00908 else {
00909
00910 while (j < k) {
00911 dN += (a1[j] = (a0[j] - a0[j-1])*dk[k][i+j-k])*N[i+j];
00912 j++;
00913 }
00914 dN += (a1[k] = -a0[k-1]*dk[k][i])*N[i+k];
00915 }
00916
00917
00918 N[i] = dN;
00919 N += order;
00920
00921
00922
00923 ptr = a0; a0 = a1; a1 = ptr;
00924 }
00925 N += Nstride;
00926 }
00927
00928
00929 dN = c = (double)d;
00930 k = der_count;
00931 while (k--) {
00932 i = order;
00933 while (i--)
00934 *N++ *= c;
00935 dN -= 1.0;
00936 c *= dN;
00937 }
00938 return true;
00939 }
00940
00941 static
00942 bool ON_EvaluateNurbsNonRationalSpan(
00943 int dim,
00944 int order,
00945 const double* knot,
00946 int cv_stride,
00947 const double* cv,
00948 int der_count,
00949 double t,
00950 int v_stride,
00951 double* v
00952 )
00953 {
00954 const int stride_minus_dim = cv_stride - dim;
00955 const int cv_len = cv_stride*order;
00956 int i, j, k;
00957 double *N;
00958 double a;
00959
00960 N = (double*)alloca( (order*order)<<3 );
00961
00962 if ( stride_minus_dim > 0)
00963 {
00964 i = (der_count+1);
00965 while( i--)
00966 {
00967 memset(v,0,dim*sizeof(v[0]));
00968 v += v_stride;
00969 }
00970 v -= ((der_count+1)*v_stride);
00971 }
00972 else
00973 {
00974 memset( v, 0, (der_count+1)*v_stride*sizeof(*v) );
00975 }
00976
00977 if ( der_count >= order )
00978 der_count = order-1;
00979
00980
00981 ON_EvaluateNurbsBasis( order, knot, t, N );
00982 if ( der_count )
00983 ON_EvaluateNurbsBasisDerivatives( order, knot, der_count, N );
00984
00985
00986 for (i = 0; i <= der_count; i++, v += v_stride, N += order) {
00987 for ( j = 0; j < order; j++ ) {
00988 a = N[j];
00989 for ( k = 0; k < dim; k++ ) {
00990 *v++ += a* *cv++;
00991 }
00992 v -= dim;
00993 cv += stride_minus_dim;
00994 }
00995 cv -= cv_len;
00996 }
00997
00998 if ( 2 == order )
00999 {
01000
01001
01002
01003 v -= (der_count+1)*v_stride;
01004 j = cv_stride;
01005 for ( i = 0; i < dim; i++, j++ )
01006 {
01007 if (cv[i] == cv[j] )
01008 v[i] = cv[i];
01009 }
01010 }
01011
01012 return true;
01013 }
01014
01015 static
01016 bool ON_EvaluateNurbsRationalSpan(
01017 int dim,
01018 int order,
01019 const double* knot,
01020 int cv_stride,
01021 const double* cv,
01022 int der_count,
01023 double t,
01024 int v_stride,
01025 double* v
01026 )
01027 {
01028 const int hv_stride = dim+1;
01029 double *hv;
01030 int i;
01031 bool rc;
01032
01033 hv = (double*)alloca( (der_count+1)*hv_stride*sizeof(*hv) );
01034
01035 rc = ON_EvaluateNurbsNonRationalSpan( dim+1, order, knot,
01036 cv_stride, cv, der_count, t, hv_stride, hv );
01037 if (rc) {
01038 rc = ON_EvaluateQuotientRule(dim, der_count, hv_stride, hv);
01039 }
01040 if ( rc ) {
01041
01042 for ( i = 0; i <= der_count; i++ ) {
01043 memcpy( v, hv, dim*sizeof(*v) );
01044 v += v_stride;
01045 hv += hv_stride;
01046 }
01047 }
01048 return rc;
01049 }
01050
01051
01052 bool ON_EvaluateNurbsSpan(
01053 int dim,
01054 ON_BOOL32 is_rat,
01055 int order,
01056 const double* knot,
01057 int cv_stride,
01058 const double* cv,
01059 int der_count,
01060 double t,
01061 int v_stride,
01062 double* v
01063 )
01064 {
01065 bool rc = false;
01066 if ( knot[0] == knot[order-2] && knot[order-1] == knot[2*order-3] ) {
01067
01068 rc = ON_EvaluateBezier(dim, is_rat, order, cv_stride, cv,
01069 knot[order-2], knot[order-1],
01070 der_count, t, v_stride, v);
01071 }
01072 else {
01073
01074 rc = (is_rat)
01075 ? ON_EvaluateNurbsRationalSpan(
01076 dim, order, knot, cv_stride, cv,
01077 der_count, t, v_stride, v )
01078 : ON_EvaluateNurbsNonRationalSpan(
01079 dim, order, knot, cv_stride, cv,
01080 der_count, t, v_stride, v );
01081 }
01082 return rc;
01083 }
01084
01085
01086 bool ON_EvaluateNurbsSurfaceSpan(
01087 int dim,
01088 ON_BOOL32 is_rat,
01089 int order0, int order1,
01090 const double* knot0,
01091 const double* knot1,
01092 int cv_stride0, int cv_stride1,
01093 const double* cv0,
01094 int der_count,
01095 double t0, double t1,
01096 int v_stride,
01097 double* v
01098 )
01099 {
01100 const int der_count0 = (der_count >= order0) ? order0-1 : der_count;
01101 const int der_count1 = (der_count >= order1) ? order1-1 : der_count;
01102 const double *cv;
01103
01104 double *N_0, *N_1, *P0, *P;
01105 double c;
01106 int d1max, d, d0, d1, i, j, j0, j1, Pcount, Psize;
01107
01108 const int cvdim = (is_rat) ? dim+1 : dim;
01109 const int dcv1 = cv_stride1 - cvdim;
01110
01111
01112 i = order0*order0;
01113 j = order1*order1;
01114 Pcount = ((der_count+1)*(der_count+2))>>1;
01115 Psize = cvdim<<3;
01116 N_0 = (double*)alloca( ((i + j) << 3) + Pcount*Psize );
01117 N_1 = N_0 + i;
01118 P0 = N_1 + j;
01119 memset( P0, 0, Pcount*Psize );
01120
01121
01122 ON_EvaluateNurbsBasis( order0, knot0, t0, N_0 );
01123 ON_EvaluateNurbsBasis( order1, knot1, t1, N_1 );
01124 if (der_count0) {
01125
01126 ON_EvaluateNurbsBasisDerivatives( order0, knot0, der_count0, N_0 );
01127 ON_EvaluateNurbsBasisDerivatives( order1, knot1, der_count1, N_1 );
01128 }
01129
01130
01131 P = P0;
01132 for ( j0 = 0; j0 < order0; j0++) {
01133 cv = cv0 + j0*cv_stride0;
01134 for ( j1 = 0; j1 < order1; j1++ ) {
01135 c = N_0[j0]*N_1[j1];
01136 j = cvdim;
01137 while (j--)
01138 *P++ += c* *cv++;
01139 P -= cvdim;
01140 cv += dcv1;
01141 }
01142 }
01143
01144 if ( der_count > 0 ) {
01145
01146 P += cvdim;
01147 for ( j0 = 0; j0 < order0; j0++) {
01148 cv = cv0 + j0*cv_stride0;
01149 for ( j1 = 0; j1 < order1; j1++ ) {
01150
01151 c = N_0[j0+order0]*N_1[j1];
01152 j = cvdim;
01153 while (j--)
01154 *P++ += c* *cv++;
01155 cv -= cvdim;
01156
01157
01158 c = N_0[j0]*N_1[j1+order1];
01159 j = cvdim;
01160 while (j--)
01161 *P++ += c* *cv++;
01162 P -= cvdim;
01163 P -= cvdim;
01164
01165 cv += dcv1;
01166 }
01167 }
01168
01169 if ( der_count > 1 ) {
01170
01171 P += cvdim;
01172 P += cvdim;
01173 if ( der_count0+der_count1 > 1 ) {
01174
01175 for ( j0 = 0; j0 < order0; j0++) {
01176
01177 cv = cv0 + j0*cv_stride0;
01178 for ( j1 = 0; j1 < order1; j1++ ) {
01179 if ( der_count0 > 1 ) {
01180
01181 c = N_0[j0+2*order0]*N_1[j1];
01182 j = cvdim;
01183 while (j--)
01184 *P++ += c* *cv++;
01185 cv -= cvdim;
01186 }
01187 else {
01188 P += cvdim;
01189 }
01190
01191
01192 c = N_0[j0+order0]*N_1[j1+order1];
01193 j = cvdim;
01194 while (j--)
01195 *P++ += c* *cv++;
01196 cv -= cvdim;
01197
01198 if ( der_count1 > 1 ) {
01199
01200 c = N_0[j0]*N_1[j1+2*order1];
01201 j = cvdim;
01202 while (j--)
01203 *P++ += c* *cv++;
01204 cv -= cvdim;
01205 P -= cvdim;
01206 }
01207
01208 P -= cvdim;
01209 P -= cvdim;
01210 cv += cv_stride1;
01211 }
01212 }
01213 }
01214
01215 if ( der_count > 2 )
01216 {
01217
01218
01219
01220 for ( d = 3; d <= der_count; d++ )
01221 {
01222 P += d*cvdim;
01223 d1max = (d > der_count1) ? der_count1 : d;
01224 for ( j0 = 0; j0 < order0; j0++)
01225 {
01226 cv = cv0 + j0*cv_stride0;
01227 for ( j1 = 0; j1 < order1; j1++ )
01228 {
01229 for (d0 = d, d1 = 0;
01230 d0 > der_count0 && d1 <= d1max;
01231 d0--, d1++ )
01232 {
01233
01234 P += cvdim;
01235 }
01236 for ( ; d1 <= d1max; d0--, d1++ )
01237 {
01238 c = N_0[j0 + d0*order0]*N_1[j1 + d1*order1];
01239 j = cvdim;
01240 while (j--)
01241 *P++ += c* *cv++;
01242 cv -= cvdim;
01243 }
01244
01245
01246 P -= d1*cvdim;
01247 cv += cv_stride1;
01248 }
01249 }
01250 }
01251 }
01252
01253 }
01254 }
01255
01256 if ( is_rat ) {
01257 ON_EvaluateQuotientRule2( dim, der_count, cvdim, P0 );
01258 Psize -= 8;
01259 }
01260 for ( i = 0; i < Pcount; i++) {
01261 memcpy( v, P0, Psize );
01262 v += v_stride;
01263 P0 += cvdim;
01264 }
01265
01266 return true;
01267 }
01268
01269
01270 bool ON_EvaluateNurbsDeBoor(
01271 int cv_dim,
01272 int order,
01273 int cv_stride,
01274 double *cv,
01275 const double *knots,
01276 int side,
01277 double mult_k,
01278 double t
01279 )
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398 {
01399 double
01400 workarray[21], alpha0, alpha1, t0, t1, dt, *delta_t, *free_delta_t, *cv0, *cv1;
01401 const double
01402 *k0, *k1;
01403 int
01404 degree, i, j, k;
01405
01406 const int cv_inc = cv_stride - cv_dim;
01407
01408 j = 0;
01409 delta_t = workarray;
01410 free_delta_t = 0;
01411 degree = order-1;
01412 t0 = knots[degree-1];
01413 t1 = knots[degree];
01414 if (t0 == t1) {
01415 ON_ERROR("ON_EvaluateNurbsDeBoor(): knots[degree-1] == knots[degree]");
01416 return false;
01417 }
01418
01419 if (side < 0) {
01420
01421
01422
01423 if (t == t1 && t1 == knots[2*degree-1])
01424 return true;
01425
01426 if (side == -2)
01427 t0 = mult_k;
01428 else if (t0 == knots[0])
01429 side = -2;
01430 else {
01431 side = -1;
01432 if (degree > 21)
01433 delta_t = free_delta_t = (double*)onmalloc(degree*sizeof(*delta_t));
01434 }
01435
01436 knots += degree-1;
01437 if (side != -2) {
01438 k0=knots; k=degree; while(k--) *delta_t++ = t - *k0--; delta_t -= degree;
01439 cv += order*cv_stride;
01440 k = order; while (--k) {
01441 cv1 = cv;
01442 cv0 = cv1 - cv_stride;
01443 k0 = knots;
01444 k1 = k0+k;
01445 i = k; while(i--) {
01446 alpha1 = *delta_t++/(*k1-- - *k0--);
01447 alpha0 = 1.0 - alpha1;
01448 cv0 -= cv_inc;
01449 cv1 -= cv_inc;
01450 j = cv_dim;
01451 while (j--) {cv0--; cv1--; *cv1 = *cv0 * alpha0 + *cv1 * alpha1;}
01452 }
01453 delta_t -= k;
01454 }
01455 }
01456 else {
01457 dt = t - t0;
01458
01459 cv += order*cv_stride;
01460 k = order; while (--k) {
01461 cv1 = cv;
01462 cv0 = cv1 - cv_stride;
01463 k1 = knots+k;
01464 i = k; while(i--) {
01465 alpha1 = dt/(*k1-- - t0);
01466 alpha0 = 1.0 - alpha1;
01467 cv0 -= cv_inc;
01468 cv1 -= cv_inc;
01469 j = cv_dim;
01470 while (j--) {cv0--; cv1--; *cv1 = *cv0 * alpha0 + *cv1 * alpha1;}
01471 }
01472 }
01473 }
01474 }
01475 else {
01476
01477
01478
01479 if (t == t0 && t0 == knots[0])
01480 return true;
01481
01482 if (side == 2)
01483 t1 = mult_k;
01484 else if (t1 == knots[2*degree-1])
01485 side = 2;
01486 else {
01487 side = 1;
01488 if (degree > 21)
01489 delta_t = free_delta_t = (double*)onmalloc(degree*sizeof(*delta_t));
01490 }
01491 knots += degree;
01492 if (side == 1) {
01493
01494
01495
01496 k1=knots; k = degree; while (k--) *delta_t++ = *k1++ - t; delta_t -= degree;
01497 k = order; while (--k) {
01498 cv0 = cv;
01499 cv1 = cv0 + cv_stride;
01500 k1 = knots;
01501 k0 = k1 - k;
01502 i = k; while(i--) {
01503 alpha0 = *delta_t++/(*k1++ - *k0++);
01504 alpha1 = 1.0 - alpha0;
01505 j = cv_dim;
01506 while(j--) {*cv0 = *cv0 * alpha0 + *cv1 * alpha1; cv0++; cv1++;}
01507 cv0 += cv_inc;
01508 cv1 += cv_inc;
01509 }
01510 delta_t -= k;
01511 }
01512 }
01513 else {
01514
01515 dt = t1 - t;
01516 k = order; while (--k) {
01517 cv0 = cv;
01518 cv1 = cv0 + cv_stride;
01519 k0 = knots - k;
01520 i = k; while(i--) {
01521 alpha0 = dt/(t1 - *k0++);
01522 alpha1 = 1.0 - alpha0;
01523 j = cv_dim;
01524 while(j--) {*cv0 = *cv0 * alpha0 + *cv1 * alpha1; cv0++; cv1++;}
01525 cv0 += cv_inc;
01526 cv1 += cv_inc;
01527 }
01528 }
01529 }
01530 }
01531
01532 if (free_delta_t)
01533 onfree(free_delta_t);
01534
01535 return true;
01536 }
01537
01538
01539 bool ON_EvaluateNurbsBlossom(int cvdim,
01540 int order,
01541 int cv_stride,
01542 const double *CV,
01543 const double *knot,
01544
01545 const double *t,
01546 double* P
01547 )
01548
01549 {
01550
01551 if (!CV || !t || !knot) return false;
01552 if (cv_stride < cvdim) return false;
01553 const double* cv;
01554 int degree = order-1;
01555 double workspace[32];
01556 double* space = workspace;
01557 double* free_space = NULL;
01558 if (order > 32){
01559 free_space = (double*)onmalloc(order*sizeof(double));
01560 space = free_space;
01561 }
01562
01563 int i, j, k;
01564
01565 for (i=1; i<2*degree; i++){
01566 if (knot[i] - knot[i-1] < 0.0) return false;
01567 }
01568
01569 if (knot[degree] - knot[degree-1] < ON_EPSILON)
01570 return false;
01571
01572 for (i=0; i<cvdim; i++){
01573
01574
01575 cv = CV+i;
01576 for (j=0; j<order; j++){
01577 space[j] = *cv;
01578 cv+=cv_stride;
01579 }
01580
01581 for (j=1; j<order; j++){
01582 for (k=j; k<order; k++){
01583 space[k-j] = (knot[degree+k-j]-t[j-1])/(knot[degree+k-j]-knot[k-1])*space[k-j] +
01584 (t[j-1]-knot[k-1])/(knot[degree+k-j]-knot[k-1])*space[k-j+1];
01585 }
01586 }
01587
01588 P[i] = space[0];
01589 }
01590
01591 if (free_space) onfree((void*)free_space);
01592 return true;
01593 }
01594
01595
01596 void ON_ConvertNurbSpanToBezier(int cvdim, int order,
01597 int cvstride, double *cv,
01598 const double *knot, double t0, double t1)
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646 {
01647 ON_EvaluateNurbsDeBoor(cvdim,order,cvstride,cv,knot, 1, 0.0, t0);
01648 ON_EvaluateNurbsDeBoor(cvdim,order,cvstride,cv,knot,-2, t0, t1);
01649 }
01650