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*/
37f220fa62Smrg
38f220fa62Smrg#include <stdlib.h>
39f220fa62Smrg#include <stdio.h>
40f220fa62Smrg#include <math.h>
41f220fa62Smrg#include "glimports.h"
42f220fa62Smrg#include "zlassert.h"
43f220fa62Smrg
44f220fa62Smrg#include "quicksort.h"
45f220fa62Smrg#include "directedLine.h"
46f220fa62Smrg#include "polyDBG.h"
47f220fa62Smrg
48f220fa62Smrg#ifdef __WATCOMC__
49f220fa62Smrg#pragma warning 726 10
50f220fa62Smrg#endif
51f220fa62Smrg
52f220fa62Smrg//we must return the newLine
53f220fa62SmrgdirectedLine* directedLine::deleteChain(directedLine* begin, directedLine* end)
54f220fa62Smrg{
55f220fa62Smrg  if(begin->head()[0] ==  end->tail()[0] &&
56f220fa62Smrg     begin->head()[1] ==  end->tail()[1]
57f220fa62Smrg     )
58f220fa62Smrg    {
59f220fa62Smrg      directedLine *ret = begin->prev;
60f220fa62Smrg      begin->prev->next = end->next;
61f220fa62Smrg      end->next->prev = begin->prev;
62f220fa62Smrg      delete begin->sline;
63f220fa62Smrg      delete end->sline;
64f220fa62Smrg      delete begin;
65f220fa62Smrg      delete end;
66f220fa62Smrg
67f220fa62Smrg      return ret;
68f220fa62Smrg    }
69f220fa62Smrg
70f220fa62Smrg  directedLine* newLine;
71f220fa62Smrg  sampledLine* sline = new sampledLine(begin->head(), end->tail());
72f220fa62Smrg  newLine =  new directedLine(INCREASING, sline);
73f220fa62Smrg  directedLine *p = begin->prev;
74f220fa62Smrg  directedLine *n = end->next;
75f220fa62Smrg  p->next = newLine;
76f220fa62Smrg  n->prev = newLine;
77f220fa62Smrg  newLine->prev = p;
78f220fa62Smrg  newLine->next = n;
79f220fa62Smrg
80f220fa62Smrg  delete begin->sline;
81f220fa62Smrg  delete end->sline;
82f220fa62Smrg  delete begin;
83f220fa62Smrg  delete end;
84f220fa62Smrg  return newLine;
85f220fa62Smrg}
86f220fa62Smrg
87f220fa62Smrg
88f220fa62Smrgvoid directedLine::deleteSingleLine(directedLine* dline)
89f220fa62Smrg{
90f220fa62Smrg  //make sure that dline->prev->tail is the same as
91f220fa62Smrg  //dline->next->head. This is for numerical erros.
92f220fa62Smrg  //for example, if we delete a line which is almost degeneate
93f220fa62Smrg  //within (epsilon), then we want to make that the polygon after deletion
94f220fa62Smrg  //is still a valid polygon
95f220fa62Smrg
96f220fa62Smrg  dline->next->head()[0] =  dline->prev->tail()[0];
97f220fa62Smrg  dline->next->head()[1] =  dline->prev->tail()[1];
98f220fa62Smrg
99f220fa62Smrg  dline->prev->next = dline->next;
100f220fa62Smrg  dline->next->prev = dline->prev;
101f220fa62Smrg
102f220fa62Smrg  delete dline;
103f220fa62Smrg
104f220fa62Smrg}
105f220fa62Smrg
106f220fa62Smrgstatic Int myequal(Real a[2], Real b[2])
107f220fa62Smrg{
108f220fa62Smrg  /*
109f220fa62Smrg  if(a[0]==b[0] && a[1] == b[1])
110f220fa62Smrg    return 1;
111f220fa62Smrg  else
112f220fa62Smrg    return 0;
113f220fa62Smrg    */
114f220fa62Smrg
115f220fa62Smrg
116f220fa62Smrg  if(fabs(a[0]-b[0]) < 0.00001 &&
117f220fa62Smrg     fabs(a[1]-b[1]) < 0.00001)
118f220fa62Smrg    return 1;
119f220fa62Smrg  else
120f220fa62Smrg    return 0;
121f220fa62Smrg
122f220fa62Smrg}
123f220fa62Smrg
124f220fa62SmrgdirectedLine* directedLine::deleteDegenerateLines()
125f220fa62Smrg{
126f220fa62Smrg  //if there is only one edge or two edges, don't do anything
127f220fa62Smrg  if(this->next == this)
128f220fa62Smrg    return this;
129f220fa62Smrg  if(this->next == this->prev)
130f220fa62Smrg    return this;
131f220fa62Smrg
132f220fa62Smrg  //find a nondegenerate line
133f220fa62Smrg  directedLine* temp;
134f220fa62Smrg  directedLine* first = NULL;
135f220fa62Smrg  if(! myequal(head(), tail()))
136f220fa62Smrg    /*
137f220fa62Smrg  if(head()[0] != tail()[0] ||
138f220fa62Smrg  head()[1] != tail()[1])
139f220fa62Smrg  */
140f220fa62Smrg    first = this;
141f220fa62Smrg  else
142f220fa62Smrg    {
143f220fa62Smrg      for(temp = this->next; temp != this; temp = temp->next)
144f220fa62Smrg	{
145f220fa62Smrg	  /*
146f220fa62Smrg	  if(temp->head()[0] != temp->tail()[0] ||
147f220fa62Smrg	     temp->head()[1] != temp->tail()[1])
148f220fa62Smrg	     */
149f220fa62Smrg	  if(! myequal(temp->head(), temp->tail()))
150f220fa62Smrg	    {
151f220fa62Smrg	      first = temp;
152f220fa62Smrg	      break;
153f220fa62Smrg	    }
154f220fa62Smrg
155f220fa62Smrg	}
156f220fa62Smrg    }
157f220fa62Smrg
158f220fa62Smrg  //if there are no non-degenerate lines, then we simply return NULL.
159f220fa62Smrg  if(first == NULL)
160f220fa62Smrg    {
161f220fa62Smrg      deleteSinglePolygonWithSline();
162f220fa62Smrg      return NULL;
163f220fa62Smrg    }
164f220fa62Smrg
165f220fa62Smrg  directedLine* tempNext = NULL;
166f220fa62Smrg  for(temp =first->next; temp != first; temp = tempNext)
167f220fa62Smrg    {
168f220fa62Smrg      tempNext = temp->getNext();
169f220fa62Smrg/*
170f220fa62Smrg      if(temp->head()[0] == temp->tail()[0] &&
171f220fa62Smrg	 temp->head()[1] == temp->tail()[1])
172f220fa62Smrg*/
173f220fa62Smrg
174f220fa62Smrg      if(myequal(temp->head(), temp->tail()))
175f220fa62Smrg	deleteSingleLine(temp);
176f220fa62Smrg    }
177f220fa62Smrg  return first;
178f220fa62Smrg}
179f220fa62Smrg
180f220fa62SmrgdirectedLine* directedLine::deleteDegenerateLinesAllPolygons()
181f220fa62Smrg{
182f220fa62Smrg  directedLine* temp;
183f220fa62Smrg  directedLine *tempNext = NULL;
184f220fa62Smrg  directedLine* ret= NULL;
185f220fa62Smrg  directedLine* retEnd = NULL;
186f220fa62Smrg  for(temp=this; temp != NULL; temp = tempNext)
187f220fa62Smrg    {
188f220fa62Smrg      tempNext = temp->nextPolygon;
189f220fa62Smrg      temp->nextPolygon = NULL;
190f220fa62Smrg      if(ret == NULL)
191f220fa62Smrg	{
192f220fa62Smrg	  ret = retEnd = temp->deleteDegenerateLines();
193f220fa62Smrg
194f220fa62Smrg	}
195f220fa62Smrg      else
196f220fa62Smrg	{
197f220fa62Smrg	  directedLine *newPolygon = temp->deleteDegenerateLines();
198f220fa62Smrg	  if(newPolygon != NULL)
199f220fa62Smrg	    {
200f220fa62Smrg	  retEnd->nextPolygon = temp->deleteDegenerateLines();
201f220fa62Smrg	  retEnd = retEnd->nextPolygon;
202f220fa62Smrg	}
203f220fa62Smrg    }
204f220fa62Smrg    }
205f220fa62Smrg  return ret;
206f220fa62Smrg}
207f220fa62Smrg
208f220fa62SmrgdirectedLine* directedLine::cutIntersectionAllPoly(int &cutOccur)
209f220fa62Smrg{
210f220fa62Smrg  directedLine* temp;
211f220fa62Smrg  directedLine *tempNext = NULL;
212f220fa62Smrg  directedLine* ret= NULL;
213f220fa62Smrg  directedLine* retEnd = NULL;
214f220fa62Smrg  cutOccur = 0;
215f220fa62Smrg  for(temp=this; temp != NULL; temp = tempNext)
216f220fa62Smrg    {
217f220fa62Smrg      int eachCutOccur=0;
218f220fa62Smrg      tempNext = temp->nextPolygon;
219f220fa62Smrg      temp->nextPolygon = NULL;
220f220fa62Smrg      if(ret == NULL)
221f220fa62Smrg	{
222f220fa62Smrg
223f220fa62Smrg	  ret = retEnd = DBG_cutIntersectionPoly(temp, eachCutOccur);
224f220fa62Smrg	  if(eachCutOccur)
225f220fa62Smrg	    cutOccur = 1;
226f220fa62Smrg	}
227f220fa62Smrg      else
228f220fa62Smrg	{
229f220fa62Smrg
230f220fa62Smrg	  retEnd->nextPolygon = DBG_cutIntersectionPoly(temp, eachCutOccur);
231f220fa62Smrg	  retEnd = retEnd->nextPolygon;
232f220fa62Smrg	  if(eachCutOccur)
233f220fa62Smrg	    cutOccur = 1;
234f220fa62Smrg	}
235f220fa62Smrg    }
236f220fa62Smrg  return ret;
237f220fa62Smrg}
238f220fa62Smrg
239f220fa62Smrg
240f220fa62Smrgvoid directedLine::deleteSinglePolygonWithSline()
241f220fa62Smrg{
242f220fa62Smrg  directedLine *temp, *tempNext;
243f220fa62Smrg  prev->next = NULL;
244f220fa62Smrg  for(temp=this; temp != NULL; temp = tempNext)
245f220fa62Smrg    {
246f220fa62Smrg      tempNext = temp->next;
247f220fa62Smrg      delete temp->sline;
248f220fa62Smrg      delete temp;
249f220fa62Smrg    }
250f220fa62Smrg}
251f220fa62Smrg
252f220fa62Smrgvoid directedLine::deletePolygonListWithSline()
253f220fa62Smrg{
254f220fa62Smrg  directedLine *temp, *tempNext;
255f220fa62Smrg  for(temp=this; temp != NULL; temp=tempNext)
256f220fa62Smrg    {
257f220fa62Smrg      tempNext = temp->nextPolygon;
258f220fa62Smrg      temp->deleteSinglePolygonWithSline();
259f220fa62Smrg    }
260f220fa62Smrg}
261f220fa62Smrg
262f220fa62Smrgvoid directedLine::deleteSinglePolygon()
263f220fa62Smrg{
264f220fa62Smrg  directedLine *temp, *tempNext;
265f220fa62Smrg  prev->next = NULL;
266f220fa62Smrg  for(temp=this; temp != NULL; temp = tempNext)
267f220fa62Smrg    {
268f220fa62Smrg      tempNext = temp->next;
269f220fa62Smrg      delete temp;
270f220fa62Smrg    }
271f220fa62Smrg}
272f220fa62Smrg
273f220fa62Smrgvoid directedLine::deletePolygonList()
274f220fa62Smrg{
275f220fa62Smrg  directedLine *temp, *tempNext;
276f220fa62Smrg  for(temp=this; temp != NULL; temp=tempNext)
277f220fa62Smrg    {
278f220fa62Smrg      tempNext = temp->nextPolygon;
279f220fa62Smrg      temp->deleteSinglePolygon();
280f220fa62Smrg    }
281f220fa62Smrg}
282f220fa62Smrg
283f220fa62Smrg
284f220fa62Smrg/*a loop by itself*/
285f220fa62SmrgdirectedLine::directedLine(short dir, sampledLine* sl)
286f220fa62Smrg{
287f220fa62Smrg  direction = dir;
288f220fa62Smrg  sline = sl;
289f220fa62Smrg  next = this;
290f220fa62Smrg  prev = this;
291f220fa62Smrg  nextPolygon = NULL;
292f220fa62Smrg//  prevPolygon = NULL;
293f220fa62Smrg  rootBit = 0;/*important to initilzae to 0 meaning not root yet*/
294f220fa62Smrg
295f220fa62Smrg  rootLink = NULL;
296f220fa62Smrg
297f220fa62Smrg}
298f220fa62Smrg
299f220fa62Smrgvoid directedLine::init(short dir, sampledLine* sl)
300f220fa62Smrg{
301f220fa62Smrg  direction = dir;
302f220fa62Smrg  sline = sl;
303f220fa62Smrg}
304f220fa62Smrg
305f220fa62SmrgdirectedLine::directedLine()
306f220fa62Smrg{
307f220fa62Smrg  next = this;
308f220fa62Smrg  prev = this;
309f220fa62Smrg  nextPolygon = NULL;
310f220fa62Smrg  rootBit = 0;/*important to initilzae to 0 meaning not root yet*/
311f220fa62Smrg  rootLink = NULL;
312f220fa62Smrg  direction = INCREASING;
313f220fa62Smrg  sline = NULL;
314f220fa62Smrg}
315f220fa62Smrg
316f220fa62SmrgdirectedLine::~directedLine()
317f220fa62Smrg{
318f220fa62Smrg}
319f220fa62Smrg
320f220fa62SmrgReal* directedLine::head()
321f220fa62Smrg{
322f220fa62Smrg
323f220fa62Smrg  return (direction==INCREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
324f220fa62Smrg}
325f220fa62Smrg
326f220fa62Smrg/*inline*/ Real* directedLine::getVertex(Int i)
327f220fa62Smrg{
328f220fa62Smrg  return (direction==INCREASING)? (sline->get_points())[i] : (sline->get_points())[sline->get_npoints() - 1 -i];
329f220fa62Smrg}
330f220fa62Smrg
331f220fa62SmrgReal* directedLine::tail()
332f220fa62Smrg{
333f220fa62Smrg  return (direction==DECREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
334f220fa62Smrg}
335f220fa62Smrg
336f220fa62Smrg /*insert a new line between prev and this*/
337f220fa62Smrgvoid directedLine::insert(directedLine* nl)
338f220fa62Smrg{
339f220fa62Smrg  nl->next = this;
340f220fa62Smrg  nl->prev = prev;
341f220fa62Smrg  prev->next = nl;
342f220fa62Smrg  prev = nl;
343f220fa62Smrg  nl->rootLink = this; /*assuming that 'this' is the root!!!*/
344f220fa62Smrg}
345f220fa62Smrg
346f220fa62SmrgInt directedLine::numEdges()
347f220fa62Smrg{
348f220fa62Smrg  Int ret=0;
349f220fa62Smrg  directedLine* temp;
350f220fa62Smrg  if(next == this) return 1;
351f220fa62Smrg
352f220fa62Smrg  ret = 1;
353f220fa62Smrg  for(temp = next; temp != this; temp = temp->next)
354f220fa62Smrg    ret++;
355f220fa62Smrg  return ret;
356f220fa62Smrg}
357f220fa62Smrg
358f220fa62SmrgInt directedLine::numEdgesAllPolygons()
359f220fa62Smrg{
360f220fa62Smrg  Int ret=0;
361f220fa62Smrg  directedLine* temp;
362f220fa62Smrg  for(temp=this; temp!= NULL; temp=temp->nextPolygon)
363f220fa62Smrg    {
364f220fa62Smrg      ret += temp->numEdges();
365f220fa62Smrg    }
366f220fa62Smrg  return ret;
367f220fa62Smrg}
368f220fa62Smrg
369f220fa62Smrg/*return 1 if the double linked list forms a polygon.
370f220fa62Smrg */
371f220fa62Smrgshort directedLine::isPolygon()
372f220fa62Smrg{
373f220fa62Smrg  directedLine* temp;
374f220fa62Smrg
375f220fa62Smrg  /*a polygon contains at least 3 edges*/
376f220fa62Smrg  if(numEdges() <=2) return 0;
377f220fa62Smrg
378f220fa62Smrg  /*check this edge*/
379f220fa62Smrg  if(! isConnected()) return 0;
380f220fa62Smrg
381f220fa62Smrg  /*check all other edges*/
382f220fa62Smrg  for(temp=next; temp != this; temp = temp->next){
383f220fa62Smrg    if(!isConnected()) return 0;
384f220fa62Smrg  }
385f220fa62Smrg  return 1;
386f220fa62Smrg}
387f220fa62Smrg
388f220fa62Smrg/*check if the head of this edge is connected to
389f220fa62Smrg *the tail of the prev
390f220fa62Smrg */
391f220fa62Smrgshort directedLine::isConnected()
392f220fa62Smrg{
393f220fa62Smrg  if( (head()[0] == prev->tail()[0]) && (head()[1] == prev->tail()[1]))
394f220fa62Smrg    return 1;
395f220fa62Smrg  else
396f220fa62Smrg    return 0;
397f220fa62Smrg}
398f220fa62Smrg
399f220fa62SmrgInt compV2InY(Real A[2], Real B[2])
400f220fa62Smrg{
401f220fa62Smrg  if(A[1] < B[1]) return -1;
402f220fa62Smrg  if(A[1] == B[1] && A[0] < B[0]) return -1;
403f220fa62Smrg  if(A[1] == B[1] && A[0] == B[0]) return 0;
404f220fa62Smrg  return 1;
405f220fa62Smrg}
406f220fa62Smrg
407f220fa62SmrgInt compV2InX(Real A[2], Real B[2])
408f220fa62Smrg{
409f220fa62Smrg  if(A[0] < B[0]) return -1;
410f220fa62Smrg  if(A[0] == B[0] && A[1] < B[1]) return -1;
411f220fa62Smrg  if(A[0] == B[0] && A[1] == B[1]) return 0;
412f220fa62Smrg  return 1;
413f220fa62Smrg}
414f220fa62Smrg
415f220fa62Smrg/*compare two vertices NOT lines!
416f220fa62Smrg *A vertex is the head of a directed line.
417f220fa62Smrg *(x_1, y_1) <= (x_2, y_2) if
418f220fa62Smrg *either y_1 < y_2
419f220fa62Smrg *or	 y_1 == y_2 && x_1 < x_2.
420f220fa62Smrg *return -1 if this->head() <= nl->head(),
421f220fa62Smrg *return  1 otherwise
422f220fa62Smrg */
423f220fa62SmrgInt directedLine::compInY(directedLine* nl)
424f220fa62Smrg{
425f220fa62Smrg  if(head()[1] < nl->head()[1]) return -1;
426f220fa62Smrg  if(head()[1] == nl->head()[1] && head()[0] < nl->head()[0]) return -1;
427f220fa62Smrg  return 1;
428f220fa62Smrg}
429f220fa62Smrg
430f220fa62Smrg/*compare two vertices NOT lines!
431f220fa62Smrg *A vertex is the head of a directed line.
432f220fa62Smrg *(x_1, y_1) <= (x_2, y_2) if
433f220fa62Smrg *either x_1 < x_2
434f220fa62Smrg *or	 x_1 == x_2 && y_1 < y_2.
435f220fa62Smrg *return -1 if this->head() <= nl->head(),
436f220fa62Smrg *return  1 otherwise
437f220fa62Smrg */
438f220fa62SmrgInt directedLine::compInX(directedLine* nl)
439f220fa62Smrg{
440f220fa62Smrg  if(head()[0] < nl->head()[0]) return -1;
441f220fa62Smrg  if(head()[0] == nl->head()[0] && head()[1] < nl->head()[1]) return -1;
442f220fa62Smrg  return 1;
443f220fa62Smrg}
444f220fa62Smrg
445f220fa62Smrg/*used by sort precedures
446f220fa62Smrg */
447f220fa62Smrgstatic Int compInY2(directedLine* v1, directedLine* v2)
448f220fa62Smrg{
449f220fa62Smrg  return v1->compInY(v2);
450f220fa62Smrg}
451f220fa62Smrg#ifdef NOT_USED
452f220fa62Smrgstatic Int compInX(directedLine* v1, directedLine* v2)
453f220fa62Smrg{
454f220fa62Smrg  return v1->compInX(v2);
455f220fa62Smrg}
456f220fa62Smrg#endif
457f220fa62Smrg
458f220fa62Smrg/*sort all the vertices NOT the lines!
459f220fa62Smrg *a vertex is the head of a directed line
460f220fa62Smrg */
461f220fa62SmrgdirectedLine** directedLine::sortAllPolygons()
462f220fa62Smrg{
463f220fa62Smrg  Int total_num_edges = 0;
464f220fa62Smrg  directedLine** array = toArrayAllPolygons(total_num_edges);
465f220fa62Smrg  quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void *, void *)) compInY2);
466f220fa62Smrg
467f220fa62Smrg  return array;
468f220fa62Smrg}
469f220fa62Smrg
470f220fa62Smrgvoid directedLine::printSingle()
471f220fa62Smrg{
472f220fa62Smrg  if(direction == INCREASING)
473f220fa62Smrg    printf("direction is INCREASING\n");
474f220fa62Smrg  else
475f220fa62Smrg    printf("direction is DECREASING\n");
476f220fa62Smrg  printf("head=%f,%f)\n", head()[0], head()[1]);
477f220fa62Smrg  sline->print();
478f220fa62Smrg}
479f220fa62Smrg
480f220fa62Smrg/*print one polygon*/
481f220fa62Smrgvoid directedLine::printList()
482f220fa62Smrg{
483f220fa62Smrg  directedLine* temp;
484f220fa62Smrg  printSingle();
485f220fa62Smrg  for(temp = next; temp!=this; temp=temp->next)
486f220fa62Smrg    temp->printSingle();
487f220fa62Smrg}
488f220fa62Smrg
489f220fa62Smrg/*print all the polygons*/
490f220fa62Smrgvoid directedLine::printAllPolygons()
491f220fa62Smrg{
492f220fa62Smrg  directedLine *temp;
493f220fa62Smrg  for(temp = this; temp!=NULL; temp = temp->nextPolygon)
494f220fa62Smrg    {
495f220fa62Smrg      printf("polygon:\n");
496f220fa62Smrg      temp->printList();
497f220fa62Smrg    }
498f220fa62Smrg}
499f220fa62Smrg
500f220fa62Smrg/*insert this polygon into the head of the old polygon List*/
501f220fa62SmrgdirectedLine* directedLine::insertPolygon(directedLine* oldList)
502f220fa62Smrg{
503f220fa62Smrg  /*this polygon is a root*/
504f220fa62Smrg  setRootBit();
505f220fa62Smrg  if(oldList == NULL) return this;
506f220fa62Smrg  nextPolygon = oldList;
507f220fa62Smrg/*  oldList->prevPolygon = this;*/
508f220fa62Smrg  return this;
509f220fa62Smrg}
510f220fa62Smrg
511f220fa62Smrg/*cutoff means delete. but we don't deallocate any space,
512f220fa62Smrg *so we use cutoff instead of delete
513f220fa62Smrg */
514f220fa62SmrgdirectedLine* directedLine::cutoffPolygon(directedLine *p)
515f220fa62Smrg{
516f220fa62Smrg  directedLine* temp;
517f220fa62Smrg  directedLine* prev_polygon  = NULL;
518f220fa62Smrg  if(p == NULL) return this;
519f220fa62Smrg
520f220fa62Smrg  for(temp=this; temp != p; temp = temp->nextPolygon)
521f220fa62Smrg    {
522f220fa62Smrg      if(temp == NULL)
523f220fa62Smrg	{
524f220fa62Smrg	  fprintf(stderr, "in cutoffPolygon, not found\n");
525f220fa62Smrg	  exit(1);
526f220fa62Smrg	}
527f220fa62Smrg      prev_polygon = temp;
528f220fa62Smrg    }
529f220fa62Smrg
530f220fa62Smrg/*  prev_polygon = p->prevPolygon;*/
531f220fa62Smrg
532f220fa62Smrg  p->resetRootBit();
533f220fa62Smrg  if(prev_polygon == NULL) /*this is the one to cutoff*/
534f220fa62Smrg    return nextPolygon;
535f220fa62Smrg  else {
536f220fa62Smrg    prev_polygon->nextPolygon = p->nextPolygon;
537f220fa62Smrg    return this;
538f220fa62Smrg  }
539f220fa62Smrg}
540f220fa62Smrg
541f220fa62SmrgInt directedLine::numPolygons()
542f220fa62Smrg{
543f220fa62Smrg  if(nextPolygon == NULL) return 1;
544f220fa62Smrg  else return 1+nextPolygon->numPolygons();
545f220fa62Smrg}
546f220fa62Smrg
547f220fa62Smrg
548f220fa62Smrg/*let  array[index ...] denote
549f220fa62Smrg *all the edges in this polygon
550f220fa62Smrg *return the next available index of array.
551f220fa62Smrg */
552f220fa62SmrgInt directedLine::toArraySinglePolygon(directedLine** array, Int index)
553f220fa62Smrg{
554f220fa62Smrg  directedLine *temp;
555f220fa62Smrg  array[index++] = this;
556f220fa62Smrg  for(temp = next; temp != this; temp = temp->next)
557f220fa62Smrg    {
558f220fa62Smrg      array[index++] = temp;
559f220fa62Smrg    }
560f220fa62Smrg  return index;
561f220fa62Smrg}
562f220fa62Smrg
563f220fa62Smrg/*the space is allocated. The caller is responsible for
564f220fa62Smrg *deallocate the space.
565f220fa62Smrg *total_num_edges is set to be the total number of edges of all polygons
566f220fa62Smrg */
567f220fa62SmrgdirectedLine** directedLine::toArrayAllPolygons(Int& total_num_edges)
568f220fa62Smrg{
569f220fa62Smrg  total_num_edges=numEdgesAllPolygons();
570f220fa62Smrg  directedLine** ret = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges);
571f220fa62Smrg  assert(ret);
572f220fa62Smrg
573f220fa62Smrg  directedLine *temp;
574f220fa62Smrg  Int index = 0;
575f220fa62Smrg  for(temp=this; temp != NULL; temp=temp->nextPolygon) {
576f220fa62Smrg    index = temp->toArraySinglePolygon(ret, index);
577f220fa62Smrg  }
578f220fa62Smrg  return ret;
579f220fa62Smrg}
580f220fa62Smrg
581f220fa62Smrg/*assume the polygon is a simple polygon, return
582f220fa62Smrg *the area enclosed by it.
583f220fa62Smrg *if thee order is counterclock wise, the area is positive.
584f220fa62Smrg */
585f220fa62SmrgReal directedLine::polyArea()
586f220fa62Smrg{
587f220fa62Smrg  directedLine* temp;
588f220fa62Smrg  Real ret=0.0;
589f220fa62Smrg  Real x1,y1,x2,y2;
590f220fa62Smrg  x1 = this->head()[0];
591f220fa62Smrg  y1 = this->head()[1];
592f220fa62Smrg  x2 = this->next->head()[0];
593f220fa62Smrg  y2 = this->next->head()[1];
594f220fa62Smrg  ret = -(x2*y1-x1*y2);
595f220fa62Smrg  for(temp=this->next; temp!=this; temp = temp->next)
596f220fa62Smrg    {
597f220fa62Smrg      x1 = temp->head()[0];
598f220fa62Smrg      y1 = temp->head()[1];
599f220fa62Smrg      x2 = temp->next->head()[0];
600f220fa62Smrg      y2 = temp->next->head()[1];
601f220fa62Smrg      ret += -( x2*y1-x1*y2);
602f220fa62Smrg    }
603f220fa62Smrg  return Real(0.5)*ret;
604f220fa62Smrg}
605f220fa62Smrg
606f220fa62Smrg/*******************split or combine polygons begin********************/
607f220fa62Smrg/*conect a diagonal of a single simple polygon or  two simple polygons.
608f220fa62Smrg *If the two vertices v1 (head) and v2 (head) are in the same simple polygon,
609f220fa62Smrg *then we actually split the simple polygon into two polygons.
610f220fa62Smrg *If instead two vertices velong to two difference polygons,
611f220fa62Smrg *then we combine the  two polygons into one polygon.
612f220fa62Smrg *It is upto the caller to decide whether this is a split or a
613f220fa62Smrg *combination.
614f220fa62Smrg *
615f220fa62Smrg *Case Split:
616f220fa62Smrg *split a single simple polygon into two simple polygons by
617f220fa62Smrg *connecting a diagonal (two vertices).
618f220fa62Smrg *v1, v2: the two vertices are the head() of the two directedLines.
619f220fa62Smrg *  this routine generates one new sampledLine which is returned in
620f220fa62Smrg *generatedLine,
621f220fa62Smrg *and it generates two directedLines returned in ret_p1 and ret_p2.
622f220fa62Smrg *ret_p1 and ret_p2 are used as the entry to the two new polygons.
623f220fa62Smrg *Notice the caller should not deallocate the space of v2 and v2 after
624f220fa62Smrg *calling this function, since all of the edges are connected to
625f220fa62Smrg *ret_p1 or ret_p2.
626f220fa62Smrg *
627f220fa62Smrg *combine:
628f220fa62Smrg *combine two simpolygons into one by connecting one diagonal.
629f220fa62Smrg *the returned polygon is returned in ret_p1.
630f220fa62Smrg */
631f220fa62Smrg/*ARGSUSED*/
632f220fa62Smrgvoid directedLine::connectDiagonal(directedLine* v1, directedLine* v2,
633f220fa62Smrg			   directedLine** ret_p1,
634f220fa62Smrg			   directedLine** ret_p2,
635f220fa62Smrg			   sampledLine** generatedLine,
636f220fa62Smrg			   directedLine* polygonList								   )
637f220fa62Smrg{
638f220fa62Smrg  sampledLine *nsline  = new sampledLine(2);
639f220fa62Smrg
640f220fa62Smrg
641f220fa62Smrg
642f220fa62Smrg  nsline->setPoint(0, v1->head());
643f220fa62Smrg  nsline->setPoint(1, v2->head());
644f220fa62Smrg
645f220fa62Smrg
646f220fa62Smrg
647f220fa62Smrg  /*the increasing line is from v1 head to v2 head*/
648f220fa62Smrg  directedLine* newLineInc = new directedLine(INCREASING, nsline);
649f220fa62Smrg
650f220fa62Smrg
651f220fa62Smrg
652f220fa62Smrg  directedLine* newLineDec = new directedLine(DECREASING, nsline);
653f220fa62Smrg
654f220fa62Smrg
655f220fa62Smrg  directedLine* v1Prev = v1->prev;
656f220fa62Smrg  directedLine* v2Prev = v2->prev;
657f220fa62Smrg
658f220fa62Smrg  v1	    ->prev = newLineDec;
659f220fa62Smrg  v2Prev    ->next = newLineDec;
660f220fa62Smrg  newLineDec->next = v1;
661f220fa62Smrg  newLineDec->prev = v2Prev;
662f220fa62Smrg
663f220fa62Smrg  v2	    ->prev = newLineInc;
664f220fa62Smrg  v1Prev    ->next = newLineInc;
665f220fa62Smrg  newLineInc->next = v2;
666f220fa62Smrg  newLineInc->prev = v1Prev;
667f220fa62Smrg
668f220fa62Smrg  *ret_p1 = newLineDec;
669f220fa62Smrg  *ret_p2 = newLineInc;
670f220fa62Smrg  *generatedLine = nsline;
671f220fa62Smrg}
672f220fa62Smrg
673f220fa62Smrg//see the function connectDiangle
674f220fa62Smrg/*ARGSUSED*/
675f220fa62Smrgvoid directedLine::connectDiagonal_2slines(directedLine* v1, directedLine* v2,
676f220fa62Smrg			   directedLine** ret_p1,
677f220fa62Smrg			   directedLine** ret_p2,
678f220fa62Smrg			   directedLine* polygonList								   )
679f220fa62Smrg{
680f220fa62Smrg  sampledLine *nsline  = new sampledLine(2);
681f220fa62Smrg  sampledLine *nsline2	= new sampledLine(2);
682f220fa62Smrg
683f220fa62Smrg  nsline->setPoint(0, v1->head());
684f220fa62Smrg  nsline->setPoint(1, v2->head());
685f220fa62Smrg  nsline2->setPoint(0, v1->head());
686f220fa62Smrg  nsline2->setPoint(1, v2->head());
687f220fa62Smrg
688f220fa62Smrg  /*the increasing line is from v1 head to v2 head*/
689f220fa62Smrg  directedLine* newLineInc = new directedLine(INCREASING, nsline);
690f220fa62Smrg
691f220fa62Smrg  directedLine* newLineDec = new directedLine(DECREASING, nsline2);
692f220fa62Smrg
693f220fa62Smrg  directedLine* v1Prev = v1->prev;
694f220fa62Smrg  directedLine* v2Prev = v2->prev;
695f220fa62Smrg
696f220fa62Smrg  v1	    ->prev = newLineDec;
697f220fa62Smrg  v2Prev    ->next = newLineDec;
698f220fa62Smrg  newLineDec->next = v1;
699f220fa62Smrg  newLineDec->prev = v2Prev;
700f220fa62Smrg
701f220fa62Smrg  v2	    ->prev = newLineInc;
702f220fa62Smrg  v1Prev    ->next = newLineInc;
703f220fa62Smrg  newLineInc->next = v2;
704f220fa62Smrg  newLineInc->prev = v1Prev;
705f220fa62Smrg
706f220fa62Smrg  *ret_p1 = newLineDec;
707f220fa62Smrg  *ret_p2 = newLineInc;
708f220fa62Smrg
709f220fa62Smrg}
710f220fa62Smrg
711f220fa62SmrgInt directedLine::samePolygon(directedLine* v1, directedLine* v2)
712f220fa62Smrg{
713f220fa62Smrg  if(v1 == v2) return 1;
714f220fa62Smrg  directedLine *temp;
715f220fa62Smrg  for(temp = v1->next; temp != v1; temp = temp->next)
716f220fa62Smrg    {
717f220fa62Smrg      if(temp == v2) return 1;
718f220fa62Smrg    }
719f220fa62Smrg  return 0;
720f220fa62Smrg}
721f220fa62Smrg
722f220fa62SmrgdirectedLine* directedLine::findRoot()
723f220fa62Smrg{
724f220fa62Smrg  if(rootBit) return this;
725f220fa62Smrg  directedLine* temp;
726f220fa62Smrg  for(temp = next; temp != this; temp = temp->next)
727f220fa62Smrg    if(temp -> rootBit ) return temp;
728f220fa62Smrg  return NULL; /*should not happen*/
729f220fa62Smrg}
730f220fa62Smrg
731f220fa62SmrgdirectedLine* directedLine::rootLinkFindRoot()
732f220fa62Smrg{
733f220fa62Smrg  directedLine* tempRoot;
734f220fa62Smrg  directedLine* tempLink;
735f220fa62Smrg  tempRoot = this;
736f220fa62Smrg  tempLink = rootLink;
737f220fa62Smrg  while(tempLink != NULL){
738f220fa62Smrg    tempRoot = tempLink;
739f220fa62Smrg    tempLink = tempRoot->rootLink;
740f220fa62Smrg  }
741f220fa62Smrg  return tempRoot;
742f220fa62Smrg}
743f220fa62Smrg
744f220fa62Smrg/*******************split or combine polygons end********************/
745f220fa62Smrg
746f220fa62Smrg/*****************IO stuff begin*******************/
747f220fa62Smrg
748f220fa62Smrg/*format:
749f220fa62Smrg *#polygons
750f220fa62Smrg * #vertices
751f220fa62Smrg *  vertices
752f220fa62Smrg * #vertices
753f220fa62Smrg *  vertices
754f220fa62Smrg *...
755f220fa62Smrg */
756f220fa62Smrgvoid directedLine::writeAllPolygons(char* filename)
757f220fa62Smrg{
758f220fa62Smrg  FILE* fp = fopen(filename, "w");
759f220fa62Smrg  assert(fp);
760f220fa62Smrg  Int nPolygons = numPolygons();
761f220fa62Smrg  directedLine *root;
762f220fa62Smrg  fprintf(fp, "%i\n", nPolygons);
763f220fa62Smrg  for(root = this; root != NULL; root = root->nextPolygon)
764f220fa62Smrg    {
765f220fa62Smrg      directedLine *temp;
766f220fa62Smrg      Int npoints=0;
767f220fa62Smrg      npoints = root->get_npoints()-1;
768f220fa62Smrg      for(temp = root->next; temp != root; temp=temp->next)
769f220fa62Smrg	npoints += temp->get_npoints()-1;
770f220fa62Smrg      fprintf(fp, "%i\n", npoints/*root->numEdges()*/);
771f220fa62Smrg
772f220fa62Smrg
773f220fa62Smrg      for(Int i=0; i<root->get_npoints()-1; i++){
774f220fa62Smrg	fprintf(fp, "%f ", root->getVertex(i)[0]);
775f220fa62Smrg	fprintf(fp, "%f ", root->getVertex(i)[1]);
776f220fa62Smrg      }
777f220fa62Smrg
778f220fa62Smrg      for(temp=root->next; temp != root; temp = temp->next)
779f220fa62Smrg	{
780f220fa62Smrg	  for(Int i=0; i<temp->get_npoints()-1; i++){
781f220fa62Smrg
782f220fa62Smrg	    fprintf(fp, "%f ", temp->getVertex(i)[0]);
783f220fa62Smrg	    fprintf(fp, "%f ", temp->getVertex(i)[1]);
784f220fa62Smrg	  }
785f220fa62Smrg	  fprintf(fp,"\n");
786f220fa62Smrg	}
787f220fa62Smrg      fprintf(fp, "\n");
788f220fa62Smrg    }
789f220fa62Smrg  fclose(fp);
790f220fa62Smrg}
791f220fa62Smrg
792f220fa62SmrgdirectedLine* readAllPolygons(char* filename)
793f220fa62Smrg{
794f220fa62Smrg  Int i,j;
795f220fa62Smrg  FILE* fp = fopen(filename, "r");
796f220fa62Smrg  Int nPolygons;
797f220fa62Smrg  int result;
798f220fa62Smrg
799f220fa62Smrg  assert(fp);
800f220fa62Smrg  result = fscanf(fp, "%i", &nPolygons);
801f220fa62Smrg  assert(result != EOF);
802f220fa62Smrg  directedLine *ret = NULL;
803f220fa62Smrg
804f220fa62Smrg  for(i=0; i<nPolygons; i++)
805f220fa62Smrg    {
806f220fa62Smrg      Int nEdges;
807f220fa62Smrg      result = fscanf(fp, "%i", &nEdges);
808f220fa62Smrg      assert(result != EOF);
809f220fa62Smrg      Real vert[2][2] = { { 0 } };
810f220fa62Smrg      Real VV[2][2];
811f220fa62Smrg      /*the first two vertices*/
812f220fa62Smrg      result = fscanf(fp, "%f", &(vert[0][0]));
813f220fa62Smrg      assert(result != EOF);
814f220fa62Smrg      result = fscanf(fp, "%f", &(vert[0][1]));
815f220fa62Smrg      assert(result != EOF);
816f220fa62Smrg      result = fscanf(fp, "%f", &(vert[1][0]));
817f220fa62Smrg      assert(result != EOF);
818f220fa62Smrg      result = fscanf(fp, "%f", &(vert[1][1]));
819f220fa62Smrg      assert(result != EOF);
820f220fa62Smrg      VV[1][0] = vert[0][0];
821f220fa62Smrg      VV[1][1] = vert[0][1];
822f220fa62Smrg      sampledLine *sLine = new sampledLine(2, vert);
823f220fa62Smrg      directedLine *thisPoly = new directedLine(INCREASING, sLine);
824f220fa62SmrgthisPoly->rootLinkSet(NULL);
825f220fa62Smrg
826f220fa62Smrg      directedLine *dLine;
827f220fa62Smrg      for(j=2; j<nEdges; j++)
828f220fa62Smrg	{
829f220fa62Smrg	  vert[0][0]=vert[1][0];
830f220fa62Smrg	  vert[0][1]=vert[1][1];
831f220fa62Smrg	  result = fscanf(fp, "%f", &(vert[1][0]));
832f220fa62Smrg	  assert(result != EOF);
833f220fa62Smrg	  result = fscanf(fp, "%f", &(vert[1][1]));
834f220fa62Smrg	  assert(result != EOF);
835f220fa62Smrg	  sLine = new sampledLine(2,vert);
836f220fa62Smrg	  dLine = new directedLine(INCREASING, sLine);
837f220fa62SmrgdLine->rootLinkSet(thisPoly);
838f220fa62Smrg	  thisPoly->insert(dLine);
839f220fa62Smrg	}
840f220fa62Smrg
841f220fa62Smrg      VV[0][0]=vert[1][0];
842f220fa62Smrg      VV[0][1]=vert[1][1];
843f220fa62Smrg      sLine = new sampledLine(2,VV);
844f220fa62Smrg      dLine = new directedLine(INCREASING, sLine);
845f220fa62SmrgdLine->rootLinkSet(thisPoly);
846f220fa62Smrg      thisPoly->insert(dLine);
847f220fa62Smrg
848f220fa62Smrg      ret = thisPoly->insertPolygon(ret);
849f220fa62Smrg    }
850f220fa62Smrg  fclose(fp);
851f220fa62Smrg  return ret;
852f220fa62Smrg}
853f220fa62Smrg
854f220fa62Smrg
855f220fa62Smrg
856f220fa62Smrg
857f220fa62Smrg
858f220fa62Smrg
859f220fa62Smrg
860f220fa62Smrg
861