source: trunk/src/opengl/glu/nurbs/internals/monotonizer.cpp

Last change on this file was 2689, checked in by jeroen, 26 years ago

* empty log message *

File size: 7.9 KB
Line 
1/* $Id: monotonizer.cpp,v 1.1 2000-02-09 08:50:26 jeroen Exp $ */
2/*
3** License Applicability. Except to the extent portions of this file are
4** made subject to an alternative license as permitted in the SGI Free
5** Software License B, Version 1.0 (the "License"), the contents of this
6** file are subject only to the provisions of the License. You may not use
7** this file except in compliance with the License. You may obtain a copy
8** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
9** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
10**
11** http://oss.sgi.com/projects/FreeB
12**
13** Note that, as provided in the License, the Software is distributed on an
14** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
15** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
16** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
17** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
18**
19** Original Code. The Original Code is: OpenGL Sample Implementation,
20** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
21** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
22** Copyright in any portions created by third parties is as indicated
23** elsewhere herein. All Rights Reserved.
24**
25** Additional Notice Provisions: The application programming interfaces
26** established by SGI in conjunction with the Original Code are The
27** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
28** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
29** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
30** Window System(R) (Version 1.3), released October 19, 1998. This software
31** was created using the OpenGL(R) version 1.2.1 Sample Implementation
32** published by SGI, but has not been independently verified as being
33** compliant with the OpenGL(R) version 1.2.1 Specification.
34*/
35
36/*
37 * monotonizer.c++
38 *
39 * $Date: 2000-02-09 08:50:26 $ $Revision: 1.1 $
40 * $Header: /home/ktk/tmp/odin/2007/netlabs.cvs/odin32/src/opengl/glu/nurbs/internals/monotonizer.cpp,v 1.1 2000-02-09 08:50:26 jeroen Exp $
41 */
42
43#include "glimports.h"
44#include "mystdio.h"
45#include "myassert.h"
46#include "arc.h"
47#include "arctess.h"
48#include "bezierarc.h"
49#include "bin.h"
50#include "mapdesc.h"
51#include "nurbsconsts.h"
52#include "subdivider.h"
53
54/*-----------------------------------------------------------------------------
55 * Subdivider::decompose - break all curves into monotone arcs
56 *-----------------------------------------------------------------------------
57 */
58int
59Subdivider::decompose( Bin& bin, REAL geo_stepsize )
60{
61 Arc_ptr jarc;
62 for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
63 if( ! jarc->isTessellated() ) {
64 /* points have not been transformed, therefore they may be either
65 homogeneous or inhomogeneous */
66 tessellate( jarc, geo_stepsize );
67 if( jarc->isDisconnected() || jarc->next->isDisconnected() )
68 return 1;
69 }
70 }
71
72 for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
73 monotonize( jarc, bin );
74 }
75
76#ifndef NDEBUG
77 for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
78 assert( isMonotone( jarc ) != 0 );
79 }
80#endif
81
82 return 0;
83}
84
85void
86Subdivider::tessellate( Arc_ptr jarc, REAL geo_stepsize )
87{
88 BezierArc *b = jarc->bezierArc;
89 Mapdesc *mapdesc = b->mapdesc;
90
91 if( mapdesc->isRational() ) {
92 REAL max = mapdesc->calcVelocityRational( b->cpts, b->stride, b->order );
93 REAL arc_stepsize = (max > 1.0) ? (1.0/max) : 1.0;
94 if( jarc->bezierArc->order != 2 )
95 arctessellator.tessellateNonlinear( jarc, geo_stepsize, arc_stepsize, 1 );
96 else {
97 arctessellator.tessellateLinear( jarc, geo_stepsize, arc_stepsize, 1 );
98 }
99 } else {
100 REAL max = mapdesc->calcVelocityNonrational( b->cpts, b->stride, b->order );
101 REAL arc_stepsize = (max > 1.0) ? (1.0/max) : 1.0;
102 if( jarc->bezierArc->order != 2 )
103 arctessellator.tessellateNonlinear( jarc, geo_stepsize, arc_stepsize, 0 );
104 else {
105 arctessellator.tessellateLinear( jarc, geo_stepsize, arc_stepsize, 0 );
106 }
107 }
108}
109
110/*-------------------------------------------------------------------------
111 * Subdivider::monotonize - break up a jordan arc into s,t-monotone
112 * components. This code will remove degenerate segments, including
113 * arcs of only a single point.
114 *-------------------------------------------------------------------------
115 */
116void
117Subdivider::monotonize( Arc_ptr jarc, Bin& bin )
118{
119 TrimVertex *firstvert = jarc->pwlArc->pts;
120 TrimVertex *lastvert = firstvert + (jarc->pwlArc->npts - 1);
121 long uid = jarc->nuid;
122 arc_side side = jarc->getside();
123 dir sdir = none;
124 dir tdir = none;
125 int degenerate = 1;
126
127 int nudegenerate;
128 int change;
129
130 TrimVertex *vert;
131 for( vert = firstvert; vert != lastvert; vert++ ) {
132
133 nudegenerate = 1;
134 change = 0;
135
136 /* check change relative to s axis, clear degenerate bit if needed */
137 REAL sdiff = vert[1].param[0] - vert[0].param[0];
138 if( sdiff == 0 ) {
139 if( sdir != same ) {
140 sdir = same;
141 change = 1;
142 }
143 } else if( sdiff < 0.0 ) {
144 if( sdir != down ) {
145 sdir = down;
146 change = 1;
147 }
148 nudegenerate = 0;
149 } else {
150 if( sdir != up ) {
151 sdir = up;
152 change = 1;
153 }
154 nudegenerate = 0;
155 }
156
157 /* check change relative to t axis, clear degenerate bit if needed */
158 REAL tdiff = vert[1].param[1] - vert[0].param[1];
159 if( tdiff == 0 ) {
160 if( tdir != same ) {
161 tdir = same;
162 change = 1;
163 }
164 } else if( tdiff < 0.0 ) {
165 if( tdir != down ) {
166 tdir = down;
167 change = 1;
168 }
169 nudegenerate = 0;
170 } else {
171 if( tdir != up ) {
172 tdir = up;
173 change = 1;
174 }
175 nudegenerate = 0;
176 }
177
178 if( change ) {
179 if( ! degenerate ) {
180 /* make last segment into separate pwl curve */
181 jarc->pwlArc->npts = vert - firstvert + 1;
182 jarc = (new(arcpool) Arc( side, uid ))->append( jarc );
183 jarc->pwlArc = new(pwlarcpool) PwlArc();
184 bin.addarc( jarc );
185 }
186 firstvert = jarc->pwlArc->pts = vert;
187 degenerate = nudegenerate;
188 }
189 }
190 jarc->pwlArc->npts = vert - firstvert + 1;
191
192 if( degenerate ) {
193 /* remove jarc from circularly linked list */
194 jarc->prev->next = jarc->next;
195 jarc->next->prev = jarc->prev;
196
197 assert( jarc->prev->check( ) != 0 );
198 assert( jarc->next->check( ) != 0 );
199
200 /* remove jarc from bin */
201 bin.remove_this_arc( jarc );
202
203 jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
204 jarc->deleteMe( arcpool );
205 }
206}
207
208/*-------------------------------------------------------------------------
209 * Subdivider::isMonotone - return true if arc is monotone AND non-degenerate
210 *-------------------------------------------------------------------------
211 */
212int
213Subdivider::isMonotone( Arc_ptr jarc )
214{
215 TrimVertex *firstvert = jarc->pwlArc->pts;
216 TrimVertex *lastvert = firstvert + (jarc->pwlArc->npts - 1);
217
218 if( firstvert == lastvert ) return 1;
219
220 TrimVertex *vert = firstvert;
221 enum dir sdir;
222 enum dir tdir;
223
224 REAL diff = vert[1].param[0] - vert[0].param[0];
225 if( diff == 0.0 )
226 sdir = same;
227 else if( diff < 0.0 )
228 sdir = down;
229 else
230 sdir = up;
231
232 diff = vert[1].param[1] - vert[0].param[1];
233 if( diff == 0.0 )
234 tdir = same;
235 else if( diff < 0.0 )
236 tdir = down;
237 else
238 tdir = up;
239
240 if( (sdir == same) && (tdir == same) ) return 0;
241
242 for( ++vert ; vert != lastvert; vert++ ) {
243 diff = vert[1].param[0] - vert[0].param[0];
244 if( diff == 0.0 ) {
245 if( sdir != same ) return 0;
246 } else if( diff < 0.0 ) {
247 if( sdir != down ) return 0;
248 } else {
249 if( sdir != up ) return 0;
250 }
251
252 diff = vert[1].param[1] - vert[0].param[1];
253 if( diff == 0.0 ) {
254 if( tdir != same ) return 0;
255 } else if( diff < 0.0 ) {
256 if( tdir != down ) return 0;
257 } else {
258 if( tdir != up ) return 0;
259 }
260 }
261 return 1;
262}
263
Note: See TracBrowser for help on using the repository browser.