00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00020
00021
00022
00023
00024 double ON_DomainTolerance( double a, double b )
00025 {
00026 if ( a == b )
00027 return 0.0;
00028 double tol = (fabs(a)+fabs(b)+fabs(a-b))* ON_SQRT_EPSILON;
00029 if ( tol < ON_EPSILON )
00030 tol = ON_EPSILON;
00031 return tol;
00032 }
00033
00035
00036
00037
00038
00039 double ON_KnotTolerance( int order, int cv_count, const double* knot,
00040 int knot_index )
00041 {
00042 const int knot_count = ON_KnotCount( order, cv_count );
00043 int i0, i1, j;
00044 double a, b, tol;
00045 i0 = knot_index-order+1;
00046 if ( i0 < 0 )
00047 i0 = 0;
00048 i1 = knot_index+order-1;
00049 if ( i1 >= knot_count )
00050 i1 = knot_count-1;
00051 for ( j = knot_index; j > i0; j-- ) {
00052 if ( knot[j] != knot[knot_index] )
00053 break;
00054 }
00055 a = fabs(knot[knot_index] - knot[j]);
00056 for ( j = knot_index; j < i1; j++ ) {
00057 if ( knot[j] != knot[knot_index] )
00058 break;
00059 }
00060 b = fabs(knot[knot_index] - knot[j]);
00061 tol = (a==0.0 && b==0.0) ? 0.0 : (a + b + fabs(knot[knot_index]))* ON_SQRT_EPSILON;
00062 return tol;
00063 }
00064
00066
00067
00068
00069
00070 double ON_SpanTolerance( int order, int cv_count, const double* knot, int span_index )
00071 {
00072 const int i0 = span_index+order-2;
00073 return ON_DomainTolerance( knot[i0], knot[i0+1] );
00074 }
00075
00077
00078
00079
00080
00081 int ON_KnotCount( int order, int cv_count )
00082 {
00083 return (order+cv_count-2);
00084 }
00085
00087
00088
00089
00090
00091 int ON_KnotMultiplicity(
00092 int order,
00093 int cv_count,
00094 const double* knot,
00095 int knot_index
00096 )
00097 {
00098 int knot_count = order+cv_count-2;
00099 int km = 0;
00100 if ( knot && knot_index >= 0 && knot_index < knot_count ) {
00101 while(knot_index > 0 && knot[knot_index] == knot[knot_index-1])
00102 knot_index--;
00103 knot += knot_index;
00104 knot_count -= knot_index;
00105 km = 1;
00106 while ( km < knot_count && knot[0] == knot[km] )
00107 km++;
00108 }
00109 return km;
00110 }
00111
00113
00114
00115
00116
00117 int ON_KnotVectorSpanCount(
00118 int order,
00119 int cv_count,
00120 const double* knot
00121 )
00122 {
00123 if ( 0 == knot )
00124 {
00125 if ( 0 != order || 0 != cv_count )
00126 {
00127 ON_ERROR("NULL knot[] passed to ON_KnotVectorSpanCount.");
00128 }
00129 return 0;
00130 }
00131 int i, span_count = 0;
00132 for ( i = order-1; i < cv_count; i++ ) {
00133 if ( knot[i] > knot[i-1] )
00134 span_count++;
00135 }
00136 return span_count;
00137 }
00138
00140
00141
00142
00143
00144 bool ON_GetKnotVectorSpanVector(
00145 int order,
00146 int cv_count,
00147 const double* knot,
00148 double* s
00149 )
00150 {
00151 if ( 0 == knot || 0 == s )
00152 {
00153 if ( 0 != order || 0 != cv_count )
00154 {
00155 ON_ERROR("NULL knot[] or s[] passed to ON_KnotVectorSpanCount.");
00156 return false;
00157 }
00158 return true;
00159 }
00160
00161 int i, span_count = 0;
00162 s[span_count++] = knot[order-2];
00163 for ( i = order-1; i < cv_count; i++ ) {
00164 if ( knot[i] > knot[i-1] )
00165 s[span_count++] = knot[i];
00166 }
00167 return (span_count>1) ? true : false;
00168 }
00169
00170
00172
00173
00174
00175
00176 int ON_NurbsSpanIndex(
00177 int order,
00178 int cv_count,
00179 const double* knot,
00180 double t,
00181 int side,
00182 int hint
00183 )
00184 {
00185 int j, len;
00186
00187
00188 knot += (order-2);
00189 len = cv_count-order+2;
00190
00191
00192 if (hint > 0 && hint < len-1) {
00193 while(hint > 0 && knot[hint-1] == knot[hint]) hint--;
00194 if (hint > 0) {
00195
00196 if (t < knot[hint]) {
00197 len = hint+1;
00198 hint = 0;
00199 }
00200 else {
00201 if (side < 0 && t == knot[hint])
00202 hint--;
00203 knot += hint;
00204 len -= hint;
00205 }
00206 }
00207 }
00208 else
00209 hint = 0;
00210
00211 j = ON_SearchMonotoneArray(knot,len,t);
00212 if (j < 0)
00213 j = 0;
00214 else if (j >= len-1)
00215 j = len-2;
00216 else if (side < 0) {
00217
00218
00219 while(j > 0 && t == knot[j])
00220 j--;
00221 }
00222 return (j + hint);
00223 }
00224
00225
00226 int ON_NextNurbsSpanIndex( int order, int cv_count, const double* knot, int span_index )
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 {
00275
00276 if (span_index < 0 || span_index > cv_count-order || !knot)
00277 return -1;
00278
00279 if ( span_index < cv_count-order ) {
00280 do {
00281 span_index++;
00282 }
00283 while ( span_index < cv_count-order &&
00284 knot[span_index+order-2] == knot[span_index+order-1] );
00285 }
00286 return span_index;
00287 }
00288
00289
00290 int ON_GetSpanIndices(int order,
00291 int cv_count,
00292 const double* knot,
00293 int* span_indices)
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 {
00305 int span_index, next_span_index, j;
00306
00307 span_index = -1;
00308 next_span_index = 0;
00309 j = 0;
00310 while (span_index != next_span_index) {
00311 span_index = next_span_index;
00312 span_indices[j] = span_index + order - 2;
00313 next_span_index = ON_NextNurbsSpanIndex(order, cv_count, knot, span_index);
00314 if (next_span_index < 0)
00315 return next_span_index;
00316 j++;
00317 }
00318
00319 span_indices[j] = span_index + order - 1;
00320
00321 return j;
00322 }
00323
00324
00326
00327
00328
00329
00330 double ON_SuperfluousKnot(
00331 int order, int cv_count, const double* knot,
00332 int end )
00333 {
00334 double k;
00335 const int knot_count = order+cv_count-2;
00336
00337 k = knot[(end) ? knot_count-1 : 0];
00338 if (order > 2 && cv_count >= 2*order - 2 && cv_count >= 6 ) {
00339
00340 if (end) {
00341 if ( knot[cv_count-1] < knot[knot_count-1] )
00342 k += (knot[order+1] - knot[order]);
00343 }
00344 else {
00345 if ( knot[0] < knot[order-2] )
00346 k -= (knot[cv_count-order+1] - knot[cv_count-order]);
00347 }
00348 }
00349 return k;
00350 }
00351
00353
00354
00355
00356
00357 bool ON_IsKnotVectorPeriodic(
00358 int order,
00359 int cv_count,
00360 const double* knot
00361 )
00362
00363 {
00364 double tol;
00365 const double* k1;
00366 int i;
00367
00368 if ( order < 2 || cv_count < order || !knot ) {
00369 ON_ERROR("ON_IsKnotVectorPeriodic(): illegal input");
00370 return false;
00371 }
00372
00373 if ( order == 2 )
00374 return false;
00375
00376 if (order <= 4) {
00377 if (cv_count < order+2)
00378 return false;
00379 }
00380 else if ( cv_count < 2*order-2 ) {
00381 return false;
00382 }
00383
00384 tol = fabs(knot[order-1] - knot[order-3])* ON_SQRT_EPSILON;
00385 if (tol < fabs(knot[cv_count-1] - knot[order-2])* ON_SQRT_EPSILON)
00386 tol = fabs(knot[cv_count-1] - knot[order-2])* ON_SQRT_EPSILON;
00387 k1 = knot+cv_count-order+1;
00388 i = 2*(order-2);
00389 while(i--) {
00390 if (fabs(knot[1] - knot[0] + k1[0] - k1[1]) > tol)
00391 return false;
00392 knot++; k1++;
00393 }
00394 return true;
00395 }
00396
00398
00399
00400
00401
00402 bool ON_IsKnotVectorClamped(
00403 int order,
00404 int cv_count,
00405 const double* knot,
00406 int end
00407 )
00408
00409 {
00410 if ( order <= 1 || cv_count < order || !knot || end < 0 || end > 2 )
00411 return false;
00412 bool rc = true;
00413 if ( (end == 0 || end == 2) && knot[0] != knot[order-2] )
00414 rc = false;
00415 if ( (end == 1 || end == 2) && knot[cv_count-1] != knot[order+cv_count-3] )
00416 rc = false;
00417 return rc;
00418 }
00419
00420 bool ON_IsKnotVectorUniform(
00421 int order,
00422 int cv_count,
00423 const double* knot
00424 )
00425 {
00426 bool rc = (order >= 2 && cv_count >= order && 0 != knot);
00427 if (rc)
00428 {
00429 const double delta = knot[order-1] - knot[order-2];
00430 const double delta_tol = ON_SQRT_EPSILON*delta;
00431 int i0, i1;
00432 double d;
00433 if ( ON_IsKnotVectorClamped(order,cv_count,knot) )
00434 {
00435 i0 = order;
00436 i1 = cv_count;
00437 }
00438 else
00439 {
00440 i0 = 1;
00441 i1 = ON_KnotCount(order,cv_count);
00442 }
00443 for (; i0 < i1 && rc; i0++ )
00444 {
00445 d = knot[i0] - knot[i0-1];
00446 if ( fabs(d - delta) > delta_tol )
00447 rc = false;
00448 }
00449 }
00450 return rc;
00451 }
00452
00454
00455
00456
00457
00458 bool ON_KnotVectorHasBezierSpans(
00459 int order,
00460 int cv_count,
00461 const double* knot
00462 )
00463 {
00464 int knot_count = ON_KnotCount( order, cv_count );
00465 if ( knot_count < 2 )
00466 return false;
00467 int span_count = ON_KnotVectorSpanCount( order, cv_count, knot );
00468 if ( span_count < 1 )
00469 return false;
00470 if ( order >= 2 &&
00471 cv_count >= order &&
00472 knot_count == (span_count+1)*(order-1) &&
00473 knot[0] == knot[order-2] && knot[cv_count-1] == knot[knot_count-1])
00474 return true;
00475 return false;
00476 }
00477
00479
00480
00481
00482
00483 ON::knot_style ON_KnotVectorStyle(
00484 int order,
00485 int cv_count,
00486 const double* knot
00487 )
00488 {
00489 ON::knot_style s = ON::unknown_knot_style;
00490 if ( order >= 2 && cv_count >= order && knot && knot[order-2] < knot[cv_count-1] ) {
00491 const int knot_count = order+cv_count-2;
00492 const double delta = 0.5*((knot[order-1] - knot[order-2]) + (knot[cv_count-1] - knot[cv_count-2]));
00493 const double ktol = delta*1.0e-6;
00494 int i;
00495 if ( ON_IsKnotVectorClamped( order, cv_count, knot ) ) {
00496 if ( order == cv_count ) {
00497 s = ON::piecewise_bezier_knots;
00498 }
00499 else {
00500 s = ON::clamped_end_knots;
00501 for ( i = order-1; i <= cv_count-1; i++ ) {
00502 if ( fabs(knot[i] - knot[i-1] - delta) > ktol ) {
00503 break;
00504 }
00505 }
00506 if ( i >= cv_count ) {
00507 s = ON::quasi_uniform_knots;
00508 }
00509 else {
00510 const int degree = order-1;
00511 for ( i = order-1; i < cv_count-1; i += degree ) {
00512 if ( knot[i] != knot[i+degree-1] )
00513 break;
00514 }
00515 if ( i >= cv_count-1 )
00516 s = ON::piecewise_bezier_knots;
00517 }
00518 }
00519 }
00520 else {
00521
00522 s = ON::non_uniform_knots;
00523 for ( i = 1; i < knot_count; i++ ) {
00524 if ( fabs(knot[i] - knot[i-1] - delta) > ktol ) {
00525 break;
00526 }
00527 }
00528 if ( i >= knot_count )
00529 s = ON::uniform_knots;
00530 }
00531 }
00532 return s;
00533 }
00534
00535
00537
00538
00539
00540
00541 bool ON_SetKnotVectorDomain( int order, int cv_count, double* knot, double t0, double t1 )
00542 {
00543 bool rc = false;
00544 if ( order < 2 || cv_count < order || 0 == knot || t0 >= t1 || !ON_IsValid(t0) || !ON_IsValid(t1) )
00545 {
00546 ON_ERROR("ON_SetKnotVectorDomain - invalid input");
00547 }
00548 else if ( knot[order-2] >= knot[cv_count-1]
00549 || !ON_IsValid(knot[order-2])
00550 || !ON_IsValid(knot[cv_count-2]) )
00551 {
00552 ON_ERROR("ON_SetKnotVectorDomain - invalid input knot vector");
00553 }
00554 else
00555 {
00556 const ON_Interval oldd(knot[order-2],knot[cv_count-1]);
00557 const ON_Interval newd(t0,t1);
00558 if ( oldd != newd )
00559 {
00560 int i, knot_count = ON_KnotCount(order,cv_count);
00561 for ( i = 0; i < knot_count; i++ )
00562 {
00563 knot[i] = newd.ParameterAt(oldd.NormalizedParameterAt(knot[i]));
00564 }
00565 }
00566 rc = true;
00567 }
00568 return rc;
00569 }
00570
00571
00573
00574
00575
00576
00577 bool ON_GetKnotVectorDomain(
00578 int order,
00579 int cv_count,
00580 const double* knot,
00581 double* k0, double* k1
00582 )
00583 {
00584 if ( order < 2 || cv_count < order || knot == NULL )
00585 return false;
00586 if ( k0 )
00587 *k0 = knot[order-2];
00588 if ( k1 )
00589 *k1 = knot[cv_count-1];
00590 return true;
00591 }
00592
00594
00595
00596
00597
00598 bool ON_ReverseKnotVector(
00599 int order,
00600 int cv_count,
00601 double* knot
00602 )
00603 {
00604 if ( order < 2 || cv_count < order || knot == NULL )
00605 return false;
00606 const int knot_count = (order+cv_count-2);
00607 double t;
00608 int i, j;
00609 for ( i = 0, j = knot_count-1; i <= j; i++, j-- ) {
00610 t = knot[i];
00611 knot[i] = -knot[j];
00612 knot[j] = -t;
00613 }
00614 return true;
00615 }
00616
00618
00619
00620
00621
00622 int ON_CompareKnotVector(
00623
00624
00625
00626 int orderA,
00627 int cv_countA,
00628 const double* knotA,
00629 int orderB,
00630 int cv_countB,
00631 const double* knotB
00632 )
00633 {
00634 const int knot_count = ON_KnotCount(orderA,cv_countA);
00635 int i;
00636 double a, b, atol, btol, ktol, tol;
00637 if ( orderA < orderB )
00638 return -1;
00639 if ( orderA > orderB )
00640 return 1;
00641 if ( cv_countA < cv_countB )
00642 return -1;
00643 if ( cv_countA > cv_countB )
00644 return 1;
00645
00646 if ( !ON_GetKnotVectorDomain( orderA, cv_countA, knotA, &a, &b ) )
00647 return -1;
00648 atol = ON_DomainTolerance( a, b );
00649 if ( !ON_GetKnotVectorDomain( orderA, cv_countA, knotA, &a, &b ) )
00650 return 1;
00651 btol = ON_DomainTolerance( a, b );
00652 tol = (atol <= btol) ? atol : btol;
00653
00654 for ( i = 0; i < knot_count; i++ ) {
00655 a = knotA[i];
00656 b = knotB[i];
00657 if ( a == b )
00658 continue;
00659 if ( a < b-tol )
00660 return -1;
00661 if ( b < a-tol )
00662 return 1;
00663 atol = ON_KnotTolerance( orderA, cv_countA, knotA, i );
00664 btol = ON_KnotTolerance( orderB, cv_countB, knotB, i );
00665 ktol = (atol <= btol) ? atol : btol;
00666 if ( a < b-ktol )
00667 return -1;
00668 if ( b < a-ktol )
00669 return 1;
00670 }
00671 return 0;
00672 }
00673
00675
00676
00677
00678
00679 static bool ON_KnotVectorIsNotValid(bool bSilentError)
00680 {
00681 return bSilentError ? false : ON_IsNotValid();
00682 }
00683
00684 bool ON_IsValidKnotVector( int order, int cv_count, const double* knot, ON_TextLog* text_logx )
00685 {
00686
00687
00688 const ON__INT_PTR lowbit = 1;
00689 const ON__INT_PTR hightbits = ~lowbit;
00690 bool bSilentError = ( 0 != (lowbit & ((ON__INT_PTR)text_logx)) );
00691 ON_TextLog* text_log = (ON_TextLog*)(((ON__INT_PTR)text_logx) & hightbits);
00692
00693 const double *k0, *k1;
00694 int i;
00695 if ( order < 2 )
00696 {
00697 if ( text_log )
00698 {
00699 text_log->Print("Knot vector order = %d (should be >= 2 )\n",order);
00700 }
00701 return ON_KnotVectorIsNotValid(bSilentError);
00702 }
00703 if ( cv_count < order )
00704 {
00705 if ( text_log )
00706 {
00707 text_log->Print("Knot vector cv_count = %d (should be >= order=%d )\n",cv_count,order);
00708 }
00709 return ON_KnotVectorIsNotValid(bSilentError);
00710 }
00711 if ( knot == NULL )
00712 {
00713 if ( text_log )
00714 {
00715 text_log->Print("Knot vector knot array = NULL.\n");
00716 }
00717 return ON_KnotVectorIsNotValid(bSilentError);
00718 }
00719
00720 for ( i = 0; i < cv_count+order-2; i++ )
00721 {
00722 if ( !ON_IsValid(knot[i]) )
00723 {
00724 if ( text_log )
00725 {
00726 text_log->Print("Knot vector knot[%d]=%g is not valid.\n",i,knot[i]);
00727 }
00728 return ON_KnotVectorIsNotValid(bSilentError);
00729 }
00730 }
00731
00732 if ( !(knot[order-2] < knot[order-1]) )
00733 {
00734 if ( text_log )
00735 {
00736 text_log->Print("Knot vector order=%d and knot[%d]=%g >= knot[%d]=%g (should have knot[order-2] < knot[order-1]).\n",
00737 order,order-2,knot[order-2],order-1,knot[order-1]);
00738 }
00739 return ON_KnotVectorIsNotValid(bSilentError);
00740 }
00741 if ( !(knot[cv_count-2] < knot[cv_count-1]) )
00742 {
00743 if ( text_log )
00744 {
00745 text_log->Print("Knot vector cv_count=%d and knot[%d]=%g >= knot[%d]=%g (should have knot[cv_count-2] < knot[cv_count-1]).\n",
00746 cv_count,cv_count-2,knot[cv_count-2],cv_count-1,knot[cv_count-1]);
00747 }
00748 return ON_KnotVectorIsNotValid(bSilentError);
00749 }
00750
00751
00752 k0 = knot;
00753 k1 = knot+1;
00754 i = order + cv_count - 3;
00755 while (i--) {
00756 if ( !(*k1 >= *k0) )
00757 {
00758 if ( text_log )
00759 {
00760 text_log->Print("Knot vector must be increasing but knot[%d]=%g > knot[%d]=%g\n",
00761 order+cv_count-4-i, *k0, order+cv_count-3-i, *k1 );
00762 }
00763 return ON_KnotVectorIsNotValid(bSilentError);
00764 }
00765 k0++;
00766 k1++;
00767 }
00768
00769
00770 k0 = knot;
00771 k1 = knot + order - 1;
00772 i = cv_count-1;
00773 while(i--) {
00774 if ( !(*k1 > *k0) )
00775 {
00776 if ( text_log )
00777 {
00778 text_log->Print("Knot vector order = %d but knot[%d]=%g >= knot[%d]=%g\n",
00779 order, cv_count-2-i, *k0, cv_count-1-i, *k1 );
00780 }
00781 return ON_KnotVectorIsNotValid(bSilentError);
00782 }
00783 k0++;
00784 k1++;
00785 }
00786
00787 return true;
00788 }
00789
00790
00791 bool ON_ClampKnotVector(
00792 int order,
00793 int cv_count,
00794 double* knot,
00795 int end
00796 )
00797 {
00798
00799 bool rc = false;
00800 int i, i0;
00801 if ( knot && order >= 2 && cv_count >= order ) {
00802 if ( end == 0 || end == 2 ) {
00803 i0 = order-2;
00804 for ( i = 0; i < i0; i++ ) {
00805 knot[i] = knot[i0];
00806 }
00807 rc = true;
00808 }
00809 if ( end == 1 || end == 2 ) {
00810 const int knot_count = ON_KnotCount(order,cv_count);
00811 i0 = cv_count-1;
00812 for ( i = i0+1; i < knot_count; i++ ) {
00813 knot[i] = knot[i0];
00814 }
00815 rc = true;
00816 }
00817 }
00818 return rc;
00819 }
00820
00821
00822 bool ON_MakeKnotVectorPeriodic(
00823 int order,
00824 int cv_count,
00825 double* knot
00826 )
00827 {
00828 double *k0, *k1;
00829 int i;
00830
00831 if ( order < 2 || cv_count < order || !knot ) {
00832 ON_ERROR("ON_MakePeriodicKnotVector(): illegal input");
00833 return false;
00834 }
00835
00836 switch(order) {
00837 case 2:
00838 if ( cv_count < 4 ) {
00839 ON_ERROR("ON_MakePeriodicKnotVector(): illegal input degree=1, cv_count<4");
00840 return false;
00841 }
00842 else {
00843 return true;
00844 }
00845 break;
00846 case 3:
00847 if ( cv_count < 4 ) {
00848 ON_ERROR("ON_MakePeriodicKnotVector(): illegal input degree=2, cv_count<5");
00849 return false;
00850 }
00851 break;
00852 default:
00853 if ( cv_count < 2*order-2 ) {
00854 ON_ERROR("ON_MakePeriodicKnotVector(): illegal input degree>=3, cv_count<2*degree");
00855 return false;
00856 }
00857 break;
00858 }
00859
00860 k0 = knot + order-2;
00861 k1 = knot + cv_count-1;
00862 i = order-2;
00863 while (i--) {
00864 k1[1] = k0[1]-k0[0]+k1[0];
00865 k0++; k1++;
00866 }
00867 k0 = knot + order-2;
00868 k1 = knot + cv_count-1;
00869 i = order-2;
00870 while (i--) {
00871 k0[-1] = k1[-1] - k1[0] + k0[0];
00872 k0--;
00873 k1--;
00874 }
00875 return true;
00876 }
00877
00878 ON_DECL
00879 bool ON_MakeClampedUniformKnotVector(
00880 int order,
00881 int cv_count,
00882 double* knot,
00883 double delta
00884 )
00885 {
00886 bool rc = false;
00887 if ( order >= 2 && cv_count >= order && knot != NULL && delta > 0.0 )
00888 {
00889 double k;
00890 int i;
00891 for ( i = order-2, k = 0.0; i < cv_count; i++, k += delta )
00892 knot[i] = k;
00893 ON_ClampKnotVector(order,cv_count,knot,2);
00894 rc = true;
00895 }
00896 return rc;
00897 }
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 ON_DECL
00914 bool ON_MakePeriodicUniformKnotVector(
00915 int order,
00916 int cv_count,
00917 double* knot,
00918 double delta
00919 )
00920 {
00921 bool rc = false;
00922 if ( order >= 2 && cv_count >= order && knot != NULL && delta > 0.0 )
00923 {
00924 double k = 0.0;
00925 int i, knot_count = ON_KnotCount(order,cv_count);
00926 for ( i = order-2, k = 0.0; i < knot_count; i++, k += delta )
00927 knot[i] = k;
00928 for ( i = order-3, k = -delta; i >= 0; i--, k -= delta )
00929 knot[i] = k;
00930 rc = true;
00931 }
00932 return rc;
00933 }
00934
00935
00936
00937 double ON_GrevilleAbcissa(
00938 int order,
00939 const double* knot
00940 )
00941 {
00942 double g=0.0;
00943 if ( order <= 2 || knot[0] == knot[order-2]) {
00944 g = knot[0];
00945 }
00946 else {
00947
00948 order--;
00949 const double k = knot[order/2];
00950 const double tol = (knot[order-1]-knot[0]);
00951 const double d = 1.0/((double)order);
00952 while ( order--) {
00953 g += *knot++;
00954 }
00955 g *= d;
00956 if ( fabs(g-k) <= (fabs(g)+tol)* ON_SQRT_EPSILON )
00957 g = k;
00958 }
00959 return g;
00960 }
00961
00962
00963 bool ON_GetGrevilleAbcissae(
00964 int order,
00965 int cv_count,
00966 const double* knot,
00967 bool bPeriodic,
00968 double* g
00969
00970 )
00971 {
00972
00973 double x, t0;
00974 int gi, periodic_check;
00975
00976 if ( order < 2 || cv_count < order || !knot || !g )
00977 return false;
00978
00979 const int g_count = (bPeriodic) ? cv_count-order+1 : cv_count;
00980
00981 if (order == 2) {
00982
00983 memcpy( g, knot, g_count*sizeof(*g) );
00984 }
00985 else {
00986
00987 t0 = knot[order-2];
00988 gi = 0;
00989 periodic_check = (bPeriodic) ? order-2 : 0;
00990 while (gi < g_count) {
00991 x = ON_GrevilleAbcissa( order, knot++ );
00992 if ( periodic_check ) {
00993 periodic_check--;
00994 if ( x < t0 )
00995 continue;
00996 }
00997 g[gi++] = x;
00998 }
00999 }
01000
01001 return true;
01002 }
01003
01004
01005 bool ON_GetGrevilleKnotVector(
01006 int g_stride,
01007 const double *g,
01008
01009
01010 bool bPeriodic,
01011 int order,
01012 int cv_count,
01013 double* knot
01014 )
01015 {
01016 bool rc = false;
01017 double* p = NULL;
01018 int ki, knot_count, g_count, gi, j, degree;
01019 double k, dd;
01020
01021 if ( g_stride < 1 || !g || !knot || order < 2 || cv_count < order )
01022 return false;
01023 if ( bPeriodic && order == 2 )
01024 return false;
01025 if ( bPeriodic && cv_count - order + 2 < 3 )
01026 return false;
01027
01028 degree = order-1;
01029 if ( degree == 1 ) {
01030 for ( j = 0; j < cv_count; j++ ) {
01031 knot[j] = g[j*g_stride];
01032 }
01033 return true;
01034 }
01035 dd = 1.0/degree;
01036 knot_count = ON_KnotCount( order, cv_count );
01037 g_count = (bPeriodic) ? cv_count-order+2 : cv_count;
01038
01039 if ( bPeriodic ) {
01040 int half_degree = (degree%2) ? degree/2 : 0;
01041
01042 p = (double*)onmalloc((g_count + 2*degree)*sizeof(*p));
01043 for ( j = 0, gi = g_count-order; j < degree; j++, gi++ ) {
01044 p[j] = g[0] - g[g_count-1] + g[gi];
01045 }
01046 for ( gi = 0, j = degree; gi < g_count; gi++, j++ ) {
01047 p[j] = g[gi];
01048 }
01049 for ( j = g_count+degree, gi = 1; j < g_count+2*degree; j++, gi++ ) {
01050 p[j] = g[g_count-1] - g[0] + g[gi];
01051 }
01052
01053
01054 for ( j = 0; j < g_count+order; j++ ) {
01055 k = p[j];
01056 for ( ki = 1; ki < degree; ki++ )
01057 k += p[j+ki];
01058 k *= dd;
01059 if ( half_degree ) {
01060
01061 if ( fabs(k-p[j+half_degree]) <= ON_SQRT_EPSILON*(p[j+degree-1]-p[j]) )
01062 k = p[j+half_degree];
01063 }
01064 p[j] = k;
01065 }
01066
01067
01068 {
01069 double* B = (double*)alloca(order*order*sizeof(B[0]));
01070 double maxB = 0.0;
01071 int maxBj = 0;
01072 for ( j = 0; j < 2*degree; j++ ) {
01073 if ( g[0] > p[j+degree] )
01074 continue;
01075 if ( g[0] < p[j+degree-1] )
01076 break;
01077 ON_EvaluateNurbsBasis( order, p+j, g[0], B );
01078 if ( B[0] > maxB ) {
01079 maxB = B[0];
01080 maxBj = j;
01081 }
01082 }
01083 memcpy( knot, &p[maxBj], knot_count*sizeof(*knot) );
01084 }
01085
01086 rc = ON_MakeKnotVectorPeriodic( order, cv_count, knot );
01087 }
01088 else {
01089
01090 rc = true;
01091 if ( g > knot && g < knot+knot_count ) {
01092 p = (double*)onmalloc(cv_count*sizeof(*p));
01093 for( j = 0; j < cv_count; j++ ) {
01094 p[j] = g[j*g_stride];
01095 }
01096 g = p;
01097 g_stride = 1;
01098 }
01099 for ( ki = 0; ki < degree; ki++ ) {
01100 knot[ki] = g[0];
01101 }
01102 for ( ki = degree, gi = 1; ki < cv_count; ki++, gi++ ) {
01103 k = 0.0;
01104 for ( j = 0; j < degree; j++ ) {
01105 k += g[(gi+j)*g_stride];
01106 }
01107 knot[ki] = k*dd;
01108 if ( knot[ki] < knot[ki-1] || knot[ki] <= knot[ki-degree] ) {
01109 rc = false;
01110 }
01111 }
01112 for ( ki = cv_count-1; ki < knot_count; ki++ ) {
01113 knot[ki] = g[(cv_count-1)*g_stride];
01114 }
01115 }
01116
01117 if (p)
01118 onfree(p);
01119 return rc;
01120 }
01121
01122 bool ON_ClampKnotVector(
01123 int cv_dim,
01124 int order,
01125 int cv_count,
01126 int cv_stride,
01127 double* cv,
01128 double* knot,
01129 int end
01130 )
01131 {
01132
01133 bool rc = false;
01134 int i, i0;
01135
01136 if ( knot && order >= 2 && cv_count >= order ) {
01137 if ( end == 0 || end == 2 ) {
01138 if ( cv ) {
01139 ON_EvaluateNurbsDeBoor(cv_dim,order,cv_stride,cv,knot,1,0.0,knot[order-2]);
01140 }
01141 i0 = order-2;
01142 for (i = 0; i < i0; i++)
01143 knot[i] = knot[i0];
01144 rc = true;
01145 }
01146 if ( end == 1 || end == 2 ) {
01147 i0 = cv_count-order;
01148 knot += i0;
01149 if ( cv ) {
01150 cv += i0*cv_stride;
01151 ON_EvaluateNurbsDeBoor(cv_dim,order,cv_stride,cv,knot,-1,0.0,knot[order-1]);
01152 }
01153 i0 = order-1;
01154 for (i = 2*order-3; i > i0; i--)
01155 knot[i] = knot[i0];
01156 rc = true;
01157 }
01158 }
01159 return rc;
01160 }
01161
01162
01163 static bool ON_InsertSingleKnot( int cv_dim, int order,
01164 int cv_stride,
01165 double *cv,
01166 double *knot,
01167
01168 double knot_value
01169
01170 )
01171 {
01172 double alpha0, alpha1;
01173 double *k0, *k1, *prev_cv;
01174 int i, d, cv_inc, degree;
01175
01176 if ( order < 2 || !knot || knot_value < knot[order-2] || knot[order-1] <= knot_value ) {
01177 ON_ERROR( "ON_InsertSingleKnot() - illegal knot input" );
01178 return false;
01179 }
01180
01181 if ( cv ) {
01182 if ( cv_dim < 1 || cv_stride < cv_dim ) {
01183 ON_ERROR( "ON_InsertSingleKnot() - illegal cv input" );
01184 return false;
01185 }
01186 }
01187
01188 degree = order-1;
01189
01190
01191 k1 = knot + 2*degree;
01192 k0 = k1-1;
01193 i = degree;
01194 while (i--)
01195 *k1-- = *k0--;
01196
01197
01198 *k1 = knot_value;
01199
01200 if ( cv ) {
01201
01202 memcpy( cv+cv_dim*order, cv+cv_dim*degree, cv_dim*sizeof(*cv) );
01203
01204
01205 k0 = knot + degree-1;
01206 k1 = k0 + order;
01207 cv += order*cv_stride;
01208 prev_cv = cv - cv_stride;
01209 cv_inc = cv_stride - cv_dim;
01210 i = degree;
01211 if (knot_value - *k0 <= *k1 - knot_value) {
01212 while (i--) {
01213 alpha1 = (knot_value - *k0)/(*k1 - *k0);
01214 alpha0 = 1.0 - alpha1;
01215 k0--; k1--;
01216 cv -= cv_inc;
01217 prev_cv -= cv_inc;
01218 d = cv_dim;
01219 while (d--) {
01220 --cv;
01221 --prev_cv;
01222 *cv = *cv * alpha1 + *prev_cv * alpha0;
01223 }
01224 }
01225 }
01226 else {
01227 while (i--) {
01228 alpha0 = (*k1 - knot_value)/(*k1 - *k0);
01229 alpha1 = 1.0 - alpha0;
01230 k0--; k1--;
01231 cv -= cv_inc;
01232 prev_cv -= cv_inc;
01233 d = cv_dim;
01234 while (d--) {
01235 --cv;
01236 --prev_cv;
01237 *cv = *cv * alpha1 + *prev_cv * alpha0;
01238 }
01239 }
01240 }
01241 }
01242
01243 return true;
01244 }
01245
01246 int ON_InsertKnot(
01247 double knot_value,
01248 int knot_multiplicity,
01249 int cv_dim,
01250 int order,
01251 int cv_count,
01252 int cv_stride,
01253 double* cv,
01254 double* knot,
01255 int* hint
01256
01257 )
01258 {
01259 int rc = 0;
01260
01261 if ( order < 2 || cv_count < order || !knot )
01262 {
01263 ON_ERROR("ON_InsertKnot(): illegal input" );
01264 return 0;
01265 }
01266
01267 if ( cv )
01268 {
01269 if ( cv_dim < 1 || cv_stride < cv_dim )
01270 {
01271 ON_ERROR("ON_InsertKnot(): illegal input" );
01272 return 0;
01273 }
01274 }
01275
01276 if ( knot_multiplicity >= order )
01277 {
01278 ON_ERROR("ON_InsertKnot(): requested knot_multiplicity > degree" );
01279 return 0;
01280 }
01281
01282
01283 int span_index = ON_NurbsSpanIndex( order, cv_count, knot, knot_value, 1, hint?*hint:0 );
01284 knot += span_index;
01285 if ( cv )
01286 cv += (span_index*cv_stride);
01287 cv_count -= span_index;
01288
01289 const double knot_tolerance = ON_SpanTolerance( order, cv_count, knot, 0 );
01290
01291
01292 if ( span_index == 0 )
01293 {
01294 if ( knot_value < knot[order-1] )
01295 {
01296 if ( knot_value <= knot[order-2] + knot_tolerance )
01297 {
01298 ON_ERROR("ON_InsertKnot(): requested knot_value at start of NURBS domain" );
01299 return 0;
01300 }
01301 }
01302 }
01303 if ( span_index == cv_count-order )
01304 {
01305 if ( knot_value > knot[order-2] && knot_value >= knot[order-1] - knot_tolerance )
01306 {
01307 ON_ERROR("ON_InsertKnot(): requested knot_value at end of NURBS domain" );
01308 return 0;
01309 }
01310 }
01311
01312
01313 if ( knot_value <= 0.5*(knot[order-2]+knot[order-1]) && fabs( knot_value - knot[order-2] ) <= knot_tolerance ) {
01314 knot_value = knot[order-2];
01315 }
01316 else if ( fabs( knot_value - knot[order-1] ) <= knot_tolerance ) {
01317 knot_value = knot[order-1];
01318 }
01319
01320 const int degree = order-1;
01321
01322
01323 int m = 0;
01324 int j;
01325 if ( knot_value == knot[order-2] ) {
01326 for ( j = order-2; m < knot_multiplicity && knot[j-m] == knot_value; m++ )
01327 ;
01328 }
01329 else if ( knot_value == knot[order-1] ) {
01330 for ( j = order-1; m < knot_multiplicity && knot[j+m] == knot_value; m++ )
01331 ;
01332 }
01333 m = knot_multiplicity - m;
01334 if ( hint )
01335 *hint = span_index+m;
01336
01337 if ( m <= 0 )
01338 return 0;
01339
01340 double* new_knot = (double*)onmalloc( ((2*degree+m) + (order+m)*cv_dim)*sizeof(*new_knot) );
01341 if ( !new_knot ) {
01342 ON_ERROR("ON_InsertKnot(): out of memory");
01343 return 0;
01344 }
01345 double* new_cv = 0;
01346 memcpy( new_knot, knot, 2*degree*sizeof(*new_knot) );
01347 if ( cv ) {
01348 new_cv = new_knot + (2*degree+m);
01349 for ( j = 0; j < order; j++ ) {
01350 memcpy( new_cv + j*cv_dim, cv + j*cv_stride, cv_dim*sizeof(*new_cv) );
01351 }
01352 }
01353
01354
01355 rc = 0;
01356 while (m>0) {
01357 if ( !ON_InsertSingleKnot(cv_dim,order,cv_dim,new_cv,new_knot,knot_value) )
01358 break;
01359 m--;
01360 if ( new_cv )
01361 new_cv += cv_stride;
01362 new_knot++;
01363 rc++;
01364 }
01365 new_knot -= rc;
01366 new_cv -= rc*cv_stride;
01367
01368 if ( rc > 0 ) {
01369
01370 int i0 = ON_KnotCount( order, cv_count ) - 1;
01371 int i1 = i0 + rc;
01372 int j = (cv_count-order);
01373 while (j--)
01374 knot[i1--] = knot[i0--];
01375
01376
01377 memcpy ( knot+degree, new_knot+degree, (degree+rc)*sizeof(*new_knot) );
01378
01379 if ( cv ) {
01380
01381 i0 = (cv_count-1)*cv_stride;
01382 i1 = i0 + rc*cv_stride;
01383 j = cv_count-order;
01384 while (j--) {
01385 memcpy( cv+i1, cv+i0, cv_dim*sizeof(*cv) );
01386 i1 -= cv_stride;
01387 i0 -= cv_stride;
01388 }
01389
01390
01391 for ( j = 0; j < order+rc; j++ ) {
01392 memcpy( cv, new_cv, cv_dim*sizeof(*new_cv) );
01393 cv += cv_stride;
01394 new_cv += cv_dim;
01395 }
01396 }
01397
01398 }
01399
01400 onfree(new_knot);
01401
01402 return rc;
01403 }
01404