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.

249 lines
7.0 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. * monotonizer.c++ - $Revision: 1.5 $
  14. * Derrick Burns - 1991
  15. */
  16. #include "glimport.h"
  17. #include "mystdio.h"
  18. #include "myassert.h"
  19. #include "arc.h"
  20. #include "arctess.h"
  21. #include "bezierar.h"
  22. #include "bin.h"
  23. #include "mapdesc.h"
  24. #include "nurbscon.h"
  25. #include "subdivid.h"
  26. /*-----------------------------------------------------------------------------
  27. * Subdivider::decompose - break all curves into monotone arcs
  28. *-----------------------------------------------------------------------------
  29. */
  30. int
  31. Subdivider::decompose( Bin& bin, REAL geo_stepsize )
  32. {
  33. for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
  34. if( ! jarc->isTessellated() ) {
  35. /* points have not been transformed, therefore they may be either
  36. homogeneous or inhomogeneous */
  37. tessellate( jarc, geo_stepsize );
  38. if( jarc->isDisconnected() || jarc->next->isDisconnected() )
  39. return 1;
  40. }
  41. }
  42. for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
  43. monotonize( jarc, bin );
  44. }
  45. #ifndef NDEBUG
  46. for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
  47. assert( isMonotone( jarc ) != 0 );
  48. }
  49. #endif
  50. return 0;
  51. }
  52. void
  53. Subdivider::tessellate( Arc_ptr jarc, REAL geo_stepsize )
  54. {
  55. BezierArc *b = jarc->bezierArc;
  56. Mapdesc *mapdesc = b->mapdesc;
  57. if( mapdesc->isRational() ) {
  58. REAL max = mapdesc->calcVelocityRational( b->cpts, b->stride, b->order );
  59. REAL arc_stepsize = (max > 1.0) ? (1.0/max) : 1.0;
  60. if( jarc->bezierArc->order != 2 )
  61. arctessellator.tessellateNonlinear( jarc, geo_stepsize, arc_stepsize, 1 );
  62. else {
  63. arctessellator.tessellateLinear( jarc, geo_stepsize, arc_stepsize, 1 );
  64. }
  65. } else {
  66. REAL max = mapdesc->calcVelocityNonrational( b->cpts, b->stride, b->order );
  67. REAL arc_stepsize = (max > 1.0) ? (1.0/max) : 1.0;
  68. if( jarc->bezierArc->order != 2 )
  69. arctessellator.tessellateNonlinear( jarc, geo_stepsize, arc_stepsize, 0 );
  70. else {
  71. arctessellator.tessellateLinear( jarc, geo_stepsize, arc_stepsize, 0 );
  72. }
  73. }
  74. }
  75. /*-------------------------------------------------------------------------
  76. * Subdivider::monotonize - break up a jordan arc into s,t-monotone
  77. * components. This code will remove degenerate segments, including
  78. * arcs of only a single point.
  79. *-------------------------------------------------------------------------
  80. */
  81. void
  82. Subdivider::monotonize( Arc_ptr jarc, Bin& bin )
  83. {
  84. TrimVertex *firstvert = jarc->pwlArc->pts;
  85. TrimVertex *lastvert = firstvert + (jarc->pwlArc->npts - 1);
  86. long uid = jarc->nuid;
  87. arc_side side = jarc->getside();
  88. dir sdir = none;
  89. dir tdir = none;
  90. int degenerate = 1;
  91. int nudegenerate;
  92. int change;
  93. for( TrimVertex *vert = firstvert; vert != lastvert; vert++ ) {
  94. nudegenerate = 1;
  95. change = 0;
  96. /* check change relative to s axis, clear degenerate bit if needed */
  97. REAL sdiff = vert[1].param[0] - vert[0].param[0];
  98. if( sdiff == 0 ) {
  99. if( sdir != same ) {
  100. sdir = same;
  101. change = 1;
  102. }
  103. } else if( sdiff < 0.0 ) {
  104. if( sdir != down ) {
  105. sdir = down;
  106. change = 1;
  107. }
  108. nudegenerate = 0;
  109. } else {
  110. if( sdir != up ) {
  111. sdir = up;
  112. change = 1;
  113. }
  114. nudegenerate = 0;
  115. }
  116. /* check change relative to t axis, clear degenerate bit if needed */
  117. REAL tdiff = vert[1].param[1] - vert[0].param[1];
  118. if( tdiff == 0 ) {
  119. if( tdir != same ) {
  120. tdir = same;
  121. change = 1;
  122. }
  123. } else if( tdiff < 0.0 ) {
  124. if( tdir != down ) {
  125. tdir = down;
  126. change = 1;
  127. }
  128. nudegenerate = 0;
  129. } else {
  130. if( tdir != up ) {
  131. tdir = up;
  132. change = 1;
  133. }
  134. nudegenerate = 0;
  135. }
  136. if( change ) {
  137. if( ! degenerate ) {
  138. /* make last segment into separate pwl curve */
  139. jarc->pwlArc->npts = vert - firstvert + 1;
  140. #ifdef NT
  141. // This works under NT.
  142. Arc_ptr prevjarc;
  143. prevjarc = jarc;
  144. jarc = new(arcpool) Arc( side, uid );
  145. jarc->append( prevjarc );
  146. #else
  147. // However this doesn't.
  148. jarc = new(arcpool) Arc( side, uid )->append( jarc );
  149. #endif
  150. jarc->pwlArc = new(pwlarcpool) PwlArc();
  151. bin.addarc( jarc );
  152. }
  153. firstvert = jarc->pwlArc->pts = vert;
  154. degenerate = nudegenerate;
  155. }
  156. }
  157. jarc->pwlArc->npts = vert - firstvert + 1;
  158. if( degenerate ) {
  159. /* remove jarc from circularly linked list */
  160. jarc->prev->next = jarc->next;
  161. jarc->next->prev = jarc->prev;
  162. assert( jarc->prev->check( ) != 0 );
  163. assert( jarc->next->check( ) != 0 );
  164. /* remove jarc from bin */
  165. bin.remove_this_arc( jarc );
  166. jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
  167. jarc->deleteMe( arcpool );
  168. }
  169. }
  170. /*-------------------------------------------------------------------------
  171. * Subdivider::isMonotone - return true if arc is monotone AND non-degenerate
  172. *-------------------------------------------------------------------------
  173. */
  174. int
  175. Subdivider::isMonotone( Arc_ptr jarc )
  176. {
  177. TrimVertex *firstvert = jarc->pwlArc->pts;
  178. TrimVertex *lastvert = firstvert + (jarc->pwlArc->npts - 1);
  179. if( firstvert == lastvert ) return 1;
  180. TrimVertex *vert = firstvert;
  181. enum dir sdir;
  182. enum dir tdir;
  183. REAL diff = vert[1].param[0] - vert[0].param[0];
  184. if( diff == 0.0 )
  185. sdir = same;
  186. else if( diff < 0.0 )
  187. sdir = down;
  188. else
  189. sdir = up;
  190. diff = vert[1].param[1] - vert[0].param[1];
  191. if( diff == 0.0 )
  192. tdir = same;
  193. else if( diff < 0.0 )
  194. tdir = down;
  195. else
  196. tdir = up;
  197. if( (sdir == same) && (tdir == same) ) return 0;
  198. for( ++vert ; vert != lastvert; vert++ ) {
  199. diff = vert[1].param[0] - vert[0].param[0];
  200. if( diff == 0.0 ) {
  201. if( sdir != same ) return 0;
  202. } else if( diff < 0.0 ) {
  203. if( sdir != down ) return 0;
  204. } else {
  205. if( sdir != up ) return 0;
  206. }
  207. diff = vert[1].param[1] - vert[0].param[1];
  208. if( diff == 0.0 ) {
  209. if( tdir != same ) return 0;
  210. } else if( diff < 0.0 ) {
  211. if( tdir != down ) return 0;
  212. } else {
  213. if( tdir != up ) return 0;
  214. }
  215. }
  216. return 1;
  217. }