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 *monoPolyPart.C
37f220fa62Smrg *
38f220fa62Smrg *To partition a v-monotone polygon into some uv-monotone polygons.
39f220fa62Smrg *The algorithm is different from the general monotone partition algorithm.
40f220fa62Smrg *while the general monotone partition algorithm works for this special case,
41f220fa62Smrg *but it is more expensive (O(nlogn)). The algorithm implemented here takes
42f220fa62Smrg *advantage of the fact that the input is a v-monotone polygon and it is
43f220fa62Smrg *conceptually simpler and  computationally cheaper (a linear time algorithm).
44f220fa62Smrg *The algorithm is described in Zicheng Liu's  paper
45f220fa62Smrg * "Quality-Oriented Linear Time Tessellation".
46f220fa62Smrg */
47f220fa62Smrg
48f220fa62Smrg#include <stdlib.h>
49f220fa62Smrg#include <stdio.h>
50f220fa62Smrg#include "directedLine.h"
51f220fa62Smrg#include "monoPolyPart.h"
52f220fa62Smrg
53f220fa62Smrg/*a vertex is u_maximal if both of its two neightbors are to the left of this
54f220fa62Smrg *vertex
55f220fa62Smrg */
56f220fa62Smrgstatic Int is_u_maximal(directedLine* v)
57f220fa62Smrg{
58f220fa62Smrg  if (compV2InX(v->getPrev()->head(), v->head()) == -1 &&
59f220fa62Smrg      compV2InX(v->getNext()->head(), v->head()) == -1)
60f220fa62Smrg    return 1;
61f220fa62Smrg  else
62f220fa62Smrg    return 0;
63f220fa62Smrg}
64f220fa62Smrg
65f220fa62Smrg/*a vertex is u_minimal if both of its two neightbors are to the right of this
66f220fa62Smrg *vertex
67f220fa62Smrg */
68f220fa62Smrgstatic Int is_u_minimal(directedLine* v)
69f220fa62Smrg{
70f220fa62Smrg  if (compV2InX(v->getPrev()->head(), v->head()) == 1 &&
71f220fa62Smrg      compV2InX(v->getNext()->head(), v->head()) == 1)
72f220fa62Smrg    return 1;
73f220fa62Smrg  else
74f220fa62Smrg    return 0;
75f220fa62Smrg}
76f220fa62Smrg
77f220fa62Smrg/*poly: a v-monotone polygon
78f220fa62Smrg *return: a linked list of uv-monotone polygons.
79f220fa62Smrg */
80f220fa62SmrgdirectedLine* monoPolyPart(directedLine* polygon)
81f220fa62Smrg{
82f220fa62Smrg  //handle special cases:
83f220fa62Smrg  if(polygon == NULL)
84f220fa62Smrg    return NULL;
85f220fa62Smrg  if(polygon->getPrev() == polygon)
86f220fa62Smrg    return polygon;
87f220fa62Smrg  if(polygon->getPrev() == polygon->getNext())
88f220fa62Smrg    return polygon;
89f220fa62Smrg  if(polygon->getPrev()->getPrev() == polygon->getNext())
90f220fa62Smrg    return polygon;
91f220fa62Smrg
92f220fa62Smrg  //find the top and bottom vertexes
93f220fa62Smrg  directedLine *tempV, *topV, *botV;
94f220fa62Smrg  topV = botV = polygon;
95f220fa62Smrg  for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
96f220fa62Smrg    {
97f220fa62Smrg      if(compV2InY(topV->head(), tempV->head())<0) {
98f220fa62Smrg	topV = tempV;
99f220fa62Smrg      }
100f220fa62Smrg      if(compV2InY(botV->head(), tempV->head())>0) {
101f220fa62Smrg	botV = tempV;
102f220fa62Smrg      }
103f220fa62Smrg    }
104f220fa62Smrg
105f220fa62Smrg  //initilization
106f220fa62Smrg  directedLine *A, *B, *C, *D, *G, *H;
107f220fa62Smrg  //find A:the first u_maximal vertex on the left chain
108f220fa62Smrg  //and C: the left most vertex between top and A
109f220fa62Smrg  A = NULL;
110f220fa62Smrg  C = topV;
111f220fa62Smrg  for(tempV=topV->getNext(); tempV != botV; tempV = tempV->getNext())
112f220fa62Smrg    {
113f220fa62Smrg      if(tempV->head()[0] < C->head()[0])
114f220fa62Smrg	C = tempV;
115f220fa62Smrg
116f220fa62Smrg      if(is_u_maximal(tempV))
117f220fa62Smrg	{
118f220fa62Smrg	  A = tempV;
119f220fa62Smrg	  break;
120f220fa62Smrg	}
121f220fa62Smrg    }
122f220fa62Smrg  if(A == NULL)
123f220fa62Smrg    {
124f220fa62Smrg      A = botV;
125f220fa62Smrg      if(A->head()[0] < C->head()[0])
126f220fa62Smrg	C = A;
127f220fa62Smrg    }
128f220fa62Smrg
129f220fa62Smrg  //find B: the first u_minimal vertex on the right chain
130f220fa62Smrg  //and  D: the right most vertex between top and B
131f220fa62Smrg  B = NULL;
132f220fa62Smrg  D = topV;
133f220fa62Smrg  for(tempV=topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
134f220fa62Smrg    {
135f220fa62Smrg      if(tempV->head()[0] > D->head()[0])
136f220fa62Smrg	D = tempV;
137f220fa62Smrg      if(is_u_minimal(tempV))
138f220fa62Smrg	{
139f220fa62Smrg	  B = tempV;
140f220fa62Smrg	  break;
141f220fa62Smrg	}
142f220fa62Smrg    }
143f220fa62Smrg  if(B == NULL)
144f220fa62Smrg    {
145f220fa62Smrg      B = botV;
146f220fa62Smrg      if(B->head()[0] > D->head()[0])
147f220fa62Smrg	D = B;
148f220fa62Smrg    }
149f220fa62Smrg
150f220fa62Smrg  //error checking XXX
151f220fa62Smrg  if(C->head()[0] >= D->head()[0])
152f220fa62Smrg    return polygon;
153f220fa62Smrg
154f220fa62Smrg  //find G on the left chain that is right above B
155f220fa62Smrg  for(tempV=topV; compV2InY(tempV->head(), B->head()) == 1;  tempV=tempV->getNext());
156f220fa62Smrg  G = tempV->getPrev();
157f220fa62Smrg  //find H on the right chain that is right above A
158f220fa62Smrg  for(tempV=topV; compV2InY(tempV->head(), A->head()) == 1; tempV = tempV->getPrev());
159f220fa62Smrg  H = tempV->getNext();
160f220fa62Smrg
161f220fa62Smrg  //Main Loop
162f220fa62Smrg  directedLine* ret = NULL;
163f220fa62Smrg  directedLine* currentPolygon = polygon;
164f220fa62Smrg  while(1)
165f220fa62Smrg    {
166f220fa62Smrg      //if both B and D are equal to botV, then this polygon is already
167f220fa62Smrg      //u-monotone
168f220fa62Smrg      if(A == botV && B == botV)
169f220fa62Smrg	{
170f220fa62Smrg	  ret = currentPolygon->insertPolygon(ret);
171f220fa62Smrg	  return ret;
172f220fa62Smrg	}
173f220fa62Smrg      else //not u-monotone
174f220fa62Smrg	{
175f220fa62Smrg	  directedLine *ret_p1, *ret_p2;
176f220fa62Smrg	  if(compV2InY(A->head(),B->head()) == 1) //A is above B
177f220fa62Smrg	    {
178f220fa62Smrg	      directedLine* E = NULL;
179f220fa62Smrg	      for(tempV = C; tempV != D; tempV = tempV->getPrev())
180f220fa62Smrg		{
181f220fa62Smrg		  if(tempV->head()[0] >= A->head()[0])
182f220fa62Smrg		    {
183f220fa62Smrg		      E = tempV;
184f220fa62Smrg		      break;
185f220fa62Smrg		    }
186f220fa62Smrg		}
187f220fa62Smrg
188f220fa62Smrg	      if(E == NULL)
189f220fa62Smrg		E = D;
190f220fa62Smrg	      if(E->head()[0]> H->head()[0])
191f220fa62Smrg		E = H;
192f220fa62Smrg	      //connect AE and output polygon ECA
193f220fa62Smrg	      polygon->connectDiagonal_2slines(A, E,
194f220fa62Smrg					       &ret_p1,
195f220fa62Smrg					       &ret_p2,
196f220fa62Smrg					       NULL);
197f220fa62Smrg	      ret = ret_p2->insertPolygon(ret);
198f220fa62Smrg	      currentPolygon = ret_p1;
199f220fa62Smrg
200f220fa62Smrg	      if(E == D)
201f220fa62Smrg		D = ret_p1;
202f220fa62Smrg	      if(E == H)
203f220fa62Smrg		H = ret_p1;
204f220fa62Smrg              if(G->head()[1] >= A->head()[1])
205f220fa62Smrg		G = A;
206f220fa62Smrg	      //update A to be the next u-maxiaml vertex on left chain
207f220fa62Smrg	      //and C the leftmost vertex between the old A and the new A
208f220fa62Smrg	      C = A;
209f220fa62Smrg	      for(tempV = A->getNext(); tempV != botV; tempV = tempV->getNext())
210f220fa62Smrg		{
211f220fa62Smrg
212f220fa62Smrg		  if(tempV->head()[0] < C->head()[0])
213f220fa62Smrg		    C = tempV;
214f220fa62Smrg		  if(is_u_maximal(tempV))
215f220fa62Smrg		    {
216f220fa62Smrg		      A = tempV;
217f220fa62Smrg		      break;
218f220fa62Smrg		    }
219f220fa62Smrg		}
220f220fa62Smrg
221f220fa62Smrg	      if(tempV == botV)
222f220fa62Smrg		{
223f220fa62Smrg		  A = botV;
224f220fa62Smrg		  if(botV->head()[0] < C->head()[0])
225f220fa62Smrg		    C = botV;
226f220fa62Smrg		}
227f220fa62Smrg	      //update H
228f220fa62Smrg
229f220fa62Smrg              if(A == botV)
230f220fa62Smrg		H = botV;
231f220fa62Smrg              else
232f220fa62Smrg		{
233f220fa62Smrg		  for(tempV = H; compV2InY(tempV->head(), A->head()) == 1; tempV = tempV->getPrev());
234f220fa62Smrg		  H = tempV->getNext();
235f220fa62Smrg		}
236f220fa62Smrg
237f220fa62Smrg	    }
238f220fa62Smrg	  else //A is below B
239f220fa62Smrg	    {
240f220fa62Smrg
241f220fa62Smrg	      directedLine* F = NULL;
242f220fa62Smrg	      for(tempV = D; tempV != C; tempV = tempV->getNext())
243f220fa62Smrg		{
244f220fa62Smrg		  if(tempV->head()[0] <= B->head()[0])
245f220fa62Smrg		    {
246f220fa62Smrg		      F = tempV;
247f220fa62Smrg		      break;
248f220fa62Smrg		    }
249f220fa62Smrg		}
250f220fa62Smrg	      if(F == NULL)
251f220fa62Smrg		F = C;
252f220fa62Smrg	      if(F->head()[0] < G->head()[0])
253f220fa62Smrg		F = G;
254f220fa62Smrg
255f220fa62Smrg	      //connect FB
256f220fa62Smrg	      polygon->connectDiagonal_2slines(F, B,
257f220fa62Smrg					       &ret_p1,
258f220fa62Smrg					       &ret_p2,
259f220fa62Smrg					       NULL);
260f220fa62Smrg	      ret = ret_p2->insertPolygon(ret);
261f220fa62Smrg	      currentPolygon = ret_p1;
262f220fa62Smrg	      B = ret_p1;
263f220fa62Smrg	      if(H ->head()[1] >= B->head()[1])
264f220fa62Smrg		H = ret_p1;
265f220fa62Smrg
266f220fa62Smrg	      //update B to be the next u-minimal vertex on right chain
267f220fa62Smrg	      //and D the rightmost vertex between the old B and the new B
268f220fa62Smrg	      D = B;
269f220fa62Smrg	      for(tempV = B->getPrev(); tempV != botV; tempV = tempV->getPrev())
270f220fa62Smrg		{
271f220fa62Smrg		  if(tempV->head()[0] > D->head()[0])
272f220fa62Smrg		    D = tempV;
273f220fa62Smrg		  if(is_u_minimal(tempV))
274f220fa62Smrg		    {
275f220fa62Smrg		      B = tempV;
276f220fa62Smrg		      break;
277f220fa62Smrg		    }
278f220fa62Smrg		}
279f220fa62Smrg	      if(tempV == botV)
280f220fa62Smrg		{
281f220fa62Smrg		  B = botV;
282f220fa62Smrg		  if(botV->head()[0] > D->head()[0])
283f220fa62Smrg		    D = botV;
284f220fa62Smrg		}
285f220fa62Smrg	      //update G
286f220fa62Smrg              if(B == botV)
287f220fa62Smrg		G = botV;
288f220fa62Smrg              else
289f220fa62Smrg		{
290f220fa62Smrg		  for(tempV = G; compV2InY(tempV->head(), B->head()) == 1;  tempV = tempV->getNext());
291f220fa62Smrg		  G = tempV->getPrev();
292f220fa62Smrg		}
293f220fa62Smrg	    } //end of A is below B
294f220fa62Smrg	} //end not u-monotone
295f220fa62Smrg    } //end of main loop
296f220fa62Smrg}
297f220fa62Smrg
298f220fa62Smrg
299f220fa62Smrg
300