Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

662 lines
20 KiB

  1. /**************************************************************************
  2. * *
  3. * Copyright (C) 1992, Silicon Graphics, Inc. *
  4. * *
  5. * These coded instructions, statements, and computer programs contain *
  6. * unpublished proprietary information of Silicon Graphics, Inc., and *
  7. * are protected by Federal copyright law. They may not be disclosed *
  8. * to third parties or copied or duplicated in any form, in whole or *
  9. * in part, without the prior written consent of Silicon Graphics, Inc. *
  10. * *
  11. **************************************************************************/
  12. /*
  13. * tobezier.c++ - $Revision: 1.6 $
  14. * Derrick Burns - 1991
  15. */
  16. #include "glimport.h"
  17. #include "myassert.h"
  18. #include "mystdio.h"
  19. #include "mystring.h"
  20. #include "quilt.h"
  21. #include "knotvect.h"
  22. /* local type definitions */
  23. struct Breakpt { /* breakpoints */
  24. Knot value; /* value */
  25. int multi; /* multiplicity */
  26. int def; /* deficit */
  27. };
  28. struct Knotspec { /* knotvector format */
  29. long order; /* order of spline */
  30. Knot_ptr inkbegin; /* input knot sequence */
  31. Knot_ptr inkend; /* location after last knot */
  32. Knot_ptr outkbegin; /* in-process knot subsequence */
  33. Knot_ptr outkend; /* location after last knot */
  34. Knot_ptr kleft; /* */
  35. Knot_ptr kright; /* */
  36. Knot_ptr kfirst; /* */
  37. Knot_ptr klast; /* */
  38. Knot_ptr sbegin; /* conversion factor values */
  39. Breakpt * bbegin; /* in-process breakpoints */
  40. Breakpt * bend; /* last breakpoint */
  41. int ncoords; /* coordinates per control point */
  42. int prestride; /* stride between input points */
  43. int poststride; /* stride between output points */
  44. int preoffset; /* scaled point offset */
  45. int postoffset; /* scaled point offset */
  46. int prewidth; /* width of dimension */
  47. int postwidth; /* width of dimension */
  48. int istransformed; /* was dimension transformed */
  49. Knotspec * next; /* next knotspec */
  50. Knotspec * kspectotrans; /* knotspec in transformation direction */
  51. Knotspec( void );
  52. ~Knotspec( void );
  53. void factors( void );
  54. void insert( REAL * );
  55. void preselect();
  56. void select( void );
  57. void copy( INREAL *, REAL * );
  58. void breakpoints( void );
  59. void knots( void );
  60. void transform( REAL * );
  61. void showpts( REAL * );
  62. void pt_io_copy( REAL *, INREAL * );
  63. void pt_oo_copy( REAL *, REAL * );
  64. void pt_oo_sum( REAL*, REAL*, REAL*, Knot, Knot );
  65. };
  66. struct Splinespec { /* a non-uniform tensor element */
  67. Splinespec( int );
  68. ~Splinespec(void);
  69. Knotspec *kspec; /* format of each param. dir. */
  70. int dim; /* domain dimension */
  71. REAL * outcpts; /* Bezier control points */
  72. void kspecinit( Knotvector & );
  73. void kspecinit( Knotvector &, Knotvector & );
  74. void select( void );
  75. void layout( long );
  76. void setupquilt( Quilt_ptr );
  77. void copy( INREAL * );
  78. void transform( void );
  79. };
  80. /*-----------------------------------------------------------------------------
  81. * Quilt::toBezier - convert from NURBS to rational Bezier
  82. *-----------------------------------------------------------------------------
  83. */
  84. void
  85. Quilt::toBezier(
  86. Knotvector& knotvector, /* a knot vector */
  87. INREAL *ctlpts, /* input contol points */
  88. long ncoords ) /* number of coordinates per control point */
  89. {
  90. Splinespec spline( 1 );
  91. spline.kspecinit( knotvector );
  92. spline.select();
  93. spline.layout( ncoords );
  94. spline.setupquilt( this );
  95. spline.copy( ctlpts );
  96. spline.transform();
  97. }
  98. void
  99. Quilt::toBezier(
  100. Knotvector& sknotvector, /* a knot vector */
  101. Knotvector& tknotvector, /* a knot vector */
  102. INREAL *ctlpts, /* input contol points */
  103. long ncoords ) /* number of coordinates per control point */
  104. {
  105. Splinespec spline( 2 );
  106. spline.kspecinit( sknotvector, tknotvector );
  107. spline.select();
  108. spline.layout( ncoords );
  109. spline.setupquilt( this );
  110. spline.copy( ctlpts );
  111. spline.transform();
  112. }
  113. Splinespec::Splinespec( int dimen )
  114. {
  115. dim = dimen;
  116. }
  117. Splinespec::~Splinespec( void )
  118. {
  119. /* Note: do NOT delete 'outcpts' here since its address (not contents)
  120. * is copied in 'cpts' in this file in function Splinespec::setupquilt().
  121. * This block of memory will eventually be deleted in file quilt.c++ in
  122. * function Quilt::deleteMe() through 'cpts' so do NOT delete it here!
  123. */
  124. Knotspec *ktrav= kspec; //start at beginning of list
  125. while (ktrav != 0) { //any items to delete?
  126. Knotspec *deleteThis= ktrav; //remember to delete this
  127. ktrav= ktrav->next; //go to next item if any
  128. delete deleteThis; //delete it
  129. }
  130. } /* ~Splinespec() */
  131. /*-----------------------------------------------------------------------------
  132. * Splinespec::kspecinit - initialize Splinespec structure
  133. *
  134. * Client: Quilt::toBezier
  135. *-----------------------------------------------------------------------------
  136. */
  137. void
  138. Splinespec::kspecinit( Knotvector& knotvector )
  139. {
  140. kspec = new Knotspec;
  141. kspec->inkbegin = knotvector.knotlist;
  142. kspec->inkend = knotvector.knotlist + knotvector.knotcount;
  143. kspec->prestride = (int) knotvector.stride;
  144. kspec->order = knotvector.order;
  145. kspec->next = NULL;
  146. }
  147. void
  148. Splinespec::kspecinit( Knotvector& sknotvector, Knotvector& tknotvector )
  149. {
  150. kspec = new Knotspec;
  151. Knotspec *tkspec = new Knotspec;
  152. kspec->inkbegin = sknotvector.knotlist;
  153. kspec->inkend = sknotvector.knotlist + sknotvector.knotcount;
  154. kspec->prestride = (int) sknotvector.stride;
  155. kspec->order = sknotvector.order;
  156. kspec->next = tkspec;
  157. tkspec->inkbegin = tknotvector.knotlist;
  158. tkspec->inkend = tknotvector.knotlist + tknotvector.knotcount;
  159. tkspec->prestride = (int) tknotvector.stride;
  160. tkspec->order = tknotvector.order;
  161. tkspec->next = NULL;
  162. }
  163. /*-----------------------------------------------------------------------------
  164. * Splinespec::select - select the subsegments to copy
  165. *
  166. * Client: gl_quilt_to_bezier
  167. *-----------------------------------------------------------------------------
  168. */
  169. void
  170. Splinespec::select( )
  171. {
  172. for( Knotspec *knotspec = kspec; knotspec; knotspec = knotspec->next ) {
  173. knotspec->preselect();
  174. knotspec->select();
  175. }
  176. }
  177. /*-----------------------------------------------------------------------------
  178. * Splinespec::layout -
  179. *
  180. * Client: gl_quilt_to_bezier
  181. *-----------------------------------------------------------------------------
  182. */
  183. void
  184. Splinespec::layout( long ncoords )
  185. {
  186. long stride = ncoords;
  187. for( Knotspec *knotspec = kspec; knotspec; knotspec=knotspec->next ) {
  188. knotspec->poststride = (int) stride;
  189. stride *= (long)((knotspec->bend-knotspec->bbegin)*knotspec->order + knotspec->postoffset);
  190. knotspec->preoffset *= knotspec->prestride;
  191. knotspec->prewidth *= knotspec->poststride;
  192. knotspec->postwidth *= knotspec->poststride;
  193. knotspec->postoffset *= knotspec->poststride;
  194. knotspec->ncoords = (int) ncoords;
  195. }
  196. outcpts = new REAL[stride];
  197. assert( outcpts != 0 );
  198. }
  199. /*-----------------------------------------------------------------------------
  200. * Splinespec::copy - copy the control points of current subobject
  201. *
  202. * Client: gl_quilt_to_bezier
  203. *-----------------------------------------------------------------------------
  204. */
  205. void
  206. Splinespec::copy( INREAL *incpts )
  207. {
  208. kspec->copy( incpts, outcpts );
  209. }
  210. /*-----------------------------------------------------------------------------
  211. * Splinespec::setupquilt - assign all quilt variables from knotspec
  212. *
  213. * Client: gl_quilt_to_bezier
  214. *-----------------------------------------------------------------------------
  215. */
  216. void
  217. Splinespec::setupquilt( Quilt_ptr quilt )
  218. {
  219. Quiltspec_ptr qspec = quilt->qspec;
  220. quilt->eqspec = qspec + dim;
  221. for( Knotspec *knotspec = kspec; knotspec; knotspec=knotspec->next, qspec++ ) {
  222. qspec->stride = knotspec->poststride;
  223. qspec->width = knotspec->bend - knotspec->bbegin;
  224. qspec->order = (int) knotspec->order;
  225. qspec->offset = knotspec->postoffset;
  226. qspec->index = 0;
  227. qspec->bdry[0] = (knotspec->kleft == knotspec->kfirst) ? 1 : 0;
  228. qspec->bdry[1] = (knotspec->kright == knotspec->klast) ? 1 : 0;
  229. qspec->breakpoints = new Knot[qspec->width+1];
  230. Knot_ptr k = qspec->breakpoints;
  231. for( Breakpt *bk = knotspec->bbegin; bk <= knotspec->bend; bk++ )
  232. *(k++) = bk->value;
  233. }
  234. quilt->cpts = outcpts;
  235. quilt->next = 0;
  236. }
  237. /*-----------------------------------------------------------------------------
  238. * Splinespec::transform - convert a spline to Bezier format
  239. *
  240. * Client: gl_quilt_to_bezier
  241. *-----------------------------------------------------------------------------
  242. */
  243. void
  244. Splinespec::transform( void )
  245. {
  246. for( Knotspec *knotspec = kspec; knotspec; knotspec=knotspec->next )
  247. knotspec->istransformed = 0;
  248. for( knotspec = kspec; knotspec; knotspec=knotspec->next ) {
  249. for( Knotspec *kspec2 = kspec; kspec2; kspec2=kspec2->next )
  250. kspec2->kspectotrans = knotspec;
  251. kspec->transform( outcpts );
  252. knotspec->istransformed = 1;
  253. }
  254. }
  255. /*-----------------------------------------------------------------------------
  256. * Knotspec::Knotspec - constuct a knot spec
  257. *-----------------------------------------------------------------------------
  258. */
  259. Knotspec::Knotspec( void )
  260. {
  261. bbegin = 0;
  262. sbegin = 0;
  263. outkbegin = 0;
  264. }
  265. /*-----------------------------------------------------------------------------
  266. * Knotspec::copy - copy the control points along minor direction
  267. *
  268. * Client: Splinespec::copy
  269. *-----------------------------------------------------------------------------
  270. */
  271. void
  272. Knotspec::copy( INREAL *inpt, REAL *outpt )
  273. {
  274. inpt = (INREAL *) (((char *) inpt) + preoffset);
  275. if( next ) {
  276. for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride ) {
  277. next->copy( inpt, outpt );
  278. inpt = (INREAL *) (((char *) inpt) + prestride);
  279. }
  280. } else {
  281. for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride ) {
  282. pt_io_copy( outpt, inpt );
  283. inpt = (INREAL *) (((char *) inpt) + prestride);
  284. }
  285. }
  286. }
  287. /*-----------------------------------------------------------------------------
  288. * Knotspec::showpts - print out points before transformation
  289. *
  290. * Client: Knotspec::select
  291. *-----------------------------------------------------------------------------
  292. */
  293. void
  294. Knotspec::showpts( REAL *outpt )
  295. {
  296. if( next ) {
  297. for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride )
  298. next->showpts( outpt );
  299. } else {
  300. for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride )
  301. dprintf( "show %g %g %g\n", outpt[0], outpt[1], outpt[2] );
  302. }
  303. }
  304. /*-----------------------------------------------------------------------------
  305. * Knotspec::factors - precompute scale factors
  306. * - overwrites knot vector, actual new knot vector is NOT produced
  307. *
  308. * Client: Knotspec::select
  309. *-----------------------------------------------------------------------------
  310. */
  311. void
  312. Knotspec::factors( void )
  313. {
  314. Knot *mid = (outkend - 1) - order + bend->multi;
  315. Knot_ptr fptr = sbegin;
  316. for( Breakpt *bpt = bend; bpt >= bbegin; bpt-- ) {
  317. mid -= bpt->multi; // last knot less than knot to insert
  318. int def = bpt->def - 1; // number of knots to insert
  319. if( def <= 0 ) continue;
  320. Knot kv = bpt->value; // knot to insert
  321. Knot *kf = (mid-def) + (order-1);
  322. for( Knot *kl = kf + def; kl != kf; kl-- ) {
  323. Knot *kh, *kt;
  324. for( kt=kl, kh=mid; kt != kf; kh--, kt-- )
  325. *(fptr++) = (kv - *kh) / (*kt - *kh);
  326. *kl = kv;
  327. }
  328. }
  329. }
  330. /*-----------------------------------------------------------------------------
  331. * Knotspec::insert - convert subobject in direction of kspec into Bezier
  332. *
  333. * Client: Knotspec::transform
  334. *-----------------------------------------------------------------------------
  335. */
  336. void
  337. Knotspec::insert( REAL *p )
  338. {
  339. Knot_ptr fptr = sbegin;
  340. REAL *srcpt = p + prewidth - poststride;
  341. REAL *dstpt = p + postwidth + postoffset - poststride;
  342. Breakpt *bpt = bend;
  343. for( REAL *pend = srcpt - poststride*bpt->def; srcpt != pend; pend +=poststride ) {
  344. REAL *p1 = srcpt;
  345. for( REAL *p2 = srcpt-poststride; p2 != pend; p1 = p2, p2 -= poststride ) {
  346. pt_oo_sum( p1, p1, p2, *fptr, 1.0-*fptr );
  347. fptr++;
  348. }
  349. }
  350. for( --bpt; bpt >= bbegin; bpt-- ) {
  351. for( int multi = bpt->multi; multi > 0; multi-- ) {
  352. pt_oo_copy( dstpt, srcpt );
  353. dstpt -= poststride;
  354. srcpt -= poststride;
  355. }
  356. for( REAL *pend = srcpt - poststride*bpt->def; srcpt != pend; pend +=poststride, dstpt-=poststride ) {
  357. pt_oo_copy( dstpt, srcpt );
  358. REAL *p1 = srcpt;
  359. for( REAL *p2 = srcpt-poststride; p2 != pend; p1=p2, p2 -= poststride ) {
  360. pt_oo_sum( p1, p1, p2, *fptr, 1.0-*fptr );
  361. fptr++;
  362. }
  363. }
  364. }
  365. }
  366. /*-----------------------------------------------------------------------------
  367. * Knotspec::preselect - initialize kspec for processing
  368. *
  369. * Client: Splinespec::select
  370. *-----------------------------------------------------------------------------
  371. */
  372. void
  373. Knotspec::preselect( void )
  374. {
  375. Knot kval;
  376. /* position klast after last knot of "last" breakpoint */
  377. for( klast = inkend - order, kval = *klast; klast != inkend; klast++ )
  378. if( ! identical( *klast, kval ) ) break;
  379. /* position kfirst after last knot of "first" breakpoint */
  380. for( kfirst = inkbegin+order-1, kval= *kfirst; kfirst != inkend; kfirst++ )
  381. if( ! identical( *kfirst, kval ) ) break;
  382. /* compute multiplicity of first breakpoint */
  383. for( Knot_ptr k = kfirst - 1; k >= inkbegin; k-- )
  384. if( ! identical( kval, *k ) ) break;
  385. k++;
  386. /* allocate space for breakpoints -
  387. use worst case estimate on number of breakpoints */
  388. bbegin = new Breakpt[(klast - kfirst)+1];
  389. /* record multiplicity and value of first breakpoint */
  390. bbegin->multi = kfirst - k;
  391. bbegin->value = kval;
  392. bend = bbegin;
  393. kleft = kright = kfirst;
  394. }
  395. /*-----------------------------------------------------------------------------
  396. * Knotspec::select - Knotspec::select segments and precompute scale factors
  397. *
  398. * Client: Splinespec::select
  399. *-----------------------------------------------------------------------------
  400. */
  401. void
  402. Knotspec::select( void )
  403. {
  404. breakpoints();
  405. knots();
  406. factors();
  407. preoffset = kleft - (inkbegin + order);
  408. postwidth = (int)((bend - bbegin) * order);
  409. prewidth = (int)((outkend - outkbegin) - order);
  410. postoffset = (bbegin->def > 1) ? (bbegin->def-1) : 0;
  411. }
  412. /*-----------------------------------------------------------------------------
  413. * Knotspec::breakpoints - compute breakpoints for knotspec
  414. *
  415. * Client: Knotspec::select
  416. *-----------------------------------------------------------------------------
  417. */
  418. void
  419. Knotspec::breakpoints( void )
  420. {
  421. Breakpt *ubpt = bbegin;
  422. Breakpt *ubend = bend;
  423. long nfactors = 0;
  424. ubpt->value = ubend->value;
  425. ubpt->multi = ubend->multi;
  426. kleft = kright;
  427. for( ; kright != klast; kright++ ) {
  428. if ( identical(*kright,ubpt->value) ) {
  429. (ubpt->multi)++;
  430. } else {
  431. ubpt->def = (int) (order - ubpt->multi);
  432. nfactors += (ubpt->def * (ubpt->def - 1)) / 2;
  433. (++ubpt)->value = *kright;
  434. ubpt->multi = 1;
  435. }
  436. }
  437. ubpt->def = (int) (order - ubpt->multi);
  438. nfactors += (ubpt->def * (ubpt->def - 1)) / 2;
  439. bend = ubpt;
  440. if( nfactors ) {
  441. sbegin = new Knot[nfactors];
  442. } else {
  443. sbegin = NULL;
  444. }
  445. }
  446. /*-----------------------------------------------------------------------------
  447. * Knotspec::knots - copy relevant subsequence of knots into temporary area
  448. *
  449. * Client: Knotspec::select
  450. *-----------------------------------------------------------------------------
  451. */
  452. void
  453. Knotspec::knots( void )
  454. {
  455. Knot_ptr inkpt = kleft - order;
  456. Knot_ptr inkend = kright + bend->def;
  457. /* allocate space for knots and factors */
  458. outkbegin = new Knot[inkend-inkpt];
  459. for( Knot_ptr outkpt = outkbegin; inkpt != inkend; inkpt++, outkpt++ )
  460. *outkpt = *inkpt;
  461. outkend = outkpt;
  462. }
  463. /*-----------------------------------------------------------------------------
  464. * Knotspec::transform - convert a spline along a given direction
  465. *
  466. * Client: Splienspec::transform
  467. *-----------------------------------------------------------------------------
  468. */
  469. void
  470. Knotspec::transform( REAL *p )
  471. {
  472. if( next ) {
  473. if( this == kspectotrans ) {
  474. next->transform( p );
  475. } else {
  476. if( istransformed ) {
  477. p += postoffset;
  478. for( REAL *pend = p + postwidth; p != pend; p += poststride )
  479. next->transform( p );
  480. } else {
  481. REAL *pend = p + prewidth;
  482. for( ; p != pend; p += poststride )
  483. next->transform( p );
  484. }
  485. }
  486. } else {
  487. if( this == kspectotrans ) {
  488. insert( p );
  489. } else {
  490. if( istransformed ) {
  491. p += postoffset;
  492. for( REAL *pend = p + postwidth; p != pend; p += poststride )
  493. kspectotrans->insert( p );
  494. } else {
  495. REAL *pend = p + prewidth;
  496. for( ; p != pend; p += poststride )
  497. kspectotrans->insert( p );
  498. }
  499. }
  500. }
  501. }
  502. /*-----------------------------------------------------------------------------
  503. * Knotspec::~Knotspec - free space alocated for knotspec
  504. *-----------------------------------------------------------------------------
  505. */
  506. Knotspec::~Knotspec( void )
  507. {
  508. if( bbegin ) delete[] bbegin;
  509. if( sbegin ) delete[] sbegin;
  510. if( outkbegin ) delete[] outkbegin;
  511. }
  512. /*-----------------------------------------------------------------------------
  513. * pt_io_copy - make internal copy of input cntrl pt. of x coords
  514. *-----------------------------------------------------------------------------
  515. */
  516. void
  517. Knotspec::pt_io_copy( REAL *topt, INREAL *frompt )
  518. {
  519. switch( ncoords ) {
  520. case 4:
  521. topt[3] = (REAL) frompt[3];
  522. case 3:
  523. topt[2] = (REAL) frompt[2];
  524. case 2:
  525. topt[1] = (REAL) frompt[1];
  526. case 1:
  527. topt[0] = (REAL) frompt[0];
  528. break;
  529. default: {
  530. for( int i = 0; i < ncoords; i++ )
  531. *topt++ = (REAL) *frompt++;
  532. }
  533. }
  534. }
  535. /*-----------------------------------------------------------------------------
  536. * pt_oo_copy - make internal copy of internal cntrl pt. of x coords
  537. *-----------------------------------------------------------------------------
  538. */
  539. void
  540. Knotspec::pt_oo_copy( REAL *topt, REAL *frompt )
  541. {
  542. switch( ncoords ) {
  543. case 4:
  544. topt[3] = frompt[3];
  545. case 3:
  546. topt[2] = frompt[2];
  547. case 2:
  548. topt[1] = frompt[1];
  549. case 1:
  550. topt[0] = frompt[0];
  551. break;
  552. default:
  553. memcpy( topt, frompt, ncoords * sizeof( REAL ) );
  554. }
  555. }
  556. /*-----------------------------------------------------------------------------
  557. * pt_oo_sum - compute affine combination of internal cntrl pts
  558. *-----------------------------------------------------------------------------
  559. */
  560. void
  561. Knotspec::pt_oo_sum( REAL *x, REAL *y, REAL *z, Knot a, Knot b )
  562. {
  563. switch( ncoords ) {
  564. case 4:
  565. x[3] = a * y[3] + b * z[3];
  566. case 3:
  567. x[2] = a * y[2] + b * z[2];
  568. case 2:
  569. x[1] = a * y[1] + b * z[1];
  570. case 1:
  571. x[0] = a * y[0] + b * z[0];
  572. break;
  573. default: {
  574. for( int i = 0; i < ncoords; i++ )
  575. *x++ = a * *y++ + b * *z++;
  576. }
  577. }
  578. }