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 static long FindBreakPoint(double u, double *kv, long m, long k){
00037 long i;
00038 if (u == kv[m+1])
00039 return m;
00040 i = m + k;
00041 while ((u < kv[i]) && (i > 0))i--;
00042 return( i );
00043 }
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 static void BasisFunctions(double u, long brkPoint, double * kv, long k,
00057 double * bvals ){
00058 register long r, s, i;
00059 register double omega;
00060 bvals[0] = 1.0;
00061 for (r = 2; r <= k; r++){
00062 i = brkPoint - r + 1;
00063 bvals[r - 1] = 0.0;
00064 for (s = r-2; s >= 0; s--){
00065 i++;
00066 if (i < 0)
00067 omega = 0;
00068 else
00069 omega = (u - kv[i]) / (kv[i + r - 1] - kv[i]);
00070 bvals[s + 1] = bvals[s + 1] + (1 - omega) * bvals[s];
00071 bvals[s] = omega * bvals[s];
00072 }
00073 }
00074 }
00075
00076 static void BasisDerivatives(double u, long brkPoint,
00077 double * kv, long k, double * dvals ){
00078
00079
00080
00081 register long s, i;
00082 register double omega, knotScale;
00083 BasisFunctions( u, brkPoint, kv, k - 1, dvals );
00084 dvals[k-1] = 0.0;
00085 knotScale = kv[brkPoint + 1L] - kv[brkPoint];
00086 i = brkPoint - k + 1L;
00087 for (s = k - 2L; s >= 0L; s--){
00088 i++;
00089 omega = knotScale * ((double)(k-1L)) / (kv[i+k-1L] - kv[i]);
00090 dvals[s + 1L] += -omega * dvals[s];
00091 dvals[s] *= omega;
00092 }
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 static void CalcPoint(double u, double v, nurbs *n, vector p,
00128 vector utan, vector vtan){
00129 long i, j, ri, rj;
00130 vector4 *cp;
00131 double tmp;
00132 double wsqrdiv;
00133 long ubrkPoint, ufirst;
00134 double bu[MAXORDER], buprime[MAXORDER];
00135 long vbrkPoint, vfirst;
00136 double bv[MAXORDER], bvprime[MAXORDER];
00137 vector4 r,rutan,rvtan;
00138 rutan.x= rvtan.x=r.x=0.0;
00139 rutan.y= rvtan.y=r.y=0.0;
00140 rutan.z= rvtan.z=r.z=0.0;
00141 rutan.w= rvtan.z=r.w=0.0;
00142
00143 ubrkPoint = FindBreakPoint( u, n->kvU, n->numU-1, n->orderU );
00144 ufirst = ubrkPoint - n->orderU + 1;
00145 BasisFunctions( u, ubrkPoint, n->kvU, n->orderU, bu );
00146 if(utan != NULL)BasisDerivatives( u, ubrkPoint, n->kvU, n->orderU, buprime );
00147 vbrkPoint = FindBreakPoint( v, n->kvV, n->numV-1, n->orderV );
00148 vfirst = vbrkPoint - n->orderV + 1;
00149 BasisFunctions( v, vbrkPoint, n->kvV, n->orderV, bv );
00150 if(vtan != NULL)BasisDerivatives( v, vbrkPoint, n->kvV, n->orderV, bvprime );
00151
00152 for (i = 0; i < n->orderV; i++)
00153 for (j = 0; j < n->orderU; j++){
00154 ri = n->orderV - 1L - i;
00155 rj = n->orderU - 1L - j;
00156 tmp = bu[rj] * bv[ri];
00157 cp = &(n->points[i+vfirst][j+ufirst]);
00158 r.x += cp->x * tmp;
00159 r.y += cp->y * tmp;
00160 r.z += cp->z * tmp;
00161 r.w += cp->w * tmp;
00162 if(utan != NULL){
00163 tmp = buprime[rj] * bv[ri];
00164 rutan.x += cp->x * tmp;
00165 rutan.y += cp->y * tmp;
00166 rutan.z += cp->z * tmp;
00167 rutan.w += cp->w * tmp;
00168 }
00169 if(vtan != NULL){
00170 tmp = bu[rj] * bvprime[ri];
00171 rvtan.x += cp->x * tmp;
00172 rvtan.y += cp->y * tmp;
00173 rvtan.z += cp->z * tmp;
00174 rvtan.w += cp->w * tmp;
00175 }
00176 }
00177
00178 if(utan != NULL && vtan != NULL)wsqrdiv = 1.0 / (r.w * r.w);
00179 if(utan != NULL){
00180 utan[0] = (r.x * rutan.x - rutan.x * r.x) * wsqrdiv;
00181 utan[1] = (r.y * rutan.y - rutan.y * r.y) * wsqrdiv;
00182 utan[2] = (r.z * rutan.z - rutan.z * r.z) * wsqrdiv;
00183 }
00184 if(vtan != NULL){
00185 vtan[0] = (r.x * rvtan.x - rvtan.x * r.x) * wsqrdiv;
00186 vtan[1] = (r.y * rvtan.y - rvtan.y * r.y) * wsqrdiv;
00187 vtan[2] = (r.z * rvtan.z - rvtan.z * r.z) * wsqrdiv;
00188 }
00189 p[0] = r.x / r.w;
00190 p[1] = r.y / r.w;
00191 p[2] = r.z / r.w;
00192 return;
00193 }
00194
00195 static BOOL CalcAlpha(double * ukv, double * wkv,
00196 long m, long n, long k,
00197 double *** alpha){
00198 register long i, j;
00199 long brkPoint, r, rm1, last, s;
00200 double omega;
00201 double aval[MAXORDER];
00202 if(*alpha == NULL){
00203 if((*alpha = (double **)X__Malloc((long)((k+1) * sizeof(double *))))
00204 == NULL)return FALSE;
00205 for (i = 0; i <= k; i++){
00206 if(((*alpha)[i] = (double *)X__Malloc((long) ((m + n + 1)
00207 * sizeof(double)))) == NULL)return FALSE;
00208 }
00209 }
00210 for (j = 0; j <= m + n; j++){
00211 brkPoint = FindBreakPoint( wkv[j], ukv, m, k );
00212 aval[0] = 1.0;
00213 for(r = 2; r <= k; r++){
00214 rm1 = r - 1;
00215 last = min(rm1,brkPoint);
00216 i = brkPoint - last;
00217 if(last < rm1)aval[last] = aval[last] * (wkv[j + r - 1] - ukv[i])
00218 / (ukv[i + r - 1] - ukv[i]);
00219 else aval[last] = 0.0;
00220 for(s = last - 1; s >= 0; s-- ){
00221 i++;
00222 omega = (wkv[j + r - 1] - ukv[i]) / (ukv[i + r - 1] - ukv[i]);
00223 aval[s + 1] = aval[s+1] + (1 - omega) * aval[s];
00224 aval[s] = omega * aval[s];
00225 }
00226 }
00227 last = min( k - 1, brkPoint );
00228 for (i = 0; i <= k; i++)(*alpha)[i][j] = 0.0;
00229 for (s = 0; s <= last; s++)(*alpha)[last - s][j] = aval[s];
00230 }
00231 return TRUE;
00232 }
00233
00234 static void RefineSurface(nurbs *src, nurbs *dest, BOOL dirflag){
00235
00236
00237
00238
00239 register long i, j, out;
00240 register vector4 *dp, *sp;
00241 long i1,brkPoint,maxj,maxout;
00242 register double tmp;
00243 double **alpha = NULL;
00244
00245 if(dirflag){
00246 if(!CalcAlpha(src->kvU, dest->kvU, src->numU - 1, dest->numU - src->numU,
00247 src->orderU, &alpha ))return;
00248 maxj = dest->numU;
00249 maxout = src->numV;
00250 }
00251 else{
00252 if(!CalcAlpha(src->kvV, dest->kvV, src->numV - 1, dest->numV - src->numV,
00253 src->orderV, &alpha))return;
00254 maxj = dest->numV;
00255 maxout = dest->numU;
00256 }
00257
00258
00259 for(out = 0; out < maxout; out++)
00260 for(j = 0; j < maxj; j++){
00261 if(dirflag){
00262 dp = &(dest->points[out][j]);
00263 brkPoint = FindBreakPoint(dest->kvU[j], src->kvU,
00264 src->numU-1, src->orderU);
00265 i1 = max( brkPoint - src->orderU + 1, 0 );
00266 sp = &(src->points[out][i1]);
00267 }
00268 else{
00269 dp = &(dest->points[j][out]);
00270 brkPoint = FindBreakPoint(dest->kvV[j], src->kvV,
00271 src->numV-1, src->orderV );
00272 i1 = max(brkPoint - src->orderV + 1, 0);
00273 sp = &(src->points[i1][out]);
00274 }
00275 dp->x = 0.0;
00276 dp->y = 0.0;
00277 dp->z = 0.0;
00278 dp->w = 0.0;
00279 for(i = i1; i <= brkPoint; i++){
00280 tmp = alpha[i - i1][j];
00281 sp = (dirflag ? &(src->points[out][i]) : &(src->points[i][out]) );
00282 dp->x += tmp * sp->x;
00283 dp->y += tmp * sp->y;
00284 dp->z += tmp * sp->z;
00285 dp->w += tmp * sp->w;
00286 }
00287 }
00288
00289 for (i = 0; i <= (dirflag ? src->orderU : src->orderV); i++)
00290 X__Free(alpha[i]);
00291 X__Free(alpha);
00292 return;
00293 }
00294
00295 #define DIVW(rpt,pt ) \
00296 { (pt[0]) = (rpt)->x / (rpt)->w; \
00297 (pt[1]) = (rpt)->y / (rpt)->w; \
00298 (pt[2]) = (rpt)->z / (rpt)->w; }
00299 #define EPSILON 0.0001
00300 #define DIVPT( p, dn ) { (p[0]) /= (dn); (p[1]) /= (dn); (p[2]) /= (dn); }
00301 #define COPYVEC(b,a) { b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; }
00302 #define maxV(surf) ((surf)->numV-1L)
00303 #define maxU(surf) ((surf)->numU-1L)
00304
00305 static void ScreenProject(vector4 *Point4, vector Point3){
00306 DIVW(Point4,Point3);
00307 return;
00308 }
00309
00310 static long SplitKV(double * srckv,
00311 double ** destkv,
00312 long * splitPt,
00313 long m, long k ){
00314
00315
00316
00317
00318
00319
00320 long i, last;
00321 long middex, extra, same;
00322 double midVal;
00323 extra = 0L;
00324 last = (m + k);
00325 middex = last / 2;
00326 midVal = srckv[middex];
00327
00328 i = middex+1L;
00329 same = 1L;
00330 while ((i < last) && (srckv[i] == midVal)){
00331 i++;
00332 same++;
00333 }
00334 i = middex-1L;
00335 while((i > 0L) && (srckv[i] == midVal)) {
00336 i--;
00337 middex--;
00338 same++;
00339 }
00340 if(i <= 0L){
00341 midVal = (srckv[0L] + srckv[last]) / 2.0;
00342 middex = last / 2L;
00343 while (srckv[middex + 1L] < midVal)middex++;
00344 same = 0L;
00345 }
00346 extra = k - same;
00347 if((*destkv = (double *)X__Malloc((long)(sizeof(double)
00348 * (m+k+extra+1L)))) == NULL)return 0;
00349 if(same < k){
00350 for(i = 0L; i <= middex; i++) (*destkv)[i] = srckv[i];
00351 for(i = middex+1L; i <= middex+extra; i++)(*destkv)[i] = midVal;
00352 for(i = middex + k - same + 1L; i <= m + k + extra; i++){
00353 (*destkv)[i] = srckv[i - extra];
00354 }
00355 }
00356 else {
00357 for (i = 0L; i <= m + k; i++) (*destkv)[i] = srckv[i];
00358 }
00359 *splitPt = (extra < k) ? middex - 1L : middex;
00360 return extra;
00361 }
00362
00363 static void ProjectToLine(vector firstPt, vector lastPt, vector midPt){
00364
00365
00366
00367
00368 vector base, v0, vm;
00369 double fraction, denom;
00370 VECCOPY(firstPt,base)
00371 VECSUB(lastPt, base, v0)
00372 VECSUB(midPt, base, vm)
00373 denom = (v0[0]*v0[0]+v0[1]*v0[1]+v0[2]*v0[2]);
00374 fraction = (denom == 0.0) ? 0.0 : (DOT(v0,vm)/denom);
00375 midPt[0] = base[0] + fraction * v0[0];
00376 midPt[1] = base[1] + fraction * v0[1];
00377 midPt[2] = base[2] + fraction * v0[2];
00378 }
00379
00380 static void FixNormals(NurbsSurfSample *s0,
00381 NurbsSurfSample *s1,
00382 NurbsSurfSample *s2){
00383
00384
00385
00386
00387
00388
00389 BOOL goodnorm;
00390 long i, j, ok;
00391 double dist;
00392 NurbsSurfSample *V[3];
00393 vector norm;
00394 norm[0]=norm[1]=norm[2]=0.0;
00395 V[0] = s0; V[1] = s1; V[2] = s2;
00396
00397 for(ok = 0, goodnorm = FALSE;
00398 (ok < 3L) && !(goodnorm = (V[ok]->normLen > 0.0)); ok++);
00399 if (! goodnorm){
00400 norm[0] = 0.0; norm[0] = 0.0; norm[0] = 0.0;
00401 for (i = 0; i < 3L; i++){
00402 j = (i + 1L) % 3L;
00403 norm[0] += (V[i]->point[1] - V[j]->point[1]) * (V[i]->point[2] + V[j]->point[2]);
00404 norm[1] += (V[i]->point[2] - V[j]->point[2]) * (V[i]->point[0] + V[j]->point[0]);
00405 norm[2] += (V[i]->point[0] - V[j]->point[0]) * (V[i]->point[1] + V[j]->point[1]);
00406 }
00407 dist = sqrt(norm[0]*norm[0]+norm[1]*norm[1]+norm[2]*norm[2]);
00408 if(dist == 0.0)return;
00409 DIVPT(norm,dist);
00410 for (i = 0; i < 3; i++){
00411 VECCOPY(norm,V[i]->normal)
00412 V[i]->normLen = dist;
00413 }
00414 }
00415 else{
00416 for (i = 0; i < 3; i++)if ((i != ok) && (V[i]->normLen == 0.0))
00417 VECCOPY(V[ok]->normal,V[i]->normal);
00418 }
00419 return;
00420 }
00421
00422 static void AdjustNormal(NurbsSurfSample *samp){
00423
00424
00425
00426
00427
00428 samp->normLen = sqrt(samp->normal[0]*samp->normal[0]+
00429 samp->normal[1]*samp->normal[1]+
00430 samp->normal[2]*samp->normal[2]);
00431 if (samp->normLen < EPSILON)samp->normLen = 0.0;
00432 else DIVPT(samp->normal,samp->normLen);
00433 }
00434
00435 static void GetNormal(nurbs *n, long indV, long indU){
00436
00437
00438
00439
00440
00441 vector tmpL,tmpR;
00442 NurbsSurfSample *crnr;
00443 if ( (indU && indV) || ((! indU) && (!indV)) ){
00444 if (indU)
00445 crnr = &(n->cnn);
00446 else
00447 crnr = &(n->c00);
00448 DIVW( &(n->points[indV][(indU ? (indU-1L) : 1L)]), tmpL);
00449 DIVW( &(n->points[(indV ? (indV-1L) : 1L)][indU]), tmpR);
00450 }
00451 else {
00452 if(indU) crnr = &(n->c0n);
00453 else crnr = &(n->cn0);
00454 DIVW( &(n->points[indV][(indU ? (indU-1L) : 1L)]), tmpR);
00455 DIVW( &(n->points[(indV ? (indV-1L) : 1L)][indU]), tmpL);
00456 }
00457 VECSUB(tmpL,crnr->point,tmpL)
00458 VECSUB(tmpR,crnr->point,tmpR)
00459 CROSS(tmpL,tmpR,crnr->normal)
00460 AdjustNormal(crnr);
00461 }
00462
00463 static void MakeNewCorners(nurbs *parent,
00464 nurbs *kid0,
00465 nurbs *kid1,
00466 BOOL dirflag){
00467
00468
00469
00470
00471 DIVW( &(kid0->points[maxV(kid0)][maxU(kid0)]), kid0->cnn.point);
00472 GetNormal( kid0, maxV(kid0), maxU(kid0) );
00473 if(dirflag){
00474 kid0->strUn = FALSE;
00475 DIVW( &(kid0->points[0L][maxU(kid0)]), kid0->c0n.point);
00476 GetNormal(kid0, 0L, maxU(kid0));
00477
00478
00479
00480
00481 COPYVEC(kid1->c00.point,kid0->c0n.point)
00482 GetNormal( kid1, 0L, 0L );
00483 COPYVEC(kid1->cn0.point,kid0->cnn.point)
00484 GetNormal( kid1, maxV(kid1), 0L );
00485
00486
00487
00488
00489 if(parent->strV0)
00490 ProjectToLine((parent->c00.point),
00491 (parent->c0n.point),
00492 (kid0->c0n.point));
00493 if(parent->strVn)
00494 ProjectToLine((parent->cn0.point),
00495 (parent->cnn.point),
00496 (kid0->cnn.point));
00497 COPYVEC(kid1->c00.point,kid0->c0n.point)
00498 COPYVEC(kid1->cn0.point,kid0->cnn.point)
00499 kid1->strU0 = FALSE;
00500 }
00501 else{
00502 kid0->strVn = FALSE;
00503 DIVW( &(kid0->points[maxV(kid0)][0]), kid0->cn0.point);
00504 GetNormal( kid0, maxV(kid0), 0L );
00505 COPYVEC(kid1->c00.point,kid0->cn0.point)
00506 GetNormal( kid1, 0L, 0L );
00507 COPYVEC(kid1->c0n.point,kid0->cnn.point)
00508 GetNormal( kid1, 0L, maxU(kid1) );
00509 if(parent->strU0)
00510 ProjectToLine((parent->c00.point),
00511 (parent->cn0.point),
00512 (kid0->cn0.point));
00513 if(parent->strUn)
00514 ProjectToLine((parent->c0n.point),
00515 (parent->cnn.point),
00516 (kid0->cnn.point));
00517 COPYVEC(kid1->c00.point,kid0->cn0.point)
00518 COPYVEC(kid1->c0n.point,kid0->cnn.point)
00519 kid1->strV0 = FALSE;
00520 }
00521 }
00522
00523 static void SplitSurface(nurbs *parent,
00524 nurbs * kid0, nurbs * kid1,
00525 BOOL dirflag){
00526
00527
00528
00529
00530
00531
00532
00533 nurbs tmp;
00534 double *newkv;
00535 long i,j,splitPt;
00536
00537
00538
00539
00540
00541 tmp = *parent;
00542 if(dirflag){
00543 tmp.numU = parent->numU + SplitKV( parent->kvU,
00544 &newkv,
00545 &splitPt,
00546 maxU(parent),
00547 parent->orderU);
00548 AllocNurbs( &tmp, newkv, NULL );
00549 for (i = 0L; i < tmp.numV + tmp.orderV; i++)tmp.kvV[i] = parent->kvV[i];
00550 }
00551 else {
00552 tmp.numV = parent->numV + SplitKV( parent->kvV,
00553 &newkv,
00554 &splitPt,
00555 maxV(parent),
00556 parent->orderV );
00557 AllocNurbs( &tmp, NULL, newkv );
00558 for (i = 0L; i < tmp.numU + tmp.orderU; i++)tmp.kvU[i] = parent->kvU[i];
00559 }
00560 RefineSurface( parent, &tmp, dirflag );
00561
00562
00563
00564
00565
00566 *kid0 = *parent;
00567 kid0->numU = dirflag ? splitPt+1L : parent->numU;
00568 kid0->numV = dirflag ? parent->numV : splitPt+1L;
00569 kid0->kvU = kid0->kvV = NULL;
00570 kid0->points = NULL;
00571 AllocNurbs( kid0, NULL, NULL );
00572 for(i = 0L; i < kid0->numV; i++)
00573 for(j = 0L; j < kid0->numU; j++)
00574 kid0->points[i][j] = tmp.points[i][j];
00575 for(i = 0L; i < kid0->orderU + kid0->numU; i++)
00576 kid0->kvU[i] = tmp.kvU[i];
00577 for(i = 0L; i < kid0->orderV + kid0->numV; i++)
00578 kid0->kvV[i] = tmp.kvV[i];
00579
00580 splitPt++;
00581 *kid1 = *parent;
00582 kid1->numU = dirflag ? tmp.numU - splitPt : parent->numU;
00583 kid1->numV = dirflag ? parent->numV : tmp.numV - splitPt;
00584 kid1->kvU = kid1->kvV = NULL;
00585 kid1->points = NULL;
00586 AllocNurbs( kid1, NULL, NULL );
00587 for (i = 0L; i < kid1->numV; i++)
00588 for (j = 0L; j < kid1->numU; j++)
00589 kid1->points[i][j]
00590 = tmp.points[dirflag ? i: (i + splitPt) ][dirflag ? (j + splitPt) : j];
00591 for (i = 0L; i < kid1->orderU + kid1->numU; i++)
00592 kid1->kvU[i] = tmp.kvU[dirflag ? (i + splitPt) : i];
00593 for (i = 0L; i < kid1->orderV + kid1->numV; i++)
00594 kid1->kvV[i] = tmp.kvV[dirflag ? i : (i + splitPt)];
00595
00596 MakeNewCorners(parent,kid0,kid1,dirflag);
00597 ReleaseNurbs(&tmp);
00598 }
00599
00600 #define GETPT(i) (( dirflag ? &(n->points[crvInd][i]) : &(n->points[i][crvInd])))
00601
00602 static BOOL IsCurveStraight(nurbs *n,
00603 double tolerance,
00604 long crvInd,
00605 BOOL dirflag){
00606
00607
00608
00609
00610
00611 vector p,vec,prod;
00612 vector cp,e0;
00613 long i,last;
00614 double linelen,dist;
00615
00616 if((dirflag ? n->numU : n->numV) == 2L)return( TRUE );
00617 last = (dirflag ? n->numU : n->numV) - 1L;
00618 ScreenProject(GETPT( 0L ),e0);
00619
00620 linelen = 0.0;
00621 for(i = last; (i > 0L) && (linelen < EPSILON); i--){
00622 ScreenProject(GETPT(i),cp);
00623 VECSUB(cp,e0,vec)
00624 linelen = sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
00625 }
00626 DIVPT(vec,linelen);
00627 if(linelen > EPSILON){
00628 for(i = 1L; i <= last; i++){
00629
00630
00631
00632 ScreenProject(GETPT(i),cp);
00633 VECSUB(cp,e0,p)
00634 CROSS(p,vec,prod)
00635 dist=sqrt(prod[0]*prod[0]+prod[1]*prod[1]+prod[2]*prod[2]);
00636 if (dist > tolerance)return FALSE;
00637 }
00638 }
00639 return TRUE;
00640 }
00641
00642 static BOOL TestFlat(nurbs *n, double tolerance){
00643
00644
00645
00646
00647
00648 long i;
00649 BOOL straight;
00650 vector cp00,cp0n,cpn0,cpnn,planeEqn;
00651 double dist,d,dd;
00652
00653 if(! n->strU0)n->strU0 = IsCurveStraight( n, tolerance, 0L, FALSE);
00654 if(! n->strUn)n->strUn = IsCurveStraight( n, tolerance, maxU(n), FALSE);
00655 if(! n->strV0)n->strV0 = IsCurveStraight( n, tolerance, 0L, TRUE);
00656 if(! n->strVn)n->strVn = IsCurveStraight( n, tolerance, maxV(n), TRUE);
00657
00658 straight = TRUE;
00659 if( (! n->flatU) && (n->strV0) && (n->strVn) ){
00660 for(i = 1L;
00661 (i < maxV(n)) && (straight = IsCurveStraight( n, tolerance, i, TRUE ));
00662 i++);
00663 }
00664 if (straight && n->strV0 && n->strVn)n->flatU = TRUE;
00665 straight = TRUE;
00666 if( (! n->flatV) && (n->strU0) && (n->strUn) ){
00667 for(i = 1L;
00668 (i < maxU(n)) && (straight = IsCurveStraight( n, tolerance, i, FALSE ));
00669 i++);
00670 }
00671 if (straight && n->strU0 && n->strUn)n->flatV = TRUE;
00672 if( (! n->flatV) || (! n->flatU))return FALSE;
00673
00674 ScreenProject( &(n->points[0L][0L]), cp00);
00675 ScreenProject( &(n->points[0L][maxU(n)]), cp0n);
00676 ScreenProject( &(n->points[maxV(n)][0L]), cpn0);
00677 ScreenProject( &(n->points[maxV(n)][maxU(n)]), cpnn);
00678 VECSUB(cp0n,cp00,cp0n)
00679 VECSUB(cpn0,cp00,cpn0)
00680
00681
00682
00683
00684
00685 CROSS(cpn0,cp0n,planeEqn)
00686
00687 dd = 1.0/sqrt((planeEqn[0]*planeEqn[0]) +
00688 (planeEqn[1]*planeEqn[1]) +
00689 (planeEqn[2]*planeEqn[2]));
00690 VECSCALE(dd,planeEqn,planeEqn)
00691 d=DOT(planeEqn,cp00);
00692 dist=fabs(DOT(planeEqn,cpnn) - d);
00693 if(dist > tolerance)return FALSE;
00694 return TRUE;
00695 }
00696
00697 static void DoSubdivision(nurbs *n, double tolerance,
00698 BOOL dirflag, long level ){
00699
00700
00701
00702
00703
00704 nurbs left, right;
00705 if(TestFlat(n,tolerance)){
00706 EmitTriangles( n );
00707 }
00708 else {
00709 if ( ((! n->flatV) && (! n->flatU)) || ((n->flatV) && (n->flatU)) )
00710 dirflag = ! dirflag;
00711 else {
00712 if(n->flatU)
00713 dirflag = FALSE;
00714 else
00715 dirflag = TRUE;
00716 }
00717 SplitSurface(n, &left, &right, dirflag );
00718 DoSubdivision(&left, tolerance, dirflag, level + 1L );
00719 DoSubdivision(&right, tolerance, dirflag, level + 1L );
00720 ReleaseNurbs(&left);
00721 ReleaseNurbs(&right);
00722 }
00723 }
00724
00725 static void EmitSubdivision(nurbs * surf){
00726 surf->flatV = FALSE;
00727 surf->flatU = FALSE;
00728 surf->strU0 = FALSE;
00729 surf->strUn = FALSE;
00730 surf->strV0 = FALSE;
00731 surf->strVn = FALSE;
00732 DIVW( &(surf->points[0L][0L]), surf->c00.point );
00733 DIVW( &(surf->points[0L][surf->numU-1L]), surf->c0n.point );
00734 DIVW( &(surf->points[surf->numV-1L][0L]), surf->cn0.point );
00735 DIVW( &(surf->points[surf->numV-1L][surf->numU-1L]), surf->cnn.point );
00736 GetNormal(surf, 0L, 0L );
00737 GetNormal(surf, 0L, maxU(surf) );
00738 GetNormal(surf, maxV(surf), 0L );
00739 GetNormal(surf, maxV(surf), maxU(surf) );
00740
00741 DoSubdivision( surf, SubdivTolerance, TRUE, 0L );
00742 return;
00743 }
00744