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